@xtctwins/tctwins-core 1.0.34 → 1.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tctwins-core.es.js +30420 -30419
- package/dist/tctwins-core.min.es.js +27 -27
- package/package.json +2 -2
- package/types/viewer/metadata/MetaModel.d.ts +10 -0
- package/types/viewer/scene/utils.d.ts +165 -165
|
@@ -1294,7 +1294,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1294
1294
|
\***********************************************/
|
|
1295
1295
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1296
1296
|
|
|
1297
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ContextMenu: () => (/* binding */ ContextMenu)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_Map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n\r\n\r\nconst idMap = new _viewer_scene_utils_Map_js__WEBPACK_IMPORTED_MODULE_0__.Map();\r\n\r\n/**\r\n * Internal data class that represents the state of a menu or a submenu.\r\n * @private\r\n */\r\nclass Menu {\r\n constructor(id) {\r\n this.id = id;\r\n this.parentItem = null; // Set to an Item when this Menu is a submenu\r\n this.groups = [];\r\n this.menuElement = null;\r\n this.shown = false;\r\n this.mouseOver = 0;\r\n }\r\n}\r\n\r\n/**\r\n * Internal data class that represents a group of Items in a Menu.\r\n * @private\r\n */\r\nclass Group {\r\n constructor() {\r\n this.items = [];\r\n }\r\n}\r\n\r\n/**\r\n * Internal data class that represents the state of a menu item.\r\n * @private\r\n */\r\nclass Item {\r\n constructor(id, getTitle, doAction, getEnabled, getShown) {\r\n this.id = id;\r\n this.getTitle = getTitle;\r\n this.doAction = doAction;\r\n this.getEnabled = getEnabled;\r\n this.getShown = getShown;\r\n this.itemElement = null;\r\n this.subMenu = null;\r\n this.enabled = true;\r\n }\r\n}\r\n\r\n/**\r\n * @desc A customizable HTML context menu.\r\n *\r\n * [<img src=\"http://xeokit.io/img/docs/ContextMenu/ContextMenu.gif\">](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)]\r\n *\r\n * ## Overview\r\n *\r\n * * A pure JavaScript, lightweight context menu\r\n * * Dynamically configure menu items\r\n * * Dynamically enable or disable items\r\n * * Dynamically show or hide items\r\n * * Supports cascading sub-menus\r\n * * Configure custom style with CSS (see examples above)\r\n *\r\n * ## Usage\r\n *\r\n * In the example below we'll create a ````ContextMenu```` that pops up whenever we right-click on an {@link Entity} within\r\n * our {@link Scene}.\r\n *\r\n * First, we'll create the ````ContextMenu````, configuring it with a list of menu items.\r\n *\r\n * Each item has:\r\n *\r\n * * a ````title```` for the item,\r\n * * a ````doAction()```` callback to fire when the item's title is clicked,\r\n * * an optional ````getShown()```` callback that indicates if the item should shown in the menu or not, and\r\n * * an optional ````getEnabled()```` callback that indicates if the item should be shown enabled in the menu or not.\r\n *\r\n * <br>\r\n *\r\n * The ````getShown()```` and ````getEnabled()```` callbacks are invoked whenever the menu is shown.\r\n *\r\n * When an item's ````getShown()```` callback\r\n * returns ````true````, then the item is shown. When it returns ````false````, then the item is hidden. An item without\r\n * a ````getShown()```` callback is always shown.\r\n *\r\n * When an item's ````getEnabled()```` callback returns ````true````, then the item is enabled and clickable (as long as it's also shown). When it\r\n * returns ````false````, then the item is disabled and cannot be clicked. An item without a ````getEnabled()````\r\n * callback is always enabled and clickable.\r\n *\r\n * Note how the ````doAction()````, ````getShown()```` and ````getEnabled()```` callbacks accept a ````context````\r\n * object. That must be set on the ````ContextMenu```` before we're able to we show it. The context object can be anything. In this example,\r\n * we'll use the context object to provide the callbacks with the Entity that we right-clicked.\r\n *\r\n * We'll also initially enable the ````ContextMenu````.\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_Custom)]\r\n *\r\n * ````javascript\r\n * const canvasContextMenu = new ContextMenu({\r\n *\r\n * enabled: true,\r\n *\r\n * items: [\r\n * [\r\n * {\r\n * title: \"Hide Object\",\r\n * getEnabled: (context) => {\r\n * return context.entity.visible; // Can't hide entity if already hidden\r\n * },\r\n * doAction: function (context) {\r\n * context.entity.visible = false;\r\n * }\r\n * }\r\n * ],\r\n * [\r\n * {\r\n * title: \"Select Object\",\r\n * getEnabled: (context) => {\r\n * return (!context.entity.selected); // Can't select an entity that's already selected\r\n * },\r\n * doAction: function (context) {\r\n * context.entity.selected = true;\r\n * }\r\n * }\r\n * ],\r\n * [\r\n * {\r\n * title: \"X-Ray Object\",\r\n * getEnabled: (context) => {\r\n * return (!context.entity.xrayed); // Can't X-ray an entity that's already X-rayed\r\n * },\r\n * doAction: (context) => {\r\n * context.entity.xrayed = true;\r\n * }\r\n * }\r\n * ]\r\n * ]\r\n * });\r\n * ````\r\n *\r\n * Next, we'll make the ````ContextMenu```` appear whenever we right-click on an Entity. Whenever we right-click\r\n * on the canvas, we'll attempt to pick the Entity at those mouse coordinates. If we succeed, we'll feed the\r\n * Entity into ````ContextMenu```` via the context object, then show the ````ContextMenu````.\r\n *\r\n * From there, each ````ContextMenu```` item's ````getEnabled()```` callback will be invoked (if provided), to determine if the item should\r\n * be enabled. If we click an item, its ````doAction()```` callback will be invoked with our context object.\r\n *\r\n * Remember that we must set the context on our ````ContextMenu```` before we show it, otherwise it will log an error to the console,\r\n * and ignore our attempt to show it.\r\n *\r\n * ````javascript*\r\n * viewer.scene.canvas.canvas.oncontextmenu = (e) => { // Right-clicked on the canvas\r\n *\r\n * if (!objectContextMenu.enabled) {\r\n * return;\r\n * }\r\n *\r\n * var hit = viewer.scene.pick({ // Try to pick an Entity at the coordinates\r\n * canvasPos: [e.pageX, e.pageY]\r\n * });\r\n *\r\n * if (hit) { // Picked an Entity\r\n *\r\n * objectContextMenu.context = { // Feed entity to ContextMenu\r\n * entity: hit.entity\r\n * };\r\n *\r\n * objectContextMenu.show(e.pageX, e.pageY); // Show the ContextMenu\r\n * }\r\n *\r\n * e.preventDefault();\r\n * });\r\n * ````\r\n *\r\n * Note how we only show the ````ContextMenu```` if it's enabled. We can use that mechanism to switch between multiple\r\n * ````ContextMenu```` instances depending on what we clicked.\r\n *\r\n * ## Dynamic Item Titles\r\n *\r\n * To make an item dynamically regenerate its title text whenever we show the ````ContextMenu````, provide its title with a\r\n * ````getTitle()```` callback. The callback will fire each time you show ````ContextMenu````, which will dynamically\r\n * set the item title text.\r\n *\r\n * In the example below, we'll create a simple ````ContextMenu```` that allows us to toggle the selection of an object\r\n * via its first item, which changes text depending on whether we are selecting or deselecting the object.\r\n *\r\n * [[Run an example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_dynamicItemTitles)]\r\n *\r\n * ````javascript\r\n * const canvasContextMenu = new ContextMenu({\r\n *\r\n * enabled: true,\r\n *\r\n * items: [\r\n * [\r\n * {\r\n * getTitle: (context) => {\r\n * return (!context.entity.selected) ? \"Select\" : \"Undo Select\";\r\n * },\r\n * doAction: function (context) {\r\n * context.entity.selected = !context.entity.selected;\r\n * }\r\n * },\r\n * {\r\n * title: \"Clear Selection\",\r\n * getEnabled: function (context) {\r\n * return (context.viewer.scene.numSelectedObjects > 0);\r\n * },\r\n * doAction: function (context) {\r\n * context.viewer.scene.setObjectsSelected(context.viewer.scene.selectedObjectIds, false);\r\n * }\r\n * }\r\n * ]\r\n * ]\r\n * });\r\n * ````\r\n *\r\n * ## Sub-menus\r\n *\r\n * Each menu item can optionally have a sub-menu, which will appear when we hover over the item.\r\n *\r\n * In the example below, we'll create a much simpler ````ContextMenu```` that has only one item, called \"Effects\", which\r\n * will open a cascading sub-menu whenever we hover over that item.\r\n *\r\n * Note that our \"Effects\" item has no ````doAction```` callback, because an item with a sub-menu performs no\r\n * action of its own.\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_subMenus)]\r\n *\r\n * ````javascript\r\n * const canvasContextMenu = new ContextMenu({\r\n * items: [ // Top level items\r\n * [\r\n * {\r\n * getTitle: (context) => {\r\n * return \"Effects\";\r\n * },\r\n *\r\n * items: [ // Sub-menu\r\n * [\r\n * {\r\n * getTitle: (context) => {\r\n * return (!context.entity.visible) ? \"Show\" : \"Hide\";\r\n * },\r\n * doAction: function (context) {\r\n * context.entity.visible = !context.entity.visible;\r\n * }\r\n * },\r\n * {\r\n * getTitle: (context) => {\r\n * return (!context.entity.selected) ? \"Select\" : \"Undo Select\";\r\n * },\r\n * doAction: function (context) {\r\n * context.entity.selected = !context.entity.selected;\r\n * }\r\n * },\r\n * {\r\n * getTitle: (context) => {\r\n * return (!context.entity.highlighted) ? \"Highlight\" : \"Undo Highlight\";\r\n * },\r\n * doAction: function (context) {\r\n * context.entity.highlighted = !context.entity.highlighted;\r\n * }\r\n * }\r\n * ]\r\n * ]\r\n * }\r\n * ]\r\n * ]\r\n * });\r\n * ````\r\n */\r\nclass ContextMenu {\r\n\r\n /**\r\n * Creates a ````ContextMenu````.\r\n *\r\n * The ````ContextMenu```` will be initially hidden.\r\n *\r\n * @param {Object} [cfg] ````ContextMenu```` configuration.\r\n * @param {Object} [cfg.items] The context menu items. These can also be dynamically set on {@link ContextMenu#items}. See the class documentation for an example.\r\n * @param {Object} [cfg.context] The context, which is passed into the item callbacks. This can also be dynamically set on {@link ContextMenu#context}. This must be set before calling {@link ContextMenu#show}.\r\n * @param {Boolean} [cfg.enabled=true] Whether this ````ContextMenu```` is initially enabled. {@link ContextMenu#show} does nothing while this is ````false````.\r\n * @param {Boolean} [cfg.hideOnMouseDown=true] Whether this ````ContextMenu```` automatically hides whenever we mouse-down or tap anywhere in the page.\r\n * @param {Boolean} [cfg.hideOnAction=true] Whether this ````ContextMenu```` automatically hides after we select a menu item. Se false if we want the menu to remain shown and show any updates to its item titles, after we've selected an item.\r\n */\r\n constructor(cfg = {}) {\r\n\r\n this._id = idMap.addItem();\r\n this._context = null;\r\n this._enabled = false; // True when the ContextMenu is enabled\r\n this._itemsCfg = []; // Items as given as configs\r\n this._rootMenu = null; // The root Menu in the tree\r\n this._menuList = []; // List of Menus\r\n this._menuMap = {}; // Menus mapped to their IDs\r\n this._itemList = []; // List of Items\r\n this._itemMap = {}; // Items mapped to their IDs\r\n this._shown = false; // True when the ContextMenu is visible\r\n this._nextId = 0;\r\n\r\n /**\r\n * Subscriptions to events fired at this ContextMenu.\r\n * @private\r\n */\r\n this._eventSubs = {};\r\n\r\n if (cfg.hideOnMouseDown !== false) {\r\n document.addEventListener(\"mousedown\", (event) => {\r\n if (!event.target.classList.contains(\"xeokit-context-menu-item\")) {\r\n this.hide();\r\n }\r\n });\r\n document.addEventListener(\"touchstart\", this._canvasTouchStartHandler = (event) => {\r\n if (!event.target.classList.contains(\"xeokit-context-menu-item\")) {\r\n this.hide();\r\n }\r\n });\r\n }\r\n\r\n if (cfg.items) {\r\n this.items = cfg.items;\r\n }\r\n\r\n this._hideOnAction = (cfg.hideOnAction !== false);\r\n\r\n this.context = cfg.context;\r\n this.enabled = cfg.enabled !== false;\r\n this.hide();\r\n }\r\n\r\n\r\n /**\r\n Subscribes to an event fired at this ````ContextMenu````.\r\n\r\n @param {String} event The event\r\n @param {Function} callback Callback fired on the event\r\n */\r\n on(event, callback) {\r\n let subs = this._eventSubs[event];\r\n if (!subs) {\r\n subs = [];\r\n this._eventSubs[event] = subs;\r\n }\r\n subs.push(callback);\r\n }\r\n\r\n /**\r\n Fires an event at this ````ContextMenu````.\r\n\r\n @param {String} event The event type name\r\n @param {Object} value The event parameters\r\n */\r\n fire(event, value) {\r\n const subs = this._eventSubs[event];\r\n if (subs) {\r\n for (let i = 0, len = subs.length; i < len; i++) {\r\n subs[i](value);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Sets the ````ContextMenu```` items.\r\n *\r\n * These can be updated dynamically at any time.\r\n *\r\n * See class documentation for an example.\r\n *\r\n * @type {Object[]}\r\n */\r\n set items(itemsCfg) {\r\n this._clear();\r\n this._itemsCfg = itemsCfg || [];\r\n this._parseItems(itemsCfg);\r\n this._createUI();\r\n }\r\n\r\n /**\r\n * Gets the ````ContextMenu```` items.\r\n *\r\n * @type {Object[]}\r\n */\r\n get items() {\r\n return this._itemsCfg;\r\n }\r\n\r\n /**\r\n * Sets whether this ````ContextMenu```` is enabled.\r\n *\r\n * Hides the menu when disabling.\r\n *\r\n * @type {Boolean}\r\n */\r\n set enabled(enabled) {\r\n enabled = (!!enabled);\r\n if (enabled === this._enabled) {\r\n return;\r\n }\r\n this._enabled = enabled;\r\n if (!this._enabled) {\r\n this.hide();\r\n }\r\n }\r\n\r\n /**\r\n * Gets whether this ````ContextMenu```` is enabled.\r\n *\r\n * {@link ContextMenu#show} does nothing while this is ````false````.\r\n *\r\n * @type {Boolean}\r\n */\r\n get enabled() {\r\n return this._enabled;\r\n }\r\n\r\n /**\r\n * Sets the ````ContextMenu```` context.\r\n *\r\n * The context can be any object that you need to be provides to the callbacks configured on {@link ContextMenu#items}.\r\n *\r\n * This must be set before calling {@link ContextMenu#show}.\r\n *\r\n * @type {Object}\r\n */\r\n set context(context) {\r\n this._context = context;\r\n }\r\n\r\n /**\r\n * Gets the ````ContextMenu```` context.\r\n *\r\n * @type {Object}\r\n */\r\n get context() {\r\n return this._context;\r\n }\r\n\r\n /**\r\n * Shows this ````ContextMenu```` at the given page coordinates.\r\n *\r\n * Does nothing when {@link ContextMenu#enabled} is ````false````.\r\n *\r\n * Logs error to console and does nothing if {@link ContextMenu#context} has not been set.\r\n *\r\n * Fires a \"shown\" event when shown.\r\n *\r\n * @param {Number} pageX Page X-coordinate.\r\n * @param {Number} pageY Page Y-coordinate.\r\n */\r\n show(pageX, pageY) {\r\n if (!this._context) {\r\n console.error(\"ContextMenu cannot be shown without a context - set context first\");\r\n return;\r\n }\r\n if (!this._enabled) {\r\n return;\r\n }\r\n if (this._shown) {\r\n return;\r\n }\r\n this._hideAllMenus();\r\n this._updateItemsTitles();\r\n this._updateItemsEnabledStatus();\r\n this._showMenu(this._rootMenu.id, pageX, pageY);\r\n this._shown = true;\r\n this.fire(\"shown\", {});\r\n }\r\n\r\n /**\r\n * Gets whether this ````ContextMenu```` is currently shown or not.\r\n *\r\n * @returns {Boolean} Whether this ````ContextMenu```` is shown.\r\n */\r\n get shown() {\r\n return this._shown;\r\n }\r\n\r\n /**\r\n * Hides this ````ContextMenu````.\r\n *\r\n * Fires a \"hidden\" event when hidden.\r\n */\r\n hide() {\r\n if (!this._enabled) {\r\n return;\r\n }\r\n if (!this._shown) {\r\n return;\r\n }\r\n this._hideAllMenus();\r\n this._shown = false;\r\n this.fire(\"hidden\", {});\r\n }\r\n\r\n /**\r\n * Destroys this ````ContextMenu````.\r\n */\r\n destroy() {\r\n this._context = null;\r\n this._clear();\r\n if (this._id !== null) {\r\n idMap.removeItem(this._id);\r\n this._id = null;\r\n }\r\n }\r\n\r\n _clear() { // Destroys DOM elements, clears menu data\r\n for (let i = 0, len = this._menuList.length; i < len; i++) {\r\n const menu = this._menuList[i];\r\n const menuElement = menu.menuElement;\r\n menuElement.parentElement.removeChild(menuElement);\r\n }\r\n this._itemsCfg = [];\r\n this._rootMenu = null;\r\n this._menuList = [];\r\n this._menuMap = {};\r\n this._itemList = [];\r\n this._itemMap = {};\r\n }\r\n\r\n _parseItems(itemsCfg) { // Parses \"items\" config into menu data\r\n\r\n const visitItems = (itemsCfg) => {\r\n\r\n const menuId = this._getNextId();\r\n const menu = new Menu(menuId);\r\n\r\n for (let i = 0, len = itemsCfg.length; i < len; i++) {\r\n\r\n const itemsGroupCfg = itemsCfg[i];\r\n\r\n const group = new Group();\r\n\r\n menu.groups.push(group);\r\n\r\n for (let j = 0, lenj = itemsGroupCfg.length; j < lenj; j++) {\r\n\r\n const itemCfg = itemsGroupCfg[j];\r\n const subItemsCfg = itemCfg.items;\r\n const hasSubItems = (subItemsCfg && (subItemsCfg.length > 0));\r\n const itemId = this._getNextId();\r\n\r\n const getTitle = itemCfg.getTitle || (() => {\r\n return (itemCfg.title || \"\");\r\n });\r\n\r\n const doAction = itemCfg.doAction || itemCfg.callback || (() => {\r\n });\r\n\r\n const getEnabled = itemCfg.getEnabled || (() => {\r\n return true;\r\n });\r\n\r\n const getShown = itemCfg.getShown || (() => {\r\n return true;\r\n });\r\n\r\n const item = new Item(itemId, getTitle, doAction, getEnabled, getShown);\r\n\r\n item.parentMenu = menu;\r\n\r\n group.items.push(item);\r\n\r\n if (hasSubItems) {\r\n const subMenu = visitItems(subItemsCfg);\r\n item.subMenu = subMenu;\r\n subMenu.parentItem = item;\r\n }\r\n\r\n this._itemList.push(item);\r\n this._itemMap[item.id] = item;\r\n }\r\n }\r\n\r\n this._menuList.push(menu);\r\n this._menuMap[menu.id] = menu;\r\n\r\n return menu;\r\n };\r\n\r\n this._rootMenu = visitItems(itemsCfg);\r\n }\r\n\r\n _getNextId() { // Returns a unique ID\r\n return \"ContextMenu_\" + this._id + \"_\" + this._nextId++; // Start ID with alpha chars to make a valid DOM element selector\r\n }\r\n\r\n _createUI() { // Builds DOM elements for the entire menu tree\r\n\r\n const visitMenu = (menu) => {\r\n\r\n this._createMenuUI(menu);\r\n\r\n const groups = menu.groups;\r\n for (let i = 0, len = groups.length; i < len; i++) {\r\n const group = groups[i];\r\n const groupItems = group.items;\r\n for (let j = 0, lenj = groupItems.length; j < lenj; j++) {\r\n const item = groupItems[j];\r\n const subMenu = item.subMenu;\r\n if (subMenu) {\r\n visitMenu(subMenu);\r\n }\r\n }\r\n }\r\n };\r\n\r\n visitMenu(this._rootMenu);\r\n }\r\n\r\n _createMenuUI(menu) { // Builds DOM elements for a menu\r\n\r\n const groups = menu.groups;\r\n const html = [];\r\n\r\n html.push('<div class=\"xeokit-context-menu ' + menu.id + '\" style=\"z-index:300000; position: absolute;\">');\r\n\r\n html.push('<ul>');\r\n\r\n if (groups) {\r\n\r\n for (let i = 0, len = groups.length; i < len; i++) {\r\n\r\n const group = groups[i];\r\n const groupIdx = i;\r\n const groupLen = len;\r\n const groupItems = group.items;\r\n\r\n if (groupItems) {\r\n\r\n for (let j = 0, lenj = groupItems.length; j < lenj; j++) {\r\n\r\n const item = groupItems[j];\r\n const itemSubMenu = item.subMenu;\r\n const actionTitle = item.title || \"\";\r\n\r\n if (itemSubMenu) {\r\n\r\n html.push(\r\n '<li id=\"' + item.id + '\" class=\"xeokit-context-menu-item\" style=\"' +\r\n ((groupIdx === groupLen - 1) || ((j < lenj - 1)) ? 'border-bottom: 0' : 'border-bottom: 1px solid black') +\r\n '\">' +\r\n actionTitle +\r\n ' [MORE]' +\r\n '</li>');\r\n\r\n } else {\r\n\r\n html.push(\r\n '<li id=\"' + item.id + '\" class=\"xeokit-context-menu-item\" style=\"' +\r\n ((groupIdx === groupLen - 1) || ((j < lenj - 1)) ? 'border-bottom: 0' : 'border-bottom: 1px solid black') +\r\n '\">' +\r\n actionTitle +\r\n '</li>');\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n html.push('</ul>');\r\n html.push('</div>');\r\n\r\n const htmlString = html.join(\"\");\r\n\r\n document.body.insertAdjacentHTML('beforeend', htmlString);\r\n\r\n const menuElement = document.querySelector(\".\" + menu.id);\r\n\r\n menu.menuElement = menuElement;\r\n\r\n menuElement.style[\"border-radius\"] = 4 + \"px\";\r\n menuElement.style.display = 'none';\r\n menuElement.style[\"z-index\"] = 300000;\r\n menuElement.style.background = \"white\";\r\n menuElement.style.border = \"1px solid black\";\r\n menuElement.style[\"box-shadow\"] = \"0 4px 5px 0 gray\";\r\n menuElement.oncontextmenu = (e) => {\r\n e.preventDefault();\r\n };\r\n\r\n // Bind event handlers\r\n\r\n const self = this;\r\n\r\n let lastSubMenu = null;\r\n\r\n if (groups) {\r\n\r\n for (let i = 0, len = groups.length; i < len; i++) {\r\n\r\n const group = groups[i];\r\n const groupItems = group.items;\r\n\r\n if (groupItems) {\r\n\r\n for (let j = 0, lenj = groupItems.length; j < lenj; j++) {\r\n\r\n const item = groupItems[j];\r\n const itemSubMenu = item.subMenu;\r\n\r\n item.itemElement = document.getElementById(item.id);\r\n\r\n if (!item.itemElement) {\r\n console.error(\"ContextMenu item element not found: \" + item.id);\r\n continue;\r\n }\r\n\r\n item.itemElement.addEventListener(\"mouseenter\", (event) => {\r\n event.preventDefault();\r\n\r\n const subMenu = item.subMenu;\r\n if (!subMenu) {\r\n if (lastSubMenu) {\r\n self._hideMenu(lastSubMenu.id);\r\n lastSubMenu = null;\r\n }\r\n return;\r\n }\r\n if (lastSubMenu && (lastSubMenu.id !== subMenu.id)) {\r\n self._hideMenu(lastSubMenu.id);\r\n lastSubMenu = null;\r\n }\r\n\r\n if (item.enabled === false) {\r\n return;\r\n }\r\n\r\n const itemElement = item.itemElement;\r\n const subMenuElement = subMenu.menuElement;\r\n\r\n const itemRect = itemElement.getBoundingClientRect();\r\n const menuRect = subMenuElement.getBoundingClientRect();\r\n\r\n const subMenuWidth = 200; // TODO\r\n const showOnLeft = ((itemRect.right + subMenuWidth) > window.innerWidth);\r\n\r\n if (showOnLeft) {\r\n self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);\r\n } else {\r\n self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);\r\n }\r\n\r\n lastSubMenu = subMenu;\r\n });\r\n\r\n if (!itemSubMenu) {\r\n\r\n // Item without sub-menu\r\n // clicking item fires the item's action callback\r\n\r\n item.itemElement.addEventListener(\"click\", (event) => {\r\n event.preventDefault();\r\n if (!self._context) {\r\n return;\r\n }\r\n if (item.enabled === false) {\r\n return;\r\n }\r\n if (item.doAction) {\r\n item.doAction(self._context);\r\n }\r\n if (this._hideOnAction) {\r\n self.hide();\r\n } else {\r\n self._updateItemsTitles();\r\n self._updateItemsEnabledStatus();\r\n }\r\n });\r\n item.itemElement.addEventListener(\"mouseenter\", (event) => {\r\n event.preventDefault();\r\n if (item.enabled === false) {\r\n return;\r\n }\r\n if (item.doHover) {\r\n item.doHover(self._context);\r\n }\r\n });\r\n\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n _updateItemsTitles() { // Dynamically updates the title of each Item to the result of Item#getTitle()\r\n if (!this._context) {\r\n return;\r\n }\r\n for (let i = 0, len = this._itemList.length; i < len; i++) {\r\n const item = this._itemList[i];\r\n const itemElement = item.itemElement;\r\n if (!itemElement) {\r\n continue;\r\n }\r\n const getShown = item.getShown;\r\n if (!getShown || !getShown(this._context)) {\r\n continue;\r\n }\r\n const title = item.getTitle(this._context);\r\n if (item.subMenu) {\r\n itemElement.innerText = title;\r\n } else {\r\n itemElement.innerText = title;\r\n }\r\n }\r\n }\r\n\r\n _updateItemsEnabledStatus() { // Enables or disables each Item, depending on the result of Item#getEnabled()\r\n if (!this._context) {\r\n return;\r\n }\r\n for (let i = 0, len = this._itemList.length; i < len; i++) {\r\n const item = this._itemList[i];\r\n const itemElement = item.itemElement;\r\n if (!itemElement) {\r\n continue;\r\n }\r\n const getEnabled = item.getEnabled;\r\n if (!getEnabled) {\r\n continue;\r\n }\r\n const getShown = item.getShown;\r\n if (!getShown) {\r\n continue;\r\n }\r\n const shown = getShown(this._context);\r\n item.shown = shown;\r\n if (!shown) {\r\n itemElement.style.visibility = \"hidden\";\r\n itemElement.style.height = \"0\";\r\n itemElement.style.padding = \"0\";\r\n continue;\r\n } else {\r\n itemElement.style.visibility = \"visible\";\r\n itemElement.style.height = \"auto\";\r\n itemElement.style.padding = null;\r\n }\r\n const enabled = getEnabled(this._context);\r\n item.enabled = enabled;\r\n if (!enabled) {\r\n itemElement.classList.add(\"disabled\");\r\n } else {\r\n itemElement.classList.remove(\"disabled\");\r\n }\r\n }\r\n }\r\n\r\n _showMenu(menuId, pageX, pageY) { // Shows the given menu, at the specified page coordinates\r\n const menu = this._menuMap[menuId];\r\n if (!menu) {\r\n console.error(\"Menu not found: \" + menuId);\r\n return;\r\n }\r\n if (menu.shown) {\r\n return;\r\n }\r\n const menuElement = menu.menuElement;\r\n if (menuElement) {\r\n this._showMenuElement(menuElement, pageX, pageY);\r\n menu.shown = true;\r\n }\r\n }\r\n\r\n _hideMenu(menuId) { // Hides the given menu\r\n const menu = this._menuMap[menuId];\r\n if (!menu) {\r\n console.error(\"Menu not found: \" + menuId);\r\n return;\r\n }\r\n if (!menu.shown) {\r\n return;\r\n }\r\n const menuElement = menu.menuElement;\r\n if (menuElement) {\r\n this._hideMenuElement(menuElement);\r\n menu.shown = false;\r\n }\r\n }\r\n\r\n _hideAllMenus() {\r\n for (let i = 0, len = this._menuList.length; i < len; i++) {\r\n const menu = this._menuList[i];\r\n this._hideMenu(menu.id);\r\n }\r\n }\r\n\r\n _showMenuElement(menuElement, pageX, pageY) { // Shows the given menu element, at the specified page coordinates\r\n menuElement.style.display = 'block';\r\n const menuHeight = menuElement.offsetHeight;\r\n const menuWidth = menuElement.offsetWidth;\r\n if ((pageY + menuHeight) > window.innerHeight) {\r\n pageY = window.innerHeight - menuHeight;\r\n }\r\n if ((pageX + menuWidth) > window.innerWidth) {\r\n pageX = window.innerWidth - menuWidth;\r\n }\r\n menuElement.style.left = pageX + 'px';\r\n menuElement.style.top = pageY + 'px';\r\n }\r\n\r\n _hideMenuElement(menuElement) {\r\n menuElement.style.display = 'none';\r\n }\r\n}\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/extras/ContextMenu/ContextMenu.js?");
|
|
1297
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ContextMenu: () => (/* binding */ ContextMenu)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_Map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n\n\nconst idMap = new _viewer_scene_utils_Map_js__WEBPACK_IMPORTED_MODULE_0__.Map();\n\n/**\n * Internal data class that represents the state of a menu or a submenu.\n * @private\n */\nclass Menu {\n constructor(id) {\n this.id = id;\n this.parentItem = null; // Set to an Item when this Menu is a submenu\n this.groups = [];\n this.menuElement = null;\n this.shown = false;\n this.mouseOver = 0;\n }\n}\n\n/**\n * Internal data class that represents a group of Items in a Menu.\n * @private\n */\nclass Group {\n constructor() {\n this.items = [];\n }\n}\n\n/**\n * Internal data class that represents the state of a menu item.\n * @private\n */\nclass Item {\n constructor(id, getTitle, doAction, getEnabled, getShown) {\n this.id = id;\n this.getTitle = getTitle;\n this.doAction = doAction;\n this.getEnabled = getEnabled;\n this.getShown = getShown;\n this.itemElement = null;\n this.subMenu = null;\n this.enabled = true;\n }\n}\n\n/**\n * @desc A customizable HTML context menu.\n *\n * [<img src=\"http://xeokit.io/img/docs/ContextMenu/ContextMenu.gif\">](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)\n *\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)]\n *\n * ## Overview\n *\n * * A pure JavaScript, lightweight context menu\n * * Dynamically configure menu items\n * * Dynamically enable or disable items\n * * Dynamically show or hide items\n * * Supports cascading sub-menus\n * * Configure custom style with CSS (see examples above)\n *\n * ## Usage\n *\n * In the example below we'll create a ````ContextMenu```` that pops up whenever we right-click on an {@link Entity} within\n * our {@link Scene}.\n *\n * First, we'll create the ````ContextMenu````, configuring it with a list of menu items.\n *\n * Each item has:\n *\n * * a ````title```` for the item,\n * * a ````doAction()```` callback to fire when the item's title is clicked,\n * * an optional ````getShown()```` callback that indicates if the item should shown in the menu or not, and\n * * an optional ````getEnabled()```` callback that indicates if the item should be shown enabled in the menu or not.\n *\n * <br>\n *\n * The ````getShown()```` and ````getEnabled()```` callbacks are invoked whenever the menu is shown.\n *\n * When an item's ````getShown()```` callback\n * returns ````true````, then the item is shown. When it returns ````false````, then the item is hidden. An item without\n * a ````getShown()```` callback is always shown.\n *\n * When an item's ````getEnabled()```` callback returns ````true````, then the item is enabled and clickable (as long as it's also shown). When it\n * returns ````false````, then the item is disabled and cannot be clicked. An item without a ````getEnabled()````\n * callback is always enabled and clickable.\n *\n * Note how the ````doAction()````, ````getShown()```` and ````getEnabled()```` callbacks accept a ````context````\n * object. That must be set on the ````ContextMenu```` before we're able to we show it. The context object can be anything. In this example,\n * we'll use the context object to provide the callbacks with the Entity that we right-clicked.\n *\n * We'll also initially enable the ````ContextMenu````.\n *\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_Custom)]\n *\n * ````javascript\n * const canvasContextMenu = new ContextMenu({\n *\n * enabled: true,\n *\n * items: [\n * [\n * {\n * title: \"Hide Object\",\n * getEnabled: (context) => {\n * return context.entity.visible; // Can't hide entity if already hidden\n * },\n * doAction: function (context) {\n * context.entity.visible = false;\n * }\n * }\n * ],\n * [\n * {\n * title: \"Select Object\",\n * getEnabled: (context) => {\n * return (!context.entity.selected); // Can't select an entity that's already selected\n * },\n * doAction: function (context) {\n * context.entity.selected = true;\n * }\n * }\n * ],\n * [\n * {\n * title: \"X-Ray Object\",\n * getEnabled: (context) => {\n * return (!context.entity.xrayed); // Can't X-ray an entity that's already X-rayed\n * },\n * doAction: (context) => {\n * context.entity.xrayed = true;\n * }\n * }\n * ]\n * ]\n * });\n * ````\n *\n * Next, we'll make the ````ContextMenu```` appear whenever we right-click on an Entity. Whenever we right-click\n * on the canvas, we'll attempt to pick the Entity at those mouse coordinates. If we succeed, we'll feed the\n * Entity into ````ContextMenu```` via the context object, then show the ````ContextMenu````.\n *\n * From there, each ````ContextMenu```` item's ````getEnabled()```` callback will be invoked (if provided), to determine if the item should\n * be enabled. If we click an item, its ````doAction()```` callback will be invoked with our context object.\n *\n * Remember that we must set the context on our ````ContextMenu```` before we show it, otherwise it will log an error to the console,\n * and ignore our attempt to show it.\n *\n * ````javascript*\n * viewer.scene.canvas.canvas.oncontextmenu = (e) => { // Right-clicked on the canvas\n *\n * if (!objectContextMenu.enabled) {\n * return;\n * }\n *\n * var hit = viewer.scene.pick({ // Try to pick an Entity at the coordinates\n * canvasPos: [e.pageX, e.pageY]\n * });\n *\n * if (hit) { // Picked an Entity\n *\n * objectContextMenu.context = { // Feed entity to ContextMenu\n * entity: hit.entity\n * };\n *\n * objectContextMenu.show(e.pageX, e.pageY); // Show the ContextMenu\n * }\n *\n * e.preventDefault();\n * });\n * ````\n *\n * Note how we only show the ````ContextMenu```` if it's enabled. We can use that mechanism to switch between multiple\n * ````ContextMenu```` instances depending on what we clicked.\n *\n * ## Dynamic Item Titles\n *\n * To make an item dynamically regenerate its title text whenever we show the ````ContextMenu````, provide its title with a\n * ````getTitle()```` callback. The callback will fire each time you show ````ContextMenu````, which will dynamically\n * set the item title text.\n *\n * In the example below, we'll create a simple ````ContextMenu```` that allows us to toggle the selection of an object\n * via its first item, which changes text depending on whether we are selecting or deselecting the object.\n *\n * [[Run an example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_dynamicItemTitles)]\n *\n * ````javascript\n * const canvasContextMenu = new ContextMenu({\n *\n * enabled: true,\n *\n * items: [\n * [\n * {\n * getTitle: (context) => {\n * return (!context.entity.selected) ? \"Select\" : \"Undo Select\";\n * },\n * doAction: function (context) {\n * context.entity.selected = !context.entity.selected;\n * }\n * },\n * {\n * title: \"Clear Selection\",\n * getEnabled: function (context) {\n * return (context.viewer.scene.numSelectedObjects > 0);\n * },\n * doAction: function (context) {\n * context.viewer.scene.setObjectsSelected(context.viewer.scene.selectedObjectIds, false);\n * }\n * }\n * ]\n * ]\n * });\n * ````\n *\n * ## Sub-menus\n *\n * Each menu item can optionally have a sub-menu, which will appear when we hover over the item.\n *\n * In the example below, we'll create a much simpler ````ContextMenu```` that has only one item, called \"Effects\", which\n * will open a cascading sub-menu whenever we hover over that item.\n *\n * Note that our \"Effects\" item has no ````doAction```` callback, because an item with a sub-menu performs no\n * action of its own.\n *\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_subMenus)]\n *\n * ````javascript\n * const canvasContextMenu = new ContextMenu({\n * items: [ // Top level items\n * [\n * {\n * getTitle: (context) => {\n * return \"Effects\";\n * },\n *\n * items: [ // Sub-menu\n * [\n * {\n * getTitle: (context) => {\n * return (!context.entity.visible) ? \"Show\" : \"Hide\";\n * },\n * doAction: function (context) {\n * context.entity.visible = !context.entity.visible;\n * }\n * },\n * {\n * getTitle: (context) => {\n * return (!context.entity.selected) ? \"Select\" : \"Undo Select\";\n * },\n * doAction: function (context) {\n * context.entity.selected = !context.entity.selected;\n * }\n * },\n * {\n * getTitle: (context) => {\n * return (!context.entity.highlighted) ? \"Highlight\" : \"Undo Highlight\";\n * },\n * doAction: function (context) {\n * context.entity.highlighted = !context.entity.highlighted;\n * }\n * }\n * ]\n * ]\n * }\n * ]\n * ]\n * });\n * ````\n */\nclass ContextMenu {\n\n /**\n * Creates a ````ContextMenu````.\n *\n * The ````ContextMenu```` will be initially hidden.\n *\n * @param {Object} [cfg] ````ContextMenu```` configuration.\n * @param {Object} [cfg.items] The context menu items. These can also be dynamically set on {@link ContextMenu#items}. See the class documentation for an example.\n * @param {Object} [cfg.context] The context, which is passed into the item callbacks. This can also be dynamically set on {@link ContextMenu#context}. This must be set before calling {@link ContextMenu#show}.\n * @param {Boolean} [cfg.enabled=true] Whether this ````ContextMenu```` is initially enabled. {@link ContextMenu#show} does nothing while this is ````false````.\n * @param {Boolean} [cfg.hideOnMouseDown=true] Whether this ````ContextMenu```` automatically hides whenever we mouse-down or tap anywhere in the page.\n * @param {Boolean} [cfg.hideOnAction=true] Whether this ````ContextMenu```` automatically hides after we select a menu item. Se false if we want the menu to remain shown and show any updates to its item titles, after we've selected an item.\n */\n constructor(cfg = {}) {\n\n this._id = idMap.addItem();\n this._context = null;\n this._enabled = false; // True when the ContextMenu is enabled\n this._itemsCfg = []; // Items as given as configs\n this._rootMenu = null; // The root Menu in the tree\n this._menuList = []; // List of Menus\n this._menuMap = {}; // Menus mapped to their IDs\n this._itemList = []; // List of Items\n this._itemMap = {}; // Items mapped to their IDs\n this._shown = false; // True when the ContextMenu is visible\n this._nextId = 0;\n\n /**\n * Subscriptions to events fired at this ContextMenu.\n * @private\n */\n this._eventSubs = {};\n\n if (cfg.hideOnMouseDown !== false) {\n document.addEventListener(\"mousedown\", (event) => {\n if (!event.target.classList.contains(\"xeokit-context-menu-item\")) {\n this.hide();\n }\n });\n document.addEventListener(\"touchstart\", this._canvasTouchStartHandler = (event) => {\n if (!event.target.classList.contains(\"xeokit-context-menu-item\")) {\n this.hide();\n }\n });\n }\n\n if (cfg.items) {\n this.items = cfg.items;\n }\n\n this._hideOnAction = (cfg.hideOnAction !== false);\n\n this.context = cfg.context;\n this.enabled = cfg.enabled !== false;\n this.hide();\n }\n\n\n /**\n Subscribes to an event fired at this ````ContextMenu````.\n\n @param {String} event The event\n @param {Function} callback Callback fired on the event\n */\n on(event, callback) {\n let subs = this._eventSubs[event];\n if (!subs) {\n subs = [];\n this._eventSubs[event] = subs;\n }\n subs.push(callback);\n }\n\n /**\n Fires an event at this ````ContextMenu````.\n\n @param {String} event The event type name\n @param {Object} value The event parameters\n */\n fire(event, value) {\n const subs = this._eventSubs[event];\n if (subs) {\n for (let i = 0, len = subs.length; i < len; i++) {\n subs[i](value);\n }\n }\n }\n\n /**\n * Sets the ````ContextMenu```` items.\n *\n * These can be updated dynamically at any time.\n *\n * See class documentation for an example.\n *\n * @type {Object[]}\n */\n set items(itemsCfg) {\n this._clear();\n this._itemsCfg = itemsCfg || [];\n this._parseItems(itemsCfg);\n this._createUI();\n }\n\n /**\n * Gets the ````ContextMenu```` items.\n *\n * @type {Object[]}\n */\n get items() {\n return this._itemsCfg;\n }\n\n /**\n * Sets whether this ````ContextMenu```` is enabled.\n *\n * Hides the menu when disabling.\n *\n * @type {Boolean}\n */\n set enabled(enabled) {\n enabled = (!!enabled);\n if (enabled === this._enabled) {\n return;\n }\n this._enabled = enabled;\n if (!this._enabled) {\n this.hide();\n }\n }\n\n /**\n * Gets whether this ````ContextMenu```` is enabled.\n *\n * {@link ContextMenu#show} does nothing while this is ````false````.\n *\n * @type {Boolean}\n */\n get enabled() {\n return this._enabled;\n }\n\n /**\n * Sets the ````ContextMenu```` context.\n *\n * The context can be any object that you need to be provides to the callbacks configured on {@link ContextMenu#items}.\n *\n * This must be set before calling {@link ContextMenu#show}.\n *\n * @type {Object}\n */\n set context(context) {\n this._context = context;\n }\n\n /**\n * Gets the ````ContextMenu```` context.\n *\n * @type {Object}\n */\n get context() {\n return this._context;\n }\n\n /**\n * Shows this ````ContextMenu```` at the given page coordinates.\n *\n * Does nothing when {@link ContextMenu#enabled} is ````false````.\n *\n * Logs error to console and does nothing if {@link ContextMenu#context} has not been set.\n *\n * Fires a \"shown\" event when shown.\n *\n * @param {Number} pageX Page X-coordinate.\n * @param {Number} pageY Page Y-coordinate.\n */\n show(pageX, pageY) {\n if (!this._context) {\n console.error(\"ContextMenu cannot be shown without a context - set context first\");\n return;\n }\n if (!this._enabled) {\n return;\n }\n if (this._shown) {\n return;\n }\n this._hideAllMenus();\n this._updateItemsTitles();\n this._updateItemsEnabledStatus();\n this._showMenu(this._rootMenu.id, pageX, pageY);\n this._shown = true;\n this.fire(\"shown\", {});\n }\n\n /**\n * Gets whether this ````ContextMenu```` is currently shown or not.\n *\n * @returns {Boolean} Whether this ````ContextMenu```` is shown.\n */\n get shown() {\n return this._shown;\n }\n\n /**\n * Hides this ````ContextMenu````.\n *\n * Fires a \"hidden\" event when hidden.\n */\n hide() {\n if (!this._enabled) {\n return;\n }\n if (!this._shown) {\n return;\n }\n this._hideAllMenus();\n this._shown = false;\n this.fire(\"hidden\", {});\n }\n\n /**\n * Destroys this ````ContextMenu````.\n */\n destroy() {\n this._context = null;\n this._clear();\n if (this._id !== null) {\n idMap.removeItem(this._id);\n this._id = null;\n }\n }\n\n _clear() { // Destroys DOM elements, clears menu data\n for (let i = 0, len = this._menuList.length; i < len; i++) {\n const menu = this._menuList[i];\n const menuElement = menu.menuElement;\n menuElement.parentElement.removeChild(menuElement);\n }\n this._itemsCfg = [];\n this._rootMenu = null;\n this._menuList = [];\n this._menuMap = {};\n this._itemList = [];\n this._itemMap = {};\n }\n\n _parseItems(itemsCfg) { // Parses \"items\" config into menu data\n\n const visitItems = (itemsCfg) => {\n\n const menuId = this._getNextId();\n const menu = new Menu(menuId);\n\n for (let i = 0, len = itemsCfg.length; i < len; i++) {\n\n const itemsGroupCfg = itemsCfg[i];\n\n const group = new Group();\n\n menu.groups.push(group);\n\n for (let j = 0, lenj = itemsGroupCfg.length; j < lenj; j++) {\n\n const itemCfg = itemsGroupCfg[j];\n const subItemsCfg = itemCfg.items;\n const hasSubItems = (subItemsCfg && (subItemsCfg.length > 0));\n const itemId = this._getNextId();\n\n const getTitle = itemCfg.getTitle || (() => {\n return (itemCfg.title || \"\");\n });\n\n const doAction = itemCfg.doAction || itemCfg.callback || (() => {\n });\n\n const getEnabled = itemCfg.getEnabled || (() => {\n return true;\n });\n\n const getShown = itemCfg.getShown || (() => {\n return true;\n });\n\n const item = new Item(itemId, getTitle, doAction, getEnabled, getShown);\n\n item.parentMenu = menu;\n\n group.items.push(item);\n\n if (hasSubItems) {\n const subMenu = visitItems(subItemsCfg);\n item.subMenu = subMenu;\n subMenu.parentItem = item;\n }\n\n this._itemList.push(item);\n this._itemMap[item.id] = item;\n }\n }\n\n this._menuList.push(menu);\n this._menuMap[menu.id] = menu;\n\n return menu;\n };\n\n this._rootMenu = visitItems(itemsCfg);\n }\n\n _getNextId() { // Returns a unique ID\n return \"ContextMenu_\" + this._id + \"_\" + this._nextId++; // Start ID with alpha chars to make a valid DOM element selector\n }\n\n _createUI() { // Builds DOM elements for the entire menu tree\n\n const visitMenu = (menu) => {\n\n this._createMenuUI(menu);\n\n const groups = menu.groups;\n for (let i = 0, len = groups.length; i < len; i++) {\n const group = groups[i];\n const groupItems = group.items;\n for (let j = 0, lenj = groupItems.length; j < lenj; j++) {\n const item = groupItems[j];\n const subMenu = item.subMenu;\n if (subMenu) {\n visitMenu(subMenu);\n }\n }\n }\n };\n\n visitMenu(this._rootMenu);\n }\n\n _createMenuUI(menu) { // Builds DOM elements for a menu\n\n const groups = menu.groups;\n const html = [];\n\n html.push('<div class=\"xeokit-context-menu ' + menu.id + '\" style=\"z-index:300000; position: absolute;\">');\n\n html.push('<ul>');\n\n if (groups) {\n\n for (let i = 0, len = groups.length; i < len; i++) {\n\n const group = groups[i];\n const groupIdx = i;\n const groupLen = len;\n const groupItems = group.items;\n\n if (groupItems) {\n\n for (let j = 0, lenj = groupItems.length; j < lenj; j++) {\n\n const item = groupItems[j];\n const itemSubMenu = item.subMenu;\n const actionTitle = item.title || \"\";\n\n if (itemSubMenu) {\n\n html.push(\n '<li id=\"' + item.id + '\" class=\"xeokit-context-menu-item\" style=\"' +\n ((groupIdx === groupLen - 1) || ((j < lenj - 1)) ? 'border-bottom: 0' : 'border-bottom: 1px solid black') +\n '\">' +\n actionTitle +\n ' [MORE]' +\n '</li>');\n\n } else {\n\n html.push(\n '<li id=\"' + item.id + '\" class=\"xeokit-context-menu-item\" style=\"' +\n ((groupIdx === groupLen - 1) || ((j < lenj - 1)) ? 'border-bottom: 0' : 'border-bottom: 1px solid black') +\n '\">' +\n actionTitle +\n '</li>');\n }\n }\n }\n }\n }\n\n html.push('</ul>');\n html.push('</div>');\n\n const htmlString = html.join(\"\");\n\n document.body.insertAdjacentHTML('beforeend', htmlString);\n\n const menuElement = document.querySelector(\".\" + menu.id);\n\n menu.menuElement = menuElement;\n\n menuElement.style[\"border-radius\"] = 4 + \"px\";\n menuElement.style.display = 'none';\n menuElement.style[\"z-index\"] = 300000;\n menuElement.style.background = \"white\";\n menuElement.style.border = \"1px solid black\";\n menuElement.style[\"box-shadow\"] = \"0 4px 5px 0 gray\";\n menuElement.oncontextmenu = (e) => {\n e.preventDefault();\n };\n\n // Bind event handlers\n\n const self = this;\n\n let lastSubMenu = null;\n\n if (groups) {\n\n for (let i = 0, len = groups.length; i < len; i++) {\n\n const group = groups[i];\n const groupItems = group.items;\n\n if (groupItems) {\n\n for (let j = 0, lenj = groupItems.length; j < lenj; j++) {\n\n const item = groupItems[j];\n const itemSubMenu = item.subMenu;\n\n item.itemElement = document.getElementById(item.id);\n\n if (!item.itemElement) {\n console.error(\"ContextMenu item element not found: \" + item.id);\n continue;\n }\n\n item.itemElement.addEventListener(\"mouseenter\", (event) => {\n event.preventDefault();\n\n const subMenu = item.subMenu;\n if (!subMenu) {\n if (lastSubMenu) {\n self._hideMenu(lastSubMenu.id);\n lastSubMenu = null;\n }\n return;\n }\n if (lastSubMenu && (lastSubMenu.id !== subMenu.id)) {\n self._hideMenu(lastSubMenu.id);\n lastSubMenu = null;\n }\n\n if (item.enabled === false) {\n return;\n }\n\n const itemElement = item.itemElement;\n const subMenuElement = subMenu.menuElement;\n\n const itemRect = itemElement.getBoundingClientRect();\n const menuRect = subMenuElement.getBoundingClientRect();\n\n const subMenuWidth = 200; // TODO\n const showOnLeft = ((itemRect.right + subMenuWidth) > window.innerWidth);\n\n if (showOnLeft) {\n self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);\n } else {\n self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);\n }\n\n lastSubMenu = subMenu;\n });\n\n if (!itemSubMenu) {\n\n // Item without sub-menu\n // clicking item fires the item's action callback\n\n item.itemElement.addEventListener(\"click\", (event) => {\n event.preventDefault();\n if (!self._context) {\n return;\n }\n if (item.enabled === false) {\n return;\n }\n if (item.doAction) {\n item.doAction(self._context);\n }\n if (this._hideOnAction) {\n self.hide();\n } else {\n self._updateItemsTitles();\n self._updateItemsEnabledStatus();\n }\n });\n item.itemElement.addEventListener(\"mouseenter\", (event) => {\n event.preventDefault();\n if (item.enabled === false) {\n return;\n }\n if (item.doHover) {\n item.doHover(self._context);\n }\n });\n\n }\n }\n }\n }\n }\n }\n\n _updateItemsTitles() { // Dynamically updates the title of each Item to the result of Item#getTitle()\n if (!this._context) {\n return;\n }\n for (let i = 0, len = this._itemList.length; i < len; i++) {\n const item = this._itemList[i];\n const itemElement = item.itemElement;\n if (!itemElement) {\n continue;\n }\n const getShown = item.getShown;\n if (!getShown || !getShown(this._context)) {\n continue;\n }\n const title = item.getTitle(this._context);\n if (item.subMenu) {\n itemElement.innerText = title;\n } else {\n itemElement.innerText = title;\n }\n }\n }\n\n _updateItemsEnabledStatus() { // Enables or disables each Item, depending on the result of Item#getEnabled()\n if (!this._context) {\n return;\n }\n for (let i = 0, len = this._itemList.length; i < len; i++) {\n const item = this._itemList[i];\n const itemElement = item.itemElement;\n if (!itemElement) {\n continue;\n }\n const getEnabled = item.getEnabled;\n if (!getEnabled) {\n continue;\n }\n const getShown = item.getShown;\n if (!getShown) {\n continue;\n }\n const shown = getShown(this._context);\n item.shown = shown;\n if (!shown) {\n itemElement.style.visibility = \"hidden\";\n itemElement.style.height = \"0\";\n itemElement.style.padding = \"0\";\n continue;\n } else {\n itemElement.style.visibility = \"visible\";\n itemElement.style.height = \"auto\";\n itemElement.style.padding = null;\n }\n const enabled = getEnabled(this._context);\n item.enabled = enabled;\n if (!enabled) {\n itemElement.classList.add(\"disabled\");\n } else {\n itemElement.classList.remove(\"disabled\");\n }\n }\n }\n\n _showMenu(menuId, pageX, pageY) { // Shows the given menu, at the specified page coordinates\n const menu = this._menuMap[menuId];\n if (!menu) {\n console.error(\"Menu not found: \" + menuId);\n return;\n }\n if (menu.shown) {\n return;\n }\n const menuElement = menu.menuElement;\n if (menuElement) {\n this._showMenuElement(menuElement, pageX, pageY);\n menu.shown = true;\n }\n }\n\n _hideMenu(menuId) { // Hides the given menu\n const menu = this._menuMap[menuId];\n if (!menu) {\n console.error(\"Menu not found: \" + menuId);\n return;\n }\n if (!menu.shown) {\n return;\n }\n const menuElement = menu.menuElement;\n if (menuElement) {\n this._hideMenuElement(menuElement);\n menu.shown = false;\n }\n }\n\n _hideAllMenus() {\n for (let i = 0, len = this._menuList.length; i < len; i++) {\n const menu = this._menuList[i];\n this._hideMenu(menu.id);\n }\n }\n\n _showMenuElement(menuElement, pageX, pageY) { // Shows the given menu element, at the specified page coordinates\n menuElement.style.display = 'block';\n const menuHeight = menuElement.offsetHeight;\n const menuWidth = menuElement.offsetWidth;\n if ((pageY + menuHeight) > window.innerHeight) {\n pageY = window.innerHeight - menuHeight;\n }\n if ((pageX + menuWidth) > window.innerWidth) {\n pageX = window.innerWidth - menuWidth;\n }\n menuElement.style.left = pageX + 'px';\n menuElement.style.top = pageY + 'px';\n }\n\n _hideMenuElement(menuElement) {\n menuElement.style.display = 'none';\n }\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/extras/ContextMenu/ContextMenu.js?");
|
|
1298
1298
|
|
|
1299
1299
|
/***/ }),
|
|
1300
1300
|
|
|
@@ -1344,7 +1344,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1344
1344
|
\***************************************************/
|
|
1345
1345
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1346
1346
|
|
|
1347
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PointerCircle: () => (/* binding */ PointerCircle)\n/* harmony export */ });\nconst SHRINK_SPEED = 3;\
|
|
1347
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PointerCircle: () => (/* binding */ PointerCircle)\n/* harmony export */ });\nconst SHRINK_SPEED = 3;\n\n/**\n * A PointerCircle shows a circle, centered at the position of the\n * mouse or touch pointer.\n */\nclass PointerCircle {\n\t/**\n\t * Constructs a new PointerCircle.\n\t * @param viewer The Viewer\n\t * @param [cfg] PointerCircle configuration.\n\t * @param [cfg.active=true] Whether PointerCircle is active. The PointerCircle can only be shown when this is `true` (default).\n\t */\n\tconstructor(viewer, cfg = {}) {\n\t\tthis.viewer = viewer;\n\t\tthis.scene = this.viewer.scene;\n\t\tthis._circleDiv = document.createElement(\"div\");\n\t\tthis._circleDiv.id = cfg.id;\n\t\tthis.viewer.scene.canvas.canvas.parentNode.insertBefore(this._circleDiv, this.viewer.scene.canvas.canvas);\n\t\tthis._circleDiv.style.backgroundColor = \"transparent\";\n\t\tthis._circleDiv.style.border = \"2px solid green\";\n\t\tthis._circleDiv.style.borderRadius = \"50px\";\n\t\tthis._circleDiv.style.width = \"50px\";\n\t\tthis._circleDiv.style.height = \"50px\";\n\t\tthis._circleDiv.style.margin = \"-200px -200px\";\n\t\tthis._circleDiv.style.zIndex = \"100000\";\n\t\tthis._circleDiv.style.position = \"absolute\";\n\t\tthis._circleDiv.style.pointerEvents = \"none\";\n\n\t\tthis._circlePos = null;\n\n\t\tthis._circleMaxRadius = 200;\n\t\tthis._circleMinRadius = 2;\n\n\t\tthis._active = cfg.active !== false;\n\t\tthis._visible = false;\n\n\t\tthis._running = false;\n\t\tthis._destroyed = false;\n\t}\n\n\t/**\n\t * Show the circle at the given canvas coordinates and begin shrinking it.\n\t */\n\tstart(circlePos) {\n\t\tif (this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tthis._circlePos = circlePos;\n\t\tthis._running = false;\n\t\tthis._circleRadius = this._circleMaxRadius;\n\t\tthis._circleDiv.style.borderRadius = `${this._circleRadius}px`;\n\t\tthis._circleDiv.style.marginLeft = `${this._circlePos[0] - this._circleRadius}px`;\n\t\tthis._circleDiv.style.marginTop = `${this._circlePos[1] - this._circleRadius}px`;\n\n\t\tconst startValue = this._circleMaxRadius;\n\t\tconst endValue = 2;\n\t\tlet startTime;\n\t\tconst duration = 300;\n\n\t\tconst animateCircle = (currentTime) => {\n\t\t\tif (!this._running) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!startTime) {\n\t\t\t\tstartTime = currentTime;\n\t\t\t}\n\n\t\t\tconst elapsedTime = currentTime - startTime;\n\t\t\tconst progress = Math.min(elapsedTime / duration, 1);\n\t\t\tconst interpolatedValue = startValue + (endValue - startValue) * progress;\n\n\t\t\tthis._circleRadius = interpolatedValue;\n\t\t\tthis._circleDiv.style.width = `${this._circleRadius}px`;\n\t\t\tthis._circleDiv.style.height = `${this._circleRadius}px`;\n\t\t\tthis._circleDiv.style.marginLeft = `${this._circlePos[0] - this._circleRadius / 2}px`;\n\t\t\tthis._circleDiv.style.marginTop = `${this._circlePos[1] - this._circleRadius / 2}px`;\n\n\t\t\tif (progress < 1) {\n\t\t\t\trequestAnimationFrame(animateCircle);\n\t\t\t}\n\t\t};\n\t\tthis._running = true;\n\t\trequestAnimationFrame(animateCircle);\n\t\tthis._circleDiv.style.visibility = \"visible\";\n\t}\n\n\t/**\n\t * Stop the shricking circle and hide it.\n\t */\n\tstop() {\n\t\tif (this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tthis._running = false;\n\t\tthis._circleRadius = this._circleMaxRadius;\n\t\tthis._circleDiv.style.borderRadius = `${this._circleRadius}px`;\n\t\tthis._circleDiv.style.visibility = \"hidden\";\n\t}\n\n\t/**\n\t * Sets the zoom factor for the lens.\n\t *\n\t * This is `2` by default.\n\t *\n\t * @param durationMs\n\t */\n\tset durationMs(durationMs) {\n\t\tthis.stop();\n\t\tthis._durationMs = durationMs;\n\t}\n\n\t/**\n\t * Gets the zoom factor for the lens.\n\t *\n\t * This is `2` by default.\n\t *\n\t * @returns Number\n\t */\n\tget durationMs() {\n\t\treturn this._durationMs;\n\t}\n\n\t/**\n\t * Destroys this PointerCircle.\n\t */\n\tdestroy() {\n\t\tif (!this._destroyed) {\n\t\t\tthis.stop();\n\t\t\tif (this._circleDiv) this._circleDiv.parentNode.removeChild(this._circleDiv);\n\t\t\tthis._destroyed = true;\n\t\t}\n\t}\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/extras/PointerCircle/PointerCircle.js?");
|
|
1348
1348
|
|
|
1349
1349
|
/***/ }),
|
|
1350
1350
|
|
|
@@ -1634,7 +1634,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1634
1634
|
\***************************************************************************************/
|
|
1635
1635
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1636
1636
|
|
|
1637
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ FaceAlignedSectionPlanesControl: () => (/* binding */ FaceAlignedSectionPlanesControl)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.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\n\r\nconst zeroVec = new Float64Array([0, 0, 1]);\r\nconst quat = new Float64Array(4);\r\n\r\n/**\r\n * Controls a {@link SectionPlane} with mouse and touch input.\r\n */\r\nclass FaceAlignedSectionPlanesControl {\r\n\t/** @private */\r\n\tconstructor(plugin) {\r\n\t\t/**\r\n\t\t * ID of this FaceAlignedSectionPlanesControl.\r\n\t\t *\r\n\t\t * FaceAlignedSectionPlanesControl are mapped by this ID in {@link FaceAlignedSectionPlanesPlugin#controls}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = null;\r\n\r\n\t\tthis._viewer = plugin.viewer;\r\n\t\tthis._plugin = plugin;\r\n\t\tthis._visible = false;\r\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the FaceAlignedSectionPlanesControl\r\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\r\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\r\n\t\tthis._displayMeshes = null; // Meshes that are always visible\r\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\r\n\r\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\r\n\t\tthis._createNodes();\r\n\t\tthis._bindEvents();\r\n\t}\r\n\r\n\t/**\r\n\t * Called by FaceAlignedSectionPlanesPlugin to assign this FaceAlignedSectionPlanesControl to a SectionPlane.\r\n\t * FaceAlignedSectionPlanesPlugin keeps FaceAlignedSectionPlanesControls in a reuse pool.\r\n\t * Call with a null or undefined value to disconnect the FaceAlignedSectionPlanesControl ffrom whatever SectionPlane it was assigned to.\r\n\t * @private\r\n\t */\r\n\t_setSectionPlane(sectionPlane) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\r\n\t\t\tthis._onSectionPlanePos = null;\r\n\t\t\tthis._onSectionPlaneDir = null;\r\n\t\t\tthis._sectionPlane = null;\r\n\t\t}\r\n\t\tif (sectionPlane) {\r\n\t\t\tthis.id = sectionPlane.id;\r\n\t\t\tthis._setPos(sectionPlane.pos);\r\n\t\t\tthis._setDir(sectionPlane.dir);\r\n\t\t\tthis._sectionPlane = sectionPlane;\r\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\r\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\r\n\t\t\t});\r\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\r\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\r\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link SectionPlane} controlled by this FaceAlignedSectionPlanesControl.\r\n\t * @returns {SectionPlane} The SectionPlane.\r\n\t */\r\n\tget sectionPlane() {\r\n\t\treturn this._sectionPlane;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setPos(xyz) {\r\n\t\tthis._pos.set(xyz);\r\n\r\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\r\n\r\n\t\tthis._rootNode.origin = this._origin;\r\n\t\tthis._rootNode.position = this._rtcPos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setDir(xyz) {\r\n\t\tthis._baseDir.set(xyz);\r\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\r\n\t}\r\n\r\n\t_setSectionPlaneDir(dir) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\r\n\t\t\tthis._sectionPlane.dir = dir;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this FaceAlignedSectionPlanesControl is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tif (this._visible === visible) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._visible = visible;\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].visible = visible;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!visible) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if this FaceAlignedSectionPlanesControl is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tgetVisible() {\r\n\t\treturn this._visible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this FaceAlignedSectionPlanesControl is culled. This is called by FaceAlignedSectionPlanesPlugin to\r\n\t * temporarily hide the FaceAlignedSectionPlanesControl while a snapshot is being taken by Viewer#getSnapshot().\r\n\t * @param culled\r\n\t */\r\n\tsetCulled(culled) {\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].culled = culled;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!culled) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Builds the Entities that represent this FaceAlignedSectionPlanesControl.\r\n\t * @private\r\n\t */\r\n\t_createNodes() {\r\n\t\tconst NO_STATE_INHERIT = false;\r\n\t\tconst scene = this._viewer.scene;\r\n\t\tconst radius = 1.0;\r\n\t\tconst handleTubeRadius = 0.06;\r\n\t\tconst hoopRadius = radius - 0.2;\r\n\t\tconst tubeRadius = 0.01;\r\n\t\tconst arrowRadius = 0.07;\r\n\r\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\r\n\t\t\tposition: [0, 0, 0],\r\n\t\t\tscale: [5, 5, 5]\r\n\t\t});\r\n\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tconst shapes = {\r\n\t\t\t// Reusable geometries\r\n\r\n\t\t\tarrowHead: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: 0.001,\r\n\t\t\t\t\tradiusBottom: arrowRadius,\r\n\t\t\t\t\tradialSegments: 32,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: 0.2,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\tarrowHeadBig: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: 0.001,\r\n\t\t\t\t\tradiusBottom: 0.09,\r\n\t\t\t\t\tradialSegments: 32,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: 0.25,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\taxis: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: tubeRadius,\r\n\t\t\t\t\tradiusBottom: tubeRadius,\r\n\t\t\t\t\tradialSegments: 20,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: radius,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t)\r\n\t\t};\r\n\r\n\t\tconst materials = {\r\n\t\t\t// Reusable materials\r\n\r\n\t\t\tred: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [1, 0.0, 0.0],\r\n\t\t\t\temissive: [1, 0.0, 0.0],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80,\r\n\t\t\t\tlineWidth: 2\r\n\t\t\t}),\r\n\r\n\t\t\tgreen: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [0, 1.0, 0.0],\r\n\t\t\t\temissive: [1, 0.0, 0.0],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80,\r\n\t\t\t\tlineWidth: 2\r\n\t\t\t}),\r\n\r\n\t\t\tblue: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [0, 0.0, 1.0],\r\n\t\t\t\temissive: [1, 0.0, 0.0],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80,\r\n\t\t\t\tlineWidth: 2\r\n\t\t\t}),\r\n\r\n\t\t\thighlightRed: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t// Emphasis for red rotation affordance hoop\r\n\t\t\t\tedges: false,\r\n\t\t\t\tfill: true,\r\n\t\t\t\tfillColor: [1, 0, 0],\r\n\t\t\t\tfillAlpha: 0.6\r\n\t\t\t})\r\n\t\t};\r\n\r\n\t\tthis._displayMeshes = {\r\n\t\t\tplane: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(rootNode, {\r\n\t\t\t\t\t\tprimitive: \"triangles\",\r\n\t\t\t\t\t\tpositions: [\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.0,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.0, // 0\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.0,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.0, // 1\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.0,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.0, // 2\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.0,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.0 // 3\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tindices: [0, 1, 2, 2, 3, 0]\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\temissive: [0, 0.0, 0],\r\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\r\n\t\t\t\t\t\tbackfaces: true\r\n\t\t\t\t\t}),\r\n\t\t\t\t\topacity: 0.6,\r\n\t\t\t\t\tghosted: true,\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [2.4, 2.4, 1]\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tplaneFrame: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\t// Visible frame\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\t\t\trootNode,\r\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\r\n\t\t\t\t\t\t\tradius: 1.7,\r\n\t\t\t\t\t\t\ttube: tubeRadius * 2,\r\n\t\t\t\t\t\t\tradialSegments: 4,\r\n\t\t\t\t\t\t\ttubeSegments: 4,\r\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\temissive: [0, 0, 0],\r\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\r\n\t\t\t\t\t\tspecular: [0, 0, 0],\r\n\t\t\t\t\t\tshininess: 0\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: false,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [1, 1, 0.1],\r\n\t\t\t\t\trotation: [0, 0, 45]\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tcenter: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\t\t\trootNode,\r\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildSphereGeometry)({\r\n\t\t\t\t\t\t\tradius: 0.05\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t),\r\n\t\t\t\t\tmaterial: materials.center,\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzShaft: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axis,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tvisible: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t)\r\n\t\t};\r\n\r\n\t\tthis._affordanceMeshes = {\r\n\t\t\tplaneFrame: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\t\t\trootNode,\r\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\r\n\t\t\t\t\t\t\tradius: 2,\r\n\t\t\t\t\t\t\ttube: tubeRadius,\r\n\t\t\t\t\t\t\tradialSegments: 4,\r\n\t\t\t\t\t\t\ttubeSegments: 4,\r\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\tambient: [1, 1, 1],\r\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\r\n\t\t\t\t\t\temissive: [1, 1, 0]\r\n\t\t\t\t\t}),\r\n\t\t\t\t\thighlighted: true,\r\n\t\t\t\t\thighlightMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t\t\tedges: false,\r\n\t\t\t\t\t\tfilled: true,\r\n\t\t\t\t\t\tfillColor: [1, 1, 0],\r\n\t\t\t\t\t\tfillAlpha: 1.0\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: false,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [1, 1, 1],\r\n\t\t\t\t\trotation: [0, 0, 45]\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t)\r\n\t\t};\r\n\t}\r\n\r\n\t_bindEvents() {\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\r\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\r\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tconst camera = this._viewer.camera;\r\n\t\tconst scene = this._viewer.scene;\r\n\r\n\t\tlet deltaUpdate = 0;\r\n\t\tlet waitForTick = false;\r\n\r\n\t\t{\r\n\t\t\t// Keep gizmo screen size constant\r\n\r\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\r\n\r\n\t\t\tlet distDirty = true;\r\n\t\t\tlet lastDist = -1;\r\n\r\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\r\n\t\t\t\twaitForTick = false;\r\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\r\n\r\n\t\t\t\tif (dist !== lastDist) {\r\n\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\r\n\t\t\t\t\t\tconst size = 0.07 * worldSize;\r\n\t\t\t\t\t\trootNode.scale = [size, size, size];\r\n\t\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (camera.projection === \"ortho\") {\r\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\r\n\t\t\t\t\tconst size = worldSize;\r\n\t\t\t\t\trootNode.scale = [size, size, size];\r\n\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (deltaUpdate !== 0) {\r\n\t\t\t\t\tmoveSectionPlane(deltaUpdate);\r\n\t\t\t\t\tdeltaUpdate = 0;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tconst getClickCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t\tcanvasPos[0] = event.x;\r\n\t\t\t\t\tcanvasPos[1] = event.y;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst moveSectionPlane = (delta) => {\r\n\t\t\tconst pos = this._sectionPlane.pos;\r\n\t\t\tconst dir = this._sectionPlane.dir;\r\n\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(pos, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, 0.1 * delta * this._plugin.getDragSensitivity(), _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3()));\r\n\t\t\tthis._sectionPlane.pos = pos;\r\n\t\t};\r\n\r\n\t\t{\r\n\t\t\tlet mouseDownLeft;\r\n\t\t\tlet mouseDownMiddle;\r\n\t\t\tlet mouseDownRight;\r\n\t\t\tlet down = false;\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"mousedown\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = true;\r\n\t\t\t\t\t\t\tdown = true;\r\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"mousemove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (waitForTick) {\r\n\t\t\t\t\t\t// Limit changes detection to one per frame\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\t\t\t\t\tmoveSectionPlane(y - lastCanvasPos[1]);\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"wheel\",\r\n\t\t\t\t(this._canvasWheelListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdeltaUpdate += Math.max(-1, Math.min(1, -e.deltaY * 40));\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t{\r\n\t\t\tlet touchStartY, touchEndY;\r\n\t\t\tlet lastTouchY = null;\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"touchstart\",\r\n\t\t\t\t(this._handleTouchStart = (e) => {\r\n\t\t\t\t\te.stopPropagation();\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttouchStartY = e.touches[0].clientY;\r\n\t\t\t\t\tlastTouchY = touchStartY;\r\n\t\t\t\t\tdeltaUpdate = 0;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"touchmove\",\r\n\t\t\t\t(this._handleTouchMove = (e) => {\r\n\t\t\t\t\te.stopPropagation();\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (waitForTick) {\r\n\t\t\t\t\t\t// Limit changes detection to one per frame\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\twaitForTick = true;\r\n\t\t\t\t\ttouchEndY = e.touches[0].clientY;\r\n\t\t\t\t\tif (lastTouchY !== null) {\r\n\t\t\t\t\t\tdeltaUpdate += touchEndY - lastTouchY;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlastTouchY = touchEndY;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._plugin._controlElement.addEventListener(\r\n\t\t\t\t\"touchend\",\r\n\t\t\t\t(this._handleTouchEnd = (e) => {\r\n\t\t\t\t\te.stopPropagation();\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttouchStartY = null;\r\n\t\t\t\t\ttouchEndY = null;\r\n\t\t\t\t\tdeltaUpdate = 0;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\tthis._plugin._controlElement.addEventListener(\"touchcancel\", this._handleTouchEnd);\r\n\t\t}\r\n\t}\r\n\r\n\t_destroy() {\r\n\t\tthis._unbindEvents();\r\n\t\tthis._destroyNodes();\r\n\t}\r\n\r\n\t_unbindEvents() {\r\n\t\tconst viewer = this._viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst canvas = scene.canvas.canvas;\r\n\t\tconst camera = viewer.camera;\r\n\t\tconst controlElement = this._plugin._controlElement;\r\n\r\n\t\tscene.off(this._onSceneTick);\r\n\r\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\r\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\r\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\r\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\r\n\r\n\t\tcontrolElement.removeEventListener(\"touchstart\", this._handleTouchStart);\r\n\t\tcontrolElement.removeEventListener(\"touchmove\", this._handleTouchMove);\r\n\t\tcontrolElement.removeEventListener(\"touchend\", this._handleTouchEnd);\r\n\t\tcontrolElement.removeEventListener(\"touchcancel\", this._handleTouchEnd);\r\n\r\n\t\tcamera.off(this._onCameraViewMatrix);\r\n\t\tcamera.off(this._onCameraProjMatrix);\r\n\t}\r\n\r\n\t_destroyNodes() {\r\n\t\tthis._setSectionPlane(null);\r\n\t\tthis._rootNode.destroy();\r\n\t\tthis._displayMeshes = {};\r\n\t\tthis._affordanceMeshes = {};\r\n\t}\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/FaceAlignedSectionPlanesPlugin/FaceAlignedSectionPlanesControl.js?");
|
|
1637
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ FaceAlignedSectionPlanesControl: () => (/* binding */ FaceAlignedSectionPlanesControl)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst zeroVec = new Float64Array([0, 0, 1]);\nconst quat = new Float64Array(4);\n\n/**\n * Controls a {@link SectionPlane} with mouse and touch input.\n */\nclass FaceAlignedSectionPlanesControl {\n\t/** @private */\n\tconstructor(plugin) {\n\t\t/**\n\t\t * ID of this FaceAlignedSectionPlanesControl.\n\t\t *\n\t\t * FaceAlignedSectionPlanesControl are mapped by this ID in {@link FaceAlignedSectionPlanesPlugin#controls}.\n\t\t *\n\t\t * @property id\n\t\t * @type {String|Number}\n\t\t */\n\t\tthis.id = null;\n\n\t\tthis._viewer = plugin.viewer;\n\t\tthis._plugin = plugin;\n\t\tthis._visible = false;\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the FaceAlignedSectionPlanesControl\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\n\t\tthis._displayMeshes = null; // Meshes that are always visible\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\n\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\n\t\tthis._createNodes();\n\t\tthis._bindEvents();\n\t}\n\n\t/**\n\t * Called by FaceAlignedSectionPlanesPlugin to assign this FaceAlignedSectionPlanesControl to a SectionPlane.\n\t * FaceAlignedSectionPlanesPlugin keeps FaceAlignedSectionPlanesControls in a reuse pool.\n\t * Call with a null or undefined value to disconnect the FaceAlignedSectionPlanesControl ffrom whatever SectionPlane it was assigned to.\n\t * @private\n\t */\n\t_setSectionPlane(sectionPlane) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\n\t\t\tthis._onSectionPlanePos = null;\n\t\t\tthis._onSectionPlaneDir = null;\n\t\t\tthis._sectionPlane = null;\n\t\t}\n\t\tif (sectionPlane) {\n\t\t\tthis.id = sectionPlane.id;\n\t\t\tthis._setPos(sectionPlane.pos);\n\t\t\tthis._setDir(sectionPlane.dir);\n\t\t\tthis._sectionPlane = sectionPlane;\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\n\t\t\t});\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\n\t\t\t\t} else {\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Gets the {@link SectionPlane} controlled by this FaceAlignedSectionPlanesControl.\n\t * @returns {SectionPlane} The SectionPlane.\n\t */\n\tget sectionPlane() {\n\t\treturn this._sectionPlane;\n\t}\n\n\t/** @private */\n\t_setPos(xyz) {\n\t\tthis._pos.set(xyz);\n\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\n\n\t\tthis._rootNode.origin = this._origin;\n\t\tthis._rootNode.position = this._rtcPos;\n\t}\n\n\t/** @private */\n\t_setDir(xyz) {\n\t\tthis._baseDir.set(xyz);\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\n\t}\n\n\t_setSectionPlaneDir(dir) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\n\t\t\tthis._sectionPlane.dir = dir;\n\t\t}\n\t}\n\n\t/**\n\t * Sets if this FaceAlignedSectionPlanesControl is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tsetVisible(visible = true) {\n\t\tif (this._visible === visible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._visible = visible;\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].visible = visible;\n\t\t\t}\n\t\t}\n\t\tif (!visible) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this FaceAlignedSectionPlanesControl is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tgetVisible() {\n\t\treturn this._visible;\n\t}\n\n\t/**\n\t * Sets if this FaceAlignedSectionPlanesControl is culled. This is called by FaceAlignedSectionPlanesPlugin to\n\t * temporarily hide the FaceAlignedSectionPlanesControl while a snapshot is being taken by Viewer#getSnapshot().\n\t * @param culled\n\t */\n\tsetCulled(culled) {\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].culled = culled;\n\t\t\t}\n\t\t}\n\t\tif (!culled) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Builds the Entities that represent this FaceAlignedSectionPlanesControl.\n\t * @private\n\t */\n\t_createNodes() {\n\t\tconst NO_STATE_INHERIT = false;\n\t\tconst scene = this._viewer.scene;\n\t\tconst radius = 1.0;\n\t\tconst handleTubeRadius = 0.06;\n\t\tconst hoopRadius = radius - 0.2;\n\t\tconst tubeRadius = 0.01;\n\t\tconst arrowRadius = 0.07;\n\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\n\t\t\tposition: [0, 0, 0],\n\t\t\tscale: [5, 5, 5]\n\t\t});\n\n\t\tconst rootNode = this._rootNode;\n\n\t\tconst shapes = {\n\t\t\t// Reusable geometries\n\n\t\t\tarrowHead: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: 0.001,\n\t\t\t\t\tradiusBottom: arrowRadius,\n\t\t\t\t\tradialSegments: 32,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: 0.2,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t),\n\n\t\t\tarrowHeadBig: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: 0.001,\n\t\t\t\t\tradiusBottom: 0.09,\n\t\t\t\t\tradialSegments: 32,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: 0.25,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t),\n\n\t\t\taxis: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: tubeRadius,\n\t\t\t\t\tradiusBottom: tubeRadius,\n\t\t\t\t\tradialSegments: 20,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: radius,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t)\n\t\t};\n\n\t\tconst materials = {\n\t\t\t// Reusable materials\n\n\t\t\tred: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [1, 0.0, 0.0],\n\t\t\t\temissive: [1, 0.0, 0.0],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80,\n\t\t\t\tlineWidth: 2\n\t\t\t}),\n\n\t\t\tgreen: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [0, 1.0, 0.0],\n\t\t\t\temissive: [1, 0.0, 0.0],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80,\n\t\t\t\tlineWidth: 2\n\t\t\t}),\n\n\t\t\tblue: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [0, 0.0, 1.0],\n\t\t\t\temissive: [1, 0.0, 0.0],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80,\n\t\t\t\tlineWidth: 2\n\t\t\t}),\n\n\t\t\thighlightRed: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t// Emphasis for red rotation affordance hoop\n\t\t\t\tedges: false,\n\t\t\t\tfill: true,\n\t\t\t\tfillColor: [1, 0, 0],\n\t\t\t\tfillAlpha: 0.6\n\t\t\t})\n\t\t};\n\n\t\tthis._displayMeshes = {\n\t\t\tplane: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(rootNode, {\n\t\t\t\t\t\tprimitive: \"triangles\",\n\t\t\t\t\t\tpositions: [\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.0,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.0, // 0\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.0,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.0, // 1\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.0,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.0, // 2\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.0,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.0 // 3\n\t\t\t\t\t\t],\n\t\t\t\t\t\tindices: [0, 1, 2, 2, 3, 0]\n\t\t\t\t\t}),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\temissive: [0, 0.0, 0],\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\n\t\t\t\t\t\tbackfaces: true\n\t\t\t\t\t}),\n\t\t\t\t\topacity: 0.6,\n\t\t\t\t\tghosted: true,\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [2.4, 2.4, 1]\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tplaneFrame: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\t// Visible frame\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\t\t\trootNode,\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\n\t\t\t\t\t\t\tradius: 1.7,\n\t\t\t\t\t\t\ttube: tubeRadius * 2,\n\t\t\t\t\t\t\tradialSegments: 4,\n\t\t\t\t\t\t\ttubeSegments: 4,\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\temissive: [0, 0, 0],\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\n\t\t\t\t\t\tspecular: [0, 0, 0],\n\t\t\t\t\t\tshininess: 0\n\t\t\t\t\t}),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: false,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [1, 1, 0.1],\n\t\t\t\t\trotation: [0, 0, 45]\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tcenter: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\t\t\trootNode,\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildSphereGeometry)({\n\t\t\t\t\t\t\tradius: 0.05\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tmaterial: materials.center,\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzShaft: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axis,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tvisible: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t)\n\t\t};\n\n\t\tthis._affordanceMeshes = {\n\t\t\tplaneFrame: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\t\t\trootNode,\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\n\t\t\t\t\t\t\tradius: 2,\n\t\t\t\t\t\t\ttube: tubeRadius,\n\t\t\t\t\t\t\tradialSegments: 4,\n\t\t\t\t\t\t\ttubeSegments: 4,\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\tambient: [1, 1, 1],\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\n\t\t\t\t\t\temissive: [1, 1, 0]\n\t\t\t\t\t}),\n\t\t\t\t\thighlighted: true,\n\t\t\t\t\thighlightMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t\t\tedges: false,\n\t\t\t\t\t\tfilled: true,\n\t\t\t\t\t\tfillColor: [1, 1, 0],\n\t\t\t\t\t\tfillAlpha: 1.0\n\t\t\t\t\t}),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: false,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [1, 1, 1],\n\t\t\t\t\trotation: [0, 0, 45]\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t)\n\t\t};\n\t}\n\n\t_bindEvents() {\n\t\tconst rootNode = this._rootNode;\n\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\t\tconst camera = this._viewer.camera;\n\t\tconst scene = this._viewer.scene;\n\n\t\tlet deltaUpdate = 0;\n\t\tlet waitForTick = false;\n\n\t\t{\n\t\t\t// Keep gizmo screen size constant\n\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\n\n\t\t\tlet distDirty = true;\n\t\t\tlet lastDist = -1;\n\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\n\t\t\t\twaitForTick = false;\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\n\n\t\t\t\tif (dist !== lastDist) {\n\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\n\t\t\t\t\t\tconst size = 0.07 * worldSize;\n\t\t\t\t\t\trootNode.scale = [size, size, size];\n\t\t\t\t\t\tlastDist = dist;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (camera.projection === \"ortho\") {\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\n\t\t\t\t\tconst size = worldSize;\n\t\t\t\t\trootNode.scale = [size, size, size];\n\t\t\t\t\tlastDist = dist;\n\t\t\t\t}\n\n\t\t\t\tif (deltaUpdate !== 0) {\n\t\t\t\t\tmoveSectionPlane(deltaUpdate);\n\t\t\t\t\tdeltaUpdate = 0;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst getClickCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t\tcanvasPos[0] = event.x;\n\t\t\t\t\tcanvasPos[1] = event.y;\n\t\t\t\t} else {\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\tconst moveSectionPlane = (delta) => {\n\t\t\tconst pos = this._sectionPlane.pos;\n\t\t\tconst dir = this._sectionPlane.dir;\n\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(pos, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, 0.1 * delta * this._plugin.getDragSensitivity(), _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3()));\n\t\t\tthis._sectionPlane.pos = pos;\n\t\t};\n\n\t\t{\n\t\t\tlet mouseDownLeft;\n\t\t\tlet mouseDownMiddle;\n\t\t\tlet mouseDownRight;\n\t\t\tlet down = false;\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = true;\n\t\t\t\t\t\t\tdown = true;\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"mousemove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (waitForTick) {\n\t\t\t\t\t\t// Limit changes detection to one per frame\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\t\t\t\t\tmoveSectionPlane(y - lastCanvasPos[1]);\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"mouseup\",\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdown = false;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"wheel\",\n\t\t\t\t(this._canvasWheelListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdeltaUpdate += Math.max(-1, Math.min(1, -e.deltaY * 40));\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\t{\n\t\t\tlet touchStartY, touchEndY;\n\t\t\tlet lastTouchY = null;\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"touchstart\",\n\t\t\t\t(this._handleTouchStart = (e) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttouchStartY = e.touches[0].clientY;\n\t\t\t\t\tlastTouchY = touchStartY;\n\t\t\t\t\tdeltaUpdate = 0;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"touchmove\",\n\t\t\t\t(this._handleTouchMove = (e) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (waitForTick) {\n\t\t\t\t\t\t// Limit changes detection to one per frame\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\twaitForTick = true;\n\t\t\t\t\ttouchEndY = e.touches[0].clientY;\n\t\t\t\t\tif (lastTouchY !== null) {\n\t\t\t\t\t\tdeltaUpdate += touchEndY - lastTouchY;\n\t\t\t\t\t}\n\t\t\t\t\tlastTouchY = touchEndY;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._plugin._controlElement.addEventListener(\n\t\t\t\t\"touchend\",\n\t\t\t\t(this._handleTouchEnd = (e) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttouchStartY = null;\n\t\t\t\t\ttouchEndY = null;\n\t\t\t\t\tdeltaUpdate = 0;\n\t\t\t\t})\n\t\t\t);\n\t\t\tthis._plugin._controlElement.addEventListener(\"touchcancel\", this._handleTouchEnd);\n\t\t}\n\t}\n\n\t_destroy() {\n\t\tthis._unbindEvents();\n\t\tthis._destroyNodes();\n\t}\n\n\t_unbindEvents() {\n\t\tconst viewer = this._viewer;\n\t\tconst scene = viewer.scene;\n\t\tconst canvas = scene.canvas.canvas;\n\t\tconst camera = viewer.camera;\n\t\tconst controlElement = this._plugin._controlElement;\n\n\t\tscene.off(this._onSceneTick);\n\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\n\n\t\tcontrolElement.removeEventListener(\"touchstart\", this._handleTouchStart);\n\t\tcontrolElement.removeEventListener(\"touchmove\", this._handleTouchMove);\n\t\tcontrolElement.removeEventListener(\"touchend\", this._handleTouchEnd);\n\t\tcontrolElement.removeEventListener(\"touchcancel\", this._handleTouchEnd);\n\n\t\tcamera.off(this._onCameraViewMatrix);\n\t\tcamera.off(this._onCameraProjMatrix);\n\t}\n\n\t_destroyNodes() {\n\t\tthis._setSectionPlane(null);\n\t\tthis._rootNode.destroy();\n\t\tthis._displayMeshes = {};\n\t\tthis._affordanceMeshes = {};\n\t}\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/FaceAlignedSectionPlanesPlugin/FaceAlignedSectionPlanesControl.js?");
|
|
1638
1638
|
|
|
1639
1639
|
/***/ }),
|
|
1640
1640
|
|
|
@@ -1704,7 +1704,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1704
1704
|
\***************************************************************/
|
|
1705
1705
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1706
1706
|
|
|
1707
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ GLTFDefaultDataSource: () => (/* binding */ GLTFDefaultDataSource)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/core */ \"./src/viewer/scene/core.js\");\n\
|
|
1707
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ GLTFDefaultDataSource: () => (/* binding */ GLTFDefaultDataSource)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/core */ \"./src/viewer/scene/core.js\");\n\n\n\n/**\n * Default data access strategy for {@link GLTFLoaderPlugin}.\n *\n * This just loads assets using XMLHttpRequest.\n */\nclass GLTFDefaultDataSource {\n\n constructor() {\n }\n\n /**\n * Gets metamodel JSON.\n *\n * @param {String|Number} metaModelSrc Identifies the metamodel JSON asset.\n * @param {Function} ok Fired on successful loading of the metamodel JSON asset.\n * @param {Function} error Fired on error while loading the metamodel JSON asset.\n */\n getMetaModel(metaModelSrc, ok, error) {\n _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.loadJSON(metaModelSrc,\n (json) => {\n ok(json);\n },\n function (errMsg) {\n error(errMsg);\n });\n }\n\n /**\n * Gets glTF JSON.\n *\n * @param {String|Number} glTFSrc Identifies the glTF JSON asset.\n * @param {Function} ok Fired on successful loading of the glTF JSON asset.\n * @param {Function} error Fired on error while loading the glTF JSON asset.\n */\n getGLTF(glTFSrc, ok, error) {\n _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.loadArraybuffer(glTFSrc,\n (gltf) => {\n ok(gltf);\n },\n function (errMsg) {\n error(errMsg);\n });\n }\n\n /**\n * Gets binary glTF file.\n *\n * @param {String|Number} glbSrc Identifies the .glb asset.\n * @param {Function} ok Fired on successful loading of the .glb asset.\n * @param {Function} error Fired on error while loading the .glb asset.\n */\n getGLB(glbSrc, ok, error) {\n _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.loadArraybuffer(glbSrc,\n (arraybuffer) => {\n ok(arraybuffer);\n },\n function (errMsg) {\n error(errMsg);\n });\n }\n\n /**\n * Gets glTF binary attachment.\n *\n * Note that this method requires the source of the glTF JSON asset. This is because the binary attachment\n * source could be relative to the glTF source, IE. it may not be a global ID.\n *\n * @param {String|Number} glTFSrc Identifies the glTF JSON asset.\n * @param {String|Number} binarySrc Identifies the glTF binary asset.\n * @param {Function} ok Fired on successful loading of the glTF binary asset.\n * @param {Function} error Fired on error while loading the glTF binary asset.\n */\n getArrayBuffer(glTFSrc, binarySrc, ok, error) {\n loadArraybuffer(glTFSrc, binarySrc,\n (arrayBuffer) => {\n ok(arrayBuffer);\n },\n function (errMsg) {\n error(errMsg);\n });\n }\n}\n\nfunction loadArraybuffer(glTFSrc, binarySrc, ok, err) {\n // Check for data: URI\n var defaultCallback = () => {\n };\n ok = ok || defaultCallback;\n err = err || defaultCallback;\n const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\n const dataUriRegexResult = binarySrc.match(dataUriRegex);\n if (dataUriRegexResult) { // Safari can't handle data URIs through XMLHttpRequest\n const isBase64 = !!dataUriRegexResult[2];\n var data = dataUriRegexResult[3];\n data = window.decodeURIComponent(data);\n if (isBase64) {\n data = window.atob(data);\n }\n try {\n const buffer = new ArrayBuffer(data.length);\n const view = new Uint8Array(buffer);\n for (var i = 0; i < data.length; i++) {\n view[i] = data.charCodeAt(i);\n }\n _viewer_scene_core__WEBPACK_IMPORTED_MODULE_1__.core.scheduleTask(function () {\n ok(buffer);\n });\n } catch (error) {\n _viewer_scene_core__WEBPACK_IMPORTED_MODULE_1__.core.scheduleTask(function () {\n err(error);\n });\n }\n } else {\n const basePath = getBasePath(glTFSrc);\n const url = basePath + binarySrc;\n const request = new XMLHttpRequest();\n request.open('GET', url, true);\n request.responseType = 'arraybuffer';\n request.onreadystatechange = function () {\n if (request.readyState === 4) {\n if (request.status === 200) {\n ok(request.response);\n } else {\n err('loadArrayBuffer error : ' + request.response);\n }\n }\n };\n request.send(null);\n }\n}\n\nfunction getBasePath(src) {\n var i = src.lastIndexOf(\"/\");\n return (i !== 0) ? src.substring(0, i + 1) : \"\";\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/GLTFLoaderPlugin/GLTFDefaultDataSource.js?");
|
|
1708
1708
|
|
|
1709
1709
|
/***/ }),
|
|
1710
1710
|
|
|
@@ -1744,7 +1744,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1744
1744
|
\*************************************************************/
|
|
1745
1745
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1746
1746
|
|
|
1747
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LASDefaultDataSource: () => (/* binding */ LASDefaultDataSource)\n/* harmony export */ });\n/**\
|
|
1747
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LASDefaultDataSource: () => (/* binding */ LASDefaultDataSource)\n/* harmony export */ });\n/**\n * Default data access strategy for {@link LASLoaderPlugin}.\n */\nclass LASDefaultDataSource {\n\n constructor() {\n }\n\n /**\n * Gets the contents of the given LAS file in an arraybuffer.\n *\n * @param {String|Number} src Path or ID of an LAS file.\n * @param {Function} ok Callback fired on success, argument is the LAS file in an arraybuffer.\n * @param {Function} error Callback fired on error.\n */\n getLAS(src, ok, error) {\n var defaultCallback = () => {\n };\n ok = ok || defaultCallback;\n error = error || defaultCallback;\n const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\n const dataUriRegexResult = src.match(dataUriRegex);\n if (dataUriRegexResult) { // Safari can't handle data URIs through XMLHttpRequest\n const isBase64 = !!dataUriRegexResult[2];\n var data = dataUriRegexResult[3];\n data = window.decodeURIComponent(data);\n if (isBase64) {\n data = window.atob(data);\n }\n try {\n const buffer = new ArrayBuffer(data.length);\n const view = new Uint8Array(buffer);\n for (var i = 0; i < data.length; i++) {\n view[i] = data.charCodeAt(i);\n }\n ok(buffer);\n } catch (errMsg) {\n error(errMsg);\n }\n } else {\n const request = new XMLHttpRequest();\n request.open('GET', src, true);\n request.responseType = 'arraybuffer';\n request.onreadystatechange = function () {\n if (request.readyState === 4) {\n if (request.status === 200) {\n ok(request.response);\n } else {\n error('getXKT error : ' + request.response);\n }\n }\n };\n request.send(null);\n }\n }\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/LASLoaderPlugin/LASDefaultDataSource.js?");
|
|
1748
1748
|
|
|
1749
1749
|
/***/ }),
|
|
1750
1750
|
|
|
@@ -1884,7 +1884,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1884
1884
|
\********************************************************/
|
|
1885
1885
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1886
1886
|
|
|
1887
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ClippingBox: () => (/* binding */ ClippingBox)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.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\n\r\nconst zeroVec = new Float64Array([0, 0, 1]);\r\nconst quat = new Float64Array(4);\r\n\r\n/**\r\n * Controls a {@link SectionPlane} with mouse and touch input.\r\n *\r\n * @private\r\n */\r\nclass ClippingBox {\r\n\t/** @private */\r\n\tconstructor(plugin, cfg) {\r\n\t\t/**\r\n\t\t * ID of this Control.\r\n\t\t *\r\n\t\t * SectionPlaneControls are mapped by this ID in {@link SectionPlanesPlugin#sectionPlaneControls}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = null;\r\n\t\tthis.type = \"box\";\r\n\r\n\t\tthis._viewer = plugin.viewer;\r\n\t\tthis._scene = plugin.viewer.scene;\r\n\r\n\t\tthis._controlFillColor = !!cfg && !!cfg.controlFillColor ? cfg.controlFillColor : [0.1, 0.4, 0.99];\r\n\t\tthis._planeSize = !!cfg && !!cfg.planeSize ? cfg.planeSize : 1;\r\n\t\tthis._controlSize = !!cfg && !!cfg.controlSize ? cfg.controlSize : 0.07;\r\n\t\tthis._planeOpacity = !!cfg && !!cfg.planeOpacity ? cfg.planeOpacity : 0.4;\r\n\r\n\t\tthis._visible = false;\r\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the Control\r\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\r\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\r\n\t\tthis._displayMeshes = null; // Meshes that are always visible\r\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\r\n\r\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\r\n\t\tthis._createNodes();\r\n\t\tthis._bindEvents();\r\n\t}\r\n\r\n\t/**\r\n\t * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.\r\n\t * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.\r\n\t * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.\r\n\t * @private\r\n\t */\r\n\t_setSectionPlane(sectionPlane) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\r\n\t\t\tthis._onSectionPlanePos = null;\r\n\t\t\tthis._onSectionPlaneDir = null;\r\n\t\t\tthis._sectionPlane = null;\r\n\t\t}\r\n\t\tif (sectionPlane) {\r\n\t\t\tthis.id = sectionPlane.id;\r\n\t\t\tthis._setPos(sectionPlane.pos);\r\n\t\t\tthis._setDir(sectionPlane.dir);\r\n\t\t\tthis._sectionPlane = sectionPlane;\r\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\r\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\r\n\t\t\t});\r\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\r\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\r\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link SectionPlane} controlled by this Control.\r\n\t * @returns {SectionPlane} The SectionPlane.\r\n\t */\r\n\tget sectionPlane() {\r\n\t\treturn this._sectionPlane;\r\n\t}\r\n\r\n\t/**\r\n\t * 设置剖切面位置\r\n\t * @param {any} value\r\n\t */\r\n\tset pos(posRate) {\r\n\t\tif (posRate < 0 || posRate > 100) return;\r\n\r\n\t\tconst { aabb } = this._scene;\r\n\t\tconst { look } = this._scene.camera;\r\n\t\tconst xRange = aabb[3] - aabb[0]; //前后\r\n\t\tconst yRange = aabb[4] - aabb[1]; //上下\r\n\t\tconst zRange = aabb[5] - aabb[2]; //左右\r\n\r\n\t\tconst newSectionPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tnewSectionPos[0] = this.pos[0];\r\n\t\tnewSectionPos[1] = this.pos[1];\r\n\t\tnewSectionPos[2] = this.pos[2];\r\n\r\n\t\tconst { dir } = this._sectionPlane;\r\n\t\tlet rateDis;\r\n\t\tif (dir[0] != 0) {\r\n\t\t\trateDis = (posRate / 100) * xRange;\r\n\t\t\tnewSectionPos[0] = look[0] - xRange / 2 + rateDis;\r\n\t\t} else if (dir[1] != 0) {\r\n\t\t\trateDis = (posRate / 100) * yRange;\r\n\t\t\tnewSectionPos[1] = look[1] - yRange / 2 + rateDis;\r\n\t\t} else if (dir[2] != 0) {\r\n\t\t\trateDis = (posRate / 100) * zRange;\r\n\t\t\tnewSectionPos[2] = look[2] - zRange / 2 + rateDis;\r\n\t\t}\r\n\r\n\t\tthis._sectionPlane.pos = newSectionPos;\r\n\t}\r\n\r\n\tget pos() {\r\n\t\treturn this._pos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setPos(xyz) {\r\n\t\tthis._pos.set(xyz);\r\n\r\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\r\n\r\n\t\tthis._rootNode.origin = this._origin;\r\n\t\tthis._rootNode.position = this._rtcPos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setDir(xyz) {\r\n\t\tthis._baseDir.set(xyz);\r\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\r\n\t}\r\n\r\n\t_setSectionPlaneDir(dir) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\r\n\t\t\tthis._sectionPlane.dir = dir;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this Control is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tif (this._visible === visible) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._visible = visible;\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].visible = visible;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!visible) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if this Control is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tgetVisible() {\r\n\t\treturn this._visible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this Control is culled. This is called by SectionPlanesPlugin to\r\n\t * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().\r\n\t * @param culled\r\n\t */\r\n\tsetCulled(culled) {\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].culled = culled;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!culled) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Builds the Entities that represent this Control.\r\n\t * @private\r\n\t */\r\n\t_createNodes() {\r\n\t\tconst NO_STATE_INHERIT = false;\r\n\t\tconst scene = this._viewer.scene;\r\n\r\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\r\n\t\t\tposition: [0, 0, 0],\r\n\t\t\tscale: [5, 5, 5],\r\n\t\t\tisObject: false\r\n\t\t});\r\n\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tconst newMesh = (color) => {\r\n\t\t\treturn new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\tgeometry: MeshConfigs.geometry,\r\n\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\temissive: [0, 0, 0],\r\n\t\t\t\t\tdiffuse: color,\r\n\t\t\t\t\tbackfaces: true\r\n\t\t\t\t}),\r\n\t\t\t\topacity: this._planeOpacity,\r\n\t\t\t\tghosted: true,\r\n\t\t\t\tghostMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t\tedges: false,\r\n\t\t\t\t\tfilled: true,\r\n\t\t\t\t\tfillColor: color,\r\n\t\t\t\t\tfillAlpha: 0.1,\r\n\t\t\t\t\tbackfaces: true\r\n\t\t\t\t}),\r\n\t\t\t\tpickable: true,\r\n\t\t\t\tcollidable: true,\r\n\t\t\t\tclippable: false,\r\n\t\t\t\tvisible: false,\r\n\t\t\t\tscale: [2.4, 2.4, 1],\r\n\t\t\t\tisObject: false\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\tthis._displayMeshes = {\r\n\t\t\tfront_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\r\n\t\t\tback_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\r\n\t\t\tright_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\r\n\t\t\tleft_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\r\n\t\t\ttop_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\r\n\t\t\tbottom_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT)\r\n\t\t};\r\n\r\n\t\tthis._affordanceMeshes = {\r\n\t\t\tfront_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\r\n\t\t\tback_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\r\n\t\t\tright_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\r\n\t\t\tleft_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\r\n\t\t\ttop_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\r\n\t\t\tbottom_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT)\r\n\t\t};\r\n\t}\r\n\r\n\t_bindEvents() {\r\n\t\tconst self = this;\r\n\t\tvar grabbed = false;\r\n\t\tconst DRAG_ACTIONS = {\r\n\t\t\tnone: -1,\r\n\t\t\tleft_Translate: 0,\r\n\t\t\ttop_Translate: 1,\r\n\t\t\tfront_Translate: 2,\r\n\t\t\tright_Translate: 3,\r\n\t\t\tbottom_Translate: 4,\r\n\t\t\tback_Translate: 5\r\n\t\t};\r\n\t\tconst rootNode = this._rootNode;\r\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\r\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\r\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tthis.lastCanvasPos = lastCanvasPos;\r\n\t\tconst xBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([1, 0, 0]);\r\n\t\tconst yBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 1, 0]);\r\n\t\tconst zBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 1]);\r\n\r\n\t\tconst canvas = this._viewer.scene.canvas.canvas;\r\n\t\tconst camera = this._viewer.camera;\r\n\t\tconst scene = this._viewer.scene;\r\n\r\n\t\t{\r\n\t\t\t// Keep gizmo screen size constant\r\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\r\n\r\n\t\t\tlet distDirty = true;\r\n\t\t\tlet lastDist = -1;\r\n\r\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\r\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\r\n\r\n\t\t\t\tif (dist !== lastDist) {\r\n\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\r\n\t\t\t\t\t\tconst size = this._controlSize * worldSize;\r\n\t\t\t\t\t\trootNode.scale = [size, size, size];\r\n\t\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (camera.projection === \"ortho\") {\r\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\r\n\t\t\t\t\tconst size = worldSize;\r\n\t\t\t\t\trootNode.scale = [size, size, size];\r\n\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t//鼠标获取屏幕点击坐标\r\n\t\tconst getClickCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t\tcanvasPos[0] = event.x;\r\n\t\t\t\t\tcanvasPos[1] = event.y;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t//触屏获取屏幕点击坐标\r\n\t\tconst getTouchCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t}\r\n\t\t\t\tif (event.touches && event.touches.length) {\r\n\t\t\t\t\t// 如果有触摸事件,使用第一个触摸点的坐标\r\n\t\t\t\t\tcanvasPos[0] = event.touches[0].pageX;\r\n\t\t\t\t\tcanvasPos[1] = event.touches[0].pageY;\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// 否则,假设是鼠标事件\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst localToWorldVec = (function () {\r\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function (localVec, worldVec) {\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(self._rootNode.quaternion, mat);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, localVec, worldVec);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(worldVec);\r\n\t\t\t\treturn worldVec;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar getTranslationPlane = (function () {\r\n\t\t\tconst planeNormal = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\treturn function (worldAxis) {\r\n\t\t\t\tconst absX = Math.abs(worldAxis[0]);\r\n\t\t\t\tif (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);\r\n\t\t\t\t}\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(planeNormal, worldAxis, planeNormal);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(planeNormal);\r\n\t\t\t\treturn planeNormal;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst dragTranslateSectionPlane = (function () {\r\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\r\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\r\n\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\r\n\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1);\r\n\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(p2, p1);\r\n\t\t\t\tconst dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\r\n\t\t\t\tself._pos[0] += worldAxis[0] * dot;\r\n\t\t\t\tself._pos[1] += worldAxis[1] * dot;\r\n\t\t\t\tself._pos[2] += worldAxis[2] * dot;\r\n\t\t\t\tself._rootNode.position = self._pos;\r\n\t\t\t\tif (self._sectionPlane) {\r\n\t\t\t\t\tself._sectionPlane.pos = self._pos;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar dragRotateSectionPlane = (function () {\r\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\tconst c = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\r\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\r\n\t\t\t\tconst hasData =\r\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);\r\n\t\t\t\tif (!hasData) {\r\n\t\t\t\t\t// Find intersections with view plane and project down to origin\r\n\t\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\r\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable\r\n\t\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2, 1);\r\n\t\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, worldAxis);\r\n\t\t\t\t\tp1[0] -= dot * worldAxis[0];\r\n\t\t\t\t\tp1[1] -= dot * worldAxis[1];\r\n\t\t\t\t\tp1[2] -= dot * worldAxis[2];\r\n\t\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\r\n\t\t\t\t\tp2[0] -= dot * worldAxis[0];\r\n\t\t\t\t\tp2[1] -= dot * worldAxis[1];\r\n\t\t\t\t\tp2[2] -= dot * worldAxis[2];\r\n\t\t\t\t}\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p1);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p2);\r\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, p2);\r\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range\r\n\t\t\t\tvar incDegrees = Math.acos(dot) * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.RADTODEG;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(p1, p2, c);\r\n\t\t\t\tif (_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(c, worldAxis) < 0.0) {\r\n\t\t\t\t\tincDegrees = -incDegrees;\r\n\t\t\t\t}\r\n\t\t\t\tself._rootNode.rotate(baseAxis, incDegrees);\r\n\t\t\t\trotateSectionPlane();\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar getPointerPlaneIntersect = (function () {\r\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4([0, 0, 0, 1]);\r\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function (mouse, axis, dest, offset) {\r\n\t\t\t\toffset = offset || 0;\r\n\t\t\t\tdir[0] = (mouse[0] / canvas.width) * 2.0 - 1.0;\r\n\t\t\t\tdir[1] = -((mouse[1] / canvas.height) * 2.0 - 1.0);\r\n\t\t\t\tdir[2] = 0.0;\r\n\t\t\t\tdir[3] = 1.0;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(matrix);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec4(matrix, dir, dir);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space\r\n\t\t\t\tvar rayO = camera.eye; // The direction\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec4(dir, rayO, dir);\r\n\t\t\t\tconst origin = self._sectionPlane.pos; // Plane origin:\r\n\t\t\t\tvar d = -_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(origin, axis) - offset;\r\n\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, dir);\r\n\t\t\t\tif (Math.abs(dot) > 0.005) {\r\n\t\t\t\t\tvar t = -(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, rayO) + d) / dot;\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, t, dest);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(dest, rayO);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(dest, origin, dest);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\treturn false;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst rotateSectionPlane = (function () {\r\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function () {\r\n\t\t\t\tif (self.sectionPlane) {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(rootNode.quaternion, mat); // << ---\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, [0, 0, 1], dir);\r\n\t\t\t\t\tself._setSectionPlaneDir(dir);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t{\r\n\t\t\tvar down = false;\r\n\t\t\tvar lastAffordanceMesh;\r\n\r\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"hoverEnter\", (hit) => {\r\n\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (down) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tgrabbed = false;\r\n\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t}\r\n\t\t\t\tvar affordanceMesh;\r\n\t\t\t\tconst meshId = hit.entity.id;\r\n\t\t\t\tswitch (meshId) {\r\n\t\t\t\t\tcase this._displayMeshes.plane.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.plane;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.front_Translate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xAxisHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yShaftHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.zAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.zAxisHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xCurveHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xHoop;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xRotate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\r\n\t\t\t\t}\r\n\t\t\t\tif (affordanceMesh) {\r\n\t\t\t\t\taffordanceMesh.visible = true;\r\n\t\t\t\t}\r\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\r\n\t\t\t\tgrabbed = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraControlHoverLeave = this._viewer.cameraControl.on(\"hoverOutEntity\", (hit) => {\r\n\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t}\r\n\t\t\t\tlastAffordanceMesh = null;\r\n\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t});\r\n\r\n\t\t\t//mousedown\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mousedown\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible || !grabbed) return;\r\n\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = true;\r\n\t\t\t\t\t\t\tdown = true;\r\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//mousemove\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mousemove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\r\n\t\t\t\t\tswitch (dragAction) {\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//mouseup\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tgrabbed = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\t//wheel\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"wheel\",\r\n\t\t\t\t(this._canvasWheelListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\r\n\t\t\t\t\tif (delta === 0) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"touchEntity\", (hit) => {\r\n\t\t\t\tif (!this._visible || down || grabbed) return;\r\n\t\t\t\tgrabbed = false;\r\n\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t}\r\n\t\t\t\tvar affordanceMesh;\r\n\t\t\t\tconst meshId = hit.entity.id;\r\n\t\t\t\tswitch (meshId) {\r\n\t\t\t\t\tcase this._displayMeshes.plane.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.plane;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t// case this._displayMeshes.xAxisArrowHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.xAxisHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.yAxisArrowHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.yShaftHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.zAxisArrowHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.zAxisHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.xCurveHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.xHoop;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.xRotate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.yCurveHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.yHoop;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.yRotate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.zCurveHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zHoop;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zRotate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\r\n\t\t\t\t}\r\n\t\t\t\tif (affordanceMesh) {\r\n\t\t\t\t\taffordanceMesh.visible = true;\r\n\t\t\t\t}\r\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\r\n\t\t\t\tgrabbed = true;\r\n\t\t\t});\r\n\t\t\t//touchstart\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchstart\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible || !grabbed) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\t\tlastAffordanceMesh.visible = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = true;\r\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\r\n\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//touchmove\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchmove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible || !down) return;\r\n\r\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\r\n\t\t\t\t\tswitch (dragAction) {\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//touchend\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchend\",\r\n\t\t\t\t(this._canvasTouchEndListener = (e) => {\r\n\t\t\t\t\t// if (!this._visible) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlastAffordanceMesh = null;\r\n\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tgrabbed = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\tcanvas.addEventListener(\"touchcancel\", this._canvasTouchEndListener);\r\n\t\t}\r\n\t}\r\n\r\n\t_destroy() {\r\n\t\tthis._unbindEvents();\r\n\t\tthis._destroyNodes();\r\n\t}\r\n\r\n\t_unbindEvents() {\r\n\t\tconst viewer = this._viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst canvas = scene.canvas.canvas;\r\n\t\tconst camera = viewer.camera;\r\n\t\tconst cameraControl = viewer.cameraControl;\r\n\r\n\t\tscene.off(this._onSceneTick);\r\n\r\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\r\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\r\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\r\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\r\n\t\tcanvas.removeEventListener(\"touchend\", this._canvasTouchEndListener);\r\n\t\tcanvas.removeEventListener(\"touchcancel\", this._canvasTouchEndListener);\r\n\r\n\t\tcamera.off(this._onCameraViewMatrix);\r\n\t\tcamera.off(this._onCameraProjMatrix);\r\n\r\n\t\tcameraControl.off(this._onCameraControlHover);\r\n\t\tcameraControl.off(this._onCameraControlHoverLeave);\r\n\t}\r\n\r\n\t_destroyNodes() {\r\n\t\tthis._setSectionPlane(null);\r\n\t\tthis._rootNode.destroy();\r\n\t\tthis._displayMeshes = {};\r\n\t\tthis._affordanceMeshes = {};\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/ClippingBox.js?");
|
|
1887
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ClippingBox: () => (/* binding */ ClippingBox)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst zeroVec = new Float64Array([0, 0, 1]);\nconst quat = new Float64Array(4);\n\n/**\n * Controls a {@link SectionPlane} with mouse and touch input.\n *\n * @private\n */\nclass ClippingBox {\n\t/** @private */\n\tconstructor(plugin, cfg) {\n\t\t/**\n\t\t * ID of this Control.\n\t\t *\n\t\t * SectionPlaneControls are mapped by this ID in {@link SectionPlanesPlugin#sectionPlaneControls}.\n\t\t *\n\t\t * @property id\n\t\t * @type {String|Number}\n\t\t */\n\t\tthis.id = null;\n\t\tthis.type = \"box\";\n\n\t\tthis._viewer = plugin.viewer;\n\t\tthis._scene = plugin.viewer.scene;\n\n\t\tthis._controlFillColor = !!cfg && !!cfg.controlFillColor ? cfg.controlFillColor : [0.1, 0.4, 0.99];\n\t\tthis._planeSize = !!cfg && !!cfg.planeSize ? cfg.planeSize : 1;\n\t\tthis._controlSize = !!cfg && !!cfg.controlSize ? cfg.controlSize : 0.07;\n\t\tthis._planeOpacity = !!cfg && !!cfg.planeOpacity ? cfg.planeOpacity : 0.4;\n\n\t\tthis._visible = false;\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the Control\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\n\t\tthis._displayMeshes = null; // Meshes that are always visible\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\n\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\n\t\tthis._createNodes();\n\t\tthis._bindEvents();\n\t}\n\n\t/**\n\t * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.\n\t * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.\n\t * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.\n\t * @private\n\t */\n\t_setSectionPlane(sectionPlane) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\n\t\t\tthis._onSectionPlanePos = null;\n\t\t\tthis._onSectionPlaneDir = null;\n\t\t\tthis._sectionPlane = null;\n\t\t}\n\t\tif (sectionPlane) {\n\t\t\tthis.id = sectionPlane.id;\n\t\t\tthis._setPos(sectionPlane.pos);\n\t\t\tthis._setDir(sectionPlane.dir);\n\t\t\tthis._sectionPlane = sectionPlane;\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\n\t\t\t});\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\n\t\t\t\t} else {\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Gets the {@link SectionPlane} controlled by this Control.\n\t * @returns {SectionPlane} The SectionPlane.\n\t */\n\tget sectionPlane() {\n\t\treturn this._sectionPlane;\n\t}\n\n\t/**\n\t * 设置剖切面位置\n\t * @param {any} value\n\t */\n\tset pos(posRate) {\n\t\tif (posRate < 0 || posRate > 100) return;\n\n\t\tconst { aabb } = this._scene;\n\t\tconst { look } = this._scene.camera;\n\t\tconst xRange = aabb[3] - aabb[0]; //前后\n\t\tconst yRange = aabb[4] - aabb[1]; //上下\n\t\tconst zRange = aabb[5] - aabb[2]; //左右\n\n\t\tconst newSectionPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tnewSectionPos[0] = this.pos[0];\n\t\tnewSectionPos[1] = this.pos[1];\n\t\tnewSectionPos[2] = this.pos[2];\n\n\t\tconst { dir } = this._sectionPlane;\n\t\tlet rateDis;\n\t\tif (dir[0] != 0) {\n\t\t\trateDis = (posRate / 100) * xRange;\n\t\t\tnewSectionPos[0] = look[0] - xRange / 2 + rateDis;\n\t\t} else if (dir[1] != 0) {\n\t\t\trateDis = (posRate / 100) * yRange;\n\t\t\tnewSectionPos[1] = look[1] - yRange / 2 + rateDis;\n\t\t} else if (dir[2] != 0) {\n\t\t\trateDis = (posRate / 100) * zRange;\n\t\t\tnewSectionPos[2] = look[2] - zRange / 2 + rateDis;\n\t\t}\n\n\t\tthis._sectionPlane.pos = newSectionPos;\n\t}\n\n\tget pos() {\n\t\treturn this._pos;\n\t}\n\n\t/** @private */\n\t_setPos(xyz) {\n\t\tthis._pos.set(xyz);\n\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\n\n\t\tthis._rootNode.origin = this._origin;\n\t\tthis._rootNode.position = this._rtcPos;\n\t}\n\n\t/** @private */\n\t_setDir(xyz) {\n\t\tthis._baseDir.set(xyz);\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\n\t}\n\n\t_setSectionPlaneDir(dir) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\n\t\t\tthis._sectionPlane.dir = dir;\n\t\t}\n\t}\n\n\t/**\n\t * Sets if this Control is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tsetVisible(visible = true) {\n\t\tif (this._visible === visible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._visible = visible;\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].visible = visible;\n\t\t\t}\n\t\t}\n\t\tif (!visible) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this Control is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tgetVisible() {\n\t\treturn this._visible;\n\t}\n\n\t/**\n\t * Sets if this Control is culled. This is called by SectionPlanesPlugin to\n\t * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().\n\t * @param culled\n\t */\n\tsetCulled(culled) {\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].culled = culled;\n\t\t\t}\n\t\t}\n\t\tif (!culled) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Builds the Entities that represent this Control.\n\t * @private\n\t */\n\t_createNodes() {\n\t\tconst NO_STATE_INHERIT = false;\n\t\tconst scene = this._viewer.scene;\n\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\n\t\t\tposition: [0, 0, 0],\n\t\t\tscale: [5, 5, 5],\n\t\t\tisObject: false\n\t\t});\n\n\t\tconst rootNode = this._rootNode;\n\n\t\tconst newMesh = (color) => {\n\t\t\treturn new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\tgeometry: MeshConfigs.geometry,\n\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\temissive: [0, 0, 0],\n\t\t\t\t\tdiffuse: color,\n\t\t\t\t\tbackfaces: true\n\t\t\t\t}),\n\t\t\t\topacity: this._planeOpacity,\n\t\t\t\tghosted: true,\n\t\t\t\tghostMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t\tedges: false,\n\t\t\t\t\tfilled: true,\n\t\t\t\t\tfillColor: color,\n\t\t\t\t\tfillAlpha: 0.1,\n\t\t\t\t\tbackfaces: true\n\t\t\t\t}),\n\t\t\t\tpickable: true,\n\t\t\t\tcollidable: true,\n\t\t\t\tclippable: false,\n\t\t\t\tvisible: false,\n\t\t\t\tscale: [2.4, 2.4, 1],\n\t\t\t\tisObject: false\n\t\t\t});\n\t\t};\n\n\t\tthis._displayMeshes = {\n\t\t\tfront_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\n\t\t\tback_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\n\t\t\tright_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\n\t\t\tleft_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\n\t\t\ttop_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT),\n\t\t\tbottom_plane: rootNode.addChild(newMesh(this._controlFillColor), NO_STATE_INHERIT)\n\t\t};\n\n\t\tthis._affordanceMeshes = {\n\t\t\tfront_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\n\t\t\tback_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\n\t\t\tright_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\n\t\t\tleft_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\n\t\t\ttop_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT),\n\t\t\tbottom_plane: rootNode.addChild(newMesh(this._controlEdgeColor), NO_STATE_INHERIT)\n\t\t};\n\t}\n\n\t_bindEvents() {\n\t\tconst self = this;\n\t\tvar grabbed = false;\n\t\tconst DRAG_ACTIONS = {\n\t\t\tnone: -1,\n\t\t\tleft_Translate: 0,\n\t\t\ttop_Translate: 1,\n\t\t\tfront_Translate: 2,\n\t\t\tright_Translate: 3,\n\t\t\tbottom_Translate: 4,\n\t\t\tback_Translate: 5\n\t\t};\n\t\tconst rootNode = this._rootNode;\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\t\tthis.lastCanvasPos = lastCanvasPos;\n\t\tconst xBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([1, 0, 0]);\n\t\tconst yBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 1, 0]);\n\t\tconst zBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 1]);\n\n\t\tconst canvas = this._viewer.scene.canvas.canvas;\n\t\tconst camera = this._viewer.camera;\n\t\tconst scene = this._viewer.scene;\n\n\t\t{\n\t\t\t// Keep gizmo screen size constant\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\n\n\t\t\tlet distDirty = true;\n\t\t\tlet lastDist = -1;\n\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\n\n\t\t\t\tif (dist !== lastDist) {\n\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\n\t\t\t\t\t\tconst size = this._controlSize * worldSize;\n\t\t\t\t\t\trootNode.scale = [size, size, size];\n\t\t\t\t\t\tlastDist = dist;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (camera.projection === \"ortho\") {\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\n\t\t\t\t\tconst size = worldSize;\n\t\t\t\t\trootNode.scale = [size, size, size];\n\t\t\t\t\tlastDist = dist;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t//鼠标获取屏幕点击坐标\n\t\tconst getClickCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t\tcanvasPos[0] = event.x;\n\t\t\t\t\tcanvasPos[1] = event.y;\n\t\t\t\t} else {\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\t//触屏获取屏幕点击坐标\n\t\tconst getTouchCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t}\n\t\t\t\tif (event.touches && event.touches.length) {\n\t\t\t\t\t// 如果有触摸事件,使用第一个触摸点的坐标\n\t\t\t\t\tcanvasPos[0] = event.touches[0].pageX;\n\t\t\t\t\tcanvasPos[1] = event.touches[0].pageY;\n\t\t\t\t} else {\n\t\t\t\t\t// 否则,假设是鼠标事件\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\tconst localToWorldVec = (function () {\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function (localVec, worldVec) {\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(self._rootNode.quaternion, mat);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, localVec, worldVec);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(worldVec);\n\t\t\t\treturn worldVec;\n\t\t\t};\n\t\t})();\n\n\t\tvar getTranslationPlane = (function () {\n\t\t\tconst planeNormal = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\treturn function (worldAxis) {\n\t\t\t\tconst absX = Math.abs(worldAxis[0]);\n\t\t\t\tif (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);\n\t\t\t\t} else {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);\n\t\t\t\t}\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(planeNormal, worldAxis, planeNormal);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(planeNormal);\n\t\t\t\treturn planeNormal;\n\t\t\t};\n\t\t})();\n\n\t\tconst dragTranslateSectionPlane = (function () {\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\n\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\n\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1);\n\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(p2, p1);\n\t\t\t\tconst dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\n\t\t\t\tself._pos[0] += worldAxis[0] * dot;\n\t\t\t\tself._pos[1] += worldAxis[1] * dot;\n\t\t\t\tself._pos[2] += worldAxis[2] * dot;\n\t\t\t\tself._rootNode.position = self._pos;\n\t\t\t\tif (self._sectionPlane) {\n\t\t\t\t\tself._sectionPlane.pos = self._pos;\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\tvar dragRotateSectionPlane = (function () {\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\tconst c = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\n\t\t\t\tconst hasData =\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);\n\t\t\t\tif (!hasData) {\n\t\t\t\t\t// Find intersections with view plane and project down to origin\n\t\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable\n\t\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2, 1);\n\t\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, worldAxis);\n\t\t\t\t\tp1[0] -= dot * worldAxis[0];\n\t\t\t\t\tp1[1] -= dot * worldAxis[1];\n\t\t\t\t\tp1[2] -= dot * worldAxis[2];\n\t\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\n\t\t\t\t\tp2[0] -= dot * worldAxis[0];\n\t\t\t\t\tp2[1] -= dot * worldAxis[1];\n\t\t\t\t\tp2[2] -= dot * worldAxis[2];\n\t\t\t\t}\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p1);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p2);\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, p2);\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range\n\t\t\t\tvar incDegrees = Math.acos(dot) * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.RADTODEG;\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(p1, p2, c);\n\t\t\t\tif (_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(c, worldAxis) < 0.0) {\n\t\t\t\t\tincDegrees = -incDegrees;\n\t\t\t\t}\n\t\t\t\tself._rootNode.rotate(baseAxis, incDegrees);\n\t\t\t\trotateSectionPlane();\n\t\t\t};\n\t\t})();\n\n\t\tvar getPointerPlaneIntersect = (function () {\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4([0, 0, 0, 1]);\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function (mouse, axis, dest, offset) {\n\t\t\t\toffset = offset || 0;\n\t\t\t\tdir[0] = (mouse[0] / canvas.width) * 2.0 - 1.0;\n\t\t\t\tdir[1] = -((mouse[1] / canvas.height) * 2.0 - 1.0);\n\t\t\t\tdir[2] = 0.0;\n\t\t\t\tdir[3] = 1.0;\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(matrix);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec4(matrix, dir, dir);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space\n\t\t\t\tvar rayO = camera.eye; // The direction\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec4(dir, rayO, dir);\n\t\t\t\tconst origin = self._sectionPlane.pos; // Plane origin:\n\t\t\t\tvar d = -_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(origin, axis) - offset;\n\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, dir);\n\t\t\t\tif (Math.abs(dot) > 0.005) {\n\t\t\t\t\tvar t = -(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, rayO) + d) / dot;\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, t, dest);\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(dest, rayO);\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(dest, origin, dest);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t\t})();\n\n\t\tconst rotateSectionPlane = (function () {\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function () {\n\t\t\t\tif (self.sectionPlane) {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(rootNode.quaternion, mat); // << ---\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, [0, 0, 1], dir);\n\t\t\t\t\tself._setSectionPlaneDir(dir);\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\t{\n\t\t\tvar down = false;\n\t\t\tvar lastAffordanceMesh;\n\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"hoverEnter\", (hit) => {\n\t\t\t\tif (!this._visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (down) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tgrabbed = false;\n\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t}\n\t\t\t\tvar affordanceMesh;\n\t\t\t\tconst meshId = hit.entity.id;\n\t\t\t\tswitch (meshId) {\n\t\t\t\t\tcase this._displayMeshes.plane.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.plane;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.front_Translate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xAxisHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yShaftHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.zAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.zAxisHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xCurveHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xHoop;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xRotate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\n\t\t\t\t}\n\t\t\t\tif (affordanceMesh) {\n\t\t\t\t\taffordanceMesh.visible = true;\n\t\t\t\t}\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\n\t\t\t\tgrabbed = true;\n\t\t\t});\n\n\t\t\tthis._onCameraControlHoverLeave = this._viewer.cameraControl.on(\"hoverOutEntity\", (hit) => {\n\t\t\t\tif (!this._visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t}\n\t\t\t\tlastAffordanceMesh = null;\n\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t});\n\n\t\t\t//mousedown\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible || !grabbed) return;\n\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = true;\n\t\t\t\t\t\t\tdown = true;\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\t\t\t//mousemove\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mousemove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\n\t\t\t\t\tswitch (dragAction) {\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\t\t\t//mouseup\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mouseup\",\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\n\t\t\t\t\tif (!this._visible) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdown = false;\n\t\t\t\t\tgrabbed = false;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\t//wheel\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"wheel\",\n\t\t\t\t(this._canvasWheelListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\n\t\t\t\t\tif (delta === 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"touchEntity\", (hit) => {\n\t\t\t\tif (!this._visible || down || grabbed) return;\n\t\t\t\tgrabbed = false;\n\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t}\n\t\t\t\tvar affordanceMesh;\n\t\t\t\tconst meshId = hit.entity.id;\n\t\t\t\tswitch (meshId) {\n\t\t\t\t\tcase this._displayMeshes.plane.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.plane;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// case this._displayMeshes.xAxisArrowHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.xAxisHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.yAxisArrowHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.yShaftHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.zAxisArrowHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.zAxisHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.xCurveHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.xHoop;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.xRotate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.yCurveHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.yHoop;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.yRotate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.zCurveHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zHoop;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zRotate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\n\t\t\t\t}\n\t\t\t\tif (affordanceMesh) {\n\t\t\t\t\taffordanceMesh.visible = true;\n\t\t\t\t}\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\n\t\t\t\tgrabbed = true;\n\t\t\t});\n\t\t\t//touchstart\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchstart\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible || !grabbed) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\t\tlastAffordanceMesh.visible = true;\n\t\t\t\t\t}\n\t\t\t\t\tdown = true;\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\n\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t})\n\t\t\t);\n\t\t\t//touchmove\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchmove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible || !down) return;\n\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\n\t\t\t\t\tswitch (dragAction) {\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\t\t\t//touchend\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchend\",\n\t\t\t\t(this._canvasTouchEndListener = (e) => {\n\t\t\t\t\t// if (!this._visible) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t\t}\n\t\t\t\t\tlastAffordanceMesh = null;\n\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\tdown = false;\n\t\t\t\t\tgrabbed = false;\n\t\t\t\t})\n\t\t\t);\n\t\t\tcanvas.addEventListener(\"touchcancel\", this._canvasTouchEndListener);\n\t\t}\n\t}\n\n\t_destroy() {\n\t\tthis._unbindEvents();\n\t\tthis._destroyNodes();\n\t}\n\n\t_unbindEvents() {\n\t\tconst viewer = this._viewer;\n\t\tconst scene = viewer.scene;\n\t\tconst canvas = scene.canvas.canvas;\n\t\tconst camera = viewer.camera;\n\t\tconst cameraControl = viewer.cameraControl;\n\n\t\tscene.off(this._onSceneTick);\n\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\n\t\tcanvas.removeEventListener(\"touchend\", this._canvasTouchEndListener);\n\t\tcanvas.removeEventListener(\"touchcancel\", this._canvasTouchEndListener);\n\n\t\tcamera.off(this._onCameraViewMatrix);\n\t\tcamera.off(this._onCameraProjMatrix);\n\n\t\tcameraControl.off(this._onCameraControlHover);\n\t\tcameraControl.off(this._onCameraControlHoverLeave);\n\t}\n\n\t_destroyNodes() {\n\t\tthis._setSectionPlane(null);\n\t\tthis._rootNode.destroy();\n\t\tthis._displayMeshes = {};\n\t\tthis._affordanceMeshes = {};\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/ClippingBox.js?");
|
|
1888
1888
|
|
|
1889
1889
|
/***/ }),
|
|
1890
1890
|
|
|
@@ -1894,7 +1894,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1894
1894
|
\**********************************************************/
|
|
1895
1895
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1896
1896
|
|
|
1897
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ClippingPlane: () => (/* binding */ ClippingPlane)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.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\n\r\nconst zeroVec = new Float64Array([0, 0, 1]);\r\nconst quat = new Float64Array(4);\r\n\r\n/**\r\n * Controls a {@link SectionPlane} with mouse and touch input.\r\n *\r\n * @private\r\n */\r\nclass ClippingPlane {\r\n\t/** @private */\r\n\tconstructor(plugin, cfg) {\r\n\t\t/**\r\n\t\t * ID of this Control.\r\n\t\t *\r\n\t\t * SectionPlaneControls are mapped by this ID in {@link SectionPlanesPlugin#sectionPlaneControls}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = null;\r\n\t\tthis.type = \"plane\";\r\n\r\n\t\tthis._viewer = plugin.viewer;\r\n\t\tthis._scene = plugin.viewer.scene;\r\n\r\n\t\tthis._controlFillColor = !!cfg && !!cfg.controlFillColor ? cfg.controlFillColor : [0.1, 0.4, 0.99];\r\n\t\tthis._planeSize = !!cfg && !!cfg.planeSize ? cfg.planeSize : 1;\r\n\t\tthis._controlSize = !!cfg && !!cfg.controlSize ? cfg.controlSize : 0.07;\r\n\t\tthis._planeOpacity = !!cfg && !!cfg.planeOpacity ? cfg.planeOpacity : 0.4;\r\n\r\n\t\tthis._visible = false;\r\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the Control\r\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\r\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\r\n\t\tthis._displayMeshes = null; // Meshes that are always visible\r\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\r\n\r\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\r\n\t\tthis._createNodes();\r\n\t\tthis._bindEvents();\r\n\t}\r\n\r\n\t/**\r\n\t * Builds the Entities that represent this Control.\r\n\t * @private\r\n\t */\r\n\t_createNodes() {\r\n\t\tconst NO_STATE_INHERIT = false;\r\n\t\tconst scene = this._viewer.scene;\r\n\r\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\r\n\t\t\tposition: [0, 0, 0],\r\n\t\t\tscale: [5, 5, 5],\r\n\t\t\tisObject: false\r\n\t\t});\r\n\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tthis._displayMeshes = {\r\n\t\t\tplane: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(rootNode, {\r\n\t\t\t\t\t\tprimitive: \"triangles\",\r\n\t\t\t\t\t\tpositions: [\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.0,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.0, // 0\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.0,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.0, // 1\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.0,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.0, // 2\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.0,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.0 // 3\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tindices: [0, 1, 2, 2, 3, 0]\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\temissive: [0, 0, 0],\r\n\t\t\t\t\t\tdiffuse: this._controlFillColor,\r\n\t\t\t\t\t\tbackfaces: true\r\n\t\t\t\t\t}),\r\n\t\t\t\t\topacity: this._planeOpacity,\r\n\t\t\t\t\tghosted: true,\r\n\t\t\t\t\tghostMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t\t\tedges: false,\r\n\t\t\t\t\t\tfilled: true,\r\n\t\t\t\t\t\tfillColor: this._controlFillColor ? this._controlFillColor : [0.1, 0.4, 0.99],\r\n\t\t\t\t\t\tfillAlpha: 0.1,\r\n\t\t\t\t\t\tbackfaces: true\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [2.4 * this._planeSize, 2.4 * this._planeSize, 1 * this._planeSize],\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t)\r\n\t\t};\r\n\r\n\t\tthis._affordanceMeshes = {\r\n\t\t\t// plane: rootNode.addChild(\r\n\t\t\t// \tnew Mesh(rootNode, {\r\n\t\t\t// \t\tgeometry: new ReadableGeometry(rootNode, {\r\n\t\t\t// \t\t\tprimitive: \"triangles\",\r\n\t\t\t// \t\t\tpositions: [\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t0.0,\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t0.0, // 0\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t0.0,\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t0.0, // 1\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t-0.0,\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t-0.0, // 2\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t-0.0,\r\n\t\t\t// \t\t\t\t-0.5,\r\n\t\t\t// \t\t\t\t0.5,\r\n\t\t\t// \t\t\t\t-0.0 // 3\r\n\t\t\t// \t\t\t],\r\n\t\t\t// \t\t\tindices: [0, 1, 2, 2, 3, 0]\r\n\t\t\t// \t\t}),\r\n\t\t\t// \t\tmaterial: new PhongMaterial(rootNode, {\r\n\t\t\t// \t\t\temissive: [0, 0, 0],\r\n\t\t\t// \t\t\tdiffuse: this._controlFillColor,\r\n\t\t\t// \t\t\tbackfaces: true\r\n\t\t\t// \t\t}),\r\n\t\t\t// \t\topacity: this._planeOpacity,\r\n\t\t\t// \t\tghosted: true,\r\n\t\t\t// \t\tghostMaterial: new EmphasisMaterial(rootNode, {\r\n\t\t\t// \t\t\tedges: false,\r\n\t\t\t// \t\t\tfilled: true,\r\n\t\t\t// \t\t\tfillColor: this._controlFillColor,\r\n\t\t\t// \t\t\tfillAlpha: 0.1,\r\n\t\t\t// \t\t\tbackfaces: true\r\n\t\t\t// \t\t}),\r\n\t\t\t// \t\tpickable: true,\r\n\t\t\t// \t\tcollidable: true,\r\n\t\t\t// \t\tclippable: false,\r\n\t\t\t// \t\tvisible: false,\r\n\t\t\t// \t\tscale: [2.4 * this._planeSize, 2.4 * this._planeSize, 1 * this._planeSize],\r\n\t\t\t// \t\tisObject: false\r\n\t\t\t// \t}),\r\n\t\t\t// \tNO_STATE_INHERIT\r\n\t\t\t// )\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.\r\n\t * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.\r\n\t * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.\r\n\t * @private\r\n\t */\r\n\t_setSectionPlane(sectionPlane) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\r\n\t\t\tthis._onSectionPlanePos = null;\r\n\t\t\tthis._onSectionPlaneDir = null;\r\n\t\t\tthis._sectionPlane = null;\r\n\t\t}\r\n\t\tif (sectionPlane) {\r\n\t\t\tthis.id = sectionPlane.id;\r\n\t\t\tthis._setPos(sectionPlane.pos);\r\n\t\t\tthis._setDir(sectionPlane.dir);\r\n\t\t\tthis._sectionPlane = sectionPlane;\r\n\t\t\tsectionPlane.control = this;\r\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\r\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\r\n\t\t\t});\r\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\r\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\r\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link SectionPlane} controlled by this Control.\r\n\t * @returns {SectionPlane} The SectionPlane.\r\n\t */\r\n\tget sectionPlane() {\r\n\t\treturn this._sectionPlane;\r\n\t}\r\n\r\n\t/**\r\n\t * 设置剖切面位置\r\n\t * @param {any} value\r\n\t */\r\n\tset pos(posRate) {\r\n\t\tif (posRate < 0 || posRate > 100) return;\r\n\r\n\t\tconst { aabb } = this._scene;\r\n\t\tconst { look } = this._scene.camera;\r\n\t\tconst xRange = aabb[3] - aabb[0]; //前后\r\n\t\tconst yRange = aabb[4] - aabb[1]; //上下\r\n\t\tconst zRange = aabb[5] - aabb[2]; //左右\r\n\r\n\t\tconst newSectionPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tnewSectionPos[0] = this.pos[0];\r\n\t\tnewSectionPos[1] = this.pos[1];\r\n\t\tnewSectionPos[2] = this.pos[2];\r\n\r\n\t\tconst { dir } = this._sectionPlane;\r\n\t\tlet rateDis;\r\n\t\tif (dir[0] != 0) {\r\n\t\t\trateDis = (posRate / 100) * xRange;\r\n\t\t\tnewSectionPos[0] = look[0] - xRange / 2 + rateDis; // console.log(\"xRange\", rateDis, rateDis + aabb[0]);\r\n\t\t} else if (dir[1] != 0) {\r\n\t\t\trateDis = (posRate / 100) * yRange;\r\n\t\t\tnewSectionPos[1] = look[1] - yRange / 2 + rateDis; // console.log(\"yRange\", rateDis, rateDis + aabb[1]);\r\n\t\t} else if (dir[2] != 0) {\r\n\t\t\trateDis = (posRate / 100) * zRange;\r\n\t\t\tnewSectionPos[2] = look[2] - zRange / 2 + rateDis; // console.log(\"zRange\", rateDis, rateDis + aabb[2]);\r\n\t\t}\r\n\r\n\t\tthis._sectionPlane.pos = newSectionPos;\r\n\t}\r\n\r\n\tget pos() {\r\n\t\treturn this._pos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setPos(xyz) {\r\n\t\tthis._pos.set(xyz);\r\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\r\n\t\tthis._rootNode.origin = this._origin;\r\n\t\tthis._rootNode.position = this._rtcPos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setDir(xyz) {\r\n\t\tthis._baseDir.set(xyz);\r\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\r\n\t}\r\n\r\n\t_setSectionPlaneDir(dir) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\r\n\t\t\tthis._sectionPlane.dir = dir;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this Control is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tif (this._visible === visible) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._visible = visible;\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].visible = visible;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!visible) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if this Control is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tgetVisible() {\r\n\t\treturn this._visible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this Control is culled. This is called by SectionPlanesPlugin to\r\n\t * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().\r\n\t * @param culled\r\n\t */\r\n\tsetCulled(culled) {\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].culled = culled;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!culled) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t_bindEvents() {\r\n\t\tconst self = this;\r\n\r\n\t\tvar grabbed = false;\r\n\r\n\t\tconst DRAG_ACTIONS = {\r\n\t\t\tnone: -1,\r\n\t\t\txTranslate: 0,\r\n\t\t\tyTranslate: 1,\r\n\t\t\tzTranslate: 2,\r\n\t\t\txRotate: 3,\r\n\t\t\tyRotate: 4,\r\n\t\t\tzRotate: 5\r\n\t\t};\r\n\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\r\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\r\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tthis.lastCanvasPos = lastCanvasPos;\r\n\t\tconst xBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([1, 0, 0]);\r\n\t\tconst yBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 1, 0]);\r\n\t\tconst zBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 1]);\r\n\r\n\t\tconst canvas = this._viewer.scene.canvas.canvas;\r\n\t\tconst camera = this._viewer.camera;\r\n\t\tconst scene = this._viewer.scene;\r\n\r\n\t\t{\r\n\t\t\t// Keep gizmo screen size constant\r\n\r\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\r\n\r\n\t\t\tlet distDirty = true;\r\n\t\t\tlet lastDist = -1;\r\n\r\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\r\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\r\n\r\n\t\t\t\tif (dist !== lastDist) {\r\n\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\r\n\t\t\t\t\t\t// const size = this._controlSize * worldSize;\r\n\t\t\t\t\t\t// rootNode.scale = [size, size, size];\r\n\t\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (camera.projection === \"ortho\") {\r\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\r\n\t\t\t\t\t// const size = worldSize;\r\n\t\t\t\t\t// rootNode.scale = [size, size, size];\r\n\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tconst getClickCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t\tcanvasPos[0] = event.x;\r\n\t\t\t\t\tcanvasPos[1] = event.y;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst getTouchCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t}\r\n\t\t\t\tif (event.touches && event.touches.length) {\r\n\t\t\t\t\t// 如果有触摸事件,使用第一个触摸点的坐标\r\n\t\t\t\t\tcanvasPos[0] = event.touches[0].pageX;\r\n\t\t\t\t\tcanvasPos[1] = event.touches[0].pageY;\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// 否则,假设是鼠标事件\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t//转换为世界坐标\r\n\t\tconst localToWorldVec = (function () {\r\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function (localVec, worldVec) {\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(self._rootNode.quaternion, mat);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, localVec, worldVec);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(worldVec);\r\n\t\t\t\treturn worldVec;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar getTranslationPlane = (function () {\r\n\t\t\tconst planeNormal = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\treturn function (worldAxis) {\r\n\t\t\t\tconst absX = Math.abs(worldAxis[0]);\r\n\t\t\t\tif (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);\r\n\t\t\t\t}\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(planeNormal, worldAxis, planeNormal);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(planeNormal);\r\n\t\t\t\treturn planeNormal;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t//拖拽平面\r\n\t\tconst dragTranslateSectionPlane = (function () {\r\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\r\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\r\n\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\r\n\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1);\r\n\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(p2, p1);\r\n\t\t\t\tconst dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\r\n\t\t\t\tself._pos[0] += worldAxis[0] * dot;\r\n\t\t\t\tself._pos[1] += worldAxis[1] * dot;\r\n\t\t\t\tself._pos[2] += worldAxis[2] * dot;\r\n\t\t\t\tself._rootNode.position = self._pos;\r\n\t\t\t\tif (self._sectionPlane) {\r\n\t\t\t\t\tself._sectionPlane.pos = self._pos;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar getPointerPlaneIntersect = (function () {\r\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4([0, 0, 0, 1]);\r\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function (mouse, axis, dest, offset) {\r\n\t\t\t\toffset = offset || 0;\r\n\t\t\t\tdir[0] = (mouse[0] / canvas.width) * 2.0 - 1.0;\r\n\t\t\t\tdir[1] = -((mouse[1] / canvas.height) * 2.0 - 1.0);\r\n\t\t\t\tdir[2] = 0.0;\r\n\t\t\t\tdir[3] = 1.0;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(matrix);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec4(matrix, dir, dir);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space\r\n\t\t\t\tvar rayO = camera.eye; // The direction\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec4(dir, rayO, dir);\r\n\t\t\t\tconst origin = self._sectionPlane.pos; // Plane origin:\r\n\t\t\t\tvar d = -_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(origin, axis) - offset;\r\n\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, dir);\r\n\t\t\t\tif (Math.abs(dot) > 0.005) {\r\n\t\t\t\t\tvar t = -(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, rayO) + d) / dot;\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, t, dest);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(dest, rayO);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(dest, origin, dest);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\treturn false;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t{\r\n\t\t\tvar mouseDownLeft;\r\n\t\t\tvar mouseDownMiddle;\r\n\t\t\tvar mouseDownRight;\r\n\t\t\tvar down = false;\r\n\t\t\t// var lastAffordanceMesh;\r\n\r\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"hoverEnter\", (hit) => {\r\n\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (down) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tgrabbed = false;\r\n\t\t\t\t// if (lastAffordanceMesh) {\r\n\t\t\t\t// \tlastAffordanceMesh.visible = false;\r\n\t\t\t\t// }\r\n\t\t\t\t// var affordanceMesh;\r\n\t\t\t\tconst meshId = hit.entity.id;\r\n\t\t\t\tswitch (meshId) {\r\n\t\t\t\t\tcase this._displayMeshes.plane.id:\r\n\t\t\t\t\t\t// affordanceMesh = this._affordanceMeshes.plane;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\r\n\t\t\t\t}\r\n\t\t\t\t// if (affordanceMesh) {\r\n\t\t\t\t// \taffordanceMesh.visible = true;\r\n\t\t\t\t// }\r\n\t\t\t\t// lastAffordanceMesh = affordanceMesh;\r\n\t\t\t\tgrabbed = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraControlHoverLeave = this._viewer.cameraControl.on(\"hoverOutEntity\", (hit) => {\r\n\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\t// if (lastAffordanceMesh) {\r\n\t\t\t\t// \tlastAffordanceMesh.visible = false;\r\n\t\t\t\t// }\r\n\t\t\t\t// lastAffordanceMesh = null;\r\n\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t});\r\n\r\n\t\t\t//mousedown\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mousedown\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible || !grabbed) return;\r\n\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = true;\r\n\t\t\t\t\t\t\tdown = true;\r\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e); //获取鼠标点击对应坐标\r\n\t\t\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//mousemove\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mousemove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\r\n\t\t\t\t\tswitch (dragAction) {\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//mouseup\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tgrabbed = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\t//wheel\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"wheel\",\r\n\t\t\t\t(this._canvasWheelListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\r\n\t\t\t\t\tif (delta === 0) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"touchEntity\", (hit) => {\r\n\t\t\t\tif (!this._visible || down || grabbed) return;\r\n\t\t\t\t// if (lastAffordanceMesh) {\r\n\t\t\t\t// \tlastAffordanceMesh.visible = false;\r\n\t\t\t\t// }\r\n\t\t\t\tvar affordanceMesh;\r\n\t\t\t\tconst meshId = hit.entity.id;\r\n\t\t\t\tswitch (meshId) {\r\n\t\t\t\t\tcase this._displayMeshes.plane.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.plane;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\r\n\t\t\t\t}\r\n\t\t\t\tif (affordanceMesh) {\r\n\t\t\t\t\taffordanceMesh.visible = true;\r\n\t\t\t\t}\r\n\t\t\t\t// lastAffordanceMesh = affordanceMesh;\r\n\t\t\t\tgrabbed = true;\r\n\t\t\t\tdown = true;\r\n\t\t\t});\r\n\t\t\t//touchstart\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchstart\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible || !grabbed || !down) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\t// if (lastAffordanceMesh) {\r\n\t\t\t\t\t// \tlastAffordanceMesh.visible = true;\r\n\t\t\t\t\t// }\r\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\r\n\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//touchmove\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchmove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible || !down || !grabbed) return;\r\n\r\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\r\n\t\t\t\t\tswitch (dragAction) {\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//touchend\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchend\",\r\n\t\t\t\t(this._canvasTouchEndListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) return;\r\n\t\t\t\t\tif (grabbed) this._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\t// if (lastAffordanceMesh) {\r\n\t\t\t\t\t// \tlastAffordanceMesh.visible = false;\r\n\t\t\t\t\t// }\r\n\t\t\t\t\t// lastAffordanceMesh = null;\r\n\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tgrabbed = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\tcanvas.addEventListener(\"touchcancel\", this._canvasTouchEndListener);\r\n\t\t}\r\n\t}\r\n\r\n\t_destroy() {\r\n\t\tthis._unbindEvents();\r\n\t\tthis._destroyNodes();\r\n\t}\r\n\r\n\t_unbindEvents() {\r\n\t\tconst viewer = this._viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst canvas = scene.canvas.canvas;\r\n\t\tconst camera = viewer.camera;\r\n\t\tconst cameraControl = viewer.cameraControl;\r\n\r\n\t\tscene.off(this._onSceneTick);\r\n\r\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\r\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\r\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\r\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\r\n\t\tcanvas.removeEventListener(\"touchend\", this._canvasTouchEndListener);\r\n\t\tcanvas.removeEventListener(\"touchcancel\", this._canvasTouchEndListener);\r\n\r\n\t\tcamera.off(this._onCameraViewMatrix);\r\n\t\tcamera.off(this._onCameraProjMatrix);\r\n\r\n\t\tcameraControl.off(this._onCameraControlHover);\r\n\t\tcameraControl.off(this._onCameraControlHoverLeave);\r\n\t}\r\n\r\n\t_destroyNodes() {\r\n\t\tthis._setSectionPlane(null);\r\n\t\tthis._rootNode.destroy();\r\n\t\tthis._displayMeshes = {};\r\n\t\tthis._affordanceMeshes = {};\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/ClippingPlane.js?");
|
|
1897
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ClippingPlane: () => (/* binding */ ClippingPlane)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst zeroVec = new Float64Array([0, 0, 1]);\nconst quat = new Float64Array(4);\n\n/**\n * Controls a {@link SectionPlane} with mouse and touch input.\n *\n * @private\n */\nclass ClippingPlane {\n\t/** @private */\n\tconstructor(plugin, cfg) {\n\t\t/**\n\t\t * ID of this Control.\n\t\t *\n\t\t * SectionPlaneControls are mapped by this ID in {@link SectionPlanesPlugin#sectionPlaneControls}.\n\t\t *\n\t\t * @property id\n\t\t * @type {String|Number}\n\t\t */\n\t\tthis.id = null;\n\t\tthis.type = \"plane\";\n\n\t\tthis._viewer = plugin.viewer;\n\t\tthis._scene = plugin.viewer.scene;\n\n\t\tthis._controlFillColor = !!cfg && !!cfg.controlFillColor ? cfg.controlFillColor : [0.1, 0.4, 0.99];\n\t\tthis._planeSize = !!cfg && !!cfg.planeSize ? cfg.planeSize : 1;\n\t\tthis._controlSize = !!cfg && !!cfg.controlSize ? cfg.controlSize : 0.07;\n\t\tthis._planeOpacity = !!cfg && !!cfg.planeOpacity ? cfg.planeOpacity : 0.4;\n\n\t\tthis._visible = false;\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the Control\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\n\t\tthis._displayMeshes = null; // Meshes that are always visible\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\n\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\n\t\tthis._createNodes();\n\t\tthis._bindEvents();\n\t}\n\n\t/**\n\t * Builds the Entities that represent this Control.\n\t * @private\n\t */\n\t_createNodes() {\n\t\tconst NO_STATE_INHERIT = false;\n\t\tconst scene = this._viewer.scene;\n\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\n\t\t\tposition: [0, 0, 0],\n\t\t\tscale: [5, 5, 5],\n\t\t\tisObject: false\n\t\t});\n\n\t\tconst rootNode = this._rootNode;\n\n\t\tthis._displayMeshes = {\n\t\t\tplane: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(rootNode, {\n\t\t\t\t\t\tprimitive: \"triangles\",\n\t\t\t\t\t\tpositions: [\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.0,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.0, // 0\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.0,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.0, // 1\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.0,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.0, // 2\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.0,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.0 // 3\n\t\t\t\t\t\t],\n\t\t\t\t\t\tindices: [0, 1, 2, 2, 3, 0]\n\t\t\t\t\t}),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\temissive: [0, 0, 0],\n\t\t\t\t\t\tdiffuse: this._controlFillColor,\n\t\t\t\t\t\tbackfaces: true\n\t\t\t\t\t}),\n\t\t\t\t\topacity: this._planeOpacity,\n\t\t\t\t\tghosted: true,\n\t\t\t\t\tghostMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t\t\tedges: false,\n\t\t\t\t\t\tfilled: true,\n\t\t\t\t\t\tfillColor: this._controlFillColor ? this._controlFillColor : [0.1, 0.4, 0.99],\n\t\t\t\t\t\tfillAlpha: 0.1,\n\t\t\t\t\t\tbackfaces: true\n\t\t\t\t\t}),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [2.4 * this._planeSize, 2.4 * this._planeSize, 1 * this._planeSize],\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t)\n\t\t};\n\n\t\tthis._affordanceMeshes = {\n\t\t\t// plane: rootNode.addChild(\n\t\t\t// \tnew Mesh(rootNode, {\n\t\t\t// \t\tgeometry: new ReadableGeometry(rootNode, {\n\t\t\t// \t\t\tprimitive: \"triangles\",\n\t\t\t// \t\t\tpositions: [\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t0.0,\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t0.0, // 0\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t0.0,\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t0.0, // 1\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t-0.0,\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t-0.0, // 2\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t-0.0,\n\t\t\t// \t\t\t\t-0.5,\n\t\t\t// \t\t\t\t0.5,\n\t\t\t// \t\t\t\t-0.0 // 3\n\t\t\t// \t\t\t],\n\t\t\t// \t\t\tindices: [0, 1, 2, 2, 3, 0]\n\t\t\t// \t\t}),\n\t\t\t// \t\tmaterial: new PhongMaterial(rootNode, {\n\t\t\t// \t\t\temissive: [0, 0, 0],\n\t\t\t// \t\t\tdiffuse: this._controlFillColor,\n\t\t\t// \t\t\tbackfaces: true\n\t\t\t// \t\t}),\n\t\t\t// \t\topacity: this._planeOpacity,\n\t\t\t// \t\tghosted: true,\n\t\t\t// \t\tghostMaterial: new EmphasisMaterial(rootNode, {\n\t\t\t// \t\t\tedges: false,\n\t\t\t// \t\t\tfilled: true,\n\t\t\t// \t\t\tfillColor: this._controlFillColor,\n\t\t\t// \t\t\tfillAlpha: 0.1,\n\t\t\t// \t\t\tbackfaces: true\n\t\t\t// \t\t}),\n\t\t\t// \t\tpickable: true,\n\t\t\t// \t\tcollidable: true,\n\t\t\t// \t\tclippable: false,\n\t\t\t// \t\tvisible: false,\n\t\t\t// \t\tscale: [2.4 * this._planeSize, 2.4 * this._planeSize, 1 * this._planeSize],\n\t\t\t// \t\tisObject: false\n\t\t\t// \t}),\n\t\t\t// \tNO_STATE_INHERIT\n\t\t\t// )\n\t\t};\n\t}\n\n\t/**\n\t * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.\n\t * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.\n\t * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.\n\t * @private\n\t */\n\t_setSectionPlane(sectionPlane) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\n\t\t\tthis._onSectionPlanePos = null;\n\t\t\tthis._onSectionPlaneDir = null;\n\t\t\tthis._sectionPlane = null;\n\t\t}\n\t\tif (sectionPlane) {\n\t\t\tthis.id = sectionPlane.id;\n\t\t\tthis._setPos(sectionPlane.pos);\n\t\t\tthis._setDir(sectionPlane.dir);\n\t\t\tthis._sectionPlane = sectionPlane;\n\t\t\tsectionPlane.control = this;\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\n\t\t\t});\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\n\t\t\t\t} else {\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Gets the {@link SectionPlane} controlled by this Control.\n\t * @returns {SectionPlane} The SectionPlane.\n\t */\n\tget sectionPlane() {\n\t\treturn this._sectionPlane;\n\t}\n\n\t/**\n\t * 设置剖切面位置\n\t * @param {any} value\n\t */\n\tset pos(posRate) {\n\t\tif (posRate < 0 || posRate > 100) return;\n\n\t\tconst { aabb } = this._scene;\n\t\tconst { look } = this._scene.camera;\n\t\tconst xRange = aabb[3] - aabb[0]; //前后\n\t\tconst yRange = aabb[4] - aabb[1]; //上下\n\t\tconst zRange = aabb[5] - aabb[2]; //左右\n\n\t\tconst newSectionPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tnewSectionPos[0] = this.pos[0];\n\t\tnewSectionPos[1] = this.pos[1];\n\t\tnewSectionPos[2] = this.pos[2];\n\n\t\tconst { dir } = this._sectionPlane;\n\t\tlet rateDis;\n\t\tif (dir[0] != 0) {\n\t\t\trateDis = (posRate / 100) * xRange;\n\t\t\tnewSectionPos[0] = look[0] - xRange / 2 + rateDis; // console.log(\"xRange\", rateDis, rateDis + aabb[0]);\n\t\t} else if (dir[1] != 0) {\n\t\t\trateDis = (posRate / 100) * yRange;\n\t\t\tnewSectionPos[1] = look[1] - yRange / 2 + rateDis; // console.log(\"yRange\", rateDis, rateDis + aabb[1]);\n\t\t} else if (dir[2] != 0) {\n\t\t\trateDis = (posRate / 100) * zRange;\n\t\t\tnewSectionPos[2] = look[2] - zRange / 2 + rateDis; // console.log(\"zRange\", rateDis, rateDis + aabb[2]);\n\t\t}\n\n\t\tthis._sectionPlane.pos = newSectionPos;\n\t}\n\n\tget pos() {\n\t\treturn this._pos;\n\t}\n\n\t/** @private */\n\t_setPos(xyz) {\n\t\tthis._pos.set(xyz);\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\n\t\tthis._rootNode.origin = this._origin;\n\t\tthis._rootNode.position = this._rtcPos;\n\t}\n\n\t/** @private */\n\t_setDir(xyz) {\n\t\tthis._baseDir.set(xyz);\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\n\t}\n\n\t_setSectionPlaneDir(dir) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\n\t\t\tthis._sectionPlane.dir = dir;\n\t\t}\n\t}\n\n\t/**\n\t * Sets if this Control is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tsetVisible(visible = true) {\n\t\tif (this._visible === visible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._visible = visible;\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].visible = visible;\n\t\t\t}\n\t\t}\n\t\tif (!visible) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this Control is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tgetVisible() {\n\t\treturn this._visible;\n\t}\n\n\t/**\n\t * Sets if this Control is culled. This is called by SectionPlanesPlugin to\n\t * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().\n\t * @param culled\n\t */\n\tsetCulled(culled) {\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].culled = culled;\n\t\t\t}\n\t\t}\n\t\tif (!culled) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t_bindEvents() {\n\t\tconst self = this;\n\n\t\tvar grabbed = false;\n\n\t\tconst DRAG_ACTIONS = {\n\t\t\tnone: -1,\n\t\t\txTranslate: 0,\n\t\t\tyTranslate: 1,\n\t\t\tzTranslate: 2,\n\t\t\txRotate: 3,\n\t\t\tyRotate: 4,\n\t\t\tzRotate: 5\n\t\t};\n\n\t\tconst rootNode = this._rootNode;\n\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\t\tthis.lastCanvasPos = lastCanvasPos;\n\t\tconst xBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([1, 0, 0]);\n\t\tconst yBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 1, 0]);\n\t\tconst zBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 1]);\n\n\t\tconst canvas = this._viewer.scene.canvas.canvas;\n\t\tconst camera = this._viewer.camera;\n\t\tconst scene = this._viewer.scene;\n\n\t\t{\n\t\t\t// Keep gizmo screen size constant\n\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\n\n\t\t\tlet distDirty = true;\n\t\t\tlet lastDist = -1;\n\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\n\n\t\t\t\tif (dist !== lastDist) {\n\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\n\t\t\t\t\t\t// const size = this._controlSize * worldSize;\n\t\t\t\t\t\t// rootNode.scale = [size, size, size];\n\t\t\t\t\t\tlastDist = dist;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (camera.projection === \"ortho\") {\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\n\t\t\t\t\t// const size = worldSize;\n\t\t\t\t\t// rootNode.scale = [size, size, size];\n\t\t\t\t\tlastDist = dist;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst getClickCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t\tcanvasPos[0] = event.x;\n\t\t\t\t\tcanvasPos[1] = event.y;\n\t\t\t\t} else {\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\tconst getTouchCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t}\n\t\t\t\tif (event.touches && event.touches.length) {\n\t\t\t\t\t// 如果有触摸事件,使用第一个触摸点的坐标\n\t\t\t\t\tcanvasPos[0] = event.touches[0].pageX;\n\t\t\t\t\tcanvasPos[1] = event.touches[0].pageY;\n\t\t\t\t} else {\n\t\t\t\t\t// 否则,假设是鼠标事件\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\t//转换为世界坐标\n\t\tconst localToWorldVec = (function () {\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function (localVec, worldVec) {\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(self._rootNode.quaternion, mat);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, localVec, worldVec);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(worldVec);\n\t\t\t\treturn worldVec;\n\t\t\t};\n\t\t})();\n\n\t\tvar getTranslationPlane = (function () {\n\t\t\tconst planeNormal = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\treturn function (worldAxis) {\n\t\t\t\tconst absX = Math.abs(worldAxis[0]);\n\t\t\t\tif (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);\n\t\t\t\t} else {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);\n\t\t\t\t}\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(planeNormal, worldAxis, planeNormal);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(planeNormal);\n\t\t\t\treturn planeNormal;\n\t\t\t};\n\t\t})();\n\n\t\t//拖拽平面\n\t\tconst dragTranslateSectionPlane = (function () {\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\n\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\n\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1);\n\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(p2, p1);\n\t\t\t\tconst dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\n\t\t\t\tself._pos[0] += worldAxis[0] * dot;\n\t\t\t\tself._pos[1] += worldAxis[1] * dot;\n\t\t\t\tself._pos[2] += worldAxis[2] * dot;\n\t\t\t\tself._rootNode.position = self._pos;\n\t\t\t\tif (self._sectionPlane) {\n\t\t\t\t\tself._sectionPlane.pos = self._pos;\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\tvar getPointerPlaneIntersect = (function () {\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4([0, 0, 0, 1]);\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function (mouse, axis, dest, offset) {\n\t\t\t\toffset = offset || 0;\n\t\t\t\tdir[0] = (mouse[0] / canvas.width) * 2.0 - 1.0;\n\t\t\t\tdir[1] = -((mouse[1] / canvas.height) * 2.0 - 1.0);\n\t\t\t\tdir[2] = 0.0;\n\t\t\t\tdir[3] = 1.0;\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(matrix);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec4(matrix, dir, dir);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space\n\t\t\t\tvar rayO = camera.eye; // The direction\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec4(dir, rayO, dir);\n\t\t\t\tconst origin = self._sectionPlane.pos; // Plane origin:\n\t\t\t\tvar d = -_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(origin, axis) - offset;\n\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, dir);\n\t\t\t\tif (Math.abs(dot) > 0.005) {\n\t\t\t\t\tvar t = -(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, rayO) + d) / dot;\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, t, dest);\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(dest, rayO);\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(dest, origin, dest);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t\t})();\n\n\t\t{\n\t\t\tvar mouseDownLeft;\n\t\t\tvar mouseDownMiddle;\n\t\t\tvar mouseDownRight;\n\t\t\tvar down = false;\n\t\t\t// var lastAffordanceMesh;\n\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"hoverEnter\", (hit) => {\n\t\t\t\tif (!this._visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (down) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tgrabbed = false;\n\t\t\t\t// if (lastAffordanceMesh) {\n\t\t\t\t// \tlastAffordanceMesh.visible = false;\n\t\t\t\t// }\n\t\t\t\t// var affordanceMesh;\n\t\t\t\tconst meshId = hit.entity.id;\n\t\t\t\tswitch (meshId) {\n\t\t\t\t\tcase this._displayMeshes.plane.id:\n\t\t\t\t\t\t// affordanceMesh = this._affordanceMeshes.plane;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\n\t\t\t\t}\n\t\t\t\t// if (affordanceMesh) {\n\t\t\t\t// \taffordanceMesh.visible = true;\n\t\t\t\t// }\n\t\t\t\t// lastAffordanceMesh = affordanceMesh;\n\t\t\t\tgrabbed = true;\n\t\t\t});\n\n\t\t\tthis._onCameraControlHoverLeave = this._viewer.cameraControl.on(\"hoverOutEntity\", (hit) => {\n\t\t\t\tif (!this._visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// if (lastAffordanceMesh) {\n\t\t\t\t// \tlastAffordanceMesh.visible = false;\n\t\t\t\t// }\n\t\t\t\t// lastAffordanceMesh = null;\n\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t});\n\n\t\t\t//mousedown\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible || !grabbed) return;\n\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = true;\n\t\t\t\t\t\t\tdown = true;\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e); //获取鼠标点击对应坐标\n\t\t\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\t\t\t//mousemove\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mousemove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\n\t\t\t\t\tswitch (dragAction) {\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\t\t\t//mouseup\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mouseup\",\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\n\t\t\t\t\tif (!this._visible) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdown = false;\n\t\t\t\t\tgrabbed = false;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\t//wheel\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"wheel\",\n\t\t\t\t(this._canvasWheelListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\n\t\t\t\t\tif (delta === 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"touchEntity\", (hit) => {\n\t\t\t\tif (!this._visible || down || grabbed) return;\n\t\t\t\t// if (lastAffordanceMesh) {\n\t\t\t\t// \tlastAffordanceMesh.visible = false;\n\t\t\t\t// }\n\t\t\t\tvar affordanceMesh;\n\t\t\t\tconst meshId = hit.entity.id;\n\t\t\t\tswitch (meshId) {\n\t\t\t\t\tcase this._displayMeshes.plane.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.plane;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\n\t\t\t\t}\n\t\t\t\tif (affordanceMesh) {\n\t\t\t\t\taffordanceMesh.visible = true;\n\t\t\t\t}\n\t\t\t\t// lastAffordanceMesh = affordanceMesh;\n\t\t\t\tgrabbed = true;\n\t\t\t\tdown = true;\n\t\t\t});\n\t\t\t//touchstart\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchstart\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible || !grabbed || !down) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\t// if (lastAffordanceMesh) {\n\t\t\t\t\t// \tlastAffordanceMesh.visible = true;\n\t\t\t\t\t// }\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\n\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t})\n\t\t\t);\n\t\t\t//touchmove\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchmove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible || !down || !grabbed) return;\n\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\n\t\t\t\t\tswitch (dragAction) {\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\t\t\t//touchend\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchend\",\n\t\t\t\t(this._canvasTouchEndListener = (e) => {\n\t\t\t\t\tif (!this._visible) return;\n\t\t\t\t\tif (grabbed) this._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\t// if (lastAffordanceMesh) {\n\t\t\t\t\t// \tlastAffordanceMesh.visible = false;\n\t\t\t\t\t// }\n\t\t\t\t\t// lastAffordanceMesh = null;\n\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\tdown = false;\n\t\t\t\t\tgrabbed = false;\n\t\t\t\t})\n\t\t\t);\n\t\t\tcanvas.addEventListener(\"touchcancel\", this._canvasTouchEndListener);\n\t\t}\n\t}\n\n\t_destroy() {\n\t\tthis._unbindEvents();\n\t\tthis._destroyNodes();\n\t}\n\n\t_unbindEvents() {\n\t\tconst viewer = this._viewer;\n\t\tconst scene = viewer.scene;\n\t\tconst canvas = scene.canvas.canvas;\n\t\tconst camera = viewer.camera;\n\t\tconst cameraControl = viewer.cameraControl;\n\n\t\tscene.off(this._onSceneTick);\n\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\n\t\tcanvas.removeEventListener(\"touchend\", this._canvasTouchEndListener);\n\t\tcanvas.removeEventListener(\"touchcancel\", this._canvasTouchEndListener);\n\n\t\tcamera.off(this._onCameraViewMatrix);\n\t\tcamera.off(this._onCameraProjMatrix);\n\n\t\tcameraControl.off(this._onCameraControlHover);\n\t\tcameraControl.off(this._onCameraControlHoverLeave);\n\t}\n\n\t_destroyNodes() {\n\t\tthis._setSectionPlane(null);\n\t\tthis._rootNode.destroy();\n\t\tthis._displayMeshes = {};\n\t\tthis._affordanceMeshes = {};\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/ClippingPlane.js?");
|
|
1898
1898
|
|
|
1899
1899
|
/***/ }),
|
|
1900
1900
|
|
|
@@ -1904,7 +1904,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1904
1904
|
\****************************************************/
|
|
1905
1905
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1906
1906
|
|
|
1907
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Control: () => (/* binding */ Control)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.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\n\r\nconst zeroVec = new Float64Array([0, 0, 1]);\r\nconst quat = new Float64Array(4);\r\n\r\n/**\r\n * Controls a {@link SectionPlane} with mouse and touch input.\r\n *\r\n * @private\r\n */\r\nclass Control {\r\n\t/** @private */\r\n\tconstructor(plugin) {\r\n\t\t/**\r\n\t\t * ID of this Control.\r\n\t\t *\r\n\t\t * SectionPlaneControls are mapped by this ID in {@link SectionPlanesPlugin#sectionPlaneControls}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = null;\r\n\t\tthis.type = \"control\";\r\n\r\n\t\tthis._viewer = plugin.viewer;\r\n\t\tthis._scene = plugin.viewer.scene;\r\n\r\n\t\tthis._visible = false;\r\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the Control\r\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\r\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\r\n\t\tthis._displayMeshes = null; // Meshes that are always visible\r\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\r\n\r\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\r\n\t\tthis._createNodes();\r\n\t\tthis._bindEvents();\r\n\t}\r\n\r\n\t/**\r\n\t * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.\r\n\t * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.\r\n\t * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.\r\n\t * @private\r\n\t */\r\n\t_setSectionPlane(sectionPlane) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\r\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\r\n\t\t\tthis._onSectionPlanePos = null;\r\n\t\t\tthis._onSectionPlaneDir = null;\r\n\t\t\tthis._sectionPlane = null;\r\n\t\t}\r\n\t\tif (sectionPlane) {\r\n\t\t\tthis.id = sectionPlane.id;\r\n\t\t\tthis._setPos(sectionPlane.pos);\r\n\t\t\tthis._setDir(sectionPlane.dir);\r\n\t\t\tthis._sectionPlane = sectionPlane;\r\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\r\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\r\n\t\t\t});\r\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\r\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\r\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link SectionPlane} controlled by this Control.\r\n\t * @returns {SectionPlane} The SectionPlane.\r\n\t */\r\n\tget sectionPlane() {\r\n\t\treturn this._sectionPlane;\r\n\t}\r\n\r\n\t/**\r\n\t * 设置剖切面位置\r\n\t * @param {any} value\r\n\t */\r\n\tset pos(posRate) {\r\n\t\tif (posRate < 0 || posRate > 100) return;\r\n\r\n\t\tconst { aabb } = this._scene;\r\n\t\tconst { look } = this._scene.camera;\r\n\t\tconst xRange = aabb[3] - aabb[0]; //前后\r\n\t\tconst yRange = aabb[4] - aabb[1]; //上下\r\n\t\tconst zRange = aabb[5] - aabb[2]; //左右\r\n\r\n\t\tconst newSectionPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tnewSectionPos[0] = this.pos[0];\r\n\t\tnewSectionPos[1] = this.pos[1];\r\n\t\tnewSectionPos[2] = this.pos[2];\r\n\r\n\t\tconst { dir } = this._sectionPlane;\r\n\t\tlet rateDis;\r\n\t\tif (dir[0] != 0) {\r\n\t\t\trateDis = (posRate / 100) * xRange;\r\n\t\t\tnewSectionPos[0] = look[0] - xRange / 2 + rateDis;\r\n\t\t} else if (dir[1] != 0) {\r\n\t\t\trateDis = (posRate / 100) * yRange;\r\n\t\t\tnewSectionPos[1] = look[1] - yRange / 2 + rateDis;\r\n\t\t} else if (dir[2] != 0) {\r\n\t\t\trateDis = (posRate / 100) * zRange;\r\n\t\t\tnewSectionPos[2] = look[2] - zRange / 2 + rateDis;\r\n\t\t}\r\n\r\n\t\tthis._sectionPlane.pos = newSectionPos;\r\n\t}\r\n\r\n\tget pos() {\r\n\t\treturn this._pos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setPos(xyz) {\r\n\t\tthis._pos.set(xyz);\r\n\r\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\r\n\r\n\t\tthis._rootNode.origin = this._origin;\r\n\t\tthis._rootNode.position = this._rtcPos;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_setDir(xyz) {\r\n\t\tthis._baseDir.set(xyz);\r\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\r\n\t}\r\n\r\n\t_setSectionPlaneDir(dir) {\r\n\t\tif (this._sectionPlane) {\r\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\r\n\t\t\tthis._sectionPlane.dir = dir;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this Control is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tif (this._visible === visible) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._visible = visible;\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].visible = visible;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!visible) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if this Control is visible.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tgetVisible() {\r\n\t\treturn this._visible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this Control is culled. This is called by SectionPlanesPlugin to\r\n\t * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().\r\n\t * @param culled\r\n\t */\r\n\tsetCulled(culled) {\r\n\t\tvar id;\r\n\t\tfor (id in this._displayMeshes) {\r\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\r\n\t\t\t\tthis._displayMeshes[id].culled = culled;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!culled) {\r\n\t\t\tfor (id in this._affordanceMeshes) {\r\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\r\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Builds the Entities that represent this Control.\r\n\t * @private\r\n\t */\r\n\t_createNodes() {\r\n\t\tconst NO_STATE_INHERIT = false;\r\n\t\tconst scene = this._viewer.scene;\r\n\t\tconst radius = 1.0;\r\n\t\tconst handleTubeRadius = 0.06;\r\n\t\tconst hoopRadius = radius - 0.2;\r\n\t\tconst tubeRadius = 0.01;\r\n\t\tconst arrowRadius = 0.07;\r\n\r\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\r\n\t\t\tposition: [0, 0, 0],\r\n\t\t\tscale: [5, 5, 5],\r\n\t\t\tisObject: false\r\n\t\t});\r\n\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tconst shapes = {\r\n\t\t\t// Reusable geometries\r\n\r\n\t\t\tarrowHead: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: 0.001,\r\n\t\t\t\t\tradiusBottom: arrowRadius,\r\n\t\t\t\t\tradialSegments: 32,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: 0.2,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\tarrowHeadBig: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: 0.001,\r\n\t\t\t\t\tradiusBottom: 0.09,\r\n\t\t\t\t\tradialSegments: 32,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: 0.25,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\tarrowHeadHandle: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: 0.09,\r\n\t\t\t\t\tradiusBottom: 0.09,\r\n\t\t\t\t\tradialSegments: 8,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: 0.37,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\tcurve: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\tradius: hoopRadius,\r\n\t\t\t\t\ttube: tubeRadius,\r\n\t\t\t\t\tradialSegments: 64,\r\n\t\t\t\t\ttubeSegments: 14,\r\n\t\t\t\t\tarc: (Math.PI * 2.0) / 4.0\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\tcurveHandle: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\tradius: hoopRadius,\r\n\t\t\t\t\ttube: handleTubeRadius,\r\n\t\t\t\t\tradialSegments: 64,\r\n\t\t\t\t\ttubeSegments: 14,\r\n\t\t\t\t\tarc: (Math.PI * 2.0) / 4.0\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\thoop: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\tradius: hoopRadius,\r\n\t\t\t\t\ttube: tubeRadius,\r\n\t\t\t\t\tradialSegments: 64,\r\n\t\t\t\t\ttubeSegments: 8,\r\n\t\t\t\t\tarc: Math.PI * 2.0\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\taxis: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: tubeRadius,\r\n\t\t\t\t\tradiusBottom: tubeRadius,\r\n\t\t\t\t\tradialSegments: 20,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: radius,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t),\r\n\r\n\t\t\taxisHandle: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\trootNode,\r\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\r\n\t\t\t\t\tradiusTop: 0.08,\r\n\t\t\t\t\tradiusBottom: 0.08,\r\n\t\t\t\t\tradialSegments: 20,\r\n\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\theight: radius,\r\n\t\t\t\t\topenEnded: false\r\n\t\t\t\t})\r\n\t\t\t)\r\n\t\t};\r\n\r\n\t\tconst materials = {\r\n\t\t\t// Reusable materials\r\n\r\n\t\t\tpickable: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t// Invisible material for pickable handles, which define a pickable 3D area\r\n\t\t\t\tdiffuse: [1, 1, 0],\r\n\t\t\t\talpha: 0, // Invisible\r\n\t\t\t\talphaMode: \"blend\"\r\n\t\t\t}),\r\n\r\n\t\t\tred: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [1, 0.0, 0.0],\r\n\t\t\t\temissive: [1, 0.0, 0.0],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80,\r\n\t\t\t\tlineWidth: 2\r\n\t\t\t}),\r\n\r\n\t\t\thighlightRed: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t// Emphasis for red rotation affordance hoop\r\n\t\t\t\tedges: false,\r\n\t\t\t\tfill: true,\r\n\t\t\t\tfillColor: [1, 0, 0],\r\n\t\t\t\tfillAlpha: 0.6\r\n\t\t\t}),\r\n\r\n\t\t\tgreen: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [0.0, 1, 0.0],\r\n\t\t\t\temissive: [0.0, 1, 0.0],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80,\r\n\t\t\t\tlineWidth: 2\r\n\t\t\t}),\r\n\r\n\t\t\thighlightGreen: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t// Emphasis for green rotation affordance hoop\r\n\t\t\t\tedges: false,\r\n\t\t\t\tfill: true,\r\n\t\t\t\tfillColor: [0, 1, 0],\r\n\t\t\t\tfillAlpha: 0.6\r\n\t\t\t}),\r\n\r\n\t\t\tblue: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [0.0, 0.0, 1],\r\n\t\t\t\temissive: [0.0, 0.0, 1],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80,\r\n\t\t\t\tlineWidth: 2\r\n\t\t\t}),\r\n\r\n\t\t\thighlightBlue: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t// Emphasis for blue rotation affordance hoop\r\n\t\t\t\tedges: false,\r\n\t\t\t\tfill: true,\r\n\t\t\t\tfillColor: [0, 0, 1],\r\n\t\t\t\tfillAlpha: 0.2\r\n\t\t\t}),\r\n\r\n\t\t\tcenter: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\tdiffuse: [0.0, 0.0, 0.0],\r\n\t\t\t\temissive: [0, 0, 0],\r\n\t\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\t\tshininess: 80\r\n\t\t\t}),\r\n\r\n\t\t\thighlightBall: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\tedges: false,\r\n\t\t\t\tfill: true,\r\n\t\t\t\tfillColor: [0.5, 0.5, 0.5],\r\n\t\t\t\tfillAlpha: 0.5,\r\n\t\t\t\tvertices: false\r\n\t\t\t}),\r\n\r\n\t\t\thighlightPlane: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\tedges: true,\r\n\t\t\t\tedgeWidth: 3,\r\n\t\t\t\tfill: false,\r\n\t\t\t\tfillColor: [0.5, 0.5, 0.5],\r\n\t\t\t\tfillAlpha: 0.5,\r\n\t\t\t\tvertices: false\r\n\t\t\t})\r\n\t\t};\r\n\r\n\t\tthis._displayMeshes = {\r\n\t\t\tplane: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(rootNode, {\r\n\t\t\t\t\t\tprimitive: \"triangles\",\r\n\t\t\t\t\t\tpositions: [\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.0,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.0, // 0\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.0,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.0, // 1\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.0,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.0, // 2\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t-0.0,\r\n\t\t\t\t\t\t\t-0.5,\r\n\t\t\t\t\t\t\t0.5,\r\n\t\t\t\t\t\t\t-0.0 // 3\r\n\t\t\t\t\t\t],\r\n\t\t\t\t\t\tindices: [0, 1, 2, 2, 3, 0]\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\temissive: [0, 0.0, 0],\r\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\r\n\t\t\t\t\t\tbackfaces: true\r\n\t\t\t\t\t}),\r\n\t\t\t\t\topacity: 0.6,\r\n\t\t\t\t\tghosted: true,\r\n\t\t\t\t\tghostMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t\t\tedges: false,\r\n\t\t\t\t\t\tfilled: true,\r\n\t\t\t\t\t\tfillColor: [1, 1, 0],\r\n\t\t\t\t\t\tedgeColor: [0, 0, 0],\r\n\t\t\t\t\t\tfillAlpha: 0.1,\r\n\t\t\t\t\t\tbackfaces: true\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [2.4, 2.4, 1],\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tplaneFrame: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\t// Visible frame\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\t\t\trootNode,\r\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\r\n\t\t\t\t\t\t\tradius: 1.7,\r\n\t\t\t\t\t\t\ttube: tubeRadius * 2,\r\n\t\t\t\t\t\t\tradialSegments: 4,\r\n\t\t\t\t\t\t\ttubeSegments: 4,\r\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\temissive: [0, 0, 0],\r\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\r\n\t\t\t\t\t\tspecular: [0, 0, 0],\r\n\t\t\t\t\t\tshininess: 0\r\n\t\t\t\t\t}),\r\n\t\t\t\t\t//highlighted: true,\r\n\t\t\t\t\thighlightMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t\t\tedges: false,\r\n\t\t\t\t\t\tedgeColor: [0.0, 0.0, 0.0],\r\n\t\t\t\t\t\tfilled: true,\r\n\t\t\t\t\t\tfillColor: [0.8, 0.8, 0.8],\r\n\t\t\t\t\t\tfillAlpha: 1.0\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: false,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [1, 1, 0.1],\r\n\t\t\t\t\trotation: [0, 0, 45],\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\txCurve: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\t// Red hoop about Y-axis\r\n\t\t\t\t\tgeometry: shapes.curve,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst rotate2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 1, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(270 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate1, rotate2, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tbackfaces: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txCurveHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\t// Red hoop about Y-axis\r\n\t\t\t\t\tgeometry: shapes.curveHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst rotate2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 1, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(270 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate1, rotate2, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tbackfaces: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txCurveArrow1: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, -0.07, -0.8, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(0 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txCurveArrow2: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0.0, -0.8, -0.07, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\tyCurve: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.curve,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\trotation: [-90, 0, 0],\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tbackfaces: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyCurveHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.curveHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\trotation: [-90, 0, 0],\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tbackfaces: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyCurveArrow1: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0.07, 0, -0.8, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyCurveArrow2: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0.8, 0.0, -0.07, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\t// zCurve: rootNode.addChild(\r\n\t\t\t// \tnew Mesh(rootNode, {\r\n\t\t\t// \t\t// Blue hoop about Z-axis\r\n\t\t\t// \t\tgeometry: shapes.curve,\r\n\t\t\t// \t\tmaterial: materials.blue,\r\n\t\t\t// \t\tmatrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),\r\n\t\t\t// \t\tpickable: false,\r\n\t\t\t// \t\tcollidable: true,\r\n\t\t\t// \t\tclippable: false,\r\n\t\t\t// \t\tvisible: false,\r\n\t\t\t// \t\tisObject: false\r\n\t\t\t// \t}),\r\n\t\t\t// \tNO_STATE_INHERIT\r\n\t\t\t// ),\r\n\r\n\t\t\t// zCurveHandle: rootNode.addChild(\r\n\t\t\t// \tnew Mesh(rootNode, {\r\n\t\t\t// \t\tgeometry: shapes.curveHandle,\r\n\t\t\t// \t\tmaterial: materials.pickable,\r\n\t\t\t// \t\tmatrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),\r\n\t\t\t// \t\tpickable: true,\r\n\t\t\t// \t\tcollidable: true,\r\n\t\t\t// \t\tclippable: false,\r\n\t\t\t// \t\tvisible: false,\r\n\t\t\t// \t\tisObject: false\r\n\t\t\t// \t}),\r\n\t\t\t// \tNO_STATE_INHERIT\r\n\t\t\t// ),\r\n\r\n\t\t\t// zCurveCurveArrow1: rootNode.addChild(\r\n\t\t\t// \tnew Mesh(rootNode, {\r\n\t\t\t// \t\tgeometry: shapes.arrowHead,\r\n\t\t\t// \t\tmaterial: materials.blue,\r\n\t\t\t// \t\tmatrix: (function () {\r\n\t\t\t// \t\t\tconst translate = math.translateMat4c(0.8, -0.07, 0, math.identityMat4());\r\n\t\t\t// \t\t\tconst scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());\r\n\t\t\t// \t\t\treturn math.mulMat4(translate, scale, math.identityMat4());\r\n\t\t\t// \t\t})(),\r\n\t\t\t// \t\tpickable: true,\r\n\t\t\t// \t\tcollidable: true,\r\n\t\t\t// \t\tclippable: false,\r\n\t\t\t// \t\tvisible: false,\r\n\t\t\t// \t\tisObject: false\r\n\t\t\t// \t}),\r\n\t\t\t// \tNO_STATE_INHERIT\r\n\t\t\t// ),\r\n\r\n\t\t\t// zCurveArrow2: rootNode.addChild(\r\n\t\t\t// \tnew Mesh(rootNode, {\r\n\t\t\t// \t\tgeometry: shapes.arrowHead,\r\n\t\t\t// \t\tmaterial: materials.blue,\r\n\t\t\t// \t\tmatrix: (function () {\r\n\t\t\t// \t\t\tconst translate = math.translateMat4c(0.05, -0.8, 0, math.identityMat4());\r\n\t\t\t// \t\t\tconst scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());\r\n\t\t\t// \t\t\tconst rotate = math.rotationMat4v(90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());\r\n\t\t\t// \t\t\treturn math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());\r\n\t\t\t// \t\t})(),\r\n\t\t\t// \t\tpickable: true,\r\n\t\t\t// \t\tcollidable: true,\r\n\t\t\t// \t\tclippable: false,\r\n\t\t\t// \t\tvisible: false,\r\n\t\t\t// \t\tisObject: false\r\n\t\t\t// \t}),\r\n\t\t\t// \tNO_STATE_INHERIT\r\n\t\t\t// ),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\tcenter: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\t\t\trootNode,\r\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildSphereGeometry)({\r\n\t\t\t\t\t\t\tradius: 0.05\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t),\r\n\t\t\t\t\tmaterial: materials.center,\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\txAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txAxisArrowHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txAxis: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axis,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txAxisHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axisHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\tyAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyAxisArrowHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\topacity: 0.2,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyShaft: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axis,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\tposition: [0, -radius / 2, 0],\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyShaftHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axisHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tposition: [0, -radius / 2, 0],\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\t\t\t//\r\n\t\t\t//----------------------------------------------------------------------------------------------------------\r\n\r\n\t\t\tzAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHead,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzAxisArrowHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzShaft: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axis,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzAxisHandle: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.axisHandle,\r\n\t\t\t\t\tmaterial: materials.pickable,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tpickable: true,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t)\r\n\t\t};\r\n\r\n\t\tthis._affordanceMeshes = {\r\n\t\t\tplaneFrame: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\r\n\t\t\t\t\t\trootNode,\r\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\r\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\r\n\t\t\t\t\t\t\tradius: 2,\r\n\t\t\t\t\t\t\ttube: tubeRadius,\r\n\t\t\t\t\t\t\tradialSegments: 4,\r\n\t\t\t\t\t\t\ttubeSegments: 4,\r\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t),\r\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\r\n\t\t\t\t\t\tambient: [1, 1, 1],\r\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\r\n\t\t\t\t\t\temissive: [1, 1, 0]\r\n\t\t\t\t\t}),\r\n\t\t\t\t\thighlighted: true,\r\n\t\t\t\t\thighlightMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\r\n\t\t\t\t\t\tedges: false,\r\n\t\t\t\t\t\tfilled: true,\r\n\t\t\t\t\t\tfillColor: [1, 1, 0],\r\n\t\t\t\t\t\tfillAlpha: 1.0\r\n\t\t\t\t\t}),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: false,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tscale: [1, 1, 1],\r\n\t\t\t\t\trotation: [0, 0, 45],\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txHoop: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\t// Full\r\n\t\t\t\t\tgeometry: shapes.hoop,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\thighlighted: true,\r\n\t\t\t\t\thighlightMaterial: materials.highlightRed,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst rotate2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 1, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(270 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate1, rotate2, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyHoop: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.hoop,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\thighlighted: true,\r\n\t\t\t\t\thighlightMaterial: materials.highlightGreen,\r\n\t\t\t\t\trotation: [-90, 0, 0],\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzHoop: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\t// Blue hoop about Z-axis\r\n\t\t\t\t\tgeometry: shapes.hoop,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\thighlighted: true,\r\n\t\t\t\t\thighlightMaterial: materials.highlightBlue,\r\n\t\t\t\t\tmatrix: _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tbackfaces: true,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\txAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\r\n\t\t\t\t\tmaterial: materials.red,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tyAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\r\n\t\t\t\t\tmaterial: materials.green,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t),\r\n\r\n\t\t\tzAxisArrow: rootNode.addChild(\r\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\r\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\r\n\t\t\t\t\tmaterial: materials.blue,\r\n\t\t\t\t\tmatrix: (function () {\r\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n\t\t\t\t\t})(),\r\n\t\t\t\t\tpickable: false,\r\n\t\t\t\t\tcollidable: true,\r\n\t\t\t\t\tclippable: false,\r\n\t\t\t\t\tvisible: false,\r\n\t\t\t\t\tisObject: false\r\n\t\t\t\t}),\r\n\t\t\t\tNO_STATE_INHERIT\r\n\t\t\t)\r\n\t\t};\r\n\t}\r\n\r\n\t_bindEvents() {\r\n\t\tconst self = this;\r\n\r\n\t\tvar grabbed = false;\r\n\r\n\t\tconst DRAG_ACTIONS = {\r\n\t\t\tnone: -1,\r\n\t\t\txTranslate: 0,\r\n\t\t\tyTranslate: 1,\r\n\t\t\tzTranslate: 2,\r\n\t\t\txRotate: 3,\r\n\t\t\tyRotate: 4,\r\n\t\t\tzRotate: 5\r\n\t\t};\r\n\r\n\t\tconst rootNode = this._rootNode;\r\n\r\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\r\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\r\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\r\n\t\tconst xBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([1, 0, 0]);\r\n\t\tconst yBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 1, 0]);\r\n\t\tconst zBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 1]);\r\n\r\n\t\tconst canvas = this._viewer.scene.canvas.canvas;\r\n\t\tconst camera = this._viewer.camera;\r\n\t\tconst scene = this._viewer.scene;\r\n\r\n\t\t{\r\n\t\t\t// Keep gizmo screen size constant\r\n\r\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\r\n\r\n\t\t\tlet distDirty = true;\r\n\t\t\tlet lastDist = -1;\r\n\r\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\r\n\t\t\t\tdistDirty = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\r\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\r\n\r\n\t\t\t\tif (dist !== lastDist) {\r\n\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\r\n\t\t\t\t\t\tconst size = 0.07 * worldSize;\r\n\t\t\t\t\t\trootNode.scale = [size, size, size];\r\n\t\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (camera.projection === \"ortho\") {\r\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\r\n\t\t\t\t\tconst size = worldSize;\r\n\t\t\t\t\trootNode.scale = [size, size, size];\r\n\t\t\t\t\tlastDist = dist;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tconst getClickCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t\tcanvasPos[0] = event.x;\r\n\t\t\t\t\tcanvasPos[1] = event.y;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst getTouchCoordsWithinElement = (function () {\r\n\t\t\tconst canvasPos = new Float64Array(2);\r\n\t\t\treturn function (event) {\r\n\t\t\t\tif (!event) {\r\n\t\t\t\t\tevent = window.event;\r\n\t\t\t\t}\r\n\t\t\t\tif (event.touches && event.touches.length) {\r\n\t\t\t\t\t// 如果有触摸事件,使用第一个触摸点的坐标\r\n\t\t\t\t\tcanvasPos[0] = event.touches[0].pageX;\r\n\t\t\t\t\tcanvasPos[1] = event.touches[0].pageY;\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// 否则,假设是鼠标事件\r\n\t\t\t\t\tvar element = event.target;\r\n\t\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\t\tvar totalOffsetTop = 0;\r\n\r\n\t\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t\t\t}\r\n\t\t\t\treturn canvasPos;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst localToWorldVec = (function () {\r\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function (localVec, worldVec) {\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(self._rootNode.quaternion, mat);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, localVec, worldVec);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(worldVec);\r\n\t\t\t\treturn worldVec;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar getTranslationPlane = (function () {\r\n\t\t\tconst planeNormal = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\treturn function (worldAxis) {\r\n\t\t\t\tconst absX = Math.abs(worldAxis[0]);\r\n\t\t\t\tif (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);\r\n\t\t\t\t}\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(planeNormal, worldAxis, planeNormal);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(planeNormal);\r\n\t\t\t\treturn planeNormal;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst dragTranslateSectionPlane = (function () {\r\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\r\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\r\n\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\r\n\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1);\r\n\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(p2, p1);\r\n\t\t\t\tconst dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\r\n\t\t\t\tself._pos[0] += worldAxis[0] * dot;\r\n\t\t\t\tself._pos[1] += worldAxis[1] * dot;\r\n\t\t\t\tself._pos[2] += worldAxis[2] * dot;\r\n\t\t\t\tself._rootNode.position = self._pos;\r\n\t\t\t\tif (self._sectionPlane) {\r\n\t\t\t\t\tself._sectionPlane.pos = self._pos;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar dragRotateSectionPlane = (function () {\r\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\tconst c = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\r\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\r\n\t\t\t\tconst hasData =\r\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);\r\n\t\t\t\tif (!hasData) {\r\n\t\t\t\t\t// Find intersections with view plane and project down to origin\r\n\t\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\r\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable\r\n\t\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2, 1);\r\n\t\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, worldAxis);\r\n\t\t\t\t\tp1[0] -= dot * worldAxis[0];\r\n\t\t\t\t\tp1[1] -= dot * worldAxis[1];\r\n\t\t\t\t\tp1[2] -= dot * worldAxis[2];\r\n\t\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\r\n\t\t\t\t\tp2[0] -= dot * worldAxis[0];\r\n\t\t\t\t\tp2[1] -= dot * worldAxis[1];\r\n\t\t\t\t\tp2[2] -= dot * worldAxis[2];\r\n\t\t\t\t}\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p1);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p2);\r\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, p2);\r\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range\r\n\t\t\t\tvar incDegrees = Math.acos(dot) * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.RADTODEG;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(p1, p2, c);\r\n\t\t\t\tif (_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(c, worldAxis) < 0.0) {\r\n\t\t\t\t\tincDegrees = -incDegrees;\r\n\t\t\t\t}\r\n\t\t\t\tself._rootNode.rotate(baseAxis, incDegrees);\r\n\t\t\t\trotateSectionPlane();\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tvar getPointerPlaneIntersect = (function () {\r\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4([0, 0, 0, 1]);\r\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function (mouse, axis, dest, offset) {\r\n\t\t\t\toffset = offset || 0;\r\n\t\t\t\tdir[0] = (mouse[0] / canvas.width) * 2.0 - 1.0;\r\n\t\t\t\tdir[1] = -((mouse[1] / canvas.height) * 2.0 - 1.0);\r\n\t\t\t\tdir[2] = 0.0;\r\n\t\t\t\tdir[3] = 1.0;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(matrix);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec4(matrix, dir, dir);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space\r\n\t\t\t\tvar rayO = camera.eye; // The direction\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec4(dir, rayO, dir);\r\n\t\t\t\tconst origin = self._sectionPlane.pos; // Plane origin:\r\n\t\t\t\tvar d = -_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(origin, axis) - offset;\r\n\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, dir);\r\n\t\t\t\tif (Math.abs(dot) > 0.005) {\r\n\t\t\t\t\tvar t = -(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, rayO) + d) / dot;\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, t, dest);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(dest, rayO);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(dest, origin, dest);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\treturn false;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tconst rotateSectionPlane = (function () {\r\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n\t\t\treturn function () {\r\n\t\t\t\tif (self.sectionPlane) {\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(rootNode.quaternion, mat); // << ---\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, [0, 0, 1], dir);\r\n\t\t\t\t\tself._setSectionPlaneDir(dir);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t{\r\n\t\t\tvar mouseDownLeft;\r\n\t\t\tvar mouseDownMiddle;\r\n\t\t\tvar mouseDownRight;\r\n\t\t\tvar down = false;\r\n\t\t\tvar lastAffordanceMesh;\r\n\r\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"hoverEnter\", (hit) => {\r\n\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (down) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tgrabbed = false;\r\n\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t}\r\n\t\t\t\tvar affordanceMesh;\r\n\t\t\t\tconst meshId = hit.entity.id;\r\n\t\t\t\tswitch (meshId) {\r\n\t\t\t\t\tcase this._displayMeshes.xAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xAxisHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yShaftHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.zAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.zAxisHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xCurveHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xHoop;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xRotate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yCurveHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yHoop;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yRotate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.zCurveHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zHoop;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zRotate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\r\n\t\t\t\t}\r\n\t\t\t\tif (affordanceMesh) {\r\n\t\t\t\t\taffordanceMesh.visible = true;\r\n\t\t\t\t}\r\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\r\n\t\t\t\tgrabbed = true;\r\n\t\t\t});\r\n\r\n\t\t\tthis._onCameraControlHoverLeave = this._viewer.cameraControl.on(\"hoverOutEntity\", (hit) => {\r\n\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t}\r\n\t\t\t\tlastAffordanceMesh = null;\r\n\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t});\r\n\r\n\t\t\t//mousedown\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mousedown\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible || !grabbed) return;\r\n\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = true;\r\n\t\t\t\t\t\t\tdown = true;\r\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//mousemove\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mousemove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\r\n\t\t\t\t\tswitch (dragAction) {\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//mouseup\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\tif (!down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tgrabbed = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\t//wheel\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"wheel\",\r\n\t\t\t\t(this._canvasWheelListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\r\n\t\t\t\t\tif (delta === 0) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"touchEntity\", (hit) => {\r\n\t\t\t\tif (!this._visible || down || grabbed) return;\r\n\t\t\t\tgrabbed = false;\r\n\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t}\r\n\t\t\t\tvar affordanceMesh;\r\n\t\t\t\tconst meshId = hit.entity.id;\r\n\t\t\t\tswitch (meshId) {\r\n\t\t\t\t\tcase this._displayMeshes.xAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xAxisHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yShaftHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.zAxisArrowHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.zAxisHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.xCurveHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xHoop;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xRotate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase this._displayMeshes.yCurveHandle.id:\r\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yHoop;\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yRotate;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t// case this._displayMeshes.zCurveHandle.id:\r\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zHoop;\r\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zRotate;\r\n\t\t\t\t\t// \tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\r\n\t\t\t\t}\r\n\t\t\t\tif (affordanceMesh) {\r\n\t\t\t\t\taffordanceMesh.visible = true;\r\n\t\t\t\t}\r\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\r\n\t\t\t\tgrabbed = true;\r\n\t\t\t});\r\n\t\t\t//touchstart\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchstart\",\r\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tif (!this._visible || !grabbed) return;\r\n\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\r\n\t\t\t\t\tdown = true;\r\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\r\n\t\t\t\t\tdragAction = nextDragAction;\r\n\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\r\n\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//touchmove\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchmove\",\r\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\r\n\t\t\t\t\tif (!this._visible || !down) return;\r\n\r\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\r\n\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\tconst y = canvasPos[1];\r\n\r\n\t\t\t\t\tswitch (dragAction) {\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\r\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\r\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlastCanvasPos[0] = x;\r\n\t\t\t\t\tlastCanvasPos[1] = y;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\t//touchend\r\n\t\t\tcanvas.addEventListener(\r\n\t\t\t\t\"touchend\",\r\n\t\t\t\t(this._canvasTouchEndListener = (e) => {\r\n\t\t\t\t\tif (!this._visible) return;\r\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\r\n\t\t\t\t\tif (lastAffordanceMesh) {\r\n\t\t\t\t\t\tlastAffordanceMesh.visible = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlastAffordanceMesh = null;\r\n\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tgrabbed = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t\tcanvas.addEventListener(\"touchcancel\", this._canvasTouchEndListener);\r\n\t\t}\r\n\t}\r\n\r\n\t_destroy() {\r\n\t\tthis._unbindEvents();\r\n\t\tthis._destroyNodes();\r\n\t}\r\n\r\n\t_unbindEvents() {\r\n\t\tconst viewer = this._viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst canvas = scene.canvas.canvas;\r\n\t\tconst camera = viewer.camera;\r\n\t\tconst cameraControl = viewer.cameraControl;\r\n\r\n\t\tscene.off(this._onSceneTick);\r\n\r\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\r\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\r\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\r\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\r\n\t\tcanvas.removeEventListener(\"touchend\", this._canvasTouchEndListener);\r\n\t\tcanvas.removeEventListener(\"touchcancel\", this._canvasTouchEndListener);\r\n\r\n\t\tcamera.off(this._onCameraViewMatrix);\r\n\t\tcamera.off(this._onCameraProjMatrix);\r\n\r\n\t\tcameraControl.off(this._onCameraControlHover);\r\n\t\tcameraControl.off(this._onCameraControlHoverLeave);\r\n\t}\r\n\r\n\t_destroyNodes() {\r\n\t\tthis._setSectionPlane(null);\r\n\t\tthis._rootNode.destroy();\r\n\t\tthis._displayMeshes = {};\r\n\t\tthis._affordanceMeshes = {};\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/Control.js?");
|
|
1907
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Control: () => (/* binding */ Control)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildTorusGeometry.js */ \"./src/viewer/scene/geometry/builders/buildTorusGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst zeroVec = new Float64Array([0, 0, 1]);\nconst quat = new Float64Array(4);\n\n/**\n * Controls a {@link SectionPlane} with mouse and touch input.\n *\n * @private\n */\nclass Control {\n\t/** @private */\n\tconstructor(plugin) {\n\t\t/**\n\t\t * ID of this Control.\n\t\t *\n\t\t * SectionPlaneControls are mapped by this ID in {@link SectionPlanesPlugin#sectionPlaneControls}.\n\t\t *\n\t\t * @property id\n\t\t * @type {String|Number}\n\t\t */\n\t\tthis.id = null;\n\t\tthis.type = \"control\";\n\n\t\tthis._viewer = plugin.viewer;\n\t\tthis._scene = plugin.viewer.scene;\n\n\t\tthis._visible = false;\n\t\tthis._pos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Full-precision position of the center of the Control\n\t\tthis._origin = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tthis._rtcPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\n\t\tthis._baseDir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.\n\t\tthis._rootNode = null; // Root of Node graph that represents this control in the 3D scene\n\t\tthis._displayMeshes = null; // Meshes that are always visible\n\t\tthis._affordanceMeshes = null; // Meshes displayed momentarily for affordance\n\n\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\n\t\tthis._createNodes();\n\t\tthis._bindEvents();\n\t}\n\n\t/**\n\t * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.\n\t * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.\n\t * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.\n\t * @private\n\t */\n\t_setSectionPlane(sectionPlane) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._sectionPlane.off(this._onSectionPlanePos);\n\t\t\tthis._sectionPlane.off(this._onSectionPlaneDir);\n\t\t\tthis._onSectionPlanePos = null;\n\t\t\tthis._onSectionPlaneDir = null;\n\t\t\tthis._sectionPlane = null;\n\t\t}\n\t\tif (sectionPlane) {\n\t\t\tthis.id = sectionPlane.id;\n\t\t\tthis._setPos(sectionPlane.pos);\n\t\t\tthis._setDir(sectionPlane.dir);\n\t\t\tthis._sectionPlane = sectionPlane;\n\t\t\tthis._onSectionPlanePos = sectionPlane.on(\"pos\", () => {\n\t\t\t\tthis._setPos(this._sectionPlane.pos);\n\t\t\t});\n\t\t\tthis._onSectionPlaneDir = sectionPlane.on(\"dir\", () => {\n\t\t\t\tif (!this._ignoreNextSectionPlaneDirUpdate) {\n\t\t\t\t\tthis._setDir(this._sectionPlane.dir);\n\t\t\t\t} else {\n\t\t\t\t\tthis._ignoreNextSectionPlaneDirUpdate = false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Gets the {@link SectionPlane} controlled by this Control.\n\t * @returns {SectionPlane} The SectionPlane.\n\t */\n\tget sectionPlane() {\n\t\treturn this._sectionPlane;\n\t}\n\n\t/**\n\t * 设置剖切面位置\n\t * @param {any} value\n\t */\n\tset pos(posRate) {\n\t\tif (posRate < 0 || posRate > 100) return;\n\n\t\tconst { aabb } = this._scene;\n\t\tconst { look } = this._scene.camera;\n\t\tconst xRange = aabb[3] - aabb[0]; //前后\n\t\tconst yRange = aabb[4] - aabb[1]; //上下\n\t\tconst zRange = aabb[5] - aabb[2]; //左右\n\n\t\tconst newSectionPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\tnewSectionPos[0] = this.pos[0];\n\t\tnewSectionPos[1] = this.pos[1];\n\t\tnewSectionPos[2] = this.pos[2];\n\n\t\tconst { dir } = this._sectionPlane;\n\t\tlet rateDis;\n\t\tif (dir[0] != 0) {\n\t\t\trateDis = (posRate / 100) * xRange;\n\t\t\tnewSectionPos[0] = look[0] - xRange / 2 + rateDis;\n\t\t} else if (dir[1] != 0) {\n\t\t\trateDis = (posRate / 100) * yRange;\n\t\t\tnewSectionPos[1] = look[1] - yRange / 2 + rateDis;\n\t\t} else if (dir[2] != 0) {\n\t\t\trateDis = (posRate / 100) * zRange;\n\t\t\tnewSectionPos[2] = look[2] - zRange / 2 + rateDis;\n\t\t}\n\n\t\tthis._sectionPlane.pos = newSectionPos;\n\t}\n\n\tget pos() {\n\t\treturn this._pos;\n\t}\n\n\t/** @private */\n\t_setPos(xyz) {\n\t\tthis._pos.set(xyz);\n\n\t\t(0,_viewer_scene_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_9__.worldToRTCPos)(this._pos, this._origin, this._rtcPos);\n\n\t\tthis._rootNode.origin = this._origin;\n\t\tthis._rootNode.position = this._rtcPos;\n\t}\n\n\t/** @private */\n\t_setDir(xyz) {\n\t\tthis._baseDir.set(xyz);\n\t\tthis._rootNode.quaternion = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3PairToQuaternion(zeroVec, xyz, quat);\n\t}\n\n\t_setSectionPlaneDir(dir) {\n\t\tif (this._sectionPlane) {\n\t\t\tthis._ignoreNextSectionPlaneDirUpdate = true;\n\t\t\tthis._sectionPlane.dir = dir;\n\t\t}\n\t}\n\n\t/**\n\t * Sets if this Control is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tsetVisible(visible = true) {\n\t\tif (this._visible === visible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._visible = visible;\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].visible = visible;\n\t\t\t}\n\t\t}\n\t\tif (!visible) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].visible = visible;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this Control is visible.\n\t *\n\t * @type {Boolean}\n\t */\n\tgetVisible() {\n\t\treturn this._visible;\n\t}\n\n\t/**\n\t * Sets if this Control is culled. This is called by SectionPlanesPlugin to\n\t * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().\n\t * @param culled\n\t */\n\tsetCulled(culled) {\n\t\tvar id;\n\t\tfor (id in this._displayMeshes) {\n\t\t\tif (this._displayMeshes.hasOwnProperty(id)) {\n\t\t\t\tthis._displayMeshes[id].culled = culled;\n\t\t\t}\n\t\t}\n\t\tif (!culled) {\n\t\t\tfor (id in this._affordanceMeshes) {\n\t\t\t\tif (this._affordanceMeshes.hasOwnProperty(id)) {\n\t\t\t\t\tthis._affordanceMeshes[id].culled = culled;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Builds the Entities that represent this Control.\n\t * @private\n\t */\n\t_createNodes() {\n\t\tconst NO_STATE_INHERIT = false;\n\t\tconst scene = this._viewer.scene;\n\t\tconst radius = 1.0;\n\t\tconst handleTubeRadius = 0.06;\n\t\tconst hoopRadius = radius - 0.2;\n\t\tconst tubeRadius = 0.01;\n\t\tconst arrowRadius = 0.07;\n\n\t\tthis._rootNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_6__.Node(scene, {\n\t\t\tposition: [0, 0, 0],\n\t\t\tscale: [5, 5, 5],\n\t\t\tisObject: false\n\t\t});\n\n\t\tconst rootNode = this._rootNode;\n\n\t\tconst shapes = {\n\t\t\t// Reusable geometries\n\n\t\t\tarrowHead: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: 0.001,\n\t\t\t\t\tradiusBottom: arrowRadius,\n\t\t\t\t\tradialSegments: 32,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: 0.2,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t),\n\n\t\t\tarrowHeadBig: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: 0.001,\n\t\t\t\t\tradiusBottom: 0.09,\n\t\t\t\t\tradialSegments: 32,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: 0.25,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t),\n\n\t\t\tarrowHeadHandle: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: 0.09,\n\t\t\t\t\tradiusBottom: 0.09,\n\t\t\t\t\tradialSegments: 8,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: 0.37,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t),\n\n\t\t\tcurve: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\tradius: hoopRadius,\n\t\t\t\t\ttube: tubeRadius,\n\t\t\t\t\tradialSegments: 64,\n\t\t\t\t\ttubeSegments: 14,\n\t\t\t\t\tarc: (Math.PI * 2.0) / 4.0\n\t\t\t\t})\n\t\t\t),\n\n\t\t\tcurveHandle: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\tradius: hoopRadius,\n\t\t\t\t\ttube: handleTubeRadius,\n\t\t\t\t\tradialSegments: 64,\n\t\t\t\t\ttubeSegments: 14,\n\t\t\t\t\tarc: (Math.PI * 2.0) / 4.0\n\t\t\t\t})\n\t\t\t),\n\n\t\t\thoop: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\tradius: hoopRadius,\n\t\t\t\t\ttube: tubeRadius,\n\t\t\t\t\tradialSegments: 64,\n\t\t\t\t\ttubeSegments: 8,\n\t\t\t\t\tarc: Math.PI * 2.0\n\t\t\t\t})\n\t\t\t),\n\n\t\t\taxis: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: tubeRadius,\n\t\t\t\t\tradiusBottom: tubeRadius,\n\t\t\t\t\tradialSegments: 20,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: radius,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t),\n\n\t\t\taxisHandle: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\trootNode,\n\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_1__.buildCylinderGeometry)({\n\t\t\t\t\tradiusTop: 0.08,\n\t\t\t\t\tradiusBottom: 0.08,\n\t\t\t\t\tradialSegments: 20,\n\t\t\t\t\theightSegments: 1,\n\t\t\t\t\theight: radius,\n\t\t\t\t\topenEnded: false\n\t\t\t\t})\n\t\t\t)\n\t\t};\n\n\t\tconst materials = {\n\t\t\t// Reusable materials\n\n\t\t\tpickable: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t// Invisible material for pickable handles, which define a pickable 3D area\n\t\t\t\tdiffuse: [1, 1, 0],\n\t\t\t\talpha: 0, // Invisible\n\t\t\t\talphaMode: \"blend\"\n\t\t\t}),\n\n\t\t\tred: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [1, 0.0, 0.0],\n\t\t\t\temissive: [1, 0.0, 0.0],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80,\n\t\t\t\tlineWidth: 2\n\t\t\t}),\n\n\t\t\thighlightRed: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t// Emphasis for red rotation affordance hoop\n\t\t\t\tedges: false,\n\t\t\t\tfill: true,\n\t\t\t\tfillColor: [1, 0, 0],\n\t\t\t\tfillAlpha: 0.6\n\t\t\t}),\n\n\t\t\tgreen: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [0.0, 1, 0.0],\n\t\t\t\temissive: [0.0, 1, 0.0],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80,\n\t\t\t\tlineWidth: 2\n\t\t\t}),\n\n\t\t\thighlightGreen: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t// Emphasis for green rotation affordance hoop\n\t\t\t\tedges: false,\n\t\t\t\tfill: true,\n\t\t\t\tfillColor: [0, 1, 0],\n\t\t\t\tfillAlpha: 0.6\n\t\t\t}),\n\n\t\t\tblue: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [0.0, 0.0, 1],\n\t\t\t\temissive: [0.0, 0.0, 1],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80,\n\t\t\t\tlineWidth: 2\n\t\t\t}),\n\n\t\t\thighlightBlue: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t// Emphasis for blue rotation affordance hoop\n\t\t\t\tedges: false,\n\t\t\t\tfill: true,\n\t\t\t\tfillColor: [0, 0, 1],\n\t\t\t\tfillAlpha: 0.2\n\t\t\t}),\n\n\t\t\tcenter: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\tdiffuse: [0.0, 0.0, 0.0],\n\t\t\t\temissive: [0, 0, 0],\n\t\t\t\tambient: [0.0, 0.0, 0.0],\n\t\t\t\tspecular: [0.6, 0.6, 0.3],\n\t\t\t\tshininess: 80\n\t\t\t}),\n\n\t\t\thighlightBall: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\tedges: false,\n\t\t\t\tfill: true,\n\t\t\t\tfillColor: [0.5, 0.5, 0.5],\n\t\t\t\tfillAlpha: 0.5,\n\t\t\t\tvertices: false\n\t\t\t}),\n\n\t\t\thighlightPlane: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\tedges: true,\n\t\t\t\tedgeWidth: 3,\n\t\t\t\tfill: false,\n\t\t\t\tfillColor: [0.5, 0.5, 0.5],\n\t\t\t\tfillAlpha: 0.5,\n\t\t\t\tvertices: false\n\t\t\t})\n\t\t};\n\n\t\tthis._displayMeshes = {\n\t\t\tplane: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(rootNode, {\n\t\t\t\t\t\tprimitive: \"triangles\",\n\t\t\t\t\t\tpositions: [\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.0,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.0, // 0\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.0,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.0, // 1\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.0,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.0, // 2\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t-0.0,\n\t\t\t\t\t\t\t-0.5,\n\t\t\t\t\t\t\t0.5,\n\t\t\t\t\t\t\t-0.0 // 3\n\t\t\t\t\t\t],\n\t\t\t\t\t\tindices: [0, 1, 2, 2, 3, 0]\n\t\t\t\t\t}),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\temissive: [0, 0.0, 0],\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\n\t\t\t\t\t\tbackfaces: true\n\t\t\t\t\t}),\n\t\t\t\t\topacity: 0.6,\n\t\t\t\t\tghosted: true,\n\t\t\t\t\tghostMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t\t\tedges: false,\n\t\t\t\t\t\tfilled: true,\n\t\t\t\t\t\tfillColor: [1, 1, 0],\n\t\t\t\t\t\tedgeColor: [0, 0, 0],\n\t\t\t\t\t\tfillAlpha: 0.1,\n\t\t\t\t\t\tbackfaces: true\n\t\t\t\t\t}),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [2.4, 2.4, 1],\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tplaneFrame: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\t// Visible frame\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\t\t\trootNode,\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\n\t\t\t\t\t\t\tradius: 1.7,\n\t\t\t\t\t\t\ttube: tubeRadius * 2,\n\t\t\t\t\t\t\tradialSegments: 4,\n\t\t\t\t\t\t\ttubeSegments: 4,\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\temissive: [0, 0, 0],\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\n\t\t\t\t\t\tspecular: [0, 0, 0],\n\t\t\t\t\t\tshininess: 0\n\t\t\t\t\t}),\n\t\t\t\t\t//highlighted: true,\n\t\t\t\t\thighlightMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t\t\tedges: false,\n\t\t\t\t\t\tedgeColor: [0.0, 0.0, 0.0],\n\t\t\t\t\t\tfilled: true,\n\t\t\t\t\t\tfillColor: [0.8, 0.8, 0.8],\n\t\t\t\t\t\tfillAlpha: 1.0\n\t\t\t\t\t}),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: false,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [1, 1, 0.1],\n\t\t\t\t\trotation: [0, 0, 45],\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\txCurve: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\t// Red hoop about Y-axis\n\t\t\t\t\tgeometry: shapes.curve,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst rotate2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 1, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(270 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate1, rotate2, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tbackfaces: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txCurveHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\t// Red hoop about Y-axis\n\t\t\t\t\tgeometry: shapes.curveHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst rotate2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 1, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(270 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate1, rotate2, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tbackfaces: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txCurveArrow1: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, -0.07, -0.8, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(0 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txCurveArrow2: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0.0, -0.8, -0.07, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\tyCurve: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.curve,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\trotation: [-90, 0, 0],\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tbackfaces: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyCurveHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.curveHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\trotation: [-90, 0, 0],\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tbackfaces: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyCurveArrow1: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0.07, 0, -0.8, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyCurveArrow2: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0.8, 0.0, -0.07, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst scale = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.scaleMat4v([0.6, 0.6, 0.6], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()), rotate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\t// zCurve: rootNode.addChild(\n\t\t\t// \tnew Mesh(rootNode, {\n\t\t\t// \t\t// Blue hoop about Z-axis\n\t\t\t// \t\tgeometry: shapes.curve,\n\t\t\t// \t\tmaterial: materials.blue,\n\t\t\t// \t\tmatrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),\n\t\t\t// \t\tpickable: false,\n\t\t\t// \t\tcollidable: true,\n\t\t\t// \t\tclippable: false,\n\t\t\t// \t\tvisible: false,\n\t\t\t// \t\tisObject: false\n\t\t\t// \t}),\n\t\t\t// \tNO_STATE_INHERIT\n\t\t\t// ),\n\n\t\t\t// zCurveHandle: rootNode.addChild(\n\t\t\t// \tnew Mesh(rootNode, {\n\t\t\t// \t\tgeometry: shapes.curveHandle,\n\t\t\t// \t\tmaterial: materials.pickable,\n\t\t\t// \t\tmatrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),\n\t\t\t// \t\tpickable: true,\n\t\t\t// \t\tcollidable: true,\n\t\t\t// \t\tclippable: false,\n\t\t\t// \t\tvisible: false,\n\t\t\t// \t\tisObject: false\n\t\t\t// \t}),\n\t\t\t// \tNO_STATE_INHERIT\n\t\t\t// ),\n\n\t\t\t// zCurveCurveArrow1: rootNode.addChild(\n\t\t\t// \tnew Mesh(rootNode, {\n\t\t\t// \t\tgeometry: shapes.arrowHead,\n\t\t\t// \t\tmaterial: materials.blue,\n\t\t\t// \t\tmatrix: (function () {\n\t\t\t// \t\t\tconst translate = math.translateMat4c(0.8, -0.07, 0, math.identityMat4());\n\t\t\t// \t\t\tconst scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());\n\t\t\t// \t\t\treturn math.mulMat4(translate, scale, math.identityMat4());\n\t\t\t// \t\t})(),\n\t\t\t// \t\tpickable: true,\n\t\t\t// \t\tcollidable: true,\n\t\t\t// \t\tclippable: false,\n\t\t\t// \t\tvisible: false,\n\t\t\t// \t\tisObject: false\n\t\t\t// \t}),\n\t\t\t// \tNO_STATE_INHERIT\n\t\t\t// ),\n\n\t\t\t// zCurveArrow2: rootNode.addChild(\n\t\t\t// \tnew Mesh(rootNode, {\n\t\t\t// \t\tgeometry: shapes.arrowHead,\n\t\t\t// \t\tmaterial: materials.blue,\n\t\t\t// \t\tmatrix: (function () {\n\t\t\t// \t\t\tconst translate = math.translateMat4c(0.05, -0.8, 0, math.identityMat4());\n\t\t\t// \t\t\tconst scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());\n\t\t\t// \t\t\tconst rotate = math.rotationMat4v(90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());\n\t\t\t// \t\t\treturn math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());\n\t\t\t// \t\t})(),\n\t\t\t// \t\tpickable: true,\n\t\t\t// \t\tcollidable: true,\n\t\t\t// \t\tclippable: false,\n\t\t\t// \t\tvisible: false,\n\t\t\t// \t\tisObject: false\n\t\t\t// \t}),\n\t\t\t// \tNO_STATE_INHERIT\n\t\t\t// ),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\tcenter: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\t\t\trootNode,\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildSphereGeometry)({\n\t\t\t\t\t\t\tradius: 0.05\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tmaterial: materials.center,\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\txAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txAxisArrowHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txAxis: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axis,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txAxisHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axisHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\tyAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyAxisArrowHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\topacity: 0.2,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyShaft: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axis,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\tposition: [0, -radius / 2, 0],\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyShaftHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axisHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tposition: [0, -radius / 2, 0],\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\t\t\t//\n\t\t\t//----------------------------------------------------------------------------------------------------------\n\n\t\t\tzAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHead,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzAxisArrowHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzShaft: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axis,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzAxisHandle: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.axisHandle,\n\t\t\t\t\tmaterial: materials.pickable,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius / 2, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tpickable: true,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t)\n\t\t};\n\n\t\tthis._affordanceMeshes = {\n\t\t\tplaneFrame: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_3__.ReadableGeometry(\n\t\t\t\t\t\trootNode,\n\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildTorusGeometry_js__WEBPACK_IMPORTED_MODULE_2__.buildTorusGeometry)({\n\t\t\t\t\t\t\tcenter: [0, 0, 0],\n\t\t\t\t\t\t\tradius: 2,\n\t\t\t\t\t\t\ttube: tubeRadius,\n\t\t\t\t\t\t\tradialSegments: 4,\n\t\t\t\t\t\t\ttubeSegments: 4,\n\t\t\t\t\t\t\tarc: Math.PI * 2.0\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_4__.PhongMaterial(rootNode, {\n\t\t\t\t\t\tambient: [1, 1, 1],\n\t\t\t\t\t\tdiffuse: [0, 0, 0],\n\t\t\t\t\t\temissive: [1, 1, 0]\n\t\t\t\t\t}),\n\t\t\t\t\thighlighted: true,\n\t\t\t\t\thighlightMaterial: new _viewer_scene_materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_5__.EmphasisMaterial(rootNode, {\n\t\t\t\t\t\tedges: false,\n\t\t\t\t\t\tfilled: true,\n\t\t\t\t\t\tfillColor: [1, 1, 0],\n\t\t\t\t\t\tfillAlpha: 1.0\n\t\t\t\t\t}),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: false,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tscale: [1, 1, 1],\n\t\t\t\t\trotation: [0, 0, 45],\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txHoop: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\t// Full\n\t\t\t\t\tgeometry: shapes.hoop,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\thighlighted: true,\n\t\t\t\t\thighlightMaterial: materials.highlightRed,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst rotate2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 1, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(270 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate1, rotate2, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyHoop: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.hoop,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\thighlighted: true,\n\t\t\t\t\thighlightMaterial: materials.highlightGreen,\n\t\t\t\t\trotation: [-90, 0, 0],\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzHoop: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\t// Blue hoop about Z-axis\n\t\t\t\t\tgeometry: shapes.hoop,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\thighlighted: true,\n\t\t\t\t\thighlightMaterial: materials.highlightBlue,\n\t\t\t\t\tmatrix: _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4()),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tbackfaces: true,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\txAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\n\t\t\t\t\tmaterial: materials.red,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0, 0, 1], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tyAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\n\t\t\t\t\tmaterial: materials.green,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(180 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [1, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t),\n\n\t\t\tzAxisArrow: rootNode.addChild(\n\t\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_7__.Mesh(rootNode, {\n\t\t\t\t\tgeometry: shapes.arrowHeadBig,\n\t\t\t\t\tmaterial: materials.blue,\n\t\t\t\t\tmatrix: (function () {\n\t\t\t\t\t\tconst translate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.translateMat4c(0, radius + 0.1, 0, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\tconst rotate = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4v(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, [0.8, 0, 0], _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(rotate, translate, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n\t\t\t\t\t})(),\n\t\t\t\t\tpickable: false,\n\t\t\t\t\tcollidable: true,\n\t\t\t\t\tclippable: false,\n\t\t\t\t\tvisible: false,\n\t\t\t\t\tisObject: false\n\t\t\t\t}),\n\t\t\t\tNO_STATE_INHERIT\n\t\t\t)\n\t\t};\n\t}\n\n\t_bindEvents() {\n\t\tconst self = this;\n\n\t\tvar grabbed = false;\n\n\t\tconst DRAG_ACTIONS = {\n\t\t\tnone: -1,\n\t\t\txTranslate: 0,\n\t\t\tyTranslate: 1,\n\t\t\tzTranslate: 2,\n\t\t\txRotate: 3,\n\t\t\tyRotate: 4,\n\t\t\tzRotate: 5\n\t\t};\n\n\t\tconst rootNode = this._rootNode;\n\n\t\tvar nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.\n\t\tvar dragAction = null; // Action we're doing while we drag an arrow or hoop.\n\t\tconst lastCanvasPos = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\n\t\tconst xBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([1, 0, 0]);\n\t\tconst yBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 1, 0]);\n\t\tconst zBaseAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 1]);\n\n\t\tconst canvas = this._viewer.scene.canvas.canvas;\n\t\tconst camera = this._viewer.camera;\n\t\tconst scene = this._viewer.scene;\n\n\t\t{\n\t\t\t// Keep gizmo screen size constant\n\n\t\t\tconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([0, 0, 0]);\n\n\t\t\tlet distDirty = true;\n\t\t\tlet lastDist = -1;\n\n\t\t\tthis._onCameraViewMatrix = scene.camera.on(\"viewMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onCameraProjMatrix = scene.camera.on(\"projMatrix\", () => {\n\t\t\t\tdistDirty = true;\n\t\t\t});\n\n\t\t\tthis._onSceneTick = scene.on(\"tick\", () => {\n\t\t\t\tconst dist = Math.abs(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(scene.camera.eye, this._pos, tempVec3a)));\n\n\t\t\t\tif (dist !== lastDist) {\n\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\tconst worldSize = Math.tan(camera.perspective.fov * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD) * dist;\n\t\t\t\t\t\tconst size = 0.07 * worldSize;\n\t\t\t\t\t\trootNode.scale = [size, size, size];\n\t\t\t\t\t\tlastDist = dist;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (camera.projection === \"ortho\") {\n\t\t\t\t\tconst worldSize = camera.ortho.scale / 10;\n\t\t\t\t\tconst size = worldSize;\n\t\t\t\t\trootNode.scale = [size, size, size];\n\t\t\t\t\tlastDist = dist;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst getClickCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t\tcanvasPos[0] = event.x;\n\t\t\t\t\tcanvasPos[1] = event.y;\n\t\t\t\t} else {\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\tconst getTouchCoordsWithinElement = (function () {\n\t\t\tconst canvasPos = new Float64Array(2);\n\t\t\treturn function (event) {\n\t\t\t\tif (!event) {\n\t\t\t\t\tevent = window.event;\n\t\t\t\t}\n\t\t\t\tif (event.touches && event.touches.length) {\n\t\t\t\t\t// 如果有触摸事件,使用第一个触摸点的坐标\n\t\t\t\t\tcanvasPos[0] = event.touches[0].pageX;\n\t\t\t\t\tcanvasPos[1] = event.touches[0].pageY;\n\t\t\t\t} else {\n\t\t\t\t\t// 否则,假设是鼠标事件\n\t\t\t\t\tvar element = event.target;\n\t\t\t\t\tvar totalOffsetLeft = 0;\n\t\t\t\t\tvar totalOffsetTop = 0;\n\n\t\t\t\t\twhile (element.offsetParent) {\n\t\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\t\t\telement = element.offsetParent;\n\t\t\t\t\t}\n\t\t\t\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\t\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t\t\t}\n\t\t\t\treturn canvasPos;\n\t\t\t};\n\t\t})();\n\n\t\tconst localToWorldVec = (function () {\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function (localVec, worldVec) {\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(self._rootNode.quaternion, mat);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, localVec, worldVec);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(worldVec);\n\t\t\t\treturn worldVec;\n\t\t\t};\n\t\t})();\n\n\t\tvar getTranslationPlane = (function () {\n\t\t\tconst planeNormal = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\treturn function (worldAxis) {\n\t\t\t\tconst absX = Math.abs(worldAxis[0]);\n\t\t\t\tif (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);\n\t\t\t\t} else {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);\n\t\t\t\t}\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(planeNormal, worldAxis, planeNormal);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(planeNormal);\n\t\t\t\treturn planeNormal;\n\t\t\t};\n\t\t})();\n\n\t\tconst dragTranslateSectionPlane = (function () {\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\n\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\n\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1);\n\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(p2, p1);\n\t\t\t\tconst dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\n\t\t\t\tself._pos[0] += worldAxis[0] * dot;\n\t\t\t\tself._pos[1] += worldAxis[1] * dot;\n\t\t\t\tself._pos[2] += worldAxis[2] * dot;\n\t\t\t\tself._rootNode.position = self._pos;\n\t\t\t\tif (self._sectionPlane) {\n\t\t\t\t\tself._sectionPlane.pos = self._pos;\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\tvar dragRotateSectionPlane = (function () {\n\t\t\tconst p1 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\tconst p2 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\tconst c = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\tconst worldAxis = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\n\t\t\treturn function (baseAxis, fromMouse, toMouse) {\n\t\t\t\tlocalToWorldVec(baseAxis, worldAxis);\n\t\t\t\tconst hasData =\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);\n\t\t\t\tif (!hasData) {\n\t\t\t\t\t// Find intersections with view plane and project down to origin\n\t\t\t\t\tconst planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);\n\t\t\t\t\tgetPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable\n\t\t\t\t\tgetPointerPlaneIntersect(toMouse, planeNormal, p2, 1);\n\t\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, worldAxis);\n\t\t\t\t\tp1[0] -= dot * worldAxis[0];\n\t\t\t\t\tp1[1] -= dot * worldAxis[1];\n\t\t\t\t\tp1[2] -= dot * worldAxis[2];\n\t\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p2, worldAxis);\n\t\t\t\t\tp2[0] -= dot * worldAxis[0];\n\t\t\t\t\tp2[1] -= dot * worldAxis[1];\n\t\t\t\t\tp2[2] -= dot * worldAxis[2];\n\t\t\t\t}\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p1);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(p2);\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(p1, p2);\n\t\t\t\tdot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range\n\t\t\t\tvar incDegrees = Math.acos(dot) * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.RADTODEG;\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(p1, p2, c);\n\t\t\t\tif (_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(c, worldAxis) < 0.0) {\n\t\t\t\t\tincDegrees = -incDegrees;\n\t\t\t\t}\n\t\t\t\tself._rootNode.rotate(baseAxis, incDegrees);\n\t\t\t\trotateSectionPlane();\n\t\t\t};\n\t\t})();\n\n\t\tvar getPointerPlaneIntersect = (function () {\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4([0, 0, 0, 1]);\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function (mouse, axis, dest, offset) {\n\t\t\t\toffset = offset || 0;\n\t\t\t\tdir[0] = (mouse[0] / canvas.width) * 2.0 - 1.0;\n\t\t\t\tdir[1] = -((mouse[1] / canvas.height) * 2.0 - 1.0);\n\t\t\t\tdir[2] = 0.0;\n\t\t\t\tdir[3] = 1.0;\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(matrix);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec4(matrix, dir, dir);\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space\n\t\t\t\tvar rayO = camera.eye; // The direction\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec4(dir, rayO, dir);\n\t\t\t\tconst origin = self._sectionPlane.pos; // Plane origin:\n\t\t\t\tvar d = -_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(origin, axis) - offset;\n\t\t\t\tvar dot = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, dir);\n\t\t\t\tif (Math.abs(dot) > 0.005) {\n\t\t\t\t\tvar t = -(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec3(axis, rayO) + d) / dot;\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(dir, t, dest);\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(dest, rayO);\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(dest, origin, dest);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t\t})();\n\n\t\tconst rotateSectionPlane = (function () {\n\t\t\tconst dir = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\t\t\tconst mat = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n\t\t\treturn function () {\n\t\t\t\tif (self.sectionPlane) {\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.quaternionToMat4(rootNode.quaternion, mat); // << ---\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(mat, [0, 0, 1], dir);\n\t\t\t\t\tself._setSectionPlaneDir(dir);\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\t{\n\t\t\tvar mouseDownLeft;\n\t\t\tvar mouseDownMiddle;\n\t\t\tvar mouseDownRight;\n\t\t\tvar down = false;\n\t\t\tvar lastAffordanceMesh;\n\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"hoverEnter\", (hit) => {\n\t\t\t\tif (!this._visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (down) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tgrabbed = false;\n\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t}\n\t\t\t\tvar affordanceMesh;\n\t\t\t\tconst meshId = hit.entity.id;\n\t\t\t\tswitch (meshId) {\n\t\t\t\t\tcase this._displayMeshes.xAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xAxisHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yShaftHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.zAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.zAxisHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xCurveHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xHoop;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xRotate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yCurveHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yHoop;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yRotate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.zCurveHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zHoop;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zRotate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\n\t\t\t\t}\n\t\t\t\tif (affordanceMesh) {\n\t\t\t\t\taffordanceMesh.visible = true;\n\t\t\t\t}\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\n\t\t\t\tgrabbed = true;\n\t\t\t});\n\n\t\t\tthis._onCameraControlHoverLeave = this._viewer.cameraControl.on(\"hoverOutEntity\", (hit) => {\n\t\t\t\tif (!this._visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t}\n\t\t\t\tlastAffordanceMesh = null;\n\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t});\n\n\t\t\t//mousedown\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible || !grabbed) return;\n\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = true;\n\t\t\t\t\t\t\tdown = true;\n\t\t\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\t\t\t//mousemove\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mousemove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar canvasPos = getClickCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\n\t\t\t\t\tswitch (dragAction) {\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\t\t\t//mouseup\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"mouseup\",\n\t\t\t\t(this._canvasMouseUpListener = (e) => {\n\t\t\t\t\tif (!this._visible) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\tif (!down) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tswitch (e.which) {\n\t\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdown = false;\n\t\t\t\t\tgrabbed = false;\n\t\t\t\t})\n\t\t\t);\n\n\t\t\t//wheel\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"wheel\",\n\t\t\t\t(this._canvasWheelListener = (e) => {\n\t\t\t\t\tif (!this._visible) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\n\t\t\t\t\tif (delta === 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tthis._onCameraControlHover = this._viewer.cameraControl.on(\"touchEntity\", (hit) => {\n\t\t\t\tif (!this._visible || down || grabbed) return;\n\t\t\t\tgrabbed = false;\n\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t}\n\t\t\t\tvar affordanceMesh;\n\t\t\t\tconst meshId = hit.entity.id;\n\t\t\t\tswitch (meshId) {\n\t\t\t\t\tcase this._displayMeshes.xAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xAxisHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yShaftHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.zAxisArrowHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.zAxisHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.zAxisArrow;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.zTranslate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.xCurveHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.xHoop;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.xRotate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase this._displayMeshes.yCurveHandle.id:\n\t\t\t\t\t\taffordanceMesh = this._affordanceMeshes.yHoop;\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.yRotate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t// case this._displayMeshes.zCurveHandle.id:\n\t\t\t\t\t// \taffordanceMesh = this._affordanceMeshes.zHoop;\n\t\t\t\t\t// \tnextDragAction = DRAG_ACTIONS.zRotate;\n\t\t\t\t\t// \tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\t\treturn; // Not clicked an arrow or hoop\n\t\t\t\t}\n\t\t\t\tif (affordanceMesh) {\n\t\t\t\t\taffordanceMesh.visible = true;\n\t\t\t\t}\n\t\t\t\tlastAffordanceMesh = affordanceMesh;\n\t\t\t\tgrabbed = true;\n\t\t\t});\n\t\t\t//touchstart\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchstart\",\n\t\t\t\t(this._canvasMouseDownListener = (e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (!this._visible || !grabbed) return;\n\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = false;\n\t\t\t\t\tdown = true;\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\n\t\t\t\t\tdragAction = nextDragAction;\n\t\t\t\t\tlastCanvasPos[0] = canvasPos[0];\n\t\t\t\t\tlastCanvasPos[1] = canvasPos[1];\n\t\t\t\t})\n\t\t\t);\n\t\t\t//touchmove\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchmove\",\n\t\t\t\t(this._canvasMouseMoveListener = (e) => {\n\t\t\t\t\tif (!this._visible || !down) return;\n\n\t\t\t\t\tvar canvasPos = getTouchCoordsWithinElement(e);\n\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\tconst y = canvasPos[1];\n\n\t\t\t\t\tswitch (dragAction) {\n\t\t\t\t\t\tcase DRAG_ACTIONS.xTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zTranslate:\n\t\t\t\t\t\t\tdragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.xRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.yRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase DRAG_ACTIONS.zRotate:\n\t\t\t\t\t\t\tdragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlastCanvasPos[0] = x;\n\t\t\t\t\tlastCanvasPos[1] = y;\n\t\t\t\t})\n\t\t\t);\n\t\t\t//touchend\n\t\t\tcanvas.addEventListener(\n\t\t\t\t\"touchend\",\n\t\t\t\t(this._canvasTouchEndListener = (e) => {\n\t\t\t\t\tif (!this._visible) return;\n\t\t\t\t\tthis._viewer.cameraControl.pointerEnabled = true;\n\t\t\t\t\tif (lastAffordanceMesh) {\n\t\t\t\t\t\tlastAffordanceMesh.visible = false;\n\t\t\t\t\t}\n\t\t\t\t\tlastAffordanceMesh = null;\n\t\t\t\t\tnextDragAction = DRAG_ACTIONS.none;\n\t\t\t\t\tdown = false;\n\t\t\t\t\tgrabbed = false;\n\t\t\t\t})\n\t\t\t);\n\t\t\tcanvas.addEventListener(\"touchcancel\", this._canvasTouchEndListener);\n\t\t}\n\t}\n\n\t_destroy() {\n\t\tthis._unbindEvents();\n\t\tthis._destroyNodes();\n\t}\n\n\t_unbindEvents() {\n\t\tconst viewer = this._viewer;\n\t\tconst scene = viewer.scene;\n\t\tconst canvas = scene.canvas.canvas;\n\t\tconst camera = viewer.camera;\n\t\tconst cameraControl = viewer.cameraControl;\n\n\t\tscene.off(this._onSceneTick);\n\n\t\tcanvas.removeEventListener(\"mousedown\", this._canvasMouseDownListener);\n\t\tcanvas.removeEventListener(\"mousemove\", this._canvasMouseMoveListener);\n\t\tcanvas.removeEventListener(\"mouseup\", this._canvasMouseUpListener);\n\t\tcanvas.removeEventListener(\"wheel\", this._canvasWheelListener);\n\t\tcanvas.removeEventListener(\"touchend\", this._canvasTouchEndListener);\n\t\tcanvas.removeEventListener(\"touchcancel\", this._canvasTouchEndListener);\n\n\t\tcamera.off(this._onCameraViewMatrix);\n\t\tcamera.off(this._onCameraProjMatrix);\n\n\t\tcameraControl.off(this._onCameraControlHover);\n\t\tcameraControl.off(this._onCameraControlHoverLeave);\n\t}\n\n\t_destroyNodes() {\n\t\tthis._setSectionPlane(null);\n\t\tthis._rootNode.destroy();\n\t\tthis._displayMeshes = {};\n\t\tthis._affordanceMeshes = {};\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/Control.js?");
|
|
1908
1908
|
|
|
1909
1909
|
/***/ }),
|
|
1910
1910
|
|
|
@@ -2094,7 +2094,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2094
2094
|
\************************************************************/
|
|
2095
2095
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2096
2096
|
|
|
2097
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XML3DLoaderPlugin: () => (/* binding */ XML3DLoaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _XML3DSceneGraphLoader_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./XML3DSceneGraphLoader.js */ \"./src/plugins/XML3DLoaderPlugin/XML3DSceneGraphLoader.js\");\n\r\n\r\n\r\n\r\n\r\n/**\r\n * {@link Viewer} plugin that loads models from [3DXML](https://en.wikipedia.org/wiki/3DXML) files.\r\n *\r\n * [<img src=\"https://xeokit.io/img/docs/XML3DLoaderPlugin/XML3DPluginTreeView.png\">](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_TreeView)\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_TreeView)]\r\n *\r\n * ## Overview\r\n *\r\n * * Currently supports 3DXML V4.2.\r\n * * Creates an {@link Entity} representing each model it loads, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.\r\n * * Creates an {@link Entity} for each object within the model, which will have {@link Entity#isObject} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#objects}.\r\n * * When loading, can set the World-space position, scale and rotation of each model within World space, along with initial properties for all the model's {@link Entity}s.\r\n * * Can optionally load a {@link MetaModel} to classify the objects within the model, from which you can create a tree view using the {@link TreeViewPlugin}.\r\n * <br>\r\n * Note that the name of this plugin is intentionally munged to \"XML3D\" because a JavaScript class name cannot begin with a numeral.\r\n *\r\n * An 3DXML model is a zip archive that bundles multiple XML files and assets. Internally, the XML3DLoaderPlugin uses the\r\n * [zip.js](https://gildas-lormeau.github.io/zip.js/) library to unzip them before loading. The zip.js library uses\r\n * [Web workers](https://www.w3.org/TR/workers/) for fast unzipping, so XML3DLoaderPlugin requires that we configure it\r\n * with a ````workerScriptsPath```` property specifying the directory where zip.js keeps its Web worker script. See\r\n * the example for how to do that.\r\n *\r\n * ## Usage\r\n *\r\n * In the example below, we'll use an XML3DLoaderPlugin to load a 3DXML model. When the model has loaded,\r\n * we'll use the {@link CameraFlightAnimation} to fly the {@link Camera} to look at boundary of the model. We'll\r\n * then get the model's {@link Entity} from the {@link Scene} and highlight the whole model.\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_Widget)]\r\n *\r\n * ````javascript\r\n * // Create a xeokit Viewer\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * // Add an XML3DLoaderPlugin to the Viewer\r\n * var plugin = new XML3DLoaderPlugin(viewer, {\r\n * id: \"XML3DLoader\", // Default value\r\n * workerScriptsPath : \"../../src/plugins/XML3DLoader/zipjs/\" // Path to zip.js workers dir\r\n * });\r\n *\r\n * // Load the 3DXML model\r\n * var model = plugin.load({ // Model is an Entity\r\n * id: \"myModel\",\r\n * src: \"./models/xml3d/3dpreview.3dxml\",\r\n * scale: [0.1, 0.1, 0.1],\r\n * rotate: [90, 0, 0],\r\n * translate: [100,0,0],\r\n * edges: true\r\n * });\r\n *\r\n * // When the model has loaded, fit it to view\r\n * model.on(\"loaded\", function() {\r\n * viewer.cameraFlight.flyTo(model);\r\n * });\r\n *\r\n * // Update properties of the model via the entity\r\n * model.highlighted = true;\r\n *\r\n * // Find the model Entity by ID\r\n * model = viewer.scene.models[\"myModel\"];\r\n *\r\n * // Destroy the model\r\n * model.destroy();\r\n * ````\r\n * ## Loading MetaModels\r\n *\r\n * We have the option to load a {@link MetaModel} that contains a hierarchy of {@link MetaObject}s that classifes the objects within\r\n * our 3DXML model.\r\n *\r\n * This is useful for building a tree view to navigate the objects, using {@link TreeViewPlugin}.\r\n *\r\n * Let's load the model again, this time creating a MetaModel:\r\n *\r\n * ````javascript\r\n * var model = plugin.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xml3d/3dpreview.3dxml\",\r\n * scale: [0.1, 0.1, 0.1],\r\n * rotate: [90, 0, 0],\r\n * translate: [100,0,0],\r\n * edges: true,\r\n *\r\n * createMetaModel: true // <<-------- Create a MetaModel\r\n * });\r\n * ````\r\n *\r\n * The MetaModel can then be found on the {@link Viewer}'s {@link MetaScene}, using the model's ID:\r\n *\r\n * ````javascript\r\n * const metaModel = viewer.metaScene.metaModels[\"myModel\"];\r\n * ````\r\n *\r\n * Now we can use {@link TreeViewPlugin} to create a tree view to navigate our model's objects:\r\n *\r\n * ````javascript\r\n * import {TreeViewPlugin} from \"xeokit-sdk.es.js\"\"xeokit-sdk.es.js\";\r\n *\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\")\r\n * });\r\n *\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"treeViewContainer\"),\r\n * autoExpandDepth: 3, // Initially expand tree three storeys deep\r\n * hierarchy: \"containment\",\r\n * autoAddModels: false\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n * treeView.addModel(model.id);\r\n * });\r\n * ````\r\n *\r\n * Note that only the TreeViewPlugin \"containment\" hierarchy makes sense for an XML3D model. A \"types\" hierarchy\r\n * does not make sense because XML3DLoaderPlugin will set each {@link MetaObject#type} to \"Default\", and \"storeys\"\r\n * does not make sense because that requires some of the MetaObject#type values to be \"IfcBuildingStorey\".\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_TreeView)]\r\n *\r\n * ## Material Type\r\n *\r\n * Although 3DXML only supports Phong materials, XML3DLoaderPlugin is able to convert them to physically-based materials.\r\n *\r\n * The plugin supports three material types:\r\n *\r\n * | Material Type | Material Components Loaded | Description | Example |\r\n * |:--------:|:----:|:-----:|:-----:|\r\n * | \"PhongMaterial\" (default) | {@link PhongMaterial} | Non-physically-correct Blinn-Phong shading model | [Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Phong) |\r\n * | \"MetallicMaterial\" | {@link MetallicMaterial} | Physically-accurate specular-glossiness shading model | [Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Metallic) |\r\n * | \"SpecularMaterial\" | {@link SpecularMaterial} | Physically-accurate metallic-roughness shading model | [Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Specular) |\r\n *\r\n * <br>\r\n * Let's load our model again, this time converting the 3DXML Blinn-Phong materials to {@link SpecularMaterial}s:\r\n *\r\n * ````javascript\r\n * var model = plugin.load({ // Model is an Entity\r\n * id: \"myModel\",\r\n * src: \"./models/xml3d/3dpreview.3dxml\",\r\n * materialtype: \"SpecularMaterial\": true\"\r\n * });\r\n * ````\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Specular)]\r\n *\r\n * @class XML3DLoaderPlugin\r\n */\r\n\r\nclass XML3DLoaderPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_2__.Plugin {\r\n\r\n /**\r\n * @constructor\r\n * @param {Viewer} viewer The Viewer.\r\n * @param {Object} cfg Plugin configuration.\r\n * @param {String} [cfg.id=\"XML3DLoader\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n * @param {String} cfg.workerScriptsPath Path to the directory that contains the\r\n * bundled [zip.js](https://gildas-lormeau.github.io/zip.js/) archive, which is a dependency of this plugin. This directory\r\n * contains the script that is used by zip.js to instantiate Web workers, which assist with unzipping the 3DXML, which is a ZIP archive.\r\n * @param {String} [cfg.materialType=\"PhongMaterial\"] What type of materials to create while loading: \"MetallicMaterial\" to create {@link MetallicMaterial}s, \"SpecularMaterial\" to create {@link SpecularMaterial}s or \"PhongMaterial\" to create {@link PhongMaterial}s. As it loads XML3D's Phong materials, the XMLLoaderPlugin will do its best approximate conversion of those to the specified workflow.\r\n * @param {Boolean} [cfg.createMetaModel=false] When true, will create a {@link MetaModel} for the model in {@link MetaScene#metaModels}.\r\n */\r\n constructor(viewer, cfg = {}) {\r\n\r\n super(\"XML3DLoader\", viewer, cfg);\r\n\r\n if (!cfg.workerScriptsPath) {\r\n this.error(\"Config expected: workerScriptsPath\");\r\n return\r\n }\r\n\r\n this._workerScriptsPath = cfg.workerScriptsPath;\r\n\r\n /**\r\n * @private\r\n */\r\n this._loader = new _XML3DSceneGraphLoader_js__WEBPACK_IMPORTED_MODULE_3__.XML3DSceneGraphLoader(this, cfg);\r\n\r\n /**\r\n * Supported 3DXML schema versions\r\n * @property supportedSchemas\r\n * @type {string[]}\r\n */\r\n this.supportedSchemas = this._loader.supportedSchemas;\r\n }\r\n\r\n /**\r\n * Loads a 3DXML model from a file into this XML3DLoaderPlugin's {@link Viewer}.\r\n *\r\n * Creates a tree of {@link Entity}s within the Viewer's {@link Scene} that represents the model.\r\n *\r\n * @param {*} params Loading parameters.\r\n * @param {String} params.id ID to assign to the model's root {@link Entity}, unique among all components in the Viewer's {@link Scene}.\r\n * @param {String} [params.src] Path to a 3DXML file.\r\n * @param {Boolean} [params.edges=false] Whether or not xeokit renders the {@link Entity} with edges emphasized.\r\n * @param {Number[]} [params.position=[0,0,0]] The model's World-space 3D position.\r\n * @param {Number[]} [params.scale=[1,1,1]] The model's World-space scale.\r\n * @param {Number[]} [params.rotation=[0,0,0]] The model's World-space rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\r\n * @param {Number[]} [params.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] The model's world transform matrix. Overrides the position, scale and rotation parameters.\r\n * @param {Boolean} [params.backfaces=false] When true, allows visible backfaces, wherever specified in the 3DXML. When false, ignores backfaces.\r\n * @param {Number} [params.edgeThreshold=20] When xraying, highlighting, selecting or edging, this is the threshold angle between normals of adjacent triangles, below which their shared wireframe edge is not drawn.\r\n * @param {String} [params.materialType=\"PhongMaterial\"] What type of materials to create while loading: \"MetallicMaterial\" to create {@link MetallicMaterial}s, \"SpecularMaterial\" to create {@link SpecularMaterial}s or \"PhongMaterial\" to create {@link PhongMaterial}s. As it loads XML3D's Phong materials, the XMLLoaderPlugin will do its best approximate conversion of those to the specified workflow.\r\n * @param {Boolean} [params.createMetaModel=false] When true, will create a {@link MetaModel} for the model in {@link MetaScene#metaModels}.\r\n * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}\r\n */\r\n load(params = {}) {\r\n\r\n params.workerScriptsPath = this._workerScriptsPath;\r\n\r\n if (params.id && this.viewer.scene.components[params.id]) {\r\n this.error(\"Component with this ID already exists in viewer: \" + params.id + \" - will autogenerate this ID\");\r\n delete params.id;\r\n }\r\n\r\n const modelNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_1__.Node(this.viewer.scene, _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.apply(params, {\r\n isModel: true\r\n }));\r\n\r\n const src = params.src;\r\n\r\n if (!src) {\r\n this.error(\"load() param expected: src\");\r\n return modelNode; // Return new empty model\r\n }\r\n\r\n this._loader.load(this, modelNode, src, params);\r\n\r\n return modelNode;\r\n }\r\n}\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/XML3DLoaderPlugin.js?");
|
|
2097
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XML3DLoaderPlugin: () => (/* binding */ XML3DLoaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _XML3DSceneGraphLoader_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./XML3DSceneGraphLoader.js */ \"./src/plugins/XML3DLoaderPlugin/XML3DSceneGraphLoader.js\");\n\n\n\n\n\n/**\n * {@link Viewer} plugin that loads models from [3DXML](https://en.wikipedia.org/wiki/3DXML) files.\n *\n * [<img src=\"https://xeokit.io/img/docs/XML3DLoaderPlugin/XML3DPluginTreeView.png\">](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_TreeView)\n *\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_TreeView)]\n *\n * ## Overview\n *\n * * Currently supports 3DXML V4.2.\n * * Creates an {@link Entity} representing each model it loads, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.\n * * Creates an {@link Entity} for each object within the model, which will have {@link Entity#isObject} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#objects}.\n * * When loading, can set the World-space position, scale and rotation of each model within World space, along with initial properties for all the model's {@link Entity}s.\n * * Can optionally load a {@link MetaModel} to classify the objects within the model, from which you can create a tree view using the {@link TreeViewPlugin}.\n * <br>\n * Note that the name of this plugin is intentionally munged to \"XML3D\" because a JavaScript class name cannot begin with a numeral.\n *\n * An 3DXML model is a zip archive that bundles multiple XML files and assets. Internally, the XML3DLoaderPlugin uses the\n * [zip.js](https://gildas-lormeau.github.io/zip.js/) library to unzip them before loading. The zip.js library uses\n * [Web workers](https://www.w3.org/TR/workers/) for fast unzipping, so XML3DLoaderPlugin requires that we configure it\n * with a ````workerScriptsPath```` property specifying the directory where zip.js keeps its Web worker script. See\n * the example for how to do that.\n *\n * ## Usage\n *\n * In the example below, we'll use an XML3DLoaderPlugin to load a 3DXML model. When the model has loaded,\n * we'll use the {@link CameraFlightAnimation} to fly the {@link Camera} to look at boundary of the model. We'll\n * then get the model's {@link Entity} from the {@link Scene} and highlight the whole model.\n *\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_Widget)]\n *\n * ````javascript\n * // Create a xeokit Viewer\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\"\n * });\n *\n * // Add an XML3DLoaderPlugin to the Viewer\n * var plugin = new XML3DLoaderPlugin(viewer, {\n * id: \"XML3DLoader\", // Default value\n * workerScriptsPath : \"../../src/plugins/XML3DLoader/zipjs/\" // Path to zip.js workers dir\n * });\n *\n * // Load the 3DXML model\n * var model = plugin.load({ // Model is an Entity\n * id: \"myModel\",\n * src: \"./models/xml3d/3dpreview.3dxml\",\n * scale: [0.1, 0.1, 0.1],\n * rotate: [90, 0, 0],\n * translate: [100,0,0],\n * edges: true\n * });\n *\n * // When the model has loaded, fit it to view\n * model.on(\"loaded\", function() {\n * viewer.cameraFlight.flyTo(model);\n * });\n *\n * // Update properties of the model via the entity\n * model.highlighted = true;\n *\n * // Find the model Entity by ID\n * model = viewer.scene.models[\"myModel\"];\n *\n * // Destroy the model\n * model.destroy();\n * ````\n * ## Loading MetaModels\n *\n * We have the option to load a {@link MetaModel} that contains a hierarchy of {@link MetaObject}s that classifes the objects within\n * our 3DXML model.\n *\n * This is useful for building a tree view to navigate the objects, using {@link TreeViewPlugin}.\n *\n * Let's load the model again, this time creating a MetaModel:\n *\n * ````javascript\n * var model = plugin.load({\n * id: \"myModel\",\n * src: \"./models/xml3d/3dpreview.3dxml\",\n * scale: [0.1, 0.1, 0.1],\n * rotate: [90, 0, 0],\n * translate: [100,0,0],\n * edges: true,\n *\n * createMetaModel: true // <<-------- Create a MetaModel\n * });\n * ````\n *\n * The MetaModel can then be found on the {@link Viewer}'s {@link MetaScene}, using the model's ID:\n *\n * ````javascript\n * const metaModel = viewer.metaScene.metaModels[\"myModel\"];\n * ````\n *\n * Now we can use {@link TreeViewPlugin} to create a tree view to navigate our model's objects:\n *\n * ````javascript\n * import {TreeViewPlugin} from \"xeokit-sdk.es.js\"\"xeokit-sdk.es.js\";\n *\n * const treeView = new TreeViewPlugin(viewer, {\n * containerElement: document.getElementById(\"myTreeViewContainer\")\n * });\n *\n * const treeView = new TreeViewPlugin(viewer, {\n * containerElement: document.getElementById(\"treeViewContainer\"),\n * autoExpandDepth: 3, // Initially expand tree three storeys deep\n * hierarchy: \"containment\",\n * autoAddModels: false\n * });\n *\n * model.on(\"loaded\", () => {\n * treeView.addModel(model.id);\n * });\n * ````\n *\n * Note that only the TreeViewPlugin \"containment\" hierarchy makes sense for an XML3D model. A \"types\" hierarchy\n * does not make sense because XML3DLoaderPlugin will set each {@link MetaObject#type} to \"Default\", and \"storeys\"\n * does not make sense because that requires some of the MetaObject#type values to be \"IfcBuildingStorey\".\n *\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_TreeView)]\n *\n * ## Material Type\n *\n * Although 3DXML only supports Phong materials, XML3DLoaderPlugin is able to convert them to physically-based materials.\n *\n * The plugin supports three material types:\n *\n * | Material Type | Material Components Loaded | Description | Example |\n * |:--------:|:----:|:-----:|:-----:|\n * | \"PhongMaterial\" (default) | {@link PhongMaterial} | Non-physically-correct Blinn-Phong shading model | [Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Phong) |\n * | \"MetallicMaterial\" | {@link MetallicMaterial} | Physically-accurate specular-glossiness shading model | [Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Metallic) |\n * | \"SpecularMaterial\" | {@link SpecularMaterial} | Physically-accurate metallic-roughness shading model | [Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Specular) |\n *\n * <br>\n * Let's load our model again, this time converting the 3DXML Blinn-Phong materials to {@link SpecularMaterial}s:\n *\n * ````javascript\n * var model = plugin.load({ // Model is an Entity\n * id: \"myModel\",\n * src: \"./models/xml3d/3dpreview.3dxml\",\n * materialtype: \"SpecularMaterial\": true\"\n * });\n * ````\n *\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_3DXML_materialType_Specular)]\n *\n * @class XML3DLoaderPlugin\n */\n\nclass XML3DLoaderPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\n /**\n * @constructor\n * @param {Viewer} viewer The Viewer.\n * @param {Object} cfg Plugin configuration.\n * @param {String} [cfg.id=\"XML3DLoader\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\n * @param {String} cfg.workerScriptsPath Path to the directory that contains the\n * bundled [zip.js](https://gildas-lormeau.github.io/zip.js/) archive, which is a dependency of this plugin. This directory\n * contains the script that is used by zip.js to instantiate Web workers, which assist with unzipping the 3DXML, which is a ZIP archive.\n * @param {String} [cfg.materialType=\"PhongMaterial\"] What type of materials to create while loading: \"MetallicMaterial\" to create {@link MetallicMaterial}s, \"SpecularMaterial\" to create {@link SpecularMaterial}s or \"PhongMaterial\" to create {@link PhongMaterial}s. As it loads XML3D's Phong materials, the XMLLoaderPlugin will do its best approximate conversion of those to the specified workflow.\n * @param {Boolean} [cfg.createMetaModel=false] When true, will create a {@link MetaModel} for the model in {@link MetaScene#metaModels}.\n */\n constructor(viewer, cfg = {}) {\n\n super(\"XML3DLoader\", viewer, cfg);\n\n if (!cfg.workerScriptsPath) {\n this.error(\"Config expected: workerScriptsPath\");\n return\n }\n\n this._workerScriptsPath = cfg.workerScriptsPath;\n\n /**\n * @private\n */\n this._loader = new _XML3DSceneGraphLoader_js__WEBPACK_IMPORTED_MODULE_3__.XML3DSceneGraphLoader(this, cfg);\n\n /**\n * Supported 3DXML schema versions\n * @property supportedSchemas\n * @type {string[]}\n */\n this.supportedSchemas = this._loader.supportedSchemas;\n }\n\n /**\n * Loads a 3DXML model from a file into this XML3DLoaderPlugin's {@link Viewer}.\n *\n * Creates a tree of {@link Entity}s within the Viewer's {@link Scene} that represents the model.\n *\n * @param {*} params Loading parameters.\n * @param {String} params.id ID to assign to the model's root {@link Entity}, unique among all components in the Viewer's {@link Scene}.\n * @param {String} [params.src] Path to a 3DXML file.\n * @param {Boolean} [params.edges=false] Whether or not xeokit renders the {@link Entity} with edges emphasized.\n * @param {Number[]} [params.position=[0,0,0]] The model's World-space 3D position.\n * @param {Number[]} [params.scale=[1,1,1]] The model's World-space scale.\n * @param {Number[]} [params.rotation=[0,0,0]] The model's World-space rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n * @param {Number[]} [params.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] The model's world transform matrix. Overrides the position, scale and rotation parameters.\n * @param {Boolean} [params.backfaces=false] When true, allows visible backfaces, wherever specified in the 3DXML. When false, ignores backfaces.\n * @param {Number} [params.edgeThreshold=20] When xraying, highlighting, selecting or edging, this is the threshold angle between normals of adjacent triangles, below which their shared wireframe edge is not drawn.\n * @param {String} [params.materialType=\"PhongMaterial\"] What type of materials to create while loading: \"MetallicMaterial\" to create {@link MetallicMaterial}s, \"SpecularMaterial\" to create {@link SpecularMaterial}s or \"PhongMaterial\" to create {@link PhongMaterial}s. As it loads XML3D's Phong materials, the XMLLoaderPlugin will do its best approximate conversion of those to the specified workflow.\n * @param {Boolean} [params.createMetaModel=false] When true, will create a {@link MetaModel} for the model in {@link MetaScene#metaModels}.\n * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}\n */\n load(params = {}) {\n\n params.workerScriptsPath = this._workerScriptsPath;\n\n if (params.id && this.viewer.scene.components[params.id]) {\n this.error(\"Component with this ID already exists in viewer: \" + params.id + \" - will autogenerate this ID\");\n delete params.id;\n }\n\n const modelNode = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_1__.Node(this.viewer.scene, _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.apply(params, {\n isModel: true\n }));\n\n const src = params.src;\n\n if (!src) {\n this.error(\"load() param expected: src\");\n return modelNode; // Return new empty model\n }\n\n this._loader.load(this, modelNode, src, params);\n\n return modelNode;\n }\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/XML3DLoaderPlugin.js?");
|
|
2098
2098
|
|
|
2099
2099
|
/***/ }),
|
|
2100
2100
|
|
|
@@ -2104,7 +2104,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2104
2104
|
\****************************************************************/
|
|
2105
2105
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2106
2106
|
|
|
2107
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XML3DSceneGraphLoader: () => (/* binding */ XML3DSceneGraphLoader)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_MetallicMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/MetallicMaterial.js */ \"./src/viewer/scene/materials/MetallicMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_SpecularMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/SpecularMaterial.js */ \"./src/viewer/scene/materials/SpecularMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_LambertMaterial_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/materials/LambertMaterial.js */ \"./src/viewer/scene/materials/LambertMaterial.js\");\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _zipjs_zip_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./zipjs/zip.js */ \"./src/plugins/XML3DLoaderPlugin/zipjs/zip.js\");\n/* harmony import */ var _zipjs_zip_ext_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./zipjs/zip-ext.js */ \"./src/plugins/XML3DLoaderPlugin/zipjs/zip-ext.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 zip = _zipjs_zip_js__WEBPACK_IMPORTED_MODULE_8__.zipLib.zip;\r\n(0,_zipjs_zip_ext_js__WEBPACK_IMPORTED_MODULE_9__.zipExt)(zip);\r\n\r\nconst supportedSchemas = [\"4.2\"];\r\n\r\n/**\r\n * @private\r\n */\r\nclass XML3DSceneGraphLoader {\r\n\r\n constructor(plugin, cfg = {}) {\r\n\r\n /**\r\n * Supported 3DXML schema versions\r\n * @property supportedSchemas\r\n * @type {string[]}\r\n */\r\n this.supportedSchemas = supportedSchemas;\r\n\r\n this._xrayOpacity = 0.7;\r\n this._src = null;\r\n this._options = cfg;\r\n\r\n /**\r\n * Default viewpoint, containing eye, look and up vectors.\r\n * Only defined if found in the 3DXML file.\r\n * @property viewpoint\r\n * @type {Number[]}\r\n */\r\n this.viewpoint = null;\r\n\r\n if (!cfg.workerScriptsPath) {\r\n plugin.error(\"Config expected: workerScriptsPath\");\r\n return\r\n }\r\n zip.workerScriptsPath = cfg.workerScriptsPath;\r\n\r\n this.src = cfg.src;\r\n this.xrayOpacity = 0.7;\r\n this.displayEffect = cfg.displayEffect;\r\n this.createMetaModel = cfg.createMetaModel;\r\n }\r\n\r\n load(plugin, modelNode, src, options, ok, error) {\r\n\r\n switch (options.materialType) {\r\n case \"MetallicMaterial\":\r\n modelNode._defaultMaterial = new _viewer_scene_materials_MetallicMaterial_js__WEBPACK_IMPORTED_MODULE_4__.MetallicMaterial(modelNode, {\r\n baseColor: [1, 1, 1],\r\n metallic: 0.6,\r\n roughness: 0.6\r\n });\r\n break;\r\n\r\n case \"SpecularMaterial\":\r\n modelNode._defaultMaterial = new _viewer_scene_materials_SpecularMaterial_js__WEBPACK_IMPORTED_MODULE_5__.SpecularMaterial(modelNode, {\r\n diffuse: [1, 1, 1],\r\n specular: _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__.math.vec3([1.0, 1.0, 1.0]),\r\n glossiness: 0.5\r\n });\r\n break;\r\n\r\n default:\r\n modelNode._defaultMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_3__.PhongMaterial(modelNode, {\r\n reflectivity: 0.75,\r\n shiness: 100,\r\n diffuse: [1, 1, 1]\r\n });\r\n }\r\n\r\n modelNode._wireframeMaterial = new _viewer_scene_materials_LambertMaterial_js__WEBPACK_IMPORTED_MODULE_6__.LambertMaterial(modelNode, {\r\n color: [0, 0, 0],\r\n lineWidth: 2\r\n });\r\n\r\n var spinner = modelNode.scene.canvas.spinner;\r\n spinner.processes++;\r\n\r\n load3DXML(plugin, modelNode, src, options, function () {\r\n spinner.processes--;\r\n if (ok) {\r\n ok();\r\n }\r\n modelNode.fire(\"loaded\", true, false);\r\n },\r\n function (msg) {\r\n spinner.processes--;\r\n modelNode.error(msg);\r\n if (error) {\r\n error(msg);\r\n }\r\n /**\r\n Fired whenever this XML3D fails to load the 3DXML file\r\n specified by {@link XML3D/src}.\r\n @event error\r\n @param msg {String} Description of the error\r\n */\r\n modelNode.fire(\"error\", msg);\r\n },\r\n function (err) {\r\n console.log(\"Error, Will Robinson: \" + err);\r\n });\r\n }\r\n}\r\n\r\nvar load3DXML = (function () {\r\n return function (plugin, modelNode, src, options, ok, error) {\r\n loadZIP(src, function (zip) { // OK\r\n parse3DXML(plugin, zip, options, modelNode, ok, error);\r\n },\r\n error);\r\n };\r\n})();\r\n\r\nvar parse3DXML = (function () {\r\n return function (plugin, zip, options, modelNode, ok) {\r\n var ctx = {\r\n plugin: plugin,\r\n zip: zip,\r\n edgeThreshold: 30, // Guess at degrees of normal deviation between adjacent tris below which we remove edge between them\r\n materialType: options.materialType,\r\n scene: modelNode.scene,\r\n modelNode: modelNode,\r\n info: {\r\n references: {}\r\n },\r\n materials: {}\r\n };\r\n\r\n if (options.createMetaModel) {\r\n ctx.metaModelData = {\r\n modelId: modelNode.id,\r\n metaObjects: [{\r\n name: modelNode.id,\r\n type: \"Default\",\r\n id: modelNode.id\r\n }]\r\n };\r\n }\r\n modelNode.scene.loading++; // Disables (re)compilation\r\n\r\n parseDocument(ctx, function () {\r\n if (ctx.metaModelData) {\r\n plugin.viewer.metaScene.createMetaModel(modelNode.id, ctx.metaModelData);\r\n }\r\n modelNode.scene.loading--; // Re-enables (re)compilation\r\n ok();\r\n });\r\n };\r\n\r\n function parseDocument(ctx, ok) {\r\n ctx.zip.getFile(\"Manifest.xml\", function (xmlDoc, json) {\r\n var node = json;\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Manifest\":\r\n parseManifest(ctx, child, ok);\r\n break;\r\n }\r\n }\r\n });\r\n }\r\n\r\n function parseManifest(ctx, manifest, ok) {\r\n var children = manifest.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Root\":\r\n var rootFileSrc = child.children[0];\r\n ctx.zip.getFile(rootFileSrc, function (xmlDoc, json) {\r\n parseRoot(ctx, json, ok);\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parseRoot(ctx, node, ok) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Model_3dxml\":\r\n parseModel(ctx, child, ok);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parseModel(ctx, node, ok) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Header\":\r\n parseHeader(ctx, child);\r\n break;\r\n case \"ProductStructure\":\r\n parseProductStructure(ctx, child, ok);\r\n break;\r\n case \"DefaultView\":\r\n parseDefaultView(ctx, child);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parseHeader(ctx, node) {\r\n var children = node.children;\r\n var metaData = {};\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"SchemaVersion\":\r\n metaData.schemaVersion = child.children[0];\r\n if (!isSchemaVersionSupported(ctx, metaData.schemaVersion)) {\r\n ctx.plugin.error(\"Schema version not supported: \" + metaData.schemaVersion + \" - supported versions are: \" + supportedSchemas.join(\",\"));\r\n } else {\r\n //ctx.plugin.log(\"Parsing schema version: \" + metaData.schemaVersion);\r\n }\r\n break;\r\n case \"Title\":\r\n metaData.title = child.children[0];\r\n break;\r\n case \"Author\":\r\n metaData.author = child.children[0];\r\n break;\r\n case \"Created\":\r\n metaData.created = child.children[0];\r\n break;\r\n }\r\n }\r\n ctx.modelNode.meta = metaData;\r\n }\r\n\r\n function isSchemaVersionSupported(ctx, schemaVersion) {\r\n for (var i = 0, len = supportedSchemas.length; i < len; i++) {\r\n if (schemaVersion === supportedSchemas[i]) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n function parseProductStructure(ctx, productStructureNode, ok) {\r\n\r\n parseReferenceReps(ctx, productStructureNode, function (referenceReps) {\r\n\r\n // Parse out an intermediate scene DAG representation, that we can then\r\n // recursive descend through to build a xeokit Object hierarchy.\r\n\r\n var children = productStructureNode.children;\r\n\r\n var reference3Ds = {};\r\n var instanceReps = {};\r\n var instance3Ds = {};\r\n\r\n var rootNode;\r\n var nodes = {};\r\n\r\n // Map all the elements\r\n\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n\r\n case \"Reference3D\":\r\n reference3Ds[child.id] = {\r\n type: \"Reference3D\",\r\n id: child.id,\r\n name: child.name,\r\n instance3Ds: {},\r\n instanceReps: {}\r\n };\r\n break;\r\n\r\n case \"InstanceRep\":\r\n var isAggregatedBy;\r\n var isInstanceOf;\r\n var relativeMatrix;\r\n for (var j = 0, lenj = child.children.length; j < lenj; j++) {\r\n var child2 = child.children[j];\r\n switch (child2.type) {\r\n case \"IsAggregatedBy\":\r\n isAggregatedBy = child2.children[0];\r\n break;\r\n case \"IsInstanceOf\":\r\n isInstanceOf = child2.children[0];\r\n break;\r\n }\r\n }\r\n instanceReps[child.id] = {\r\n type: \"InstanceRep\",\r\n id: child.id,\r\n name: child.name,\r\n isAggregatedBy: isAggregatedBy,\r\n isInstanceOf: isInstanceOf,\r\n referenceReps: {}\r\n };\r\n break;\r\n\r\n case \"Instance3D\":\r\n var isAggregatedBy;\r\n var isInstanceOf;\r\n var relativeMatrix;\r\n for (var j = 0, lenj = child.children.length; j < lenj; j++) {\r\n var child2 = child.children[j];\r\n switch (child2.type) {\r\n case \"IsAggregatedBy\":\r\n isAggregatedBy = child2.children[0];\r\n break;\r\n case \"IsInstanceOf\":\r\n isInstanceOf = child2.children[0];\r\n break;\r\n case \"RelativeMatrix\":\r\n relativeMatrix = child2.children[0];\r\n break;\r\n }\r\n }\r\n instance3Ds[child.id] = {\r\n type: \"Instance3D\",\r\n id: child.id,\r\n name: child.name,\r\n isAggregatedBy: isAggregatedBy,\r\n isInstanceOf: isInstanceOf,\r\n relativeMatrix: relativeMatrix,\r\n reference3Ds: {}\r\n };\r\n break;\r\n }\r\n }\r\n\r\n // Connect Reference3Ds to the Instance3Ds they aggregate\r\n\r\n for (var id in instance3Ds) {\r\n var instance3D = instance3Ds[id];\r\n var reference3D = reference3Ds[instance3D.isAggregatedBy];\r\n if (reference3D) {\r\n reference3D.instance3Ds[instance3D.id] = instance3D;\r\n } else {\r\n alert(\"foo\")\r\n }\r\n }\r\n\r\n // Connect Instance3Ds to the Reference3Ds they instantiate\r\n\r\n for (var id in instance3Ds) {\r\n var instance3D = instance3Ds[id];\r\n var reference3D = reference3Ds[instance3D.isInstanceOf];\r\n instance3D.reference3Ds[reference3D.id] = reference3D;\r\n reference3D.instance3D = instance3D;\r\n }\r\n\r\n // Connect InstanceReps to the ReferenceReps they instantiate\r\n\r\n for (var id in instanceReps) {\r\n var instanceRep = instanceReps[id];\r\n var referenceRep = referenceReps[instanceRep.isInstanceOf];\r\n if (referenceRep) {\r\n instanceRep.referenceReps[referenceRep.id] = referenceRep;\r\n }\r\n }\r\n\r\n // Connect Reference3Ds to the InstanceReps they aggregate\r\n\r\n for (var id in instanceReps) {\r\n var instanceRep = instanceReps[id];\r\n var reference3D = reference3Ds[instanceRep.isAggregatedBy];\r\n if (reference3D) {\r\n reference3D.instanceReps[instanceRep.id] = instanceRep;\r\n }\r\n }\r\n\r\n function parseReference3D(ctx, reference3D, group) {\r\n //ctx.plugin.log(\"parseReference3D( \" + reference3D.id + \" )\");\r\n for (var id in reference3D.instance3Ds) {\r\n parseInstance3D(ctx, reference3D.instance3Ds[id], group);\r\n }\r\n for (var id in reference3D.instanceReps) {\r\n parseInstanceRep(ctx, reference3D.instanceReps[id], group);\r\n }\r\n }\r\n\r\n function parseInstance3D(ctx, instance3D, group) {\r\n //ctx.plugin.log(\"parseInstance3D( \" + instance3D.id + \" )\");\r\n\r\n if (instance3D.relativeMatrix) {\r\n var matrix = parseFloatArray(instance3D.relativeMatrix, 12);\r\n var translate = [matrix[9], matrix[10], matrix[11]];\r\n var mat3 = matrix.slice(0, 9); // Rotation matrix\r\n var mat4 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__.math.mat3ToMat4(mat3, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__.math.identityMat4()); // Convert rotation matrix to 4x4\r\n var childGroup = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__.Node(ctx.modelNode, {\r\n position: translate\r\n });\r\n if (ctx.metaModelData) {\r\n ctx.metaModelData.metaObjects.push({\r\n id: childGroup.id,\r\n type: \"Default\",\r\n name: instance3D.name,\r\n parent: group ? group.id : ctx.modelNode.id\r\n });\r\n }\r\n if (group) {\r\n group.addChild(childGroup, true);\r\n } else {\r\n ctx.modelNode.addChild(childGroup, true);\r\n }\r\n group = childGroup;\r\n childGroup = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__.Node(ctx.modelNode, {\r\n matrix: mat4\r\n });\r\n if (ctx.metaModelData) {\r\n ctx.metaModelData.metaObjects.push({\r\n id: childGroup.id,\r\n type: \"Default\",\r\n name: instance3D.name,\r\n parent: group ? group.id : ctx.modelNode.id\r\n });\r\n }\r\n group.addChild(childGroup, true);\r\n group = childGroup;\r\n } else {\r\n var childGroup = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__.Node(ctx.modelNode, {});\r\n if (ctx.metaModelData) {\r\n ctx.metaModelData.metaObjects.push({\r\n id: childGroup.id,\r\n type: \"Default\",\r\n name: instance3D.name,\r\n parent: group ? group.id : ctx.modelNode.id\r\n });\r\n }\r\n if (group) {\r\n group.addChild(childGroup, true);\r\n } else {\r\n ctx.modelNode.addChild(childGroup, true);\r\n }\r\n group = childGroup;\r\n }\r\n for (var id in instance3D.reference3Ds) {\r\n parseReference3D(ctx, instance3D.reference3Ds[id], group);\r\n }\r\n }\r\n\r\n function parseInstanceRep(ctx, instanceRep, group) {\r\n //ctx.plugin.log(\"parseInstanceRep( \" + instanceRep.id + \" )\");\r\n if (instanceRep.referenceReps) {\r\n for (var id in instanceRep.referenceReps) {\r\n var referenceRep = instanceRep.referenceReps[id];\r\n for (var id2 in referenceRep) {\r\n if (id2 === \"id\") {\r\n continue; // HACK\r\n }\r\n var meshCfg = referenceRep[id2];\r\n var lines = meshCfg.geometry.primitive === \"lines\";\r\n var material = lines ? ctx.modelNode._wireframeMaterial : (meshCfg.materialId ? ctx.materials[meshCfg.materialId] : null);\r\n var colorize = meshCfg.color;\r\n var mesh = new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_1__.Mesh(ctx.modelNode, {\r\n isObject: true,\r\n geometry: meshCfg.geometry,\r\n material: material || ctx.modelNode._defaultMaterial,\r\n colorize: colorize,\r\n backfaces: false\r\n });\r\n if (ctx.metaModelData) {\r\n ctx.metaModelData.metaObjects.push({\r\n id: mesh.id,\r\n type: \"Default\",\r\n name: instanceRep.name,\r\n parent: group ? group.id : ctx.modelNode.id\r\n });\r\n }\r\n if (group) {\r\n group.addChild(mesh, true);\r\n } else {\r\n ctx.modelNode.addChild(mesh, true);\r\n }\r\n mesh.colorize = colorize; // HACK: Mesh has inherited modelNode's colorize state, so we need to restore it (we'd better not modify colorize on the modelNode).\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Find the root Reference3D\r\n\r\n for (var id in reference3Ds) {\r\n var reference3D = reference3Ds[id];\r\n if (!reference3D.instance3D) {\r\n parseReference3D(ctx, reference3D, null); // HACK: Assuming that root has id == \"1\"\r\n ok();\r\n return;\r\n }\r\n }\r\n\r\n alert(\"No root Reference3D element found in this modelNode - can't load.\");\r\n\r\n ok();\r\n });\r\n }\r\n\r\n function parseIntArray(str) {\r\n var parts = str.trim().split(\" \");\r\n var result = new Int32Array(parts.length);\r\n for (var i = 0; i < parts.length; i++) {\r\n result[i] = parseInt(parts[i]);\r\n }\r\n return result;\r\n }\r\n\r\n function parseReferenceReps(ctx, node, ok) {\r\n var referenceReps = {};\r\n var children = node.children;\r\n var numToLoad = 0;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n if (child.type === \"ReferenceRep\") {\r\n numToLoad++;\r\n }\r\n }\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"ReferenceRep\":\r\n if (child.associatedFile) {\r\n var src = stripURN(child.associatedFile);\r\n (function () {\r\n var childId = child.id;\r\n ctx.zip.getFile(src, function (xmlDoc, json) {\r\n\r\n var materialIds = xmlDoc.getElementsByTagName(\"MaterialId\");\r\n\r\n loadCATMaterialRefDocuments(ctx, materialIds, function () {\r\n\r\n // ctx.plugin.log(\"reference loaded: \" + src);\r\n var referenceRep = {\r\n id: childId\r\n };\r\n parse3DRepDocument(ctx, json, referenceRep);\r\n referenceReps[childId] = referenceRep;\r\n if (--numToLoad === 0) {\r\n ok(referenceReps);\r\n }\r\n });\r\n },\r\n function (error) {\r\n // TODO:\r\n });\r\n })();\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n\r\n\r\n function parseDefaultView(ctx, node) {\r\n // ctx.plugin.log(\"parseDefaultView\");\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Viewpoint\":\r\n var children2 = child.children;\r\n ctx.modelNode.viewpoint = {};\r\n for (var i2 = 0, len2 = children2.length; i2 < len2; i2++) {\r\n var child2 = children2[i];\r\n switch (child2.type) {\r\n case \"Position\":\r\n ctx.modelNode.viewpoint.eye = parseFloatArray(child2.children[0], 3);\r\n break;\r\n case \"Sight\":\r\n ctx.modelNode.viewpoint.look = parseFloatArray(child2.children[0], 3);\r\n break;\r\n case \"Up\":\r\n ctx.modelNode.viewpoint.up = parseFloatArray(child2.children[0], 3);\r\n break;\r\n }\r\n }\r\n break;\r\n case \"DefaultViewProperty\":\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parse3DRepDocument(ctx, node, result) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"XMLRepresentation\":\r\n parseXMLRepresentation(ctx, child, result);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parseXMLRepresentation(ctx, node, result) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Root\":\r\n parse3DRepRoot(ctx, child, result);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parse3DRepRoot(ctx, node, result) {\r\n switch (node[\"xsi:type\"]) {\r\n case \"BagRepType\":\r\n break;\r\n case \"PolygonalRepType\":\r\n break;\r\n }\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Rep\":\r\n parse3DRepRep(ctx, child, result);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parse3DRepRep(ctx, node, result) {\r\n switch (node[\"xsi:type\"]) {\r\n case \"BagRepType\":\r\n break;\r\n case \"PolygonalRepType\":\r\n break;\r\n }\r\n var meshesResult = {\r\n edgeThreshold: ctx.edgeThreshold || 30,\r\n compressGeometry: true\r\n };\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Rep\":\r\n parse3DRepRep(ctx, child, result);\r\n break;\r\n case \"Edges\":\r\n // Ignoring edges because we auto-generate our own using xeokit\r\n break;\r\n case \"Faces\":\r\n meshesResult.primitive = \"triangles\";\r\n parseFaces(ctx, child, meshesResult);\r\n break;\r\n case \"VertexBuffer\":\r\n parseVertexBuffer(ctx, child, meshesResult);\r\n break;\r\n case \"SurfaceAttributes\":\r\n parseSurfaceAttributes(ctx, child, meshesResult);\r\n break;\r\n }\r\n }\r\n if (meshesResult.positions) {\r\n var geometry = new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_2__.ReadableGeometry(ctx.modelNode, meshesResult);\r\n result[geometry.id] = {\r\n geometry: geometry,\r\n color: meshesResult.color || [1.0, 1.0, 1.0, 1.0],\r\n materialId: meshesResult.materialId\r\n };\r\n }\r\n }\r\n\r\n function parseEdges(ctx, node, result) {\r\n result.positions = [];\r\n result.indices = [];\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Polyline\":\r\n parsePolyline(ctx, child, result);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parsePolyline(ctx, node, result) {\r\n var vertices = node.vertices;\r\n if (vertices) {\r\n var positions = parseFloatArray(vertices, 3);\r\n if (positions.length > 0) {\r\n var positionsOffset = result.positions.length / 3;\r\n for (var i = 0, len = positions.length; i < len; i++) {\r\n result.positions.push(positions[i]);\r\n }\r\n for (var i = 0, len = (positions.length / 3) - 1; i < len; i++) {\r\n result.indices.push(positionsOffset + i);\r\n result.indices.push(positionsOffset + i + 1);\r\n }\r\n }\r\n }\r\n }\r\n\r\n function parseFaces(ctx, node, result) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Face\":\r\n parseFace(ctx, child, result);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parseFace(ctx, node, result) {\r\n var strips = node.strips;\r\n if (strips) {\r\n // Triangle strips\r\n var arrays = parseIntArrays(strips);\r\n if (arrays.length > 0) {\r\n result.primitive = \"triangles\";\r\n var indices = [];\r\n for (var i = 0, len = arrays.length; i < len; i++) {\r\n var array = convertTriangleStrip(arrays[i]);\r\n for (var j = 0, lenj = array.length; j < lenj; j++) {\r\n indices.push(array[j]);\r\n }\r\n }\r\n result.indices = indices; // TODO\r\n }\r\n } else {\r\n // Triangle meshes\r\n var triangles = node.triangles;\r\n if (triangles) {\r\n result.primitive = \"triangles\";\r\n result.indices = parseIntArray(triangles);\r\n }\r\n }\r\n // Material\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"SurfaceAttributes\":\r\n parseSurfaceAttributes(ctx, child, result);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function convertTriangleStrip(indices) {\r\n var ccw = false;\r\n var indices2 = [];\r\n for (var i = 0, len = indices.length; i < len - 2; i++) {\r\n if (ccw) {\r\n if (i & 1) { //\r\n indices2.push(indices[i]);\r\n indices2.push(indices[i + 1]);\r\n indices2.push(indices[i + 2]);\r\n } else {\r\n indices2.push(indices[i]);\r\n indices2.push(indices[i + 2]);\r\n indices2.push(indices[i + 1]);\r\n }\r\n } else {\r\n if (i & 1) { //\r\n indices2.push(indices[i]);\r\n indices2.push(indices[i + 2]);\r\n indices2.push(indices[i + 1]);\r\n } else {\r\n indices2.push(indices[i]);\r\n indices2.push(indices[i + 1]);\r\n indices2.push(indices[i + 2]);\r\n }\r\n }\r\n }\r\n return indices2;\r\n }\r\n\r\n function parseVertexBuffer(ctx, node, result) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Positions\":\r\n result.positions = parseFloatArray(child.children[0], 3);\r\n break;\r\n case \"Normals\":\r\n result.normals = parseFloatArray(child.children[0], 3);\r\n break;\r\n case \"TextureCoordinates\": // TODO: Support dimension and channel?\r\n result.uv = parseFloatArray(child.children[0], 2);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n function parseIntArrays(str) {\r\n var coordStrings = str.split(\",\");\r\n var array = [];\r\n for (var i = 0, len = coordStrings.length; i < len; i++) {\r\n var coordStr = coordStrings[i].trim();\r\n if (coordStr.length > 0) {\r\n var elemStrings = coordStr.trim().split(\" \");\r\n var arr = new Int16Array(elemStrings.length);\r\n var arrIdx = 0;\r\n for (var j = 0, lenj = elemStrings.length; j < lenj; j++) {\r\n if (elemStrings[j] !== \"\") {\r\n arr[arrIdx++] = parseInt(elemStrings[j]);\r\n }\r\n }\r\n array.push(arr);\r\n }\r\n }\r\n return array;\r\n }\r\n\r\n function parseFloatArray(str, numElems) {\r\n str = str.split(\",\");\r\n var arr = new Float32Array(str.length * numElems);\r\n var arrIdx = 0;\r\n for (var i = 0, len = str.length; i < len; i++) {\r\n var value = str[i];\r\n value = value.split(\" \");\r\n for (var j = 0, lenj = value.length; j < lenj; j++) {\r\n if (value[j] !== \"\") {\r\n arr[arrIdx++] = parseFloat(value[j]);\r\n }\r\n }\r\n }\r\n return arr;\r\n }\r\n\r\n function parseIntArray(str) {\r\n str = str.trim().split(\" \");\r\n var arr = new Int32Array(str.length);\r\n var arrIdx = 0;\r\n for (var i = 0, len = str.length; i < len; i++) {\r\n var value = str[i];\r\n arr[i] = parseInt(value);\r\n }\r\n return arr;\r\n }\r\n\r\n function parseSurfaceAttributes(ctx, node, result) {\r\n result.color = [1, 1, 1, 1];\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Color\":\r\n result.color[0] = child.red;\r\n result.color[1] = child.green;\r\n result.color[2] = child.blue;\r\n result.color[3] = child.alpha;\r\n break;\r\n case \"MaterialApplication\":\r\n var children2 = child.children;\r\n for (var j = 0, lenj = children2.length; j < lenj; j++) {\r\n var child2 = children2[j];\r\n switch (child2.type) {\r\n case \"MaterialId\":\r\n var materialId = getIDFromURI(child2.id);\r\n var material = ctx.materials[materialId];\r\n if (!material) {\r\n ctx.plugin.error(\"material not found: \" + materialId);\r\n }\r\n result.materialId = materialId;\r\n break;\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n})();\r\n\r\nfunction loadCATMaterialRefDocuments(ctx, materialIds, ok) {\r\n var loaded = {};\r\n\r\n function load(i, done) {\r\n if (i >= materialIds.length) {\r\n ok();\r\n return;\r\n }\r\n var materialId = materialIds[i];\r\n var src = materialId.id;\r\n var colonIdx = src.lastIndexOf(\":\");\r\n if (colonIdx > 0) {\r\n src = src.substring(colonIdx + 1);\r\n }\r\n var hashIdx = src.lastIndexOf(\"#\");\r\n if (hashIdx > 0) {\r\n src = src.substring(0, hashIdx);\r\n }\r\n if (!loaded[src]) {\r\n loadCATMaterialRefDocument(ctx, src, function () {\r\n loaded[src] = true;\r\n load(i + 1, done);\r\n });\r\n } else {\r\n load(i + 1, done);\r\n }\r\n }\r\n\r\n load(0, ok);\r\n}\r\n\r\nfunction loadCATMaterialRefDocument(ctx, src, ok) { // Loads CATMaterialRef.3dxml\r\n ctx.zip.getFile(src, function (xmlDoc, json) {\r\n parseCATMaterialRefDocument(ctx, json, ok);\r\n });\r\n}\r\n\r\nfunction parseCATMaterialRefDocument(ctx, node, ok) { // Parse CATMaterialRef.3dxml\r\n // ctx.plugin.log(\"parseCATMaterialRefDocument\");\r\n var children = node.children;\r\n var child;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n child = children[i];\r\n if (child.type === \"Model_3dxml\") {\r\n parseModel_3dxml(ctx, child, ok);\r\n }\r\n }\r\n}\r\n\r\nfunction parseModel_3dxml(ctx, node, ok) { // Parse CATMaterialRef.3dxml\r\n // ctx.plugin.log(\"parseModel_3dxml\");\r\n var children = node.children;\r\n var child;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n child = children[i];\r\n if (child.type === \"CATMaterialRef\") {\r\n parseCATMaterialRef(ctx, child, ok);\r\n }\r\n }\r\n}\r\n\r\nfunction parseCATMaterialRef(ctx, node, ok) {\r\n var domainToReferenceMap = {};\r\n var materials = {};\r\n var result = {};\r\n var children = node.children;\r\n var child;\r\n var numToLoad = 0;\r\n for (var j = 0, lenj = children.length; j < lenj; j++) {\r\n var child2 = children[j];\r\n switch (child2.type) {\r\n case \"MaterialDomainInstance\":\r\n var isAggregatedBy;\r\n var isInstanceOf;\r\n for (var k = 0, lenk = child2.children.length; k < lenk; k++) {\r\n var child3 = child2.children[k];\r\n switch (child3.type) {\r\n case \"IsAggregatedBy\":\r\n isAggregatedBy = child3.children[0];\r\n break;\r\n case \"IsInstanceOf\":\r\n isInstanceOf = child3.children[0];\r\n break;\r\n }\r\n }\r\n domainToReferenceMap[isInstanceOf] = isAggregatedBy;\r\n break;\r\n }\r\n }\r\n for (var j = 0, lenj = children.length; j < lenj; j++) {\r\n var child2 = children[j];\r\n switch (child2.type) {\r\n case \"MaterialDomain\":\r\n numToLoad++;\r\n break;\r\n }\r\n }\r\n // Now load them\r\n for (var j = 0, lenj = children.length; j < lenj; j++) {\r\n var child2 = children[j];\r\n switch (child2.type) {\r\n case \"MaterialDomain\":\r\n if (child2.associatedFile) {\r\n (function () {\r\n var childId = child2.id;\r\n var src = stripURN(child2.associatedFile);\r\n ctx.zip.getFile(src, function (xmlDoc, json) {\r\n // ctx.plugin.log(\"Material def loaded: \" + src);\r\n ctx.materials[domainToReferenceMap[childId]] = parseMaterialDefDocument(ctx, json);\r\n\r\n if (--numToLoad === 0) {\r\n // console.log(\"All ReferenceReps loaded.\");\r\n ok();\r\n }\r\n },\r\n function (error) {\r\n // TODO:\r\n });\r\n })();\r\n }\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction parseMaterialDefDocument(ctx, node) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"Osm\":\r\n return parseMaterialDefDocumentOsm(ctx, child);\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction parseMaterialDefDocumentOsm(ctx, node) {\r\n var children = node.children;\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n var child = children[i];\r\n switch (child.type) {\r\n case \"RenderingRootFeature\":\r\n //..\r\n break;\r\n case \"Feature\":\r\n\r\n if (child.Alias === \"RenderingFeature\") {\r\n // Parse the coefficients, then parse the colors, scaling those by their coefficients.\r\n var coeffs = {};\r\n var materialCfg = {};\r\n var children2 = child.children;\r\n var j;\r\n var lenj;\r\n var child2;\r\n for (j = 0, lenj = children2.length; j < lenj; j++) {\r\n child2 = children2[j];\r\n switch (child2.Name) {\r\n case \"AmbientCoef\":\r\n coeffs.ambient = parseFloat(child2.Value);\r\n break;\r\n case \"DiffuseCoef\":\r\n coeffs.diffuse = parseFloat(child2.Value);\r\n break;\r\n case \"EmissiveCoef\":\r\n coeffs.emissive = parseFloat(child2.Value);\r\n break;\r\n case \"SpecularExponent\":\r\n coeffs.specular = parseFloat(child2.Value);\r\n break;\r\n }\r\n }\r\n for (j = 0, lenj = children2.length; j < lenj; j++) {\r\n child2 = children2[j];\r\n switch (child2.Name) {\r\n case \"AmbientColor\":\r\n materialCfg.ambient = parseRGB(child2.Value, coeffs.ambient);\r\n break;\r\n case \"DiffuseColor\":\r\n materialCfg.diffuse = parseRGB(child2.Value, coeffs.diffuse);\r\n break;\r\n case \"EmissiveColor\":\r\n materialCfg.emissive = parseRGB(child2.Value, coeffs.emissive);\r\n break;\r\n case \"SpecularColor\":\r\n materialCfg.specular = parseRGB(child2.Value, coeffs.specular);\r\n break;\r\n case \"Transparency\":\r\n var alpha = 1.0 - parseFloat(child2.Value); // GOTCHA: Degree of transparency, not degree of opacity\r\n if (alpha < 1.0) {\r\n materialCfg.alpha = alpha;\r\n materialCfg.alphaMode = \"blend\";\r\n }\r\n break;\r\n }\r\n }\r\n\r\n var material;\r\n\r\n switch (ctx.materialType) {\r\n case \"MetallicMaterial\":\r\n material = new _viewer_scene_materials_MetallicMaterial_js__WEBPACK_IMPORTED_MODULE_4__.MetallicMaterial(ctx.modelNode, {\r\n baseColor: materialCfg.diffuse,\r\n metallic: 0.7,\r\n roughness: 0.5,\r\n emissive: materialCfg.emissive,\r\n alpha: materialCfg.alpha,\r\n alphaMode: materialCfg.alphaMode\r\n });\r\n break;\r\n\r\n case \"SpecularMaterial\":\r\n material = new _viewer_scene_materials_SpecularMaterial_js__WEBPACK_IMPORTED_MODULE_5__.SpecularMaterial(ctx.modelNode, {\r\n diffuse: materialCfg.diffuse,\r\n specular: materialCfg.specular,\r\n glossiness: 0.5,\r\n emissive: materialCfg.emissive,\r\n alpha: materialCfg.alpha,\r\n alphaMode: materialCfg.alphaMode\r\n });\r\n break;\r\n\r\n default:\r\n material = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_3__.PhongMaterial(ctx.modelNode, {\r\n reflectivity: 0.5,\r\n ambient: materialCfg.ambient,\r\n diffuse: materialCfg.diffuse,\r\n specular: materialCfg.specular,\r\n // shininess: node.shine,\r\n emissive: materialCfg.emissive,\r\n alphaMode: materialCfg.alphaMode,\r\n alpha: node.alpha\r\n });\r\n }\r\n return material;\r\n }\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction parseRGB(str, coeff) {\r\n coeff = (coeff !== undefined) ? coeff : 0.5;\r\n var openBracketIndex = str.indexOf(\"[\");\r\n var closeBracketIndex = str.indexOf(\"]\");\r\n str = str.substring(openBracketIndex + 1, closeBracketIndex - openBracketIndex);\r\n str = str.split(\",\");\r\n var arr = new Float32Array(str.length);\r\n var arrIdx = 0;\r\n for (var i = 0, len = str.length; i < len; i++) {\r\n var value = str[i];\r\n value = value.trim().split(\" \");\r\n for (var j = 0, lenj = value.length; j < lenj; j++) {\r\n if (value[j] !== \"\") {\r\n arr[arrIdx++] = parseFloat(value[j]) * coeff;\r\n }\r\n }\r\n }\r\n return arr;\r\n}\r\n\r\n\r\n//----------------------------------------------------------------------------------------------------\r\n\r\n/**\r\n * Wraps zip.js to provide an in-memory ZIP archive representing the 3DXML file bundle.\r\n *\r\n * Allows us to pluck each file from it as XML and JSON.\r\n *\r\n * @constructor\r\n */\r\nvar ZIP = function () {\r\n\r\n var reader;\r\n var files = {};\r\n\r\n /**\r\n Loads this ZIP\r\n\r\n @param src\r\n @param ok\r\n @param error\r\n */\r\n this.load = function (src, ok, error) {\r\n var self = this;\r\n zip.createReader(new zip.HttpReader(src), function (reader) {\r\n reader.getEntries(function (entries) {\r\n if (entries.length > 0) {\r\n for (var i = 0, len = entries.length; i < len; i++) {\r\n var entry = entries[i];\r\n files[entry.filename] = entry;\r\n }\r\n }\r\n ok();\r\n });\r\n }, error);\r\n };\r\n\r\n /**\r\n Gets a file as XML and JSON from this ZIP\r\n @param src\r\n @param ok\r\n @param error\r\n */\r\n this.getFile = function (src, ok, error) {\r\n var entry = files[src];\r\n if (!entry) {\r\n var errMsg = \"ZIP entry not found: \" + src;\r\n console.error(errMsg);\r\n if (error) {\r\n error(errMsg);\r\n }\r\n return;\r\n }\r\n entry.getData(new zip.TextWriter(), function (text) {\r\n\r\n // Parse to XML\r\n var parser = new DOMParser();\r\n var xmlDoc = parser.parseFromString(text, \"text/xml\");\r\n\r\n // Parse to JSON\r\n var json = xmlToJSON(xmlDoc, {});\r\n\r\n ok(xmlDoc, json);\r\n });\r\n };\r\n\r\n function xmlToJSON(node, attributeRenamer) {\r\n if (node.nodeType === node.TEXT_NODE) {\r\n var v = node.nodeValue;\r\n if (v.match(/^\\s+$/) === null) {\r\n return v;\r\n }\r\n } else if (node.nodeType === node.ELEMENT_NODE ||\r\n node.nodeType === node.DOCUMENT_NODE) {\r\n var json = {type: node.nodeName, children: []};\r\n if (node.nodeType === node.ELEMENT_NODE) {\r\n for (var j = 0; j < node.attributes.length; j++) {\r\n var attribute = node.attributes[j];\r\n var nm = attributeRenamer[attribute.nodeName] || attribute.nodeName;\r\n json[nm] = attribute.nodeValue;\r\n }\r\n }\r\n for (var i = 0; i < node.childNodes.length; i++) {\r\n var item = node.childNodes[i];\r\n var j = xmlToJSON(item, attributeRenamer);\r\n if (j) json.children.push(j);\r\n }\r\n return json;\r\n }\r\n }\r\n\r\n /**\r\n Disposes of this ZIP\r\n */\r\n this.destroy = function () {\r\n reader.close(function () {\r\n // onclose callback\r\n });\r\n };\r\n};\r\n\r\nfunction\r\n\r\nloadZIP(src, ok, err) {\r\n var zip = new ZIP();\r\n zip.load(src, function () {\r\n ok(zip);\r\n }, function (errMsg) {\r\n err(\"Error loading ZIP archive: \" + errMsg);\r\n })\r\n}\r\n\r\nfunction\r\n\r\nstripURN(str) {\r\n var subStr = \"urn:3DXML:\";\r\n return (str.indexOf(subStr) === 0) ? str.substring(subStr.length) : str;\r\n}\r\n\r\n\r\nfunction\r\n\r\ngetIDFromURI(str) {\r\n var hashIdx = str.lastIndexOf(\"#\");\r\n return hashIdx !== -1 ? str.substring(hashIdx + 1) : str;\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/XML3DSceneGraphLoader.js?");
|
|
2107
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XML3DSceneGraphLoader: () => (/* binding */ XML3DSceneGraphLoader)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/nodes/Node.js */ \"./src/viewer/scene/nodes/Node.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_MetallicMaterial_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/materials/MetallicMaterial.js */ \"./src/viewer/scene/materials/MetallicMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_SpecularMaterial_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/materials/SpecularMaterial.js */ \"./src/viewer/scene/materials/SpecularMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_LambertMaterial_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/materials/LambertMaterial.js */ \"./src/viewer/scene/materials/LambertMaterial.js\");\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _zipjs_zip_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./zipjs/zip.js */ \"./src/plugins/XML3DLoaderPlugin/zipjs/zip.js\");\n/* harmony import */ var _zipjs_zip_ext_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./zipjs/zip-ext.js */ \"./src/plugins/XML3DLoaderPlugin/zipjs/zip-ext.js\");\n\n\n\n\n\n\n\n\n\n\n\n\nconst zip = _zipjs_zip_js__WEBPACK_IMPORTED_MODULE_8__.zipLib.zip;\n(0,_zipjs_zip_ext_js__WEBPACK_IMPORTED_MODULE_9__.zipExt)(zip);\n\nconst supportedSchemas = [\"4.2\"];\n\n/**\n * @private\n */\nclass XML3DSceneGraphLoader {\n\n constructor(plugin, cfg = {}) {\n\n /**\n * Supported 3DXML schema versions\n * @property supportedSchemas\n * @type {string[]}\n */\n this.supportedSchemas = supportedSchemas;\n\n this._xrayOpacity = 0.7;\n this._src = null;\n this._options = cfg;\n\n /**\n * Default viewpoint, containing eye, look and up vectors.\n * Only defined if found in the 3DXML file.\n * @property viewpoint\n * @type {Number[]}\n */\n this.viewpoint = null;\n\n if (!cfg.workerScriptsPath) {\n plugin.error(\"Config expected: workerScriptsPath\");\n return\n }\n zip.workerScriptsPath = cfg.workerScriptsPath;\n\n this.src = cfg.src;\n this.xrayOpacity = 0.7;\n this.displayEffect = cfg.displayEffect;\n this.createMetaModel = cfg.createMetaModel;\n }\n\n load(plugin, modelNode, src, options, ok, error) {\n\n switch (options.materialType) {\n case \"MetallicMaterial\":\n modelNode._defaultMaterial = new _viewer_scene_materials_MetallicMaterial_js__WEBPACK_IMPORTED_MODULE_4__.MetallicMaterial(modelNode, {\n baseColor: [1, 1, 1],\n metallic: 0.6,\n roughness: 0.6\n });\n break;\n\n case \"SpecularMaterial\":\n modelNode._defaultMaterial = new _viewer_scene_materials_SpecularMaterial_js__WEBPACK_IMPORTED_MODULE_5__.SpecularMaterial(modelNode, {\n diffuse: [1, 1, 1],\n specular: _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__.math.vec3([1.0, 1.0, 1.0]),\n glossiness: 0.5\n });\n break;\n\n default:\n modelNode._defaultMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_3__.PhongMaterial(modelNode, {\n reflectivity: 0.75,\n shiness: 100,\n diffuse: [1, 1, 1]\n });\n }\n\n modelNode._wireframeMaterial = new _viewer_scene_materials_LambertMaterial_js__WEBPACK_IMPORTED_MODULE_6__.LambertMaterial(modelNode, {\n color: [0, 0, 0],\n lineWidth: 2\n });\n\n var spinner = modelNode.scene.canvas.spinner;\n spinner.processes++;\n\n load3DXML(plugin, modelNode, src, options, function () {\n spinner.processes--;\n if (ok) {\n ok();\n }\n modelNode.fire(\"loaded\", true, false);\n },\n function (msg) {\n spinner.processes--;\n modelNode.error(msg);\n if (error) {\n error(msg);\n }\n /**\n Fired whenever this XML3D fails to load the 3DXML file\n specified by {@link XML3D/src}.\n @event error\n @param msg {String} Description of the error\n */\n modelNode.fire(\"error\", msg);\n },\n function (err) {\n console.log(\"Error, Will Robinson: \" + err);\n });\n }\n}\n\nvar load3DXML = (function () {\n return function (plugin, modelNode, src, options, ok, error) {\n loadZIP(src, function (zip) { // OK\n parse3DXML(plugin, zip, options, modelNode, ok, error);\n },\n error);\n };\n})();\n\nvar parse3DXML = (function () {\n return function (plugin, zip, options, modelNode, ok) {\n var ctx = {\n plugin: plugin,\n zip: zip,\n edgeThreshold: 30, // Guess at degrees of normal deviation between adjacent tris below which we remove edge between them\n materialType: options.materialType,\n scene: modelNode.scene,\n modelNode: modelNode,\n info: {\n references: {}\n },\n materials: {}\n };\n\n if (options.createMetaModel) {\n ctx.metaModelData = {\n modelId: modelNode.id,\n metaObjects: [{\n name: modelNode.id,\n type: \"Default\",\n id: modelNode.id\n }]\n };\n }\n modelNode.scene.loading++; // Disables (re)compilation\n\n parseDocument(ctx, function () {\n if (ctx.metaModelData) {\n plugin.viewer.metaScene.createMetaModel(modelNode.id, ctx.metaModelData);\n }\n modelNode.scene.loading--; // Re-enables (re)compilation\n ok();\n });\n };\n\n function parseDocument(ctx, ok) {\n ctx.zip.getFile(\"Manifest.xml\", function (xmlDoc, json) {\n var node = json;\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Manifest\":\n parseManifest(ctx, child, ok);\n break;\n }\n }\n });\n }\n\n function parseManifest(ctx, manifest, ok) {\n var children = manifest.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Root\":\n var rootFileSrc = child.children[0];\n ctx.zip.getFile(rootFileSrc, function (xmlDoc, json) {\n parseRoot(ctx, json, ok);\n });\n break;\n }\n }\n }\n\n function parseRoot(ctx, node, ok) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Model_3dxml\":\n parseModel(ctx, child, ok);\n break;\n }\n }\n }\n\n function parseModel(ctx, node, ok) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Header\":\n parseHeader(ctx, child);\n break;\n case \"ProductStructure\":\n parseProductStructure(ctx, child, ok);\n break;\n case \"DefaultView\":\n parseDefaultView(ctx, child);\n break;\n }\n }\n }\n\n function parseHeader(ctx, node) {\n var children = node.children;\n var metaData = {};\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"SchemaVersion\":\n metaData.schemaVersion = child.children[0];\n if (!isSchemaVersionSupported(ctx, metaData.schemaVersion)) {\n ctx.plugin.error(\"Schema version not supported: \" + metaData.schemaVersion + \" - supported versions are: \" + supportedSchemas.join(\",\"));\n } else {\n //ctx.plugin.log(\"Parsing schema version: \" + metaData.schemaVersion);\n }\n break;\n case \"Title\":\n metaData.title = child.children[0];\n break;\n case \"Author\":\n metaData.author = child.children[0];\n break;\n case \"Created\":\n metaData.created = child.children[0];\n break;\n }\n }\n ctx.modelNode.meta = metaData;\n }\n\n function isSchemaVersionSupported(ctx, schemaVersion) {\n for (var i = 0, len = supportedSchemas.length; i < len; i++) {\n if (schemaVersion === supportedSchemas[i]) {\n return true;\n }\n }\n return false;\n }\n\n function parseProductStructure(ctx, productStructureNode, ok) {\n\n parseReferenceReps(ctx, productStructureNode, function (referenceReps) {\n\n // Parse out an intermediate scene DAG representation, that we can then\n // recursive descend through to build a xeokit Object hierarchy.\n\n var children = productStructureNode.children;\n\n var reference3Ds = {};\n var instanceReps = {};\n var instance3Ds = {};\n\n var rootNode;\n var nodes = {};\n\n // Map all the elements\n\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n\n case \"Reference3D\":\n reference3Ds[child.id] = {\n type: \"Reference3D\",\n id: child.id,\n name: child.name,\n instance3Ds: {},\n instanceReps: {}\n };\n break;\n\n case \"InstanceRep\":\n var isAggregatedBy;\n var isInstanceOf;\n var relativeMatrix;\n for (var j = 0, lenj = child.children.length; j < lenj; j++) {\n var child2 = child.children[j];\n switch (child2.type) {\n case \"IsAggregatedBy\":\n isAggregatedBy = child2.children[0];\n break;\n case \"IsInstanceOf\":\n isInstanceOf = child2.children[0];\n break;\n }\n }\n instanceReps[child.id] = {\n type: \"InstanceRep\",\n id: child.id,\n name: child.name,\n isAggregatedBy: isAggregatedBy,\n isInstanceOf: isInstanceOf,\n referenceReps: {}\n };\n break;\n\n case \"Instance3D\":\n var isAggregatedBy;\n var isInstanceOf;\n var relativeMatrix;\n for (var j = 0, lenj = child.children.length; j < lenj; j++) {\n var child2 = child.children[j];\n switch (child2.type) {\n case \"IsAggregatedBy\":\n isAggregatedBy = child2.children[0];\n break;\n case \"IsInstanceOf\":\n isInstanceOf = child2.children[0];\n break;\n case \"RelativeMatrix\":\n relativeMatrix = child2.children[0];\n break;\n }\n }\n instance3Ds[child.id] = {\n type: \"Instance3D\",\n id: child.id,\n name: child.name,\n isAggregatedBy: isAggregatedBy,\n isInstanceOf: isInstanceOf,\n relativeMatrix: relativeMatrix,\n reference3Ds: {}\n };\n break;\n }\n }\n\n // Connect Reference3Ds to the Instance3Ds they aggregate\n\n for (var id in instance3Ds) {\n var instance3D = instance3Ds[id];\n var reference3D = reference3Ds[instance3D.isAggregatedBy];\n if (reference3D) {\n reference3D.instance3Ds[instance3D.id] = instance3D;\n } else {\n alert(\"foo\")\n }\n }\n\n // Connect Instance3Ds to the Reference3Ds they instantiate\n\n for (var id in instance3Ds) {\n var instance3D = instance3Ds[id];\n var reference3D = reference3Ds[instance3D.isInstanceOf];\n instance3D.reference3Ds[reference3D.id] = reference3D;\n reference3D.instance3D = instance3D;\n }\n\n // Connect InstanceReps to the ReferenceReps they instantiate\n\n for (var id in instanceReps) {\n var instanceRep = instanceReps[id];\n var referenceRep = referenceReps[instanceRep.isInstanceOf];\n if (referenceRep) {\n instanceRep.referenceReps[referenceRep.id] = referenceRep;\n }\n }\n\n // Connect Reference3Ds to the InstanceReps they aggregate\n\n for (var id in instanceReps) {\n var instanceRep = instanceReps[id];\n var reference3D = reference3Ds[instanceRep.isAggregatedBy];\n if (reference3D) {\n reference3D.instanceReps[instanceRep.id] = instanceRep;\n }\n }\n\n function parseReference3D(ctx, reference3D, group) {\n //ctx.plugin.log(\"parseReference3D( \" + reference3D.id + \" )\");\n for (var id in reference3D.instance3Ds) {\n parseInstance3D(ctx, reference3D.instance3Ds[id], group);\n }\n for (var id in reference3D.instanceReps) {\n parseInstanceRep(ctx, reference3D.instanceReps[id], group);\n }\n }\n\n function parseInstance3D(ctx, instance3D, group) {\n //ctx.plugin.log(\"parseInstance3D( \" + instance3D.id + \" )\");\n\n if (instance3D.relativeMatrix) {\n var matrix = parseFloatArray(instance3D.relativeMatrix, 12);\n var translate = [matrix[9], matrix[10], matrix[11]];\n var mat3 = matrix.slice(0, 9); // Rotation matrix\n var mat4 = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__.math.mat3ToMat4(mat3, _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_7__.math.identityMat4()); // Convert rotation matrix to 4x4\n var childGroup = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__.Node(ctx.modelNode, {\n position: translate\n });\n if (ctx.metaModelData) {\n ctx.metaModelData.metaObjects.push({\n id: childGroup.id,\n type: \"Default\",\n name: instance3D.name,\n parent: group ? group.id : ctx.modelNode.id\n });\n }\n if (group) {\n group.addChild(childGroup, true);\n } else {\n ctx.modelNode.addChild(childGroup, true);\n }\n group = childGroup;\n childGroup = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__.Node(ctx.modelNode, {\n matrix: mat4\n });\n if (ctx.metaModelData) {\n ctx.metaModelData.metaObjects.push({\n id: childGroup.id,\n type: \"Default\",\n name: instance3D.name,\n parent: group ? group.id : ctx.modelNode.id\n });\n }\n group.addChild(childGroup, true);\n group = childGroup;\n } else {\n var childGroup = new _viewer_scene_nodes_Node_js__WEBPACK_IMPORTED_MODULE_0__.Node(ctx.modelNode, {});\n if (ctx.metaModelData) {\n ctx.metaModelData.metaObjects.push({\n id: childGroup.id,\n type: \"Default\",\n name: instance3D.name,\n parent: group ? group.id : ctx.modelNode.id\n });\n }\n if (group) {\n group.addChild(childGroup, true);\n } else {\n ctx.modelNode.addChild(childGroup, true);\n }\n group = childGroup;\n }\n for (var id in instance3D.reference3Ds) {\n parseReference3D(ctx, instance3D.reference3Ds[id], group);\n }\n }\n\n function parseInstanceRep(ctx, instanceRep, group) {\n //ctx.plugin.log(\"parseInstanceRep( \" + instanceRep.id + \" )\");\n if (instanceRep.referenceReps) {\n for (var id in instanceRep.referenceReps) {\n var referenceRep = instanceRep.referenceReps[id];\n for (var id2 in referenceRep) {\n if (id2 === \"id\") {\n continue; // HACK\n }\n var meshCfg = referenceRep[id2];\n var lines = meshCfg.geometry.primitive === \"lines\";\n var material = lines ? ctx.modelNode._wireframeMaterial : (meshCfg.materialId ? ctx.materials[meshCfg.materialId] : null);\n var colorize = meshCfg.color;\n var mesh = new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_1__.Mesh(ctx.modelNode, {\n isObject: true,\n geometry: meshCfg.geometry,\n material: material || ctx.modelNode._defaultMaterial,\n colorize: colorize,\n backfaces: false\n });\n if (ctx.metaModelData) {\n ctx.metaModelData.metaObjects.push({\n id: mesh.id,\n type: \"Default\",\n name: instanceRep.name,\n parent: group ? group.id : ctx.modelNode.id\n });\n }\n if (group) {\n group.addChild(mesh, true);\n } else {\n ctx.modelNode.addChild(mesh, true);\n }\n mesh.colorize = colorize; // HACK: Mesh has inherited modelNode's colorize state, so we need to restore it (we'd better not modify colorize on the modelNode).\n }\n }\n }\n }\n\n // Find the root Reference3D\n\n for (var id in reference3Ds) {\n var reference3D = reference3Ds[id];\n if (!reference3D.instance3D) {\n parseReference3D(ctx, reference3D, null); // HACK: Assuming that root has id == \"1\"\n ok();\n return;\n }\n }\n\n alert(\"No root Reference3D element found in this modelNode - can't load.\");\n\n ok();\n });\n }\n\n function parseIntArray(str) {\n var parts = str.trim().split(\" \");\n var result = new Int32Array(parts.length);\n for (var i = 0; i < parts.length; i++) {\n result[i] = parseInt(parts[i]);\n }\n return result;\n }\n\n function parseReferenceReps(ctx, node, ok) {\n var referenceReps = {};\n var children = node.children;\n var numToLoad = 0;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n if (child.type === \"ReferenceRep\") {\n numToLoad++;\n }\n }\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"ReferenceRep\":\n if (child.associatedFile) {\n var src = stripURN(child.associatedFile);\n (function () {\n var childId = child.id;\n ctx.zip.getFile(src, function (xmlDoc, json) {\n\n var materialIds = xmlDoc.getElementsByTagName(\"MaterialId\");\n\n loadCATMaterialRefDocuments(ctx, materialIds, function () {\n\n // ctx.plugin.log(\"reference loaded: \" + src);\n var referenceRep = {\n id: childId\n };\n parse3DRepDocument(ctx, json, referenceRep);\n referenceReps[childId] = referenceRep;\n if (--numToLoad === 0) {\n ok(referenceReps);\n }\n });\n },\n function (error) {\n // TODO:\n });\n })();\n }\n break;\n }\n }\n }\n\n\n function parseDefaultView(ctx, node) {\n // ctx.plugin.log(\"parseDefaultView\");\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Viewpoint\":\n var children2 = child.children;\n ctx.modelNode.viewpoint = {};\n for (var i2 = 0, len2 = children2.length; i2 < len2; i2++) {\n var child2 = children2[i];\n switch (child2.type) {\n case \"Position\":\n ctx.modelNode.viewpoint.eye = parseFloatArray(child2.children[0], 3);\n break;\n case \"Sight\":\n ctx.modelNode.viewpoint.look = parseFloatArray(child2.children[0], 3);\n break;\n case \"Up\":\n ctx.modelNode.viewpoint.up = parseFloatArray(child2.children[0], 3);\n break;\n }\n }\n break;\n case \"DefaultViewProperty\":\n break;\n }\n }\n }\n\n function parse3DRepDocument(ctx, node, result) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"XMLRepresentation\":\n parseXMLRepresentation(ctx, child, result);\n break;\n }\n }\n }\n\n function parseXMLRepresentation(ctx, node, result) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Root\":\n parse3DRepRoot(ctx, child, result);\n break;\n }\n }\n }\n\n function parse3DRepRoot(ctx, node, result) {\n switch (node[\"xsi:type\"]) {\n case \"BagRepType\":\n break;\n case \"PolygonalRepType\":\n break;\n }\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Rep\":\n parse3DRepRep(ctx, child, result);\n break;\n }\n }\n }\n\n function parse3DRepRep(ctx, node, result) {\n switch (node[\"xsi:type\"]) {\n case \"BagRepType\":\n break;\n case \"PolygonalRepType\":\n break;\n }\n var meshesResult = {\n edgeThreshold: ctx.edgeThreshold || 30,\n compressGeometry: true\n };\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Rep\":\n parse3DRepRep(ctx, child, result);\n break;\n case \"Edges\":\n // Ignoring edges because we auto-generate our own using xeokit\n break;\n case \"Faces\":\n meshesResult.primitive = \"triangles\";\n parseFaces(ctx, child, meshesResult);\n break;\n case \"VertexBuffer\":\n parseVertexBuffer(ctx, child, meshesResult);\n break;\n case \"SurfaceAttributes\":\n parseSurfaceAttributes(ctx, child, meshesResult);\n break;\n }\n }\n if (meshesResult.positions) {\n var geometry = new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_2__.ReadableGeometry(ctx.modelNode, meshesResult);\n result[geometry.id] = {\n geometry: geometry,\n color: meshesResult.color || [1.0, 1.0, 1.0, 1.0],\n materialId: meshesResult.materialId\n };\n }\n }\n\n function parseEdges(ctx, node, result) {\n result.positions = [];\n result.indices = [];\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Polyline\":\n parsePolyline(ctx, child, result);\n break;\n }\n }\n }\n\n function parsePolyline(ctx, node, result) {\n var vertices = node.vertices;\n if (vertices) {\n var positions = parseFloatArray(vertices, 3);\n if (positions.length > 0) {\n var positionsOffset = result.positions.length / 3;\n for (var i = 0, len = positions.length; i < len; i++) {\n result.positions.push(positions[i]);\n }\n for (var i = 0, len = (positions.length / 3) - 1; i < len; i++) {\n result.indices.push(positionsOffset + i);\n result.indices.push(positionsOffset + i + 1);\n }\n }\n }\n }\n\n function parseFaces(ctx, node, result) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Face\":\n parseFace(ctx, child, result);\n break;\n }\n }\n }\n\n function parseFace(ctx, node, result) {\n var strips = node.strips;\n if (strips) {\n // Triangle strips\n var arrays = parseIntArrays(strips);\n if (arrays.length > 0) {\n result.primitive = \"triangles\";\n var indices = [];\n for (var i = 0, len = arrays.length; i < len; i++) {\n var array = convertTriangleStrip(arrays[i]);\n for (var j = 0, lenj = array.length; j < lenj; j++) {\n indices.push(array[j]);\n }\n }\n result.indices = indices; // TODO\n }\n } else {\n // Triangle meshes\n var triangles = node.triangles;\n if (triangles) {\n result.primitive = \"triangles\";\n result.indices = parseIntArray(triangles);\n }\n }\n // Material\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"SurfaceAttributes\":\n parseSurfaceAttributes(ctx, child, result);\n break;\n }\n }\n }\n\n function convertTriangleStrip(indices) {\n var ccw = false;\n var indices2 = [];\n for (var i = 0, len = indices.length; i < len - 2; i++) {\n if (ccw) {\n if (i & 1) { //\n indices2.push(indices[i]);\n indices2.push(indices[i + 1]);\n indices2.push(indices[i + 2]);\n } else {\n indices2.push(indices[i]);\n indices2.push(indices[i + 2]);\n indices2.push(indices[i + 1]);\n }\n } else {\n if (i & 1) { //\n indices2.push(indices[i]);\n indices2.push(indices[i + 2]);\n indices2.push(indices[i + 1]);\n } else {\n indices2.push(indices[i]);\n indices2.push(indices[i + 1]);\n indices2.push(indices[i + 2]);\n }\n }\n }\n return indices2;\n }\n\n function parseVertexBuffer(ctx, node, result) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Positions\":\n result.positions = parseFloatArray(child.children[0], 3);\n break;\n case \"Normals\":\n result.normals = parseFloatArray(child.children[0], 3);\n break;\n case \"TextureCoordinates\": // TODO: Support dimension and channel?\n result.uv = parseFloatArray(child.children[0], 2);\n break;\n }\n }\n }\n\n function parseIntArrays(str) {\n var coordStrings = str.split(\",\");\n var array = [];\n for (var i = 0, len = coordStrings.length; i < len; i++) {\n var coordStr = coordStrings[i].trim();\n if (coordStr.length > 0) {\n var elemStrings = coordStr.trim().split(\" \");\n var arr = new Int16Array(elemStrings.length);\n var arrIdx = 0;\n for (var j = 0, lenj = elemStrings.length; j < lenj; j++) {\n if (elemStrings[j] !== \"\") {\n arr[arrIdx++] = parseInt(elemStrings[j]);\n }\n }\n array.push(arr);\n }\n }\n return array;\n }\n\n function parseFloatArray(str, numElems) {\n str = str.split(\",\");\n var arr = new Float32Array(str.length * numElems);\n var arrIdx = 0;\n for (var i = 0, len = str.length; i < len; i++) {\n var value = str[i];\n value = value.split(\" \");\n for (var j = 0, lenj = value.length; j < lenj; j++) {\n if (value[j] !== \"\") {\n arr[arrIdx++] = parseFloat(value[j]);\n }\n }\n }\n return arr;\n }\n\n function parseIntArray(str) {\n str = str.trim().split(\" \");\n var arr = new Int32Array(str.length);\n var arrIdx = 0;\n for (var i = 0, len = str.length; i < len; i++) {\n var value = str[i];\n arr[i] = parseInt(value);\n }\n return arr;\n }\n\n function parseSurfaceAttributes(ctx, node, result) {\n result.color = [1, 1, 1, 1];\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Color\":\n result.color[0] = child.red;\n result.color[1] = child.green;\n result.color[2] = child.blue;\n result.color[3] = child.alpha;\n break;\n case \"MaterialApplication\":\n var children2 = child.children;\n for (var j = 0, lenj = children2.length; j < lenj; j++) {\n var child2 = children2[j];\n switch (child2.type) {\n case \"MaterialId\":\n var materialId = getIDFromURI(child2.id);\n var material = ctx.materials[materialId];\n if (!material) {\n ctx.plugin.error(\"material not found: \" + materialId);\n }\n result.materialId = materialId;\n break;\n }\n }\n break;\n }\n }\n }\n})();\n\nfunction loadCATMaterialRefDocuments(ctx, materialIds, ok) {\n var loaded = {};\n\n function load(i, done) {\n if (i >= materialIds.length) {\n ok();\n return;\n }\n var materialId = materialIds[i];\n var src = materialId.id;\n var colonIdx = src.lastIndexOf(\":\");\n if (colonIdx > 0) {\n src = src.substring(colonIdx + 1);\n }\n var hashIdx = src.lastIndexOf(\"#\");\n if (hashIdx > 0) {\n src = src.substring(0, hashIdx);\n }\n if (!loaded[src]) {\n loadCATMaterialRefDocument(ctx, src, function () {\n loaded[src] = true;\n load(i + 1, done);\n });\n } else {\n load(i + 1, done);\n }\n }\n\n load(0, ok);\n}\n\nfunction loadCATMaterialRefDocument(ctx, src, ok) { // Loads CATMaterialRef.3dxml\n ctx.zip.getFile(src, function (xmlDoc, json) {\n parseCATMaterialRefDocument(ctx, json, ok);\n });\n}\n\nfunction parseCATMaterialRefDocument(ctx, node, ok) { // Parse CATMaterialRef.3dxml\n // ctx.plugin.log(\"parseCATMaterialRefDocument\");\n var children = node.children;\n var child;\n for (var i = 0, len = children.length; i < len; i++) {\n child = children[i];\n if (child.type === \"Model_3dxml\") {\n parseModel_3dxml(ctx, child, ok);\n }\n }\n}\n\nfunction parseModel_3dxml(ctx, node, ok) { // Parse CATMaterialRef.3dxml\n // ctx.plugin.log(\"parseModel_3dxml\");\n var children = node.children;\n var child;\n for (var i = 0, len = children.length; i < len; i++) {\n child = children[i];\n if (child.type === \"CATMaterialRef\") {\n parseCATMaterialRef(ctx, child, ok);\n }\n }\n}\n\nfunction parseCATMaterialRef(ctx, node, ok) {\n var domainToReferenceMap = {};\n var materials = {};\n var result = {};\n var children = node.children;\n var child;\n var numToLoad = 0;\n for (var j = 0, lenj = children.length; j < lenj; j++) {\n var child2 = children[j];\n switch (child2.type) {\n case \"MaterialDomainInstance\":\n var isAggregatedBy;\n var isInstanceOf;\n for (var k = 0, lenk = child2.children.length; k < lenk; k++) {\n var child3 = child2.children[k];\n switch (child3.type) {\n case \"IsAggregatedBy\":\n isAggregatedBy = child3.children[0];\n break;\n case \"IsInstanceOf\":\n isInstanceOf = child3.children[0];\n break;\n }\n }\n domainToReferenceMap[isInstanceOf] = isAggregatedBy;\n break;\n }\n }\n for (var j = 0, lenj = children.length; j < lenj; j++) {\n var child2 = children[j];\n switch (child2.type) {\n case \"MaterialDomain\":\n numToLoad++;\n break;\n }\n }\n // Now load them\n for (var j = 0, lenj = children.length; j < lenj; j++) {\n var child2 = children[j];\n switch (child2.type) {\n case \"MaterialDomain\":\n if (child2.associatedFile) {\n (function () {\n var childId = child2.id;\n var src = stripURN(child2.associatedFile);\n ctx.zip.getFile(src, function (xmlDoc, json) {\n // ctx.plugin.log(\"Material def loaded: \" + src);\n ctx.materials[domainToReferenceMap[childId]] = parseMaterialDefDocument(ctx, json);\n\n if (--numToLoad === 0) {\n // console.log(\"All ReferenceReps loaded.\");\n ok();\n }\n },\n function (error) {\n // TODO:\n });\n })();\n }\n break;\n }\n }\n}\n\nfunction parseMaterialDefDocument(ctx, node) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"Osm\":\n return parseMaterialDefDocumentOsm(ctx, child);\n break;\n }\n }\n}\n\nfunction parseMaterialDefDocumentOsm(ctx, node) {\n var children = node.children;\n for (var i = 0, len = children.length; i < len; i++) {\n var child = children[i];\n switch (child.type) {\n case \"RenderingRootFeature\":\n //..\n break;\n case \"Feature\":\n\n if (child.Alias === \"RenderingFeature\") {\n // Parse the coefficients, then parse the colors, scaling those by their coefficients.\n var coeffs = {};\n var materialCfg = {};\n var children2 = child.children;\n var j;\n var lenj;\n var child2;\n for (j = 0, lenj = children2.length; j < lenj; j++) {\n child2 = children2[j];\n switch (child2.Name) {\n case \"AmbientCoef\":\n coeffs.ambient = parseFloat(child2.Value);\n break;\n case \"DiffuseCoef\":\n coeffs.diffuse = parseFloat(child2.Value);\n break;\n case \"EmissiveCoef\":\n coeffs.emissive = parseFloat(child2.Value);\n break;\n case \"SpecularExponent\":\n coeffs.specular = parseFloat(child2.Value);\n break;\n }\n }\n for (j = 0, lenj = children2.length; j < lenj; j++) {\n child2 = children2[j];\n switch (child2.Name) {\n case \"AmbientColor\":\n materialCfg.ambient = parseRGB(child2.Value, coeffs.ambient);\n break;\n case \"DiffuseColor\":\n materialCfg.diffuse = parseRGB(child2.Value, coeffs.diffuse);\n break;\n case \"EmissiveColor\":\n materialCfg.emissive = parseRGB(child2.Value, coeffs.emissive);\n break;\n case \"SpecularColor\":\n materialCfg.specular = parseRGB(child2.Value, coeffs.specular);\n break;\n case \"Transparency\":\n var alpha = 1.0 - parseFloat(child2.Value); // GOTCHA: Degree of transparency, not degree of opacity\n if (alpha < 1.0) {\n materialCfg.alpha = alpha;\n materialCfg.alphaMode = \"blend\";\n }\n break;\n }\n }\n\n var material;\n\n switch (ctx.materialType) {\n case \"MetallicMaterial\":\n material = new _viewer_scene_materials_MetallicMaterial_js__WEBPACK_IMPORTED_MODULE_4__.MetallicMaterial(ctx.modelNode, {\n baseColor: materialCfg.diffuse,\n metallic: 0.7,\n roughness: 0.5,\n emissive: materialCfg.emissive,\n alpha: materialCfg.alpha,\n alphaMode: materialCfg.alphaMode\n });\n break;\n\n case \"SpecularMaterial\":\n material = new _viewer_scene_materials_SpecularMaterial_js__WEBPACK_IMPORTED_MODULE_5__.SpecularMaterial(ctx.modelNode, {\n diffuse: materialCfg.diffuse,\n specular: materialCfg.specular,\n glossiness: 0.5,\n emissive: materialCfg.emissive,\n alpha: materialCfg.alpha,\n alphaMode: materialCfg.alphaMode\n });\n break;\n\n default:\n material = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_3__.PhongMaterial(ctx.modelNode, {\n reflectivity: 0.5,\n ambient: materialCfg.ambient,\n diffuse: materialCfg.diffuse,\n specular: materialCfg.specular,\n // shininess: node.shine,\n emissive: materialCfg.emissive,\n alphaMode: materialCfg.alphaMode,\n alpha: node.alpha\n });\n }\n return material;\n }\n break;\n }\n }\n}\n\nfunction parseRGB(str, coeff) {\n coeff = (coeff !== undefined) ? coeff : 0.5;\n var openBracketIndex = str.indexOf(\"[\");\n var closeBracketIndex = str.indexOf(\"]\");\n str = str.substring(openBracketIndex + 1, closeBracketIndex - openBracketIndex);\n str = str.split(\",\");\n var arr = new Float32Array(str.length);\n var arrIdx = 0;\n for (var i = 0, len = str.length; i < len; i++) {\n var value = str[i];\n value = value.trim().split(\" \");\n for (var j = 0, lenj = value.length; j < lenj; j++) {\n if (value[j] !== \"\") {\n arr[arrIdx++] = parseFloat(value[j]) * coeff;\n }\n }\n }\n return arr;\n}\n\n\n//----------------------------------------------------------------------------------------------------\n\n/**\n * Wraps zip.js to provide an in-memory ZIP archive representing the 3DXML file bundle.\n *\n * Allows us to pluck each file from it as XML and JSON.\n *\n * @constructor\n */\nvar ZIP = function () {\n\n var reader;\n var files = {};\n\n /**\n Loads this ZIP\n\n @param src\n @param ok\n @param error\n */\n this.load = function (src, ok, error) {\n var self = this;\n zip.createReader(new zip.HttpReader(src), function (reader) {\n reader.getEntries(function (entries) {\n if (entries.length > 0) {\n for (var i = 0, len = entries.length; i < len; i++) {\n var entry = entries[i];\n files[entry.filename] = entry;\n }\n }\n ok();\n });\n }, error);\n };\n\n /**\n Gets a file as XML and JSON from this ZIP\n @param src\n @param ok\n @param error\n */\n this.getFile = function (src, ok, error) {\n var entry = files[src];\n if (!entry) {\n var errMsg = \"ZIP entry not found: \" + src;\n console.error(errMsg);\n if (error) {\n error(errMsg);\n }\n return;\n }\n entry.getData(new zip.TextWriter(), function (text) {\n\n // Parse to XML\n var parser = new DOMParser();\n var xmlDoc = parser.parseFromString(text, \"text/xml\");\n\n // Parse to JSON\n var json = xmlToJSON(xmlDoc, {});\n\n ok(xmlDoc, json);\n });\n };\n\n function xmlToJSON(node, attributeRenamer) {\n if (node.nodeType === node.TEXT_NODE) {\n var v = node.nodeValue;\n if (v.match(/^\\s+$/) === null) {\n return v;\n }\n } else if (node.nodeType === node.ELEMENT_NODE ||\n node.nodeType === node.DOCUMENT_NODE) {\n var json = {type: node.nodeName, children: []};\n if (node.nodeType === node.ELEMENT_NODE) {\n for (var j = 0; j < node.attributes.length; j++) {\n var attribute = node.attributes[j];\n var nm = attributeRenamer[attribute.nodeName] || attribute.nodeName;\n json[nm] = attribute.nodeValue;\n }\n }\n for (var i = 0; i < node.childNodes.length; i++) {\n var item = node.childNodes[i];\n var j = xmlToJSON(item, attributeRenamer);\n if (j) json.children.push(j);\n }\n return json;\n }\n }\n\n /**\n Disposes of this ZIP\n */\n this.destroy = function () {\n reader.close(function () {\n // onclose callback\n });\n };\n};\n\nfunction\n\nloadZIP(src, ok, err) {\n var zip = new ZIP();\n zip.load(src, function () {\n ok(zip);\n }, function (errMsg) {\n err(\"Error loading ZIP archive: \" + errMsg);\n })\n}\n\nfunction\n\nstripURN(str) {\n var subStr = \"urn:3DXML:\";\n return (str.indexOf(subStr) === 0) ? str.substring(subStr.length) : str;\n}\n\n\nfunction\n\ngetIDFromURI(str) {\n var hashIdx = str.lastIndexOf(\"#\");\n return hashIdx !== -1 ? str.substring(hashIdx + 1) : str;\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/XML3DSceneGraphLoader.js?");
|
|
2108
2108
|
|
|
2109
2109
|
/***/ }),
|
|
2110
2110
|
|
|
@@ -2124,7 +2124,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2124
2124
|
\********************************************************/
|
|
2125
2125
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2126
2126
|
|
|
2127
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ zipExt: () => (/* binding */ zipExt)\n/* harmony export */ });\n/*\
|
|
2127
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ zipExt: () => (/* binding */ zipExt)\n/* harmony export */ });\n/*\n Copyright (c) 2013 Gildas Lormeau. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n\n 2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n\n 3. The names of the authors may not be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/**\n * @private\n */\nconst zipExt = function(zipObj) {\n\n\tvar ERR_HTTP_RANGE = \"HTTP Range not supported.\";\n\n\tvar Reader = zipObj.Reader;\n\tvar Writer = zipObj.Writer;\n\n\tvar ZipDirectoryEntry;\n\n\tvar appendABViewSupported;\n\ttry {\n\t\tappendABViewSupported = new Blob([new DataView(new ArrayBuffer(0))]).size === 0;\n\t} catch (e) {\n\t}\n\n\tfunction isHttpFamily(url) {\n\t\tvar a = document.createElement(\"a\");\n\t\ta.href = url;\n\t\treturn a.protocol === \"http:\" || a.protocol === \"https:\";\n\t}\n\n\tfunction HttpReader(url) {\n\t\tvar that = this;\n\n\t\tfunction getData(callback, onerror) {\n\t\t\tvar request;\n\t\t\tif (!that.data) {\n\t\t\t\trequest = new XMLHttpRequest();\n\t\t\t\trequest.addEventListener(\"load\", function () {\n\t\t\t\t\tif (!that.size)\n\t\t\t\t\t\tthat.size = Number(request.getResponseHeader(\"Content-Length\")) || Number(request.response.byteLength);\n\t\t\t\t\tthat.data = new Uint8Array(request.response);\n\t\t\t\t\tcallback();\n\t\t\t\t}, false);\n\t\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\t\trequest.open(\"GET\", url);\n\t\t\t\trequest.responseType = \"arraybuffer\";\n\t\t\t\trequest.send();\n\t\t\t} else\n\t\t\t\tcallback();\n\t\t}\n\n\t\tfunction init(callback, onerror) {\n\t\t\tif (!isHttpFamily(url)) {\n\t\t\t\t// For schemas other than http(s), HTTP HEAD may be unavailable,\n\t\t\t\t// so use HTTP GET instead.\n\t\t\t\tgetData(callback, onerror);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar request = new XMLHttpRequest();\n\t\t\trequest.addEventListener(\"load\", function () {\n\t\t\t\tthat.size = Number(request.getResponseHeader(\"Content-Length\"));\n\t\t\t\t// If response header doesn't return size then prefetch the content.\n\t\t\t\tif (!that.size) {\n\t\t\t\t\tgetData(callback, onerror);\n\t\t\t\t} else {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}, false);\n\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\trequest.open(\"HEAD\", url);\n\t\t\trequest.send();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\tgetData(function () {\n\t\t\t\tcallback(new Uint8Array(that.data.subarray(index, index + length)));\n\t\t\t}, onerror);\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\n\tHttpReader.prototype = new Reader();\n\tHttpReader.prototype.constructor = HttpReader;\n\n\tfunction HttpRangeReader(url) {\n\t\tvar that = this;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tvar request = new XMLHttpRequest();\n\t\t\trequest.addEventListener(\"load\", function () {\n\t\t\t\tthat.size = Number(request.getResponseHeader(\"Content-Length\"));\n\t\t\t\tif (request.getResponseHeader(\"Accept-Ranges\") == \"bytes\")\n\t\t\t\t\tcallback();\n\t\t\t\telse\n\t\t\t\t\tonerror(ERR_HTTP_RANGE);\n\t\t\t}, false);\n\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\trequest.open(\"HEAD\", url);\n\t\t\trequest.send();\n\t\t}\n\n\t\tfunction readArrayBuffer(index, length, callback, onerror) {\n\t\t\tvar request = new XMLHttpRequest();\n\t\t\trequest.open(\"GET\", url);\n\t\t\trequest.responseType = \"arraybuffer\";\n\t\t\trequest.setRequestHeader(\"Range\", \"bytes=\" + index + \"-\" + (index + length - 1));\n\t\t\trequest.addEventListener(\"load\", function () {\n\t\t\t\tcallback(request.response);\n\t\t\t}, false);\n\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\trequest.send();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\treadArrayBuffer(index, length, function (arraybuffer) {\n\t\t\t\tcallback(new Uint8Array(arraybuffer));\n\t\t\t}, onerror);\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\n\tHttpRangeReader.prototype = new Reader();\n\tHttpRangeReader.prototype.constructor = HttpRangeReader;\n\n\tfunction ArrayBufferReader(arrayBuffer) {\n\t\tvar that = this;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tthat.size = arrayBuffer.byteLength;\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\tcallback(new Uint8Array(arrayBuffer.slice(index, index + length)));\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\n\tArrayBufferReader.prototype = new Reader();\n\tArrayBufferReader.prototype.constructor = ArrayBufferReader;\n\n\tfunction ArrayBufferWriter() {\n\t\tvar array, that = this;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tarray = new Uint8Array();\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction writeUint8Array(arr, callback, onerror) {\n\t\t\tvar tmpArray = new Uint8Array(array.length + arr.length);\n\t\t\ttmpArray.set(array);\n\t\t\ttmpArray.set(arr, array.length);\n\t\t\tarray = tmpArray;\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction getData(callback) {\n\t\t\tcallback(array.buffer);\n\t\t}\n\n\t\tthat.init = init;\n\t\tthat.writeUint8Array = writeUint8Array;\n\t\tthat.getData = getData;\n\t}\n\n\tArrayBufferWriter.prototype = new Writer();\n\tArrayBufferWriter.prototype.constructor = ArrayBufferWriter;\n\n\tfunction FileWriter(fileEntry, contentType) {\n\t\tvar writer, that = this;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tfileEntry.createWriter(function (fileWriter) {\n\t\t\t\twriter = fileWriter;\n\t\t\t\tcallback();\n\t\t\t}, onerror);\n\t\t}\n\n\t\tfunction writeUint8Array(array, callback, onerror) {\n\t\t\tvar blob = new Blob([appendABViewSupported ? array : array.buffer], {\n\t\t\t\ttype: contentType\n\t\t\t});\n\t\t\twriter.onwrite = function () {\n\t\t\t\twriter.onwrite = null;\n\t\t\t\tcallback();\n\t\t\t};\n\t\t\twriter.onerror = onerror;\n\t\t\twriter.write(blob);\n\t\t}\n\n\t\tfunction getData(callback) {\n\t\t\tfileEntry.file(callback);\n\t\t}\n\n\t\tthat.init = init;\n\t\tthat.writeUint8Array = writeUint8Array;\n\t\tthat.getData = getData;\n\t}\n\n\tFileWriter.prototype = new Writer();\n\tFileWriter.prototype.constructor = FileWriter;\n\n\tzipObj.FileWriter = FileWriter;\n\tzipObj.HttpReader = HttpReader;\n\tzipObj.HttpRangeReader = HttpRangeReader;\n\tzipObj.ArrayBufferReader = ArrayBufferReader;\n\tzipObj.ArrayBufferWriter = ArrayBufferWriter;\n\n\tif (zipObj.fs) {\n\t\tZipDirectoryEntry = zipObj.fs.ZipDirectoryEntry;\n\t\tZipDirectoryEntry.prototype.addHttpContent = function (name, URL, useRangeHeader) {\n\t\t\tfunction addChild(parent, name, params, directory) {\n\t\t\t\tif (parent.directory)\n\t\t\t\t\treturn directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new zipObj.fs.ZipFileEntry(parent.fs, name, params, parent);\n\t\t\t\telse\n\t\t\t\t\tthrow \"Parent entry is not a directory.\";\n\t\t\t}\n\n\t\t\treturn addChild(this, name, {\n\t\t\t\tdata: URL,\n\t\t\t\tReader: useRangeHeader ? HttpRangeReader : HttpReader\n\t\t\t});\n\t\t};\n\t\tZipDirectoryEntry.prototype.importHttpContent = function (URL, useRangeHeader, onend, onerror) {\n\t\t\tthis.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror);\n\t\t};\n\t\tzipObj.fs.FS.prototype.importHttpContent = function (URL, useRangeHeader, onend, onerror) {\n\t\t\tthis.entries = [];\n\t\t\tthis.root = new ZipDirectoryEntry(this);\n\t\t\tthis.root.importHttpContent(URL, useRangeHeader, onend, onerror);\n\t\t};\n\t}\n};\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/zipjs/zip-ext.js?");
|
|
2128
2128
|
|
|
2129
2129
|
/***/ }),
|
|
2130
2130
|
|
|
@@ -2134,7 +2134,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2134
2134
|
\****************************************************/
|
|
2135
2135
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2136
2136
|
|
|
2137
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ zipLib: () => (/* binding */ zipLib)\n/* harmony export */ });\n/*\r\n Copyright (c) 2013 Gildas Lormeau. All rights reserved.\r\n\r\n Redistribution and use in source and binary forms, with or without\r\n modification, are permitted provided that the following conditions are met:\r\n\r\n 1. Redistributions of source code must retain the above copyright notice,\r\n this list of conditions and the following disclaimer.\r\n\r\n 2. Redistributions in binary form must reproduce the above copyright\r\n notice, this list of conditions and the following disclaimer in\r\n the documentation and/or other materials provided with the distribution.\r\n\r\n 3. The names of the authors may not be used to endorse or promote products\r\n derived from this software without specific prior written permission.\r\n\r\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\r\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\r\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n\r\n/**\r\n * @private\r\n * @type {{}}\r\n */\r\nvar zipLib = {};\r\n\r\n(function (obj) {\r\n \"use strict\";\r\n\r\n var ERR_BAD_FORMAT = \"File format is not recognized.\";\r\n var ERR_CRC = \"CRC failed.\";\r\n var ERR_ENCRYPTED = \"File contains encrypted entry.\";\r\n var ERR_ZIP64 = \"File is using Zip64 (4gb+ file size).\";\r\n var ERR_READ = \"Error while reading zip file.\";\r\n var ERR_WRITE = \"Error while writing zip file.\";\r\n var ERR_WRITE_DATA = \"Error while writing file data.\";\r\n var ERR_READ_DATA = \"Error while reading file data.\";\r\n var ERR_DUPLICATED_NAME = \"File already exists.\";\r\n var CHUNK_SIZE = 512 * 1024;\r\n\r\n var TEXT_PLAIN = \"text/plain\";\r\n\r\n var appendABViewSupported;\r\n try {\r\n appendABViewSupported = new Blob([new DataView(new ArrayBuffer(0))]).size === 0;\r\n } catch (e) {\r\n }\r\n\r\n function Crc32() {\r\n this.crc = -1;\r\n }\r\n\r\n Crc32.prototype.append = function append(data) {\r\n var crc = this.crc | 0, table = this.table;\r\n for (var offset = 0, len = data.length | 0; offset < len; offset++)\r\n crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];\r\n this.crc = crc;\r\n };\r\n Crc32.prototype.get = function get() {\r\n return ~this.crc;\r\n };\r\n Crc32.prototype.table = (function () {\r\n var i, j, t, table = []; // Uint32Array is actually slower than []\r\n for (i = 0; i < 256; i++) {\r\n t = i;\r\n for (j = 0; j < 8; j++)\r\n if (t & 1)\r\n t = (t >>> 1) ^ 0xEDB88320;\r\n else\r\n t = t >>> 1;\r\n table[i] = t;\r\n }\r\n return table;\r\n })();\r\n\r\n // \"no-op\" codec\r\n function NOOP() {\r\n }\r\n\r\n NOOP.prototype.append = function append(bytes, onprogress) {\r\n return bytes;\r\n };\r\n NOOP.prototype.flush = function flush() {\r\n };\r\n\r\n function blobSlice(blob, index, length) {\r\n if (index < 0 || length < 0 || index + length > blob.size)\r\n throw new RangeError('offset:' + index + ', length:' + length + ', size:' + blob.size);\r\n if (blob.slice)\r\n return blob.slice(index, index + length);\r\n else if (blob.webkitSlice)\r\n return blob.webkitSlice(index, index + length);\r\n else if (blob.mozSlice)\r\n return blob.mozSlice(index, index + length);\r\n else if (blob.msSlice)\r\n return blob.msSlice(index, index + length);\r\n }\r\n\r\n function getDataHelper(byteLength, bytes) {\r\n var dataBuffer, dataArray;\r\n dataBuffer = new ArrayBuffer(byteLength);\r\n dataArray = new Uint8Array(dataBuffer);\r\n if (bytes)\r\n dataArray.set(bytes, 0);\r\n return {\r\n buffer: dataBuffer,\r\n array: dataArray,\r\n view: new DataView(dataBuffer)\r\n };\r\n }\r\n\r\n // Readers\r\n function Reader() {\r\n }\r\n\r\n function TextReader(text) {\r\n var that = this, blobReader;\r\n\r\n function init(callback, onerror) {\r\n var blob = new Blob([text], {\r\n type: TEXT_PLAIN\r\n });\r\n blobReader = new BlobReader(blob);\r\n blobReader.init(function () {\r\n that.size = blobReader.size;\r\n callback();\r\n }, onerror);\r\n }\r\n\r\n function readUint8Array(index, length, callback, onerror) {\r\n blobReader.readUint8Array(index, length, callback, onerror);\r\n }\r\n\r\n that.size = 0;\r\n that.init = init;\r\n that.readUint8Array = readUint8Array;\r\n }\r\n\r\n TextReader.prototype = new Reader();\r\n TextReader.prototype.constructor = TextReader;\r\n\r\n function Data64URIReader(dataURI) {\r\n var that = this, dataStart;\r\n\r\n function init(callback) {\r\n var dataEnd = dataURI.length;\r\n while (dataURI.charAt(dataEnd - 1) == \"=\")\r\n dataEnd--;\r\n dataStart = dataURI.indexOf(\",\") + 1;\r\n that.size = Math.floor((dataEnd - dataStart) * 0.75);\r\n callback();\r\n }\r\n\r\n function readUint8Array(index, length, callback) {\r\n var i, data = getDataHelper(length);\r\n var start = Math.floor(index / 3) * 4;\r\n var end = Math.ceil((index + length) / 3) * 4;\r\n var bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));\r\n var delta = index - Math.floor(start / 4) * 3;\r\n for (i = delta; i < delta + length; i++)\r\n data.array[i - delta] = bytes.charCodeAt(i);\r\n callback(data.array);\r\n }\r\n\r\n that.size = 0;\r\n that.init = init;\r\n that.readUint8Array = readUint8Array;\r\n }\r\n\r\n Data64URIReader.prototype = new Reader();\r\n Data64URIReader.prototype.constructor = Data64URIReader;\r\n\r\n function BlobReader(blob) {\r\n var that = this;\r\n\r\n function init(callback) {\r\n that.size = blob.size;\r\n callback();\r\n }\r\n\r\n function readUint8Array(index, length, callback, onerror) {\r\n var reader = new FileReader();\r\n reader.onload = function (e) {\r\n callback(new Uint8Array(e.target.result));\r\n };\r\n reader.onerror = onerror;\r\n try {\r\n reader.readAsArrayBuffer(blobSlice(blob, index, length));\r\n } catch (e) {\r\n onerror(e);\r\n }\r\n }\r\n\r\n that.size = 0;\r\n that.init = init;\r\n that.readUint8Array = readUint8Array;\r\n }\r\n\r\n BlobReader.prototype = new Reader();\r\n BlobReader.prototype.constructor = BlobReader;\r\n\r\n // Writers\r\n\r\n function Writer() {\r\n }\r\n\r\n Writer.prototype.getData = function (callback) {\r\n callback(this.data);\r\n };\r\n\r\n function TextWriter(encoding) {\r\n var that = this, blob;\r\n\r\n function init(callback) {\r\n blob = new Blob([], {\r\n type: TEXT_PLAIN\r\n });\r\n callback();\r\n }\r\n\r\n function writeUint8Array(array, callback) {\r\n blob = new Blob([blob, appendABViewSupported ? array : array.buffer], {\r\n type: TEXT_PLAIN\r\n });\r\n callback();\r\n }\r\n\r\n function getData(callback, onerror) {\r\n var reader = new FileReader();\r\n reader.onload = function (e) {\r\n callback(e.target.result);\r\n };\r\n reader.onerror = onerror;\r\n reader.readAsText(blob, encoding);\r\n }\r\n\r\n that.init = init;\r\n that.writeUint8Array = writeUint8Array;\r\n that.getData = getData;\r\n }\r\n\r\n TextWriter.prototype = new Writer();\r\n TextWriter.prototype.constructor = TextWriter;\r\n\r\n function Data64URIWriter(contentType) {\r\n var that = this, data = \"\", pending = \"\";\r\n\r\n function init(callback) {\r\n data += \"data:\" + (contentType || \"\") + \";base64,\";\r\n callback();\r\n }\r\n\r\n function writeUint8Array(array, callback) {\r\n var i, delta = pending.length, dataString = pending;\r\n pending = \"\";\r\n for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)\r\n dataString += String.fromCharCode(array[i]);\r\n for (; i < array.length; i++)\r\n pending += String.fromCharCode(array[i]);\r\n if (dataString.length > 2)\r\n data += obj.btoa(dataString);\r\n else\r\n pending = dataString;\r\n callback();\r\n }\r\n\r\n function getData(callback) {\r\n callback(data + obj.btoa(pending));\r\n }\r\n\r\n that.init = init;\r\n that.writeUint8Array = writeUint8Array;\r\n that.getData = getData;\r\n }\r\n\r\n Data64URIWriter.prototype = new Writer();\r\n Data64URIWriter.prototype.constructor = Data64URIWriter;\r\n\r\n function BlobWriter(contentType) {\r\n var blob, that = this;\r\n\r\n function init(callback) {\r\n blob = new Blob([], {\r\n type: contentType\r\n });\r\n callback();\r\n }\r\n\r\n function writeUint8Array(array, callback) {\r\n blob = new Blob([blob, appendABViewSupported ? array : array.buffer], {\r\n type: contentType\r\n });\r\n callback();\r\n }\r\n\r\n function getData(callback) {\r\n callback(blob);\r\n }\r\n\r\n that.init = init;\r\n that.writeUint8Array = writeUint8Array;\r\n that.getData = getData;\r\n }\r\n\r\n BlobWriter.prototype = new Writer();\r\n BlobWriter.prototype.constructor = BlobWriter;\r\n\r\n /**\r\n * inflate/deflate core functions\r\n * @param worker {Worker} web worker for the task.\r\n * @param initialMessage {Object} initial message to be sent to the worker. should contain\r\n * sn(serial number for distinguishing multiple tasks sent to the worker), and codecClass.\r\n * This function may add more properties before sending.\r\n */\r\n function launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror) {\r\n var chunkIndex = 0, index, outputSize, sn = initialMessage.sn, crc;\r\n\r\n function onflush() {\r\n worker.removeEventListener('message', onmessage, false);\r\n onend(outputSize, crc);\r\n }\r\n\r\n function onmessage(event) {\r\n var message = event.data, data = message.data, err = message.error;\r\n if (err) {\r\n err.toString = function () {\r\n return 'Error: ' + this.message;\r\n };\r\n onreaderror(err);\r\n return;\r\n }\r\n if (message.sn !== sn)\r\n return;\r\n if (typeof message.codecTime === 'number')\r\n worker.codecTime += message.codecTime; // should be before onflush()\r\n if (typeof message.crcTime === 'number')\r\n worker.crcTime += message.crcTime;\r\n\r\n switch (message.type) {\r\n case 'append':\r\n if (data) {\r\n outputSize += data.length;\r\n writer.writeUint8Array(data, function () {\r\n step();\r\n }, onwriteerror);\r\n } else\r\n step();\r\n break;\r\n case 'flush':\r\n crc = message.crc;\r\n if (data) {\r\n outputSize += data.length;\r\n writer.writeUint8Array(data, function () {\r\n onflush();\r\n }, onwriteerror);\r\n } else\r\n onflush();\r\n break;\r\n case 'progress':\r\n if (onprogress)\r\n onprogress(index + message.loaded, size);\r\n break;\r\n case 'importScripts': //no need to handle here\r\n case 'newTask':\r\n case 'echo':\r\n break;\r\n default:\r\n console.warn('zip.js:launchWorkerProcess: unknown message: ', message);\r\n }\r\n }\r\n\r\n function step() {\r\n index = chunkIndex * CHUNK_SIZE;\r\n // use `<=` instead of `<`, because `size` may be 0.\r\n if (index <= size) {\r\n reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function (array) {\r\n if (onprogress)\r\n onprogress(index, size);\r\n var msg = index === 0 ? initialMessage : {sn: sn};\r\n msg.type = 'append';\r\n msg.data = array;\r\n\r\n // posting a message with transferables will fail on IE10\r\n try {\r\n worker.postMessage(msg, [array.buffer]);\r\n } catch (ex) {\r\n worker.postMessage(msg); // retry without transferables\r\n }\r\n chunkIndex++;\r\n }, onreaderror);\r\n } else {\r\n worker.postMessage({\r\n sn: sn,\r\n type: 'flush'\r\n });\r\n }\r\n }\r\n\r\n outputSize = 0;\r\n worker.addEventListener('message', onmessage, false);\r\n step();\r\n }\r\n\r\n function launchProcess(process, reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror) {\r\n var chunkIndex = 0, index, outputSize = 0,\r\n crcInput = crcType === 'input',\r\n crcOutput = crcType === 'output',\r\n crc = new Crc32();\r\n\r\n function step() {\r\n var outputData;\r\n index = chunkIndex * CHUNK_SIZE;\r\n if (index < size)\r\n reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function (inputData) {\r\n var outputData;\r\n try {\r\n outputData = process.append(inputData, function (loaded) {\r\n if (onprogress)\r\n onprogress(index + loaded, size);\r\n });\r\n } catch (e) {\r\n onreaderror(e);\r\n return;\r\n }\r\n if (outputData) {\r\n outputSize += outputData.length;\r\n writer.writeUint8Array(outputData, function () {\r\n chunkIndex++;\r\n setTimeout(step, 1);\r\n }, onwriteerror);\r\n if (crcOutput)\r\n crc.append(outputData);\r\n } else {\r\n chunkIndex++;\r\n setTimeout(step, 1);\r\n }\r\n if (crcInput)\r\n crc.append(inputData);\r\n if (onprogress)\r\n onprogress(index, size);\r\n }, onreaderror);\r\n else {\r\n try {\r\n outputData = process.flush();\r\n } catch (e) {\r\n onreaderror(e);\r\n return;\r\n }\r\n if (outputData) {\r\n if (crcOutput)\r\n crc.append(outputData);\r\n outputSize += outputData.length;\r\n writer.writeUint8Array(outputData, function () {\r\n onend(outputSize, crc.get());\r\n }, onwriteerror);\r\n } else\r\n onend(outputSize, crc.get());\r\n }\r\n }\r\n\r\n step();\r\n }\r\n\r\n function inflate(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\r\n var crcType = computeCrc32 ? 'output' : 'none';\r\n if (obj.zip.useWebWorkers) {\r\n var initialMessage = {\r\n sn: sn,\r\n codecClass: 'Inflater',\r\n crcType: crcType,\r\n };\r\n launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);\r\n } else\r\n launchProcess(new obj.zip.Inflater(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);\r\n }\r\n\r\n function deflate(worker, sn, reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {\r\n var crcType = 'input';\r\n if (obj.zip.useWebWorkers) {\r\n var initialMessage = {\r\n sn: sn,\r\n options: {level: level},\r\n codecClass: 'Deflater',\r\n crcType: crcType,\r\n };\r\n launchWorkerProcess(worker, initialMessage, reader, writer, 0, reader.size, onprogress, onend, onreaderror, onwriteerror);\r\n } else\r\n launchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, crcType, onprogress, onend, onreaderror, onwriteerror);\r\n }\r\n\r\n function copy(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\r\n var crcType = 'input';\r\n if (obj.zip.useWebWorkers && computeCrc32) {\r\n var initialMessage = {\r\n sn: sn,\r\n codecClass: 'NOOP',\r\n crcType: crcType,\r\n };\r\n launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);\r\n } else\r\n launchProcess(new NOOP(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);\r\n }\r\n\r\n // ZipReader\r\n\r\n function decodeASCII(str) {\r\n var i, out = \"\", charCode, extendedASCII = ['\\u00C7', '\\u00FC', '\\u00E9', '\\u00E2', '\\u00E4', '\\u00E0', '\\u00E5', '\\u00E7', '\\u00EA', '\\u00EB',\r\n '\\u00E8', '\\u00EF', '\\u00EE', '\\u00EC', '\\u00C4', '\\u00C5', '\\u00C9', '\\u00E6', '\\u00C6', '\\u00F4', '\\u00F6', '\\u00F2', '\\u00FB', '\\u00F9',\r\n '\\u00FF', '\\u00D6', '\\u00DC', '\\u00F8', '\\u00A3', '\\u00D8', '\\u00D7', '\\u0192', '\\u00E1', '\\u00ED', '\\u00F3', '\\u00FA', '\\u00F1', '\\u00D1',\r\n '\\u00AA', '\\u00BA', '\\u00BF', '\\u00AE', '\\u00AC', '\\u00BD', '\\u00BC', '\\u00A1', '\\u00AB', '\\u00BB', '_', '_', '_', '\\u00A6', '\\u00A6',\r\n '\\u00C1', '\\u00C2', '\\u00C0', '\\u00A9', '\\u00A6', '\\u00A6', '+', '+', '\\u00A2', '\\u00A5', '+', '+', '-', '-', '+', '-', '+', '\\u00E3',\r\n '\\u00C3', '+', '+', '-', '-', '\\u00A6', '-', '+', '\\u00A4', '\\u00F0', '\\u00D0', '\\u00CA', '\\u00CB', '\\u00C8', 'i', '\\u00CD', '\\u00CE',\r\n '\\u00CF', '+', '+', '_', '_', '\\u00A6', '\\u00CC', '_', '\\u00D3', '\\u00DF', '\\u00D4', '\\u00D2', '\\u00F5', '\\u00D5', '\\u00B5', '\\u00FE',\r\n '\\u00DE', '\\u00DA', '\\u00DB', '\\u00D9', '\\u00FD', '\\u00DD', '\\u00AF', '\\u00B4', '\\u00AD', '\\u00B1', '_', '\\u00BE', '\\u00B6', '\\u00A7',\r\n '\\u00F7', '\\u00B8', '\\u00B0', '\\u00A8', '\\u00B7', '\\u00B9', '\\u00B3', '\\u00B2', '_', ' '];\r\n for (i = 0; i < str.length; i++) {\r\n charCode = str.charCodeAt(i) & 0xFF;\r\n if (charCode > 127)\r\n out += extendedASCII[charCode - 128];\r\n else\r\n out += String.fromCharCode(charCode);\r\n }\r\n return out;\r\n }\r\n\r\n function decodeUTF8(string) {\r\n return decodeURIComponent(escape(string));\r\n }\r\n\r\n function getString(bytes) {\r\n var i, str = \"\";\r\n for (i = 0; i < bytes.length; i++)\r\n str += String.fromCharCode(bytes[i]);\r\n return str;\r\n }\r\n\r\n function getDate(timeRaw) {\r\n var date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;\r\n try {\r\n return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,\r\n (time & 0x001F) * 2, 0);\r\n } catch (e) {\r\n }\r\n }\r\n\r\n function readCommonHeader(entry, data, index, centralDirectory, onerror) {\r\n entry.version = data.view.getUint16(index, true);\r\n entry.bitFlag = data.view.getUint16(index + 2, true);\r\n entry.compressionMethod = data.view.getUint16(index + 4, true);\r\n entry.lastModDateRaw = data.view.getUint32(index + 6, true);\r\n entry.lastModDate = getDate(entry.lastModDateRaw);\r\n if ((entry.bitFlag & 0x01) === 0x01) {\r\n onerror(ERR_ENCRYPTED);\r\n return;\r\n }\r\n if (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {\r\n entry.crc32 = data.view.getUint32(index + 10, true);\r\n entry.compressedSize = data.view.getUint32(index + 14, true);\r\n entry.uncompressedSize = data.view.getUint32(index + 18, true);\r\n }\r\n if (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {\r\n onerror(ERR_ZIP64);\r\n return;\r\n }\r\n entry.filenameLength = data.view.getUint16(index + 22, true);\r\n entry.extraFieldLength = data.view.getUint16(index + 24, true);\r\n }\r\n\r\n function createZipReader(reader, callback, onerror) {\r\n var inflateSN = 0;\r\n\r\n function Entry() {\r\n }\r\n\r\n Entry.prototype.getData = function (writer, onend, onprogress, checkCrc32) {\r\n var that = this;\r\n\r\n function testCrc32(crc32) {\r\n var dataCrc32 = getDataHelper(4);\r\n dataCrc32.view.setUint32(0, crc32);\r\n return that.crc32 == dataCrc32.view.getUint32(0);\r\n }\r\n\r\n function getWriterData(uncompressedSize, crc32) {\r\n if (checkCrc32 && !testCrc32(crc32))\r\n onerror(ERR_CRC);\r\n else\r\n writer.getData(function (data) {\r\n onend(data);\r\n });\r\n }\r\n\r\n function onreaderror(err) {\r\n onerror(err || ERR_READ_DATA);\r\n }\r\n\r\n function onwriteerror(err) {\r\n onerror(err || ERR_WRITE_DATA);\r\n }\r\n\r\n reader.readUint8Array(that.offset, 30, function (bytes) {\r\n var data = getDataHelper(bytes.length, bytes), dataOffset;\r\n if (data.view.getUint32(0) != 0x504b0304) {\r\n onerror(ERR_BAD_FORMAT);\r\n return;\r\n }\r\n readCommonHeader(that, data, 4, false, onerror);\r\n dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;\r\n writer.init(function () {\r\n if (that.compressionMethod === 0)\r\n copy(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\r\n else\r\n inflate(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\r\n }, onwriteerror);\r\n }, onreaderror);\r\n };\r\n\r\n function seekEOCDR(eocdrCallback) {\r\n // \"End of central directory record\" is the last part of a zip archive, and is at least 22 bytes long.\r\n // Zip file comment is the last part of EOCDR and has max length of 64KB,\r\n // so we only have to search the last 64K + 22 bytes of a archive for EOCDR signature (0x06054b50).\r\n var EOCDR_MIN = 22;\r\n if (reader.size < EOCDR_MIN) {\r\n onerror(ERR_BAD_FORMAT);\r\n return;\r\n }\r\n var ZIP_COMMENT_MAX = 256 * 256, EOCDR_MAX = EOCDR_MIN + ZIP_COMMENT_MAX;\r\n\r\n // In most cases, the EOCDR is EOCDR_MIN bytes long\r\n doSeek(EOCDR_MIN, function () {\r\n // If not found, try within EOCDR_MAX bytes\r\n doSeek(Math.min(EOCDR_MAX, reader.size), function () {\r\n onerror(ERR_BAD_FORMAT);\r\n });\r\n });\r\n\r\n // seek last length bytes of file for EOCDR\r\n function doSeek(length, eocdrNotFoundCallback) {\r\n reader.readUint8Array(reader.size - length, length, function (bytes) {\r\n for (var i = bytes.length - EOCDR_MIN; i >= 0; i--) {\r\n if (bytes[i] === 0x50 && bytes[i + 1] === 0x4b && bytes[i + 2] === 0x05 && bytes[i + 3] === 0x06) {\r\n eocdrCallback(new DataView(bytes.buffer, i, EOCDR_MIN));\r\n return;\r\n }\r\n }\r\n eocdrNotFoundCallback();\r\n }, function () {\r\n onerror(ERR_READ);\r\n });\r\n }\r\n }\r\n\r\n var zipReader = {\r\n getEntries: function (callback) {\r\n var worker = this._worker;\r\n // look for End of central directory record\r\n seekEOCDR(function (dataView) {\r\n var datalength, fileslength;\r\n datalength = dataView.getUint32(16, true);\r\n fileslength = dataView.getUint16(8, true);\r\n if (datalength < 0 || datalength >= reader.size) {\r\n onerror(ERR_BAD_FORMAT);\r\n return;\r\n }\r\n reader.readUint8Array(datalength, reader.size - datalength, function (bytes) {\r\n var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);\r\n for (i = 0; i < fileslength; i++) {\r\n entry = new Entry();\r\n entry._worker = worker;\r\n if (data.view.getUint32(index) != 0x504b0102) {\r\n onerror(ERR_BAD_FORMAT);\r\n return;\r\n }\r\n readCommonHeader(entry, data, index + 6, true, onerror);\r\n entry.commentLength = data.view.getUint16(index + 32, true);\r\n entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);\r\n entry.offset = data.view.getUint32(index + 42, true);\r\n filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));\r\n entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);\r\n if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == \"/\")\r\n entry.directory = true;\r\n comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46\r\n + entry.filenameLength + entry.extraFieldLength + entry.commentLength));\r\n entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);\r\n entries.push(entry);\r\n index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;\r\n }\r\n callback(entries);\r\n }, function () {\r\n onerror(ERR_READ);\r\n });\r\n });\r\n },\r\n close: function (callback) {\r\n if (this._worker) {\r\n this._worker.terminate();\r\n this._worker = null;\r\n }\r\n if (callback)\r\n callback();\r\n },\r\n _worker: null\r\n };\r\n\r\n if (!obj.zip.useWebWorkers)\r\n callback(zipReader);\r\n else {\r\n createWorker('inflater',\r\n function (worker) {\r\n zipReader._worker = worker;\r\n callback(zipReader);\r\n },\r\n function (err) {\r\n onerror(err);\r\n }\r\n );\r\n }\r\n }\r\n\r\n // ZipWriter\r\n\r\n function encodeUTF8(string) {\r\n return unescape(encodeURIComponent(string));\r\n }\r\n\r\n function getBytes(str) {\r\n var i, array = [];\r\n for (i = 0; i < str.length; i++)\r\n array.push(str.charCodeAt(i));\r\n return array;\r\n }\r\n\r\n function createZipWriter(writer, callback, onerror, dontDeflate) {\r\n var files = {}, filenames = [], datalength = 0;\r\n var deflateSN = 0;\r\n\r\n function onwriteerror(err) {\r\n onerror(err || ERR_WRITE);\r\n }\r\n\r\n function onreaderror(err) {\r\n onerror(err || ERR_READ_DATA);\r\n }\r\n\r\n var zipWriter = {\r\n add: function (name, reader, onend, onprogress, options) {\r\n var header, filename, date;\r\n var worker = this._worker;\r\n\r\n function writeHeader(callback) {\r\n var data;\r\n date = options.lastModDate || new Date();\r\n header = getDataHelper(26);\r\n files[name] = {\r\n headerArray: header.array,\r\n directory: options.directory,\r\n filename: filename,\r\n offset: datalength,\r\n comment: getBytes(encodeUTF8(options.comment || \"\"))\r\n };\r\n header.view.setUint32(0, 0x14000808);\r\n if (options.version)\r\n header.view.setUint8(0, options.version);\r\n if (!dontDeflate && options.level !== 0 && !options.directory)\r\n header.view.setUint16(4, 0x0800);\r\n header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);\r\n header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);\r\n header.view.setUint16(22, filename.length, true);\r\n data = getDataHelper(30 + filename.length);\r\n data.view.setUint32(0, 0x504b0304);\r\n data.array.set(header.array, 4);\r\n data.array.set(filename, 30);\r\n datalength += data.array.length;\r\n writer.writeUint8Array(data.array, callback, onwriteerror);\r\n }\r\n\r\n function writeFooter(compressedLength, crc32) {\r\n var footer = getDataHelper(16);\r\n datalength += compressedLength || 0;\r\n footer.view.setUint32(0, 0x504b0708);\r\n if (typeof crc32 != \"undefined\") {\r\n header.view.setUint32(10, crc32, true);\r\n footer.view.setUint32(4, crc32, true);\r\n }\r\n if (reader) {\r\n footer.view.setUint32(8, compressedLength, true);\r\n header.view.setUint32(14, compressedLength, true);\r\n footer.view.setUint32(12, reader.size, true);\r\n header.view.setUint32(18, reader.size, true);\r\n }\r\n writer.writeUint8Array(footer.array, function () {\r\n datalength += 16;\r\n onend();\r\n }, onwriteerror);\r\n }\r\n\r\n function writeFile() {\r\n options = options || {};\r\n name = name.trim();\r\n if (options.directory && name.charAt(name.length - 1) != \"/\")\r\n name += \"/\";\r\n if (files.hasOwnProperty(name)) {\r\n onerror(ERR_DUPLICATED_NAME);\r\n return;\r\n }\r\n filename = getBytes(encodeUTF8(name));\r\n filenames.push(name);\r\n writeHeader(function () {\r\n if (reader)\r\n if (dontDeflate || options.level === 0)\r\n copy(worker, deflateSN++, reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);\r\n else\r\n deflate(worker, deflateSN++, reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);\r\n else\r\n writeFooter();\r\n }, onwriteerror);\r\n }\r\n\r\n if (reader)\r\n reader.init(writeFile, onreaderror);\r\n else\r\n writeFile();\r\n },\r\n close: function (callback) {\r\n if (this._worker) {\r\n this._worker.terminate();\r\n this._worker = null;\r\n }\r\n\r\n var data, length = 0, index = 0, indexFilename, file;\r\n for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {\r\n file = files[filenames[indexFilename]];\r\n length += 46 + file.filename.length + file.comment.length;\r\n }\r\n data = getDataHelper(length + 22);\r\n for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {\r\n file = files[filenames[indexFilename]];\r\n data.view.setUint32(index, 0x504b0102);\r\n data.view.setUint16(index + 4, 0x1400);\r\n data.array.set(file.headerArray, index + 6);\r\n data.view.setUint16(index + 32, file.comment.length, true);\r\n if (file.directory)\r\n data.view.setUint8(index + 38, 0x10);\r\n data.view.setUint32(index + 42, file.offset, true);\r\n data.array.set(file.filename, index + 46);\r\n data.array.set(file.comment, index + 46 + file.filename.length);\r\n index += 46 + file.filename.length + file.comment.length;\r\n }\r\n data.view.setUint32(index, 0x504b0506);\r\n data.view.setUint16(index + 8, filenames.length, true);\r\n data.view.setUint16(index + 10, filenames.length, true);\r\n data.view.setUint32(index + 12, length, true);\r\n data.view.setUint32(index + 16, datalength, true);\r\n writer.writeUint8Array(data.array, function () {\r\n writer.getData(callback);\r\n }, onwriteerror);\r\n },\r\n _worker: null\r\n };\r\n\r\n if (!obj.zip.useWebWorkers)\r\n callback(zipWriter);\r\n else {\r\n createWorker('deflater',\r\n function (worker) {\r\n zipWriter._worker = worker;\r\n callback(zipWriter);\r\n },\r\n function (err) {\r\n onerror(err);\r\n }\r\n );\r\n }\r\n }\r\n\r\n function resolveURLs(urls) {\r\n var a = document.createElement('a');\r\n return urls.map(function (url) {\r\n a.href = url;\r\n return a.href;\r\n });\r\n }\r\n\r\n var DEFAULT_WORKER_SCRIPTS = {\r\n deflater: ['z-worker.js', 'deflate.js'],\r\n inflater: ['z-worker.js', 'inflate.js']\r\n };\r\n\r\n function createWorker(type, callback, onerror) {\r\n if (obj.zip.workerScripts !== null && obj.zip.workerScriptsPath !== null) {\r\n onerror(new Error('Either zip.workerScripts or zip.workerScriptsPath may be set, not both.'));\r\n return;\r\n }\r\n var scripts;\r\n if (obj.zip.workerScripts) {\r\n scripts = obj.zip.workerScripts[type];\r\n if (!Array.isArray(scripts)) {\r\n onerror(new Error('zip.workerScripts.' + type + ' is not an array!'));\r\n return;\r\n }\r\n scripts = resolveURLs(scripts);\r\n } else {\r\n scripts = DEFAULT_WORKER_SCRIPTS[type].slice(0);\r\n scripts[0] = (obj.zip.workerScriptsPath || '') + scripts[0];\r\n }\r\n var worker = new Worker(scripts[0]);\r\n // record total consumed time by inflater/deflater/crc32 in this worker\r\n worker.codecTime = worker.crcTime = 0;\r\n worker.postMessage({type: 'importScripts', scripts: scripts.slice(1)});\r\n worker.addEventListener('message', onmessage);\r\n function onmessage(ev) {\r\n var msg = ev.data;\r\n if (msg.error) {\r\n worker.terminate(); // should before onerror(), because onerror() may throw.\r\n onerror(msg.error);\r\n return;\r\n }\r\n if (msg.type === 'importScripts') {\r\n worker.removeEventListener('message', onmessage);\r\n worker.removeEventListener('error', errorHandler);\r\n callback(worker);\r\n }\r\n }\r\n\r\n // catch entry script loading error and other unhandled errors\r\n worker.addEventListener('error', errorHandler);\r\n function errorHandler(err) {\r\n worker.terminate();\r\n onerror(err);\r\n }\r\n }\r\n\r\n function onerror_default(error) {\r\n console.error(error);\r\n }\r\n\r\n obj.zip = {\r\n Reader: Reader,\r\n Writer: Writer,\r\n BlobReader: BlobReader,\r\n Data64URIReader: Data64URIReader,\r\n TextReader: TextReader,\r\n BlobWriter: BlobWriter,\r\n Data64URIWriter: Data64URIWriter,\r\n TextWriter: TextWriter,\r\n createReader: function (reader, callback, onerror) {\r\n onerror = onerror || onerror_default;\r\n\r\n reader.init(function () {\r\n createZipReader(reader, callback, onerror);\r\n }, onerror);\r\n },\r\n createWriter: function (writer, callback, onerror, dontDeflate) {\r\n onerror = onerror || onerror_default;\r\n dontDeflate = !!dontDeflate;\r\n\r\n writer.init(function () {\r\n createZipWriter(writer, callback, onerror, dontDeflate);\r\n }, onerror);\r\n },\r\n useWebWorkers: true,\r\n /**\r\n * Directory containing the default worker scripts (z-worker.js, deflate.js, and inflate.js), relative to current base url.\r\n * E.g.: zip.workerScripts = './';\r\n */\r\n workerScriptsPath: null,\r\n /**\r\n * Advanced option to control which scripts are loaded in the Web worker. If this option is specified, then workerScriptsPath must not be set.\r\n * workerScripts.deflater/workerScripts.inflater should be arrays of urls to scripts for deflater/inflater, respectively.\r\n * Scripts in the array are executed in order, and the first one should be z-worker.js, which is used to start the worker.\r\n * All urls are relative to current base url.\r\n * E.g.:\r\n * zip.workerScripts = {\r\n\t\t * deflater: ['z-worker.js', 'deflate.js'],\r\n\t\t * inflater: ['z-worker.js', 'inflate.js']\r\n\t\t * };\r\n */\r\n workerScripts: null,\r\n };\r\n\r\n})(zipLib);\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/zipjs/zip.js?");
|
|
2137
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ zipLib: () => (/* binding */ zipLib)\n/* harmony export */ });\n/*\n Copyright (c) 2013 Gildas Lormeau. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n\n 2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n\n 3. The names of the authors may not be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/**\n * @private\n * @type {{}}\n */\nvar zipLib = {};\n\n(function (obj) {\n \"use strict\";\n\n var ERR_BAD_FORMAT = \"File format is not recognized.\";\n var ERR_CRC = \"CRC failed.\";\n var ERR_ENCRYPTED = \"File contains encrypted entry.\";\n var ERR_ZIP64 = \"File is using Zip64 (4gb+ file size).\";\n var ERR_READ = \"Error while reading zip file.\";\n var ERR_WRITE = \"Error while writing zip file.\";\n var ERR_WRITE_DATA = \"Error while writing file data.\";\n var ERR_READ_DATA = \"Error while reading file data.\";\n var ERR_DUPLICATED_NAME = \"File already exists.\";\n var CHUNK_SIZE = 512 * 1024;\n\n var TEXT_PLAIN = \"text/plain\";\n\n var appendABViewSupported;\n try {\n appendABViewSupported = new Blob([new DataView(new ArrayBuffer(0))]).size === 0;\n } catch (e) {\n }\n\n function Crc32() {\n this.crc = -1;\n }\n\n Crc32.prototype.append = function append(data) {\n var crc = this.crc | 0, table = this.table;\n for (var offset = 0, len = data.length | 0; offset < len; offset++)\n crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];\n this.crc = crc;\n };\n Crc32.prototype.get = function get() {\n return ~this.crc;\n };\n Crc32.prototype.table = (function () {\n var i, j, t, table = []; // Uint32Array is actually slower than []\n for (i = 0; i < 256; i++) {\n t = i;\n for (j = 0; j < 8; j++)\n if (t & 1)\n t = (t >>> 1) ^ 0xEDB88320;\n else\n t = t >>> 1;\n table[i] = t;\n }\n return table;\n })();\n\n // \"no-op\" codec\n function NOOP() {\n }\n\n NOOP.prototype.append = function append(bytes, onprogress) {\n return bytes;\n };\n NOOP.prototype.flush = function flush() {\n };\n\n function blobSlice(blob, index, length) {\n if (index < 0 || length < 0 || index + length > blob.size)\n throw new RangeError('offset:' + index + ', length:' + length + ', size:' + blob.size);\n if (blob.slice)\n return blob.slice(index, index + length);\n else if (blob.webkitSlice)\n return blob.webkitSlice(index, index + length);\n else if (blob.mozSlice)\n return blob.mozSlice(index, index + length);\n else if (blob.msSlice)\n return blob.msSlice(index, index + length);\n }\n\n function getDataHelper(byteLength, bytes) {\n var dataBuffer, dataArray;\n dataBuffer = new ArrayBuffer(byteLength);\n dataArray = new Uint8Array(dataBuffer);\n if (bytes)\n dataArray.set(bytes, 0);\n return {\n buffer: dataBuffer,\n array: dataArray,\n view: new DataView(dataBuffer)\n };\n }\n\n // Readers\n function Reader() {\n }\n\n function TextReader(text) {\n var that = this, blobReader;\n\n function init(callback, onerror) {\n var blob = new Blob([text], {\n type: TEXT_PLAIN\n });\n blobReader = new BlobReader(blob);\n blobReader.init(function () {\n that.size = blobReader.size;\n callback();\n }, onerror);\n }\n\n function readUint8Array(index, length, callback, onerror) {\n blobReader.readUint8Array(index, length, callback, onerror);\n }\n\n that.size = 0;\n that.init = init;\n that.readUint8Array = readUint8Array;\n }\n\n TextReader.prototype = new Reader();\n TextReader.prototype.constructor = TextReader;\n\n function Data64URIReader(dataURI) {\n var that = this, dataStart;\n\n function init(callback) {\n var dataEnd = dataURI.length;\n while (dataURI.charAt(dataEnd - 1) == \"=\")\n dataEnd--;\n dataStart = dataURI.indexOf(\",\") + 1;\n that.size = Math.floor((dataEnd - dataStart) * 0.75);\n callback();\n }\n\n function readUint8Array(index, length, callback) {\n var i, data = getDataHelper(length);\n var start = Math.floor(index / 3) * 4;\n var end = Math.ceil((index + length) / 3) * 4;\n var bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));\n var delta = index - Math.floor(start / 4) * 3;\n for (i = delta; i < delta + length; i++)\n data.array[i - delta] = bytes.charCodeAt(i);\n callback(data.array);\n }\n\n that.size = 0;\n that.init = init;\n that.readUint8Array = readUint8Array;\n }\n\n Data64URIReader.prototype = new Reader();\n Data64URIReader.prototype.constructor = Data64URIReader;\n\n function BlobReader(blob) {\n var that = this;\n\n function init(callback) {\n that.size = blob.size;\n callback();\n }\n\n function readUint8Array(index, length, callback, onerror) {\n var reader = new FileReader();\n reader.onload = function (e) {\n callback(new Uint8Array(e.target.result));\n };\n reader.onerror = onerror;\n try {\n reader.readAsArrayBuffer(blobSlice(blob, index, length));\n } catch (e) {\n onerror(e);\n }\n }\n\n that.size = 0;\n that.init = init;\n that.readUint8Array = readUint8Array;\n }\n\n BlobReader.prototype = new Reader();\n BlobReader.prototype.constructor = BlobReader;\n\n // Writers\n\n function Writer() {\n }\n\n Writer.prototype.getData = function (callback) {\n callback(this.data);\n };\n\n function TextWriter(encoding) {\n var that = this, blob;\n\n function init(callback) {\n blob = new Blob([], {\n type: TEXT_PLAIN\n });\n callback();\n }\n\n function writeUint8Array(array, callback) {\n blob = new Blob([blob, appendABViewSupported ? array : array.buffer], {\n type: TEXT_PLAIN\n });\n callback();\n }\n\n function getData(callback, onerror) {\n var reader = new FileReader();\n reader.onload = function (e) {\n callback(e.target.result);\n };\n reader.onerror = onerror;\n reader.readAsText(blob, encoding);\n }\n\n that.init = init;\n that.writeUint8Array = writeUint8Array;\n that.getData = getData;\n }\n\n TextWriter.prototype = new Writer();\n TextWriter.prototype.constructor = TextWriter;\n\n function Data64URIWriter(contentType) {\n var that = this, data = \"\", pending = \"\";\n\n function init(callback) {\n data += \"data:\" + (contentType || \"\") + \";base64,\";\n callback();\n }\n\n function writeUint8Array(array, callback) {\n var i, delta = pending.length, dataString = pending;\n pending = \"\";\n for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)\n dataString += String.fromCharCode(array[i]);\n for (; i < array.length; i++)\n pending += String.fromCharCode(array[i]);\n if (dataString.length > 2)\n data += obj.btoa(dataString);\n else\n pending = dataString;\n callback();\n }\n\n function getData(callback) {\n callback(data + obj.btoa(pending));\n }\n\n that.init = init;\n that.writeUint8Array = writeUint8Array;\n that.getData = getData;\n }\n\n Data64URIWriter.prototype = new Writer();\n Data64URIWriter.prototype.constructor = Data64URIWriter;\n\n function BlobWriter(contentType) {\n var blob, that = this;\n\n function init(callback) {\n blob = new Blob([], {\n type: contentType\n });\n callback();\n }\n\n function writeUint8Array(array, callback) {\n blob = new Blob([blob, appendABViewSupported ? array : array.buffer], {\n type: contentType\n });\n callback();\n }\n\n function getData(callback) {\n callback(blob);\n }\n\n that.init = init;\n that.writeUint8Array = writeUint8Array;\n that.getData = getData;\n }\n\n BlobWriter.prototype = new Writer();\n BlobWriter.prototype.constructor = BlobWriter;\n\n /**\n * inflate/deflate core functions\n * @param worker {Worker} web worker for the task.\n * @param initialMessage {Object} initial message to be sent to the worker. should contain\n * sn(serial number for distinguishing multiple tasks sent to the worker), and codecClass.\n * This function may add more properties before sending.\n */\n function launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror) {\n var chunkIndex = 0, index, outputSize, sn = initialMessage.sn, crc;\n\n function onflush() {\n worker.removeEventListener('message', onmessage, false);\n onend(outputSize, crc);\n }\n\n function onmessage(event) {\n var message = event.data, data = message.data, err = message.error;\n if (err) {\n err.toString = function () {\n return 'Error: ' + this.message;\n };\n onreaderror(err);\n return;\n }\n if (message.sn !== sn)\n return;\n if (typeof message.codecTime === 'number')\n worker.codecTime += message.codecTime; // should be before onflush()\n if (typeof message.crcTime === 'number')\n worker.crcTime += message.crcTime;\n\n switch (message.type) {\n case 'append':\n if (data) {\n outputSize += data.length;\n writer.writeUint8Array(data, function () {\n step();\n }, onwriteerror);\n } else\n step();\n break;\n case 'flush':\n crc = message.crc;\n if (data) {\n outputSize += data.length;\n writer.writeUint8Array(data, function () {\n onflush();\n }, onwriteerror);\n } else\n onflush();\n break;\n case 'progress':\n if (onprogress)\n onprogress(index + message.loaded, size);\n break;\n case 'importScripts': //no need to handle here\n case 'newTask':\n case 'echo':\n break;\n default:\n console.warn('zip.js:launchWorkerProcess: unknown message: ', message);\n }\n }\n\n function step() {\n index = chunkIndex * CHUNK_SIZE;\n // use `<=` instead of `<`, because `size` may be 0.\n if (index <= size) {\n reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function (array) {\n if (onprogress)\n onprogress(index, size);\n var msg = index === 0 ? initialMessage : {sn: sn};\n msg.type = 'append';\n msg.data = array;\n\n // posting a message with transferables will fail on IE10\n try {\n worker.postMessage(msg, [array.buffer]);\n } catch (ex) {\n worker.postMessage(msg); // retry without transferables\n }\n chunkIndex++;\n }, onreaderror);\n } else {\n worker.postMessage({\n sn: sn,\n type: 'flush'\n });\n }\n }\n\n outputSize = 0;\n worker.addEventListener('message', onmessage, false);\n step();\n }\n\n function launchProcess(process, reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror) {\n var chunkIndex = 0, index, outputSize = 0,\n crcInput = crcType === 'input',\n crcOutput = crcType === 'output',\n crc = new Crc32();\n\n function step() {\n var outputData;\n index = chunkIndex * CHUNK_SIZE;\n if (index < size)\n reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function (inputData) {\n var outputData;\n try {\n outputData = process.append(inputData, function (loaded) {\n if (onprogress)\n onprogress(index + loaded, size);\n });\n } catch (e) {\n onreaderror(e);\n return;\n }\n if (outputData) {\n outputSize += outputData.length;\n writer.writeUint8Array(outputData, function () {\n chunkIndex++;\n setTimeout(step, 1);\n }, onwriteerror);\n if (crcOutput)\n crc.append(outputData);\n } else {\n chunkIndex++;\n setTimeout(step, 1);\n }\n if (crcInput)\n crc.append(inputData);\n if (onprogress)\n onprogress(index, size);\n }, onreaderror);\n else {\n try {\n outputData = process.flush();\n } catch (e) {\n onreaderror(e);\n return;\n }\n if (outputData) {\n if (crcOutput)\n crc.append(outputData);\n outputSize += outputData.length;\n writer.writeUint8Array(outputData, function () {\n onend(outputSize, crc.get());\n }, onwriteerror);\n } else\n onend(outputSize, crc.get());\n }\n }\n\n step();\n }\n\n function inflate(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\n var crcType = computeCrc32 ? 'output' : 'none';\n if (obj.zip.useWebWorkers) {\n var initialMessage = {\n sn: sn,\n codecClass: 'Inflater',\n crcType: crcType,\n };\n launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);\n } else\n launchProcess(new obj.zip.Inflater(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);\n }\n\n function deflate(worker, sn, reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {\n var crcType = 'input';\n if (obj.zip.useWebWorkers) {\n var initialMessage = {\n sn: sn,\n options: {level: level},\n codecClass: 'Deflater',\n crcType: crcType,\n };\n launchWorkerProcess(worker, initialMessage, reader, writer, 0, reader.size, onprogress, onend, onreaderror, onwriteerror);\n } else\n launchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, crcType, onprogress, onend, onreaderror, onwriteerror);\n }\n\n function copy(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\n var crcType = 'input';\n if (obj.zip.useWebWorkers && computeCrc32) {\n var initialMessage = {\n sn: sn,\n codecClass: 'NOOP',\n crcType: crcType,\n };\n launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);\n } else\n launchProcess(new NOOP(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);\n }\n\n // ZipReader\n\n function decodeASCII(str) {\n var i, out = \"\", charCode, extendedASCII = ['\\u00C7', '\\u00FC', '\\u00E9', '\\u00E2', '\\u00E4', '\\u00E0', '\\u00E5', '\\u00E7', '\\u00EA', '\\u00EB',\n '\\u00E8', '\\u00EF', '\\u00EE', '\\u00EC', '\\u00C4', '\\u00C5', '\\u00C9', '\\u00E6', '\\u00C6', '\\u00F4', '\\u00F6', '\\u00F2', '\\u00FB', '\\u00F9',\n '\\u00FF', '\\u00D6', '\\u00DC', '\\u00F8', '\\u00A3', '\\u00D8', '\\u00D7', '\\u0192', '\\u00E1', '\\u00ED', '\\u00F3', '\\u00FA', '\\u00F1', '\\u00D1',\n '\\u00AA', '\\u00BA', '\\u00BF', '\\u00AE', '\\u00AC', '\\u00BD', '\\u00BC', '\\u00A1', '\\u00AB', '\\u00BB', '_', '_', '_', '\\u00A6', '\\u00A6',\n '\\u00C1', '\\u00C2', '\\u00C0', '\\u00A9', '\\u00A6', '\\u00A6', '+', '+', '\\u00A2', '\\u00A5', '+', '+', '-', '-', '+', '-', '+', '\\u00E3',\n '\\u00C3', '+', '+', '-', '-', '\\u00A6', '-', '+', '\\u00A4', '\\u00F0', '\\u00D0', '\\u00CA', '\\u00CB', '\\u00C8', 'i', '\\u00CD', '\\u00CE',\n '\\u00CF', '+', '+', '_', '_', '\\u00A6', '\\u00CC', '_', '\\u00D3', '\\u00DF', '\\u00D4', '\\u00D2', '\\u00F5', '\\u00D5', '\\u00B5', '\\u00FE',\n '\\u00DE', '\\u00DA', '\\u00DB', '\\u00D9', '\\u00FD', '\\u00DD', '\\u00AF', '\\u00B4', '\\u00AD', '\\u00B1', '_', '\\u00BE', '\\u00B6', '\\u00A7',\n '\\u00F7', '\\u00B8', '\\u00B0', '\\u00A8', '\\u00B7', '\\u00B9', '\\u00B3', '\\u00B2', '_', ' '];\n for (i = 0; i < str.length; i++) {\n charCode = str.charCodeAt(i) & 0xFF;\n if (charCode > 127)\n out += extendedASCII[charCode - 128];\n else\n out += String.fromCharCode(charCode);\n }\n return out;\n }\n\n function decodeUTF8(string) {\n return decodeURIComponent(escape(string));\n }\n\n function getString(bytes) {\n var i, str = \"\";\n for (i = 0; i < bytes.length; i++)\n str += String.fromCharCode(bytes[i]);\n return str;\n }\n\n function getDate(timeRaw) {\n var date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;\n try {\n return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,\n (time & 0x001F) * 2, 0);\n } catch (e) {\n }\n }\n\n function readCommonHeader(entry, data, index, centralDirectory, onerror) {\n entry.version = data.view.getUint16(index, true);\n entry.bitFlag = data.view.getUint16(index + 2, true);\n entry.compressionMethod = data.view.getUint16(index + 4, true);\n entry.lastModDateRaw = data.view.getUint32(index + 6, true);\n entry.lastModDate = getDate(entry.lastModDateRaw);\n if ((entry.bitFlag & 0x01) === 0x01) {\n onerror(ERR_ENCRYPTED);\n return;\n }\n if (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {\n entry.crc32 = data.view.getUint32(index + 10, true);\n entry.compressedSize = data.view.getUint32(index + 14, true);\n entry.uncompressedSize = data.view.getUint32(index + 18, true);\n }\n if (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {\n onerror(ERR_ZIP64);\n return;\n }\n entry.filenameLength = data.view.getUint16(index + 22, true);\n entry.extraFieldLength = data.view.getUint16(index + 24, true);\n }\n\n function createZipReader(reader, callback, onerror) {\n var inflateSN = 0;\n\n function Entry() {\n }\n\n Entry.prototype.getData = function (writer, onend, onprogress, checkCrc32) {\n var that = this;\n\n function testCrc32(crc32) {\n var dataCrc32 = getDataHelper(4);\n dataCrc32.view.setUint32(0, crc32);\n return that.crc32 == dataCrc32.view.getUint32(0);\n }\n\n function getWriterData(uncompressedSize, crc32) {\n if (checkCrc32 && !testCrc32(crc32))\n onerror(ERR_CRC);\n else\n writer.getData(function (data) {\n onend(data);\n });\n }\n\n function onreaderror(err) {\n onerror(err || ERR_READ_DATA);\n }\n\n function onwriteerror(err) {\n onerror(err || ERR_WRITE_DATA);\n }\n\n reader.readUint8Array(that.offset, 30, function (bytes) {\n var data = getDataHelper(bytes.length, bytes), dataOffset;\n if (data.view.getUint32(0) != 0x504b0304) {\n onerror(ERR_BAD_FORMAT);\n return;\n }\n readCommonHeader(that, data, 4, false, onerror);\n dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;\n writer.init(function () {\n if (that.compressionMethod === 0)\n copy(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\n else\n inflate(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\n }, onwriteerror);\n }, onreaderror);\n };\n\n function seekEOCDR(eocdrCallback) {\n // \"End of central directory record\" is the last part of a zip archive, and is at least 22 bytes long.\n // Zip file comment is the last part of EOCDR and has max length of 64KB,\n // so we only have to search the last 64K + 22 bytes of a archive for EOCDR signature (0x06054b50).\n var EOCDR_MIN = 22;\n if (reader.size < EOCDR_MIN) {\n onerror(ERR_BAD_FORMAT);\n return;\n }\n var ZIP_COMMENT_MAX = 256 * 256, EOCDR_MAX = EOCDR_MIN + ZIP_COMMENT_MAX;\n\n // In most cases, the EOCDR is EOCDR_MIN bytes long\n doSeek(EOCDR_MIN, function () {\n // If not found, try within EOCDR_MAX bytes\n doSeek(Math.min(EOCDR_MAX, reader.size), function () {\n onerror(ERR_BAD_FORMAT);\n });\n });\n\n // seek last length bytes of file for EOCDR\n function doSeek(length, eocdrNotFoundCallback) {\n reader.readUint8Array(reader.size - length, length, function (bytes) {\n for (var i = bytes.length - EOCDR_MIN; i >= 0; i--) {\n if (bytes[i] === 0x50 && bytes[i + 1] === 0x4b && bytes[i + 2] === 0x05 && bytes[i + 3] === 0x06) {\n eocdrCallback(new DataView(bytes.buffer, i, EOCDR_MIN));\n return;\n }\n }\n eocdrNotFoundCallback();\n }, function () {\n onerror(ERR_READ);\n });\n }\n }\n\n var zipReader = {\n getEntries: function (callback) {\n var worker = this._worker;\n // look for End of central directory record\n seekEOCDR(function (dataView) {\n var datalength, fileslength;\n datalength = dataView.getUint32(16, true);\n fileslength = dataView.getUint16(8, true);\n if (datalength < 0 || datalength >= reader.size) {\n onerror(ERR_BAD_FORMAT);\n return;\n }\n reader.readUint8Array(datalength, reader.size - datalength, function (bytes) {\n var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);\n for (i = 0; i < fileslength; i++) {\n entry = new Entry();\n entry._worker = worker;\n if (data.view.getUint32(index) != 0x504b0102) {\n onerror(ERR_BAD_FORMAT);\n return;\n }\n readCommonHeader(entry, data, index + 6, true, onerror);\n entry.commentLength = data.view.getUint16(index + 32, true);\n entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);\n entry.offset = data.view.getUint32(index + 42, true);\n filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));\n entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);\n if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == \"/\")\n entry.directory = true;\n comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46\n + entry.filenameLength + entry.extraFieldLength + entry.commentLength));\n entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);\n entries.push(entry);\n index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;\n }\n callback(entries);\n }, function () {\n onerror(ERR_READ);\n });\n });\n },\n close: function (callback) {\n if (this._worker) {\n this._worker.terminate();\n this._worker = null;\n }\n if (callback)\n callback();\n },\n _worker: null\n };\n\n if (!obj.zip.useWebWorkers)\n callback(zipReader);\n else {\n createWorker('inflater',\n function (worker) {\n zipReader._worker = worker;\n callback(zipReader);\n },\n function (err) {\n onerror(err);\n }\n );\n }\n }\n\n // ZipWriter\n\n function encodeUTF8(string) {\n return unescape(encodeURIComponent(string));\n }\n\n function getBytes(str) {\n var i, array = [];\n for (i = 0; i < str.length; i++)\n array.push(str.charCodeAt(i));\n return array;\n }\n\n function createZipWriter(writer, callback, onerror, dontDeflate) {\n var files = {}, filenames = [], datalength = 0;\n var deflateSN = 0;\n\n function onwriteerror(err) {\n onerror(err || ERR_WRITE);\n }\n\n function onreaderror(err) {\n onerror(err || ERR_READ_DATA);\n }\n\n var zipWriter = {\n add: function (name, reader, onend, onprogress, options) {\n var header, filename, date;\n var worker = this._worker;\n\n function writeHeader(callback) {\n var data;\n date = options.lastModDate || new Date();\n header = getDataHelper(26);\n files[name] = {\n headerArray: header.array,\n directory: options.directory,\n filename: filename,\n offset: datalength,\n comment: getBytes(encodeUTF8(options.comment || \"\"))\n };\n header.view.setUint32(0, 0x14000808);\n if (options.version)\n header.view.setUint8(0, options.version);\n if (!dontDeflate && options.level !== 0 && !options.directory)\n header.view.setUint16(4, 0x0800);\n header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);\n header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);\n header.view.setUint16(22, filename.length, true);\n data = getDataHelper(30 + filename.length);\n data.view.setUint32(0, 0x504b0304);\n data.array.set(header.array, 4);\n data.array.set(filename, 30);\n datalength += data.array.length;\n writer.writeUint8Array(data.array, callback, onwriteerror);\n }\n\n function writeFooter(compressedLength, crc32) {\n var footer = getDataHelper(16);\n datalength += compressedLength || 0;\n footer.view.setUint32(0, 0x504b0708);\n if (typeof crc32 != \"undefined\") {\n header.view.setUint32(10, crc32, true);\n footer.view.setUint32(4, crc32, true);\n }\n if (reader) {\n footer.view.setUint32(8, compressedLength, true);\n header.view.setUint32(14, compressedLength, true);\n footer.view.setUint32(12, reader.size, true);\n header.view.setUint32(18, reader.size, true);\n }\n writer.writeUint8Array(footer.array, function () {\n datalength += 16;\n onend();\n }, onwriteerror);\n }\n\n function writeFile() {\n options = options || {};\n name = name.trim();\n if (options.directory && name.charAt(name.length - 1) != \"/\")\n name += \"/\";\n if (files.hasOwnProperty(name)) {\n onerror(ERR_DUPLICATED_NAME);\n return;\n }\n filename = getBytes(encodeUTF8(name));\n filenames.push(name);\n writeHeader(function () {\n if (reader)\n if (dontDeflate || options.level === 0)\n copy(worker, deflateSN++, reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);\n else\n deflate(worker, deflateSN++, reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);\n else\n writeFooter();\n }, onwriteerror);\n }\n\n if (reader)\n reader.init(writeFile, onreaderror);\n else\n writeFile();\n },\n close: function (callback) {\n if (this._worker) {\n this._worker.terminate();\n this._worker = null;\n }\n\n var data, length = 0, index = 0, indexFilename, file;\n for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {\n file = files[filenames[indexFilename]];\n length += 46 + file.filename.length + file.comment.length;\n }\n data = getDataHelper(length + 22);\n for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {\n file = files[filenames[indexFilename]];\n data.view.setUint32(index, 0x504b0102);\n data.view.setUint16(index + 4, 0x1400);\n data.array.set(file.headerArray, index + 6);\n data.view.setUint16(index + 32, file.comment.length, true);\n if (file.directory)\n data.view.setUint8(index + 38, 0x10);\n data.view.setUint32(index + 42, file.offset, true);\n data.array.set(file.filename, index + 46);\n data.array.set(file.comment, index + 46 + file.filename.length);\n index += 46 + file.filename.length + file.comment.length;\n }\n data.view.setUint32(index, 0x504b0506);\n data.view.setUint16(index + 8, filenames.length, true);\n data.view.setUint16(index + 10, filenames.length, true);\n data.view.setUint32(index + 12, length, true);\n data.view.setUint32(index + 16, datalength, true);\n writer.writeUint8Array(data.array, function () {\n writer.getData(callback);\n }, onwriteerror);\n },\n _worker: null\n };\n\n if (!obj.zip.useWebWorkers)\n callback(zipWriter);\n else {\n createWorker('deflater',\n function (worker) {\n zipWriter._worker = worker;\n callback(zipWriter);\n },\n function (err) {\n onerror(err);\n }\n );\n }\n }\n\n function resolveURLs(urls) {\n var a = document.createElement('a');\n return urls.map(function (url) {\n a.href = url;\n return a.href;\n });\n }\n\n var DEFAULT_WORKER_SCRIPTS = {\n deflater: ['z-worker.js', 'deflate.js'],\n inflater: ['z-worker.js', 'inflate.js']\n };\n\n function createWorker(type, callback, onerror) {\n if (obj.zip.workerScripts !== null && obj.zip.workerScriptsPath !== null) {\n onerror(new Error('Either zip.workerScripts or zip.workerScriptsPath may be set, not both.'));\n return;\n }\n var scripts;\n if (obj.zip.workerScripts) {\n scripts = obj.zip.workerScripts[type];\n if (!Array.isArray(scripts)) {\n onerror(new Error('zip.workerScripts.' + type + ' is not an array!'));\n return;\n }\n scripts = resolveURLs(scripts);\n } else {\n scripts = DEFAULT_WORKER_SCRIPTS[type].slice(0);\n scripts[0] = (obj.zip.workerScriptsPath || '') + scripts[0];\n }\n var worker = new Worker(scripts[0]);\n // record total consumed time by inflater/deflater/crc32 in this worker\n worker.codecTime = worker.crcTime = 0;\n worker.postMessage({type: 'importScripts', scripts: scripts.slice(1)});\n worker.addEventListener('message', onmessage);\n function onmessage(ev) {\n var msg = ev.data;\n if (msg.error) {\n worker.terminate(); // should before onerror(), because onerror() may throw.\n onerror(msg.error);\n return;\n }\n if (msg.type === 'importScripts') {\n worker.removeEventListener('message', onmessage);\n worker.removeEventListener('error', errorHandler);\n callback(worker);\n }\n }\n\n // catch entry script loading error and other unhandled errors\n worker.addEventListener('error', errorHandler);\n function errorHandler(err) {\n worker.terminate();\n onerror(err);\n }\n }\n\n function onerror_default(error) {\n console.error(error);\n }\n\n obj.zip = {\n Reader: Reader,\n Writer: Writer,\n BlobReader: BlobReader,\n Data64URIReader: Data64URIReader,\n TextReader: TextReader,\n BlobWriter: BlobWriter,\n Data64URIWriter: Data64URIWriter,\n TextWriter: TextWriter,\n createReader: function (reader, callback, onerror) {\n onerror = onerror || onerror_default;\n\n reader.init(function () {\n createZipReader(reader, callback, onerror);\n }, onerror);\n },\n createWriter: function (writer, callback, onerror, dontDeflate) {\n onerror = onerror || onerror_default;\n dontDeflate = !!dontDeflate;\n\n writer.init(function () {\n createZipWriter(writer, callback, onerror, dontDeflate);\n }, onerror);\n },\n useWebWorkers: true,\n /**\n * Directory containing the default worker scripts (z-worker.js, deflate.js, and inflate.js), relative to current base url.\n * E.g.: zip.workerScripts = './';\n */\n workerScriptsPath: null,\n /**\n * Advanced option to control which scripts are loaded in the Web worker. If this option is specified, then workerScriptsPath must not be set.\n * workerScripts.deflater/workerScripts.inflater should be arrays of urls to scripts for deflater/inflater, respectively.\n * Scripts in the array are executed in order, and the first one should be z-worker.js, which is used to start the worker.\n * All urls are relative to current base url.\n * E.g.:\n * zip.workerScripts = {\n\t\t * deflater: ['z-worker.js', 'deflate.js'],\n\t\t * inflater: ['z-worker.js', 'inflate.js']\n\t\t * };\n */\n workerScripts: null,\n };\n\n})(zipLib);\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XML3DLoaderPlugin/zipjs/zip.js?");
|
|
2138
2138
|
|
|
2139
2139
|
/***/ }),
|
|
2140
2140
|
|
|
@@ -2544,7 +2544,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2544
2544
|
\*************************************************************************/
|
|
2545
2545
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2546
2546
|
|
|
2547
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MouseMiscHandler: () => (/* binding */ MouseMiscHandler)\n/* harmony export */ });\n/**\
|
|
2547
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MouseMiscHandler: () => (/* binding */ MouseMiscHandler)\n/* harmony export */ });\n/**\n * @private\n */\nclass MouseMiscHandler {\n\tconstructor(scene, controllers, configs, states, updates) {\n\t\tthis._scene = scene;\n\n\t\tthis.canvas = this._scene.canvas.canvas;\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mouseenter\",\n\t\t\t(this._mouseEnterHandler = () => {\n\t\t\t\tstates.mouseover = true;\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mouseleave\",\n\t\t\t(this._mouseLeaveHandler = () => {\n\t\t\t\tstates.mouseover = false;\n\t\t\t\tthis.canvas.style.cursor = null;\n\t\t\t})\n\t\t);\n\n\t\tdocument.addEventListener(\n\t\t\t\"mousemove\",\n\t\t\t(this._mouseMoveHandler = (e) => {\n\t\t\t\tgetCanvasPosFromEvent(e, this.canvas, states.pointerCanvasPos);\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mousedown\",\n\t\t\t(this._mouseDownHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tgetCanvasPosFromEvent(e, this.canvas, states.pointerCanvasPos);\n\t\t\t\tstates.mouseover = true;\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mouseup\",\n\t\t\t(this._mouseUpHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\treset() {}\n\n\tdestroy() {\n\t\t//网络问题导致的模型加载失败等情况时,如果切换模型,会找不到canvas\n\t\t//因此暂时在此加判断\n\t\tif (this.canvas != null) {\n\t\t\tthis.canvas.removeEventListener(\"mouseenter\", this._mouseEnterHandler);\n\t\t\tthis.canvas.removeEventListener(\"mouseleave\", this._mouseLeaveHandler);\n\t\t\tthis.canvas.removeEventListener(\"mousedown\", this._mouseDownHandler);\n\t\t\tthis.canvas.removeEventListener(\"mouseup\", this._mouseUpHandler);\n\t\t}\n\t\tdocument.removeEventListener(\"mousemove\", this._mouseMoveHandler);\n\t}\n}\n\nfunction getCanvasPosFromEvent(event, canvas, canvasPos) {\n\tif (!event) {\n\t\tevent = window.event;\n\t\tcanvasPos[0] = event.x;\n\t\tcanvasPos[1] = event.y;\n\t} else {\n\t\tconst { x, y } = canvas.getBoundingClientRect();\n\t\tcanvasPos[0] = event.clientX - x;\n\t\tcanvasPos[1] = event.clientY - y;\n\t}\n\treturn canvasPos;\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/MouseMiscHandler.js?");
|
|
2548
2548
|
|
|
2549
2549
|
/***/ }),
|
|
2550
2550
|
|
|
@@ -2554,7 +2554,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2554
2554
|
\***********************************************************************************/
|
|
2555
2555
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2556
2556
|
|
|
2557
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MousePanRotateDollyHandler: () => (/* binding */ MousePanRotateDollyHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\nconst canvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\r\nconst getCanvasPosFromEvent = function (event, canvasPos) {\r\n\tif (!event) {\r\n\t\tevent = window.event;\r\n\t\tcanvasPos[0] = event.x;\r\n\t\tcanvasPos[1] = event.y;\r\n\t} else {\r\n\t\tlet element = event.target;\r\n\t\tlet totalOffsetLeft = 0;\r\n\t\tlet totalOffsetTop = 0;\r\n\t\tlet totalScrollX = 0;\r\n\t\tlet totalScrollY = 0;\r\n\t\twhile (element.offsetParent) {\r\n\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\ttotalScrollX += element.scrollLeft;\r\n\t\t\ttotalScrollY += element.scrollTop;\r\n\t\t\telement = element.offsetParent;\r\n\t\t}\r\n\t\tcanvasPos[0] = event.pageX + totalScrollX - totalOffsetLeft;\r\n\t\tcanvasPos[1] = event.pageY + totalScrollY - totalOffsetTop;\r\n\t}\r\n\treturn canvasPos;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nclass MousePanRotateDollyHandler {\r\n\tconstructor(scene, controllers, configs, states, updates) {\r\n\t\tthis._scene = scene;\r\n\r\n\t\tconst pickController = controllers.pickController;\r\n\r\n\t\tlet lastX = 0;\r\n\t\tlet lastY = 0;\r\n\t\tlet lastXDown = 0;\r\n\t\tlet lastYDown = 0;\r\n\t\tlet xRotateDelta = 0;\r\n\t\tlet yRotateDelta = 0;\r\n\r\n\t\tlet mouseDownLeft;\r\n\t\tlet mouseDownMiddle;\r\n\t\tlet mouseDownRight;\r\n\r\n\t\tlet mouseDownPicked = false;\r\n\t\tconst pickedWorldPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tlet mouseMovedOnCanvasSinceLastWheel = true;\r\n\r\n\t\tthis.canvas = this._scene.canvas.canvas;\r\n\r\n\t\tconst keyDown = [];\r\n\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"keydown\",\r\n\t\t\t(this._documentKeyDownHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled) || !scene.input.keyboardEnabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tconst keyCode = e.keyCode;\r\n\t\t\t\tkeyDown[keyCode] = true;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"keyup\",\r\n\t\t\t(this._documentKeyUpHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled) || !scene.input.keyboardEnabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tconst keyCode = e.keyCode;\r\n\t\t\t\tkeyDown[keyCode] = false;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst setMousedownState = (pick = true) => {\r\n\t\t\tthis.canvas.style.cursor = \"move\";\r\n\t\t\tsetMousedownPositions();\r\n\t\t\tif (pick) {\r\n\t\t\t\tsetMousedownPick();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tfunction setMousedownPositions() {\r\n\t\t\txRotateDelta = 0;\r\n\t\t\tyRotateDelta = 0;\r\n\r\n\t\t\tlastX = states.pointerCanvasPos[0];\r\n\t\t\tlastY = states.pointerCanvasPos[1];\r\n\t\t\tlastXDown = states.pointerCanvasPos[0];\r\n\t\t\tlastYDown = states.pointerCanvasPos[1];\r\n\t\t}\r\n\r\n\t\tfunction setMousedownPick() {\r\n\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\tpickController.schedulePickSurface = true;\r\n\t\t\tpickController.update();\r\n\r\n\t\t\tif (\r\n\t\t\t\tpickController.picked &&\r\n\t\t\t\tpickController.pickedSurface &&\r\n\t\t\t\tpickController.pickResult &&\r\n\t\t\t\tpickController.pickResult.worldPos\r\n\t\t\t) {\r\n\t\t\t\tmouseDownPicked = true;\r\n\t\t\t\tpickedWorldPos.set(pickController.pickResult.worldPos);\r\n\t\t\t} else {\r\n\t\t\t\tmouseDownPicked = false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"mousedown\",\r\n\t\t\t(this._mouseDownHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\tif (keyDown[scene.input.KEY_SHIFT] || configs.planView) {\r\n\t\t\t\t\t\t\tmouseDownLeft = true;\r\n\r\n\t\t\t\t\t\t\tsetMousedownState();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tmouseDownLeft = true;\r\n\r\n\t\t\t\t\t\t\tsetMousedownState(false);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\tmouseDownMiddle = true;\r\n\r\n\t\t\t\t\t\tsetMousedownState();\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tmouseDownRight = true;\r\n\r\n\t\t\t\t\t\tif (configs.panRightClick) {\r\n\t\t\t\t\t\t\tsetMousedownState();\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"mousemove\",\r\n\t\t\t(this._documentMouseMoveHandler = () => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Scaling drag-rotate to canvas boundary\r\n\r\n\t\t\t\tconst canvasBoundary = scene.canvas.boundary;\r\n\r\n\t\t\t\tconst canvasWidth = canvasBoundary[2];\r\n\t\t\t\tconst canvasHeight = canvasBoundary[3];\r\n\t\t\t\tconst x = states.pointerCanvasPos[0];\r\n\t\t\t\tconst y = states.pointerCanvasPos[1];\r\n\r\n\t\t\t\tconst panning =\r\n\t\t\t\t\tkeyDown[scene.input.KEY_SHIFT] ||\r\n\t\t\t\t\tconfigs.planView ||\r\n\t\t\t\t\t(!configs.panRightClick && mouseDownMiddle) ||\r\n\t\t\t\t\t(configs.panRightClick && mouseDownRight);\r\n\r\n\t\t\t\tif (panning) {\r\n\t\t\t\t\tconst xPanDelta = x - lastX;\r\n\t\t\t\t\tconst yPanDelta = y - lastY;\r\n\r\n\t\t\t\t\tconst camera = scene.camera;\r\n\r\n\t\t\t\t\t// We use only canvasHeight here so that aspect ratio does not distort speed\r\n\r\n\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\tconst depth = Math.abs(\r\n\t\t\t\t\t\t\tmouseDownPicked\r\n\t\t\t\t\t\t\t\t? _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(pickedWorldPos, scene.camera.eye, []))\r\n\t\t\t\t\t\t\t\t: scene.camera.eyeLookDist\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\tconst targetDistance = depth * Math.tan(((camera.perspective.fov / 2) * Math.PI) / 180.0);\r\n\r\n\t\t\t\t\t\tupdates.panDeltaX += (1.5 * xPanDelta * targetDistance) / canvasHeight;\r\n\t\t\t\t\t\tupdates.panDeltaY += (1.5 * yPanDelta * targetDistance) / canvasHeight;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tupdates.panDeltaX += 0.5 * camera.ortho.scale * (xPanDelta / canvasHeight);\r\n\t\t\t\t\t\tupdates.panDeltaY += 0.5 * camera.ortho.scale * (yPanDelta / canvasHeight);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {\r\n\t\t\t\t\tif (!configs.planView) {\r\n\t\t\t\t\t\t// No rotating in plan-view mode\r\n\r\n\t\t\t\t\t\tif (configs.firstPerson) {\r\n\t\t\t\t\t\t\tupdates.rotateDeltaY -= (((x - lastX) / canvasWidth) * configs.dragRotationRate) / 2;\r\n\t\t\t\t\t\t\tupdates.rotateDeltaX += ((y - lastY) / canvasHeight) * (configs.dragRotationRate / 4);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tupdates.rotateDeltaY -= ((x - lastX) / canvasWidth) * (configs.dragRotationRate * 1.5);\r\n\t\t\t\t\t\t\tupdates.rotateDeltaX += ((y - lastY) / canvasHeight) * (configs.dragRotationRate * 1.5);\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\tlastX = x;\r\n\t\t\t\tlastY = y;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"mousemove\",\r\n\t\t\t(this._canvasMouseMoveHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!states.mouseover) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmouseMovedOnCanvasSinceLastWheel = true;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"mouseup\",\r\n\t\t\t(this._documentMouseUpHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tmouseDownLeft = false;\r\n\t\t\t\t\t\tmouseDownMiddle = false;\r\n\t\t\t\t\t\tmouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\txRotateDelta = 0;\r\n\t\t\t\tyRotateDelta = 0;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"mouseup\",\r\n\t\t\t(this._mouseUpHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tgetCanvasPosFromEvent(e, canvasPos);\r\n\t\t\t\t\t\tconst x = canvasPos[0];\r\n\t\t\t\t\t\tconst y = canvasPos[1];\r\n\t\t\t\t\t\tif (Math.abs(x - lastXDown) < 3 && Math.abs(y - lastYDown) < 3) {\r\n\t\t\t\t\t\t\tcontrollers.cameraControl.fire(\r\n\t\t\t\t\t\t\t\t\"rightClick\",\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// For context menus\r\n\t\t\t\t\t\t\t\t\tpagePos: [Math.round(e.pageX), Math.round(e.pageY)],\r\n\t\t\t\t\t\t\t\t\tcanvasPos: canvasPos,\r\n\t\t\t\t\t\t\t\t\tevent: e\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\ttrue\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tthis.canvas.style.removeProperty(\"cursor\");\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"mouseenter\",\r\n\t\t\t(this._mouseEnterHandler = () => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\txRotateDelta = 0;\r\n\t\t\t\tyRotateDelta = 0;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst maxElapsed = 1 / 20;\r\n\t\tconst minElapsed = 1 / 60;\r\n\r\n\t\tlet secsNowLast = null;\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"wheel\",\r\n\t\t\t(this._mouseWheelHandler = (e) => {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tconst secsNow = performance.now() / 1000.0;\r\n\t\t\t\tvar secsElapsed = secsNowLast !== null ? secsNow - secsNowLast : 0;\r\n\t\t\t\tsecsNowLast = secsNow;\r\n\t\t\t\tif (secsElapsed > maxElapsed) {\r\n\t\t\t\t\tsecsElapsed = maxElapsed;\r\n\t\t\t\t}\r\n\t\t\t\tif (secsElapsed < minElapsed) {\r\n\t\t\t\t\tsecsElapsed = minElapsed;\r\n\t\t\t\t}\r\n\t\t\t\tconst delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\r\n\t\t\t\tif (delta === 0) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tconst normalizedDelta = delta / Math.abs(delta);\r\n\t\t\t\tupdates.dollyDelta += -normalizedDelta * secsElapsed * configs.mouseWheelDollyRate;\r\n\r\n\t\t\t\tif (mouseMovedOnCanvasSinceLastWheel) {\r\n\t\t\t\t\tstates.followPointerDirty = true;\r\n\t\t\t\t\tmouseMovedOnCanvasSinceLastWheel = false;\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\treset() {}\r\n\r\n\tdestroy() {\r\n\t\tif (this.canvas != null) {\r\n\t\t\tthis.canvas.removeEventListener(\"mousedown\", this._mouseDownHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"mousemove\", this._canvasMouseMoveHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"mouseup\", this._mouseUpHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"mouseenter\", this._mouseEnterHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"wheel\", this._mouseWheelHandler);\r\n\t\t}\r\n\t\tdocument.removeEventListener(\"keydown\", this._documentKeyDownHandler);\r\n\t\tdocument.removeEventListener(\"keyup\", this._documentKeyUpHandler);\r\n\t\tdocument.removeEventListener(\"mousemove\", this._documentMouseMoveHandler);\r\n\t\tdocument.removeEventListener(\"mouseup\", this._documentMouseUpHandler);\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/MousePanRotateDollyHandler.js?");
|
|
2557
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MousePanRotateDollyHandler: () => (/* binding */ MousePanRotateDollyHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\n\nconst canvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\nconst getCanvasPosFromEvent = function (event, canvasPos) {\n\tif (!event) {\n\t\tevent = window.event;\n\t\tcanvasPos[0] = event.x;\n\t\tcanvasPos[1] = event.y;\n\t} else {\n\t\tlet element = event.target;\n\t\tlet totalOffsetLeft = 0;\n\t\tlet totalOffsetTop = 0;\n\t\tlet totalScrollX = 0;\n\t\tlet totalScrollY = 0;\n\t\twhile (element.offsetParent) {\n\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\ttotalScrollX += element.scrollLeft;\n\t\t\ttotalScrollY += element.scrollTop;\n\t\t\telement = element.offsetParent;\n\t\t}\n\t\tcanvasPos[0] = event.pageX + totalScrollX - totalOffsetLeft;\n\t\tcanvasPos[1] = event.pageY + totalScrollY - totalOffsetTop;\n\t}\n\treturn canvasPos;\n};\n\n/**\n * @private\n */\nclass MousePanRotateDollyHandler {\n\tconstructor(scene, controllers, configs, states, updates) {\n\t\tthis._scene = scene;\n\n\t\tconst pickController = controllers.pickController;\n\n\t\tlet lastX = 0;\n\t\tlet lastY = 0;\n\t\tlet lastXDown = 0;\n\t\tlet lastYDown = 0;\n\t\tlet xRotateDelta = 0;\n\t\tlet yRotateDelta = 0;\n\n\t\tlet mouseDownLeft;\n\t\tlet mouseDownMiddle;\n\t\tlet mouseDownRight;\n\n\t\tlet mouseDownPicked = false;\n\t\tconst pickedWorldPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\n\n\t\tlet mouseMovedOnCanvasSinceLastWheel = true;\n\n\t\tthis.canvas = this._scene.canvas.canvas;\n\n\t\tconst keyDown = [];\n\n\t\tdocument.addEventListener(\n\t\t\t\"keydown\",\n\t\t\t(this._documentKeyDownHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled) || !scene.input.keyboardEnabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst keyCode = e.keyCode;\n\t\t\t\tkeyDown[keyCode] = true;\n\t\t\t})\n\t\t);\n\n\t\tdocument.addEventListener(\n\t\t\t\"keyup\",\n\t\t\t(this._documentKeyUpHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled) || !scene.input.keyboardEnabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst keyCode = e.keyCode;\n\t\t\t\tkeyDown[keyCode] = false;\n\t\t\t})\n\t\t);\n\n\t\tconst setMousedownState = (pick = true) => {\n\t\t\tthis.canvas.style.cursor = \"move\";\n\t\t\tsetMousedownPositions();\n\t\t\tif (pick) {\n\t\t\t\tsetMousedownPick();\n\t\t\t}\n\t\t};\n\n\t\tfunction setMousedownPositions() {\n\t\t\txRotateDelta = 0;\n\t\t\tyRotateDelta = 0;\n\n\t\t\tlastX = states.pointerCanvasPos[0];\n\t\t\tlastY = states.pointerCanvasPos[1];\n\t\t\tlastXDown = states.pointerCanvasPos[0];\n\t\t\tlastYDown = states.pointerCanvasPos[1];\n\t\t}\n\n\t\tfunction setMousedownPick() {\n\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\tpickController.schedulePickSurface = true;\n\t\t\tpickController.update();\n\n\t\t\tif (\n\t\t\t\tpickController.picked &&\n\t\t\t\tpickController.pickedSurface &&\n\t\t\t\tpickController.pickResult &&\n\t\t\t\tpickController.pickResult.worldPos\n\t\t\t) {\n\t\t\t\tmouseDownPicked = true;\n\t\t\t\tpickedWorldPos.set(pickController.pickResult.worldPos);\n\t\t\t} else {\n\t\t\t\tmouseDownPicked = false;\n\t\t\t}\n\t\t}\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mousedown\",\n\t\t\t(this._mouseDownHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\tif (keyDown[scene.input.KEY_SHIFT] || configs.planView) {\n\t\t\t\t\t\t\tmouseDownLeft = true;\n\n\t\t\t\t\t\t\tsetMousedownState();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmouseDownLeft = true;\n\n\t\t\t\t\t\t\tsetMousedownState(false);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\tmouseDownMiddle = true;\n\n\t\t\t\t\t\tsetMousedownState();\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tmouseDownRight = true;\n\n\t\t\t\t\t\tif (configs.panRightClick) {\n\t\t\t\t\t\t\tsetMousedownState();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tdocument.addEventListener(\n\t\t\t\"mousemove\",\n\t\t\t(this._documentMouseMoveHandler = () => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Scaling drag-rotate to canvas boundary\n\n\t\t\t\tconst canvasBoundary = scene.canvas.boundary;\n\n\t\t\t\tconst canvasWidth = canvasBoundary[2];\n\t\t\t\tconst canvasHeight = canvasBoundary[3];\n\t\t\t\tconst x = states.pointerCanvasPos[0];\n\t\t\t\tconst y = states.pointerCanvasPos[1];\n\n\t\t\t\tconst panning =\n\t\t\t\t\tkeyDown[scene.input.KEY_SHIFT] ||\n\t\t\t\t\tconfigs.planView ||\n\t\t\t\t\t(!configs.panRightClick && mouseDownMiddle) ||\n\t\t\t\t\t(configs.panRightClick && mouseDownRight);\n\n\t\t\t\tif (panning) {\n\t\t\t\t\tconst xPanDelta = x - lastX;\n\t\t\t\t\tconst yPanDelta = y - lastY;\n\n\t\t\t\t\tconst camera = scene.camera;\n\n\t\t\t\t\t// We use only canvasHeight here so that aspect ratio does not distort speed\n\n\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\tconst depth = Math.abs(\n\t\t\t\t\t\t\tmouseDownPicked\n\t\t\t\t\t\t\t\t? _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(pickedWorldPos, scene.camera.eye, []))\n\t\t\t\t\t\t\t\t: scene.camera.eyeLookDist\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst targetDistance = depth * Math.tan(((camera.perspective.fov / 2) * Math.PI) / 180.0);\n\n\t\t\t\t\t\tupdates.panDeltaX += (1.5 * xPanDelta * targetDistance) / canvasHeight;\n\t\t\t\t\t\tupdates.panDeltaY += (1.5 * yPanDelta * targetDistance) / canvasHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tupdates.panDeltaX += 0.5 * camera.ortho.scale * (xPanDelta / canvasHeight);\n\t\t\t\t\t\tupdates.panDeltaY += 0.5 * camera.ortho.scale * (yPanDelta / canvasHeight);\n\t\t\t\t\t}\n\t\t\t\t} else if (mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {\n\t\t\t\t\tif (!configs.planView) {\n\t\t\t\t\t\t// No rotating in plan-view mode\n\n\t\t\t\t\t\tif (configs.firstPerson) {\n\t\t\t\t\t\t\tupdates.rotateDeltaY -= (((x - lastX) / canvasWidth) * configs.dragRotationRate) / 2;\n\t\t\t\t\t\t\tupdates.rotateDeltaX += ((y - lastY) / canvasHeight) * (configs.dragRotationRate / 4);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tupdates.rotateDeltaY -= ((x - lastX) / canvasWidth) * (configs.dragRotationRate * 1.5);\n\t\t\t\t\t\t\tupdates.rotateDeltaX += ((y - lastY) / canvasHeight) * (configs.dragRotationRate * 1.5);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mousemove\",\n\t\t\t(this._canvasMouseMoveHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!states.mouseover) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tmouseMovedOnCanvasSinceLastWheel = true;\n\t\t\t})\n\t\t);\n\n\t\tdocument.addEventListener(\n\t\t\t\"mouseup\",\n\t\t\t(this._documentMouseUpHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tmouseDownLeft = false;\n\t\t\t\t\t\tmouseDownMiddle = false;\n\t\t\t\t\t\tmouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\txRotateDelta = 0;\n\t\t\t\tyRotateDelta = 0;\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mouseup\",\n\t\t\t(this._mouseUpHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tgetCanvasPosFromEvent(e, canvasPos);\n\t\t\t\t\t\tconst x = canvasPos[0];\n\t\t\t\t\t\tconst y = canvasPos[1];\n\t\t\t\t\t\tif (Math.abs(x - lastXDown) < 3 && Math.abs(y - lastYDown) < 3) {\n\t\t\t\t\t\t\tcontrollers.cameraControl.fire(\n\t\t\t\t\t\t\t\t\"rightClick\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// For context menus\n\t\t\t\t\t\t\t\t\tpagePos: [Math.round(e.pageX), Math.round(e.pageY)],\n\t\t\t\t\t\t\t\t\tcanvasPos: canvasPos,\n\t\t\t\t\t\t\t\t\tevent: e\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis.canvas.style.removeProperty(\"cursor\");\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mouseenter\",\n\t\t\t(this._mouseEnterHandler = () => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\txRotateDelta = 0;\n\t\t\t\tyRotateDelta = 0;\n\t\t\t})\n\t\t);\n\n\t\tconst maxElapsed = 1 / 20;\n\t\tconst minElapsed = 1 / 60;\n\n\t\tlet secsNowLast = null;\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"wheel\",\n\t\t\t(this._mouseWheelHandler = (e) => {\n\t\t\t\te.preventDefault();\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst secsNow = performance.now() / 1000.0;\n\t\t\t\tvar secsElapsed = secsNowLast !== null ? secsNow - secsNowLast : 0;\n\t\t\t\tsecsNowLast = secsNow;\n\t\t\t\tif (secsElapsed > maxElapsed) {\n\t\t\t\t\tsecsElapsed = maxElapsed;\n\t\t\t\t}\n\t\t\t\tif (secsElapsed < minElapsed) {\n\t\t\t\t\tsecsElapsed = minElapsed;\n\t\t\t\t}\n\t\t\t\tconst delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\n\t\t\t\tif (delta === 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst normalizedDelta = delta / Math.abs(delta);\n\t\t\t\tupdates.dollyDelta += -normalizedDelta * secsElapsed * configs.mouseWheelDollyRate;\n\n\t\t\t\tif (mouseMovedOnCanvasSinceLastWheel) {\n\t\t\t\t\tstates.followPointerDirty = true;\n\t\t\t\t\tmouseMovedOnCanvasSinceLastWheel = false;\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\treset() {}\n\n\tdestroy() {\n\t\tif (this.canvas != null) {\n\t\t\tthis.canvas.removeEventListener(\"mousedown\", this._mouseDownHandler);\n\t\t\tthis.canvas.removeEventListener(\"mousemove\", this._canvasMouseMoveHandler);\n\t\t\tthis.canvas.removeEventListener(\"mouseup\", this._mouseUpHandler);\n\t\t\tthis.canvas.removeEventListener(\"mouseenter\", this._mouseEnterHandler);\n\t\t\tthis.canvas.removeEventListener(\"wheel\", this._mouseWheelHandler);\n\t\t}\n\t\tdocument.removeEventListener(\"keydown\", this._documentKeyDownHandler);\n\t\tdocument.removeEventListener(\"keyup\", this._documentKeyUpHandler);\n\t\tdocument.removeEventListener(\"mousemove\", this._documentMouseMoveHandler);\n\t\tdocument.removeEventListener(\"mouseup\", this._documentMouseUpHandler);\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/MousePanRotateDollyHandler.js?");
|
|
2558
2558
|
|
|
2559
2559
|
/***/ }),
|
|
2560
2560
|
|
|
@@ -2564,7 +2564,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2564
2564
|
\*************************************************************************/
|
|
2565
2565
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2566
2566
|
|
|
2567
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MousePickHandler: () => (/* binding */ MousePickHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\n/**\r\n * @private\r\n */\r\nclass MousePickHandler {\r\n\tconstructor(scene, controllers, configs, states, updates) {\r\n\t\tthis._scene = scene;\r\n\r\n\t\tconst pickController = controllers.pickController;\r\n\t\tconst pivotController = controllers.pivotController;\r\n\t\tconst cameraControl = controllers.cameraControl;\r\n\r\n\t\tthis._clicks = 0;\r\n\t\tthis._timeout = null;\r\n\t\tthis._lastPickedEntityId = null;\r\n\r\n\t\tlet leftDown = false;\r\n\t\tlet rightDown = false;\r\n\r\n\t\tlet clickedEntity = null;\r\n\r\n\t\tthis.canvas = this._scene.canvas.canvas;\r\n\r\n\t\tconst flyCameraTo = (pickResult) => {\r\n\t\t\tlet pos;\r\n\t\t\tif (pickResult && pickResult.worldPos) {\r\n\t\t\t\tpos = pickResult.worldPos;\r\n\t\t\t}\r\n\t\t\tconst aabb = pickResult && pickResult.entity ? pickResult.entity.aabb : scene.aabb;\r\n\t\t\tif (pos) {\r\n\t\t\t\t// Fly to look at point, don't change eye->look dist\r\n\t\t\t\tconst camera = scene.camera;\r\n\t\t\t\tconst diff = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, camera.look, []);\r\n\t\t\t\tcontrollers.cameraFlight.flyTo({\r\n\t\t\t\t\t// look: pos,\r\n\t\t\t\t\t// eye: xeokit.math.addVec3(pos, diff, []),\r\n\t\t\t\t\t// up: camera.up,\r\n\t\t\t\t\taabb: aabb\r\n\t\t\t\t});\r\n\t\t\t\t// TODO: Option to back off to fit AABB in view\r\n\t\t\t} else {\r\n\t\t\t\t// Fly to fit target boundary in view\r\n\t\t\t\tcontrollers.cameraFlight.flyTo({\r\n\t\t\t\t\taabb: aabb\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst tickifiedMouseMoveFn = scene.tickify(\r\n\t\t\t(this._canvasMouseMoveHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (leftDown || rightDown) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst hoverSubs = cameraControl.hasSubs(\"hover\");\r\n\t\t\t\tconst hoverEnterSubs = cameraControl.hasSubs(\"hoverEnter\");\r\n\t\t\t\tconst hoverOutSubs = cameraControl.hasSubs(\"hoverOut\");\r\n\t\t\t\tconst hoverOffSubs = cameraControl.hasSubs(\"hoverOff\");\r\n\t\t\t\tconst hoverSurfaceSubs = cameraControl.hasSubs(\"hoverSurface\");\r\n\t\t\t\tconst hoverSnapOrSurfaceSubs = cameraControl.hasSubs(\"hoverSnapOrSurface\");\r\n\r\n\t\t\t\tif (hoverSubs || hoverEnterSubs || hoverOutSubs || hoverOffSubs || hoverSurfaceSubs || hoverSnapOrSurfaceSubs) {\r\n\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\t\t\tpickController.schedulePickEntity = true;\r\n\t\t\t\t\tpickController.schedulePickSurface = hoverSurfaceSubs;\r\n\t\t\t\t\tpickController.scheduleSnapOrPick = hoverSnapOrSurfaceSubs;\r\n\r\n\t\t\t\t\tpickController.update();\r\n\r\n\t\t\t\t\tif (pickController.pickResult) {\r\n\t\t\t\t\t\tif (pickController.pickResult.entity) {\r\n\t\t\t\t\t\t\tconst pickedEntityId = pickController.pickResult.entity.id;\r\n\r\n\t\t\t\t\t\t\tif (this._lastPickedEntityId !== pickedEntityId) {\r\n\t\t\t\t\t\t\t\tif (this._lastPickedEntityId !== undefined) {\r\n\t\t\t\t\t\t\t\t\tcameraControl.fire(\r\n\t\t\t\t\t\t\t\t\t\t\"hoverOut\",\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\t// Hovered off an entity\r\n\t\t\t\t\t\t\t\t\t\t\tentity: scene.objects[this._lastPickedEntityId]\r\n\t\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\t\ttrue\r\n\t\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\t\t\tcameraControl.fire(\"hoverEnter\", pickController.pickResult, true); // Hovering over a new entity\r\n\r\n\t\t\t\t\t\t\t\tthis._lastPickedEntityId = pickedEntityId;\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\tcameraControl.fire(\"hover\", pickController.pickResult, true);\r\n\r\n\t\t\t\t\t\tif (pickController.pickResult.worldPos || pickController.pickResult.snappedWorldPos) {\r\n\t\t\t\t\t\t\t// Hovering the surface of an entity\r\n\t\t\t\t\t\t\tcameraControl.fire(\"hoverSurface\", pickController.pickResult, true);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tif (this._lastPickedEntityId !== undefined) {\r\n\t\t\t\t\t\t\tcameraControl.fire(\r\n\t\t\t\t\t\t\t\t\"hoverOut\",\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Hovered off an entity\r\n\t\t\t\t\t\t\t\t\tentity: scene.objects[this._lastPickedEntityId]\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\ttrue\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tthis._lastPickedEntityId = undefined;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tcameraControl.fire(\r\n\t\t\t\t\t\t\t\"hoverOff\",\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Not hovering on any entity\r\n\t\t\t\t\t\t\t\tcanvasPos: pickController.pickCursorPos\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\ttrue\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\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\"mousemove\", tickifiedMouseMoveFn);\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"dblclick\",\r\n\t\t\t(this._canvasDblClickHandler = (e) => {\r\n\t\t\t\tstates.mouseDownClientX = e.clientX;\r\n\t\t\t\tstates.mouseDownClientY = e.clientY;\r\n\t\t\t\tstates.mouseDownCursorX = states.pointerCanvasPos[0];\r\n\t\t\t\tstates.mouseDownCursorY = states.pointerCanvasPos[1];\r\n\t\t\t\tif (!configs.firstPerson && configs.followPointer) {\r\n\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\t\t\tpickController.schedulePickSurface = true;\r\n\t\t\t\t\tpickController.update();\r\n\t\t\t\t}\r\n\t\t\t\tconst pickResult = pickController.pickResult;\r\n\t\t\t\tif (pickResult) {\r\n\t\t\t\t\tcameraControl.fire(\"doublePicked\", pickController.pickResult, true);\r\n\r\n\t\t\t\t\tif (pickController.pickedSurface) {\r\n\t\t\t\t\t\tcameraControl.fire(\"doublePickedSurface\", pickController.pickResult, true);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tcameraControl.fire(\r\n\t\t\t\t\t\t\"doublePickedNothing\",\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcanvasPos: states.pointerCanvasPos\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\ttrue\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"mousedown\",\r\n\t\t\t(this._canvasMouseDownHandler = (e) => {\r\n\t\t\t\tif (e.which === 1) {\r\n\t\t\t\t\tleftDown = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (e.which === 3) {\r\n\t\t\t\t\trightDown = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst leftButtonDown = e.which === 1;\r\n\r\n\t\t\t\tif (!leftButtonDown) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Left mouse button down to start pivoting\r\n\r\n\t\t\t\tstates.mouseDownClientX = e.clientX;\r\n\t\t\t\tstates.mouseDownClientY = e.clientY;\r\n\t\t\t\tstates.mouseDownCursorX = states.pointerCanvasPos[0];\r\n\t\t\t\tstates.mouseDownCursorY = states.pointerCanvasPos[1];\r\n\r\n\t\t\t\tif (!configs.firstPerson && configs.followPointer) {\r\n\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\t\t\tpickController.schedulePickSurface = true;\r\n\r\n\t\t\t\t\tpickController.update();\r\n\r\n\t\t\t\t\tif (e.which === 1) {\r\n\t\t\t\t\t\t// Left button\r\n\t\t\t\t\t\tconst pickResult = pickController.pickResult;\r\n\r\n\t\t\t\t\t\tif (pickResult && pickResult.worldPos) {\r\n\t\t\t\t\t\t\tpivotController.setCanvasPivotPos(states.pointerCanvasPos);\r\n\t\t\t\t\t\t\tcameraControl.fire(\"mouseDownEntity\", pickController.pickResult, true);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tif (configs.smartPivot) {\r\n\t\t\t\t\t\t\t\tpivotController.setCanvasPivotPos(states.pointerCanvasPos);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tpivotController.setPivotPos(scene.camera.look);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tpivotController.startPivot();\r\n\t\t\t\t\t\t\tcameraControl.fire(\"mouseDownNothing\", pickController.pickResult, true);\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\t\t);\r\n\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"mouseup\",\r\n\t\t\t(this._documentMouseUpHandler = (e) => {\r\n\t\t\t\tif (e.which === 1) {\r\n\t\t\t\t\tleftDown = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (e.which === 3) {\r\n\t\t\t\t\trightDown = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (pivotController.getPivoting()) {\r\n\t\t\t\t\tpivotController.endPivot();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"mouseup\",\r\n\t\t\t(this._canvasMouseUpHandler = (e) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst leftButtonUp = e.which === 1;\r\n\r\n\t\t\t\tif (!leftButtonUp) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Left mouse button up to possibly pick or double-pick\r\n\r\n\t\t\t\tpivotController.hidePivot();\r\n\r\n\t\t\t\tif (Math.abs(e.clientX - states.mouseDownClientX) > 3 || Math.abs(e.clientY - states.mouseDownClientY) > 3) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst pickedSubs = cameraControl.hasSubs(\"picked\");\r\n\t\t\t\tconst pickedNothingSubs = cameraControl.hasSubs(\"pickedNothing\");\r\n\t\t\t\tconst pickedSurfaceSubs = cameraControl.hasSubs(\"pickedSurface\");\r\n\t\t\t\tconst doublePickedSubs = cameraControl.hasSubs(\"doublePicked\");\r\n\t\t\t\tconst doublePickedSurfaceSubs = cameraControl.hasSubs(\"doublePickedSurface\");\r\n\t\t\t\tconst doublePickedNothingSubs = cameraControl.hasSubs(\"doublePickedNothing\");\r\n\r\n\t\t\t\tif (!configs.doublePickFlyTo && !doublePickedSubs && !doublePickedSurfaceSubs && !doublePickedNothingSubs) {\r\n\t\t\t\t\t// Avoid the single/double click differentiation timeout\r\n\r\n\t\t\t\t\tif (pickedSubs || pickedNothingSubs || pickedSurfaceSubs) {\r\n\t\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\t\t\t\tpickController.schedulePickEntity = true;\r\n\t\t\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\r\n\t\t\t\t\t\tpickController.update();\r\n\r\n\t\t\t\t\t\tif (pickController.pickResult) {\r\n\t\t\t\t\t\t\tcameraControl.fire(\"picked\", pickController.pickResult, true);\r\n\r\n\t\t\t\t\t\t\tif (pickController.pickedSurface) {\r\n\t\t\t\t\t\t\t\tcameraControl.fire(\"pickedSurface\", pickController.pickResult, true);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tcameraControl.fire(\r\n\t\t\t\t\t\t\t\t\"pickedNothing\",\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tcanvasPos: states.pointerCanvasPos\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\ttrue\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\r\n\t\t\t\t\tthis._clicks = 0;\r\n\t\t\t\t\tclickedEntity = null;\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// this._clicks++;\r\n\r\n\t\t\t\t// if (this._clicks === 1) {\r\n\t\t\t\t// First click\r\n\r\n\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\t\tpickController.schedulePickEntity = configs.doublePickFlyTo;\r\n\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\r\n\t\t\t\tpickController.update();\r\n\r\n\t\t\t\tconst firstClickPickResult = pickController.pickResult;\r\n\t\t\t\tconst firstClickPickSurface = pickController.pickedSurface;\r\n\r\n\t\t\t\tthis._timeout = setTimeout(() => {\r\n\t\t\t\t\tif (firstClickPickResult) {\r\n\t\t\t\t\t\tcameraControl.fire(\"picked\", firstClickPickResult, true);\r\n\r\n\t\t\t\t\t\tif (firstClickPickSurface) {\r\n\t\t\t\t\t\t\tcameraControl.fire(\"pickedSurface\", firstClickPickResult, true);\r\n\r\n\t\t\t\t\t\t\tif (!configs.firstPerson && configs.followPointer) {\r\n\t\t\t\t\t\t\t\tcontrollers.pivotController.setPivotPos(firstClickPickResult.worldPos);\r\n\t\t\t\t\t\t\t\tif (controllers.pivotController.startPivot()) {\r\n\t\t\t\t\t\t\t\t\tcontrollers.pivotController.showPivot();\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} else {\r\n\t\t\t\t\t\tcameraControl.fire(\r\n\t\t\t\t\t\t\t\"pickedNothing\",\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcanvasPos: states.pointerCanvasPos\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\ttrue\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis._clicks = 0;\r\n\t\t\t\t}, configs.doubleClickTimeFrame);\r\n\t\t\t\t// }\r\n\t\t\t\t// else {\r\n\t\t\t\t// \t// Second click\r\n\r\n\t\t\t\t// \tif (this._timeout !== null) {\r\n\t\t\t\t// \t\twindow.clearTimeout(this._timeout);\r\n\t\t\t\t// \t\tthis._timeout = null;\r\n\t\t\t\t// \t}\r\n\r\n\t\t\t\t// \tpickController.pickCursorPos = states.pointerCanvasPos;\r\n\t\t\t\t// \tpickController.schedulePickEntity = configs.doublePickFlyTo || doublePickedSubs || doublePickedSurfaceSubs;\r\n\t\t\t\t// \tpickController.schedulePickSurface = pickController.schedulePickEntity && doublePickedSurfaceSubs;\r\n\t\t\t\t// \tpickController.update();\r\n\r\n\t\t\t\t// \tif (pickController.pickResult) {\r\n\t\t\t\t// \t\tcameraControl.fire(\"doublePicked\", pickController.pickResult, true);\r\n\r\n\t\t\t\t// \t\tif (pickController.pickedSurface) {\r\n\t\t\t\t// \t\t\tcameraControl.fire(\"doublePickedSurface\", pickController.pickResult, true);\r\n\t\t\t\t// \t\t}\r\n\r\n\t\t\t\t// \t\tif (configs.doublePickFlyTo) {\r\n\t\t\t\t// \t\t\tflyCameraTo(pickController.pickResult);\r\n\r\n\t\t\t\t// \t\t\tif (!configs.firstPerson && configs.followPointer) {\r\n\t\t\t\t// \t\t\t\tconst pickedEntityAABB = pickController.pickResult.entity.aabb;\r\n\t\t\t\t// \t\t\t\tconst pickedEntityCenterPos = math.getAABB3Center(pickedEntityAABB);\r\n\r\n\t\t\t\t// \t\t\t\tcontrollers.pivotController.setPivotPos(pickedEntityCenterPos);\r\n\r\n\t\t\t\t// \t\t\t\tif (controllers.pivotController.startPivot()) {\r\n\t\t\t\t// \t\t\t\t\tcontrollers.pivotController.showPivot();\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} else {\r\n\t\t\t\t// \t\tcameraControl.fire(\r\n\t\t\t\t// \t\t\t\"doublePickedNothing\",\r\n\t\t\t\t// \t\t\t{\r\n\t\t\t\t// \t\t\t\tcanvasPos: states.pointerCanvasPos\r\n\t\t\t\t// \t\t\t},\r\n\t\t\t\t// \t\t\ttrue\r\n\t\t\t\t// \t\t);\r\n\r\n\t\t\t\t// \t\tif (configs.doublePickFlyTo) {\r\n\t\t\t\t// \t\t\tflyCameraTo();\r\n\r\n\t\t\t\t// \t\t\tif (!configs.firstPerson && configs.followPointer) {\r\n\t\t\t\t// \t\t\t\tconst sceneAABB = scene.aabb;\r\n\t\t\t\t// \t\t\t\tconst sceneCenterPos = math.getAABB3Center(sceneAABB);\r\n\r\n\t\t\t\t// \t\t\t\tcontrollers.pivotController.setPivotPos(sceneCenterPos);\r\n\r\n\t\t\t\t// \t\t\t\tif (controllers.pivotController.startPivot()) {\r\n\t\t\t\t// \t\t\t\t\tcontrollers.pivotController.showPivot();\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\r\n\t\t\t\t// \tthis._clicks = 0;\r\n\t\t\t\t// }\r\n\t\t\t}),\r\n\t\t\tfalse\r\n\t\t);\r\n\t}\r\n\r\n\treset() {\r\n\t\tthis._clicks = 0;\r\n\t\tthis._lastPickedEntityId = null;\r\n\t\tif (this._timeout) {\r\n\t\t\twindow.clearTimeout(this._timeout);\r\n\t\t\tthis._timeout = null;\r\n\t\t}\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tif (this.canvas != null) {\r\n\t\t\tthis.canvas.removeEventListener(\"mousemove\", this._canvasMouseMoveHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"mousedown\", this._canvasMouseDownHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"dblclick\", this._canvasDblClickHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"mouseup\", this._canvasMouseUpHandler);\r\n\t\t}\r\n\t\tdocument.removeEventListener(\"mouseup\", this._documentMouseUpHandler);\r\n\t\tif (this._timeout) {\r\n\t\t\twindow.clearTimeout(this._timeout);\r\n\t\t\tthis._timeout = null;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js?");
|
|
2567
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MousePickHandler: () => (/* binding */ MousePickHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\n\n/**\n * @private\n */\nclass MousePickHandler {\n\tconstructor(scene, controllers, configs, states, updates) {\n\t\tthis._scene = scene;\n\n\t\tconst pickController = controllers.pickController;\n\t\tconst pivotController = controllers.pivotController;\n\t\tconst cameraControl = controllers.cameraControl;\n\n\t\tthis._clicks = 0;\n\t\tthis._timeout = null;\n\t\tthis._lastPickedEntityId = null;\n\n\t\tlet leftDown = false;\n\t\tlet rightDown = false;\n\n\t\tlet clickedEntity = null;\n\n\t\tthis.canvas = this._scene.canvas.canvas;\n\n\t\tconst flyCameraTo = (pickResult) => {\n\t\t\tlet pos;\n\t\t\tif (pickResult && pickResult.worldPos) {\n\t\t\t\tpos = pickResult.worldPos;\n\t\t\t}\n\t\t\tconst aabb = pickResult && pickResult.entity ? pickResult.entity.aabb : scene.aabb;\n\t\t\tif (pos) {\n\t\t\t\t// Fly to look at point, don't change eye->look dist\n\t\t\t\tconst camera = scene.camera;\n\t\t\t\tconst diff = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, camera.look, []);\n\t\t\t\tcontrollers.cameraFlight.flyTo({\n\t\t\t\t\t// look: pos,\n\t\t\t\t\t// eye: xeokit.math.addVec3(pos, diff, []),\n\t\t\t\t\t// up: camera.up,\n\t\t\t\t\taabb: aabb\n\t\t\t\t});\n\t\t\t\t// TODO: Option to back off to fit AABB in view\n\t\t\t} else {\n\t\t\t\t// Fly to fit target boundary in view\n\t\t\t\tcontrollers.cameraFlight.flyTo({\n\t\t\t\t\taabb: aabb\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tconst tickifiedMouseMoveFn = scene.tickify(\n\t\t\t(this._canvasMouseMoveHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (leftDown || rightDown) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst hoverSubs = cameraControl.hasSubs(\"hover\");\n\t\t\t\tconst hoverEnterSubs = cameraControl.hasSubs(\"hoverEnter\");\n\t\t\t\tconst hoverOutSubs = cameraControl.hasSubs(\"hoverOut\");\n\t\t\t\tconst hoverOffSubs = cameraControl.hasSubs(\"hoverOff\");\n\t\t\t\tconst hoverSurfaceSubs = cameraControl.hasSubs(\"hoverSurface\");\n\t\t\t\tconst hoverSnapOrSurfaceSubs = cameraControl.hasSubs(\"hoverSnapOrSurface\");\n\n\t\t\t\tif (hoverSubs || hoverEnterSubs || hoverOutSubs || hoverOffSubs || hoverSurfaceSubs || hoverSnapOrSurfaceSubs) {\n\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\t\t\tpickController.schedulePickEntity = true;\n\t\t\t\t\tpickController.schedulePickSurface = hoverSurfaceSubs;\n\t\t\t\t\tpickController.scheduleSnapOrPick = hoverSnapOrSurfaceSubs;\n\n\t\t\t\t\tpickController.update();\n\n\t\t\t\t\tif (pickController.pickResult) {\n\t\t\t\t\t\tif (pickController.pickResult.entity) {\n\t\t\t\t\t\t\tconst pickedEntityId = pickController.pickResult.entity.id;\n\n\t\t\t\t\t\t\tif (this._lastPickedEntityId !== pickedEntityId) {\n\t\t\t\t\t\t\t\tif (this._lastPickedEntityId !== undefined) {\n\t\t\t\t\t\t\t\t\tcameraControl.fire(\n\t\t\t\t\t\t\t\t\t\t\"hoverOut\",\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t// Hovered off an entity\n\t\t\t\t\t\t\t\t\t\t\tentity: scene.objects[this._lastPickedEntityId]\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcameraControl.fire(\"hoverEnter\", pickController.pickResult, true); // Hovering over a new entity\n\n\t\t\t\t\t\t\t\tthis._lastPickedEntityId = pickedEntityId;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcameraControl.fire(\"hover\", pickController.pickResult, true);\n\n\t\t\t\t\t\tif (pickController.pickResult.worldPos || pickController.pickResult.snappedWorldPos) {\n\t\t\t\t\t\t\t// Hovering the surface of an entity\n\t\t\t\t\t\t\tcameraControl.fire(\"hoverSurface\", pickController.pickResult, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (this._lastPickedEntityId !== undefined) {\n\t\t\t\t\t\t\tcameraControl.fire(\n\t\t\t\t\t\t\t\t\"hoverOut\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// Hovered off an entity\n\t\t\t\t\t\t\t\t\tentity: scene.objects[this._lastPickedEntityId]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tthis._lastPickedEntityId = undefined;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcameraControl.fire(\n\t\t\t\t\t\t\t\"hoverOff\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Not hovering on any entity\n\t\t\t\t\t\t\t\tcanvasPos: pickController.pickCursorPos\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\"mousemove\", tickifiedMouseMoveFn);\n\t\tthis.canvas.addEventListener(\n\t\t\t\"dblclick\",\n\t\t\t(this._canvasDblClickHandler = (e) => {\n\t\t\t\tstates.mouseDownClientX = e.clientX;\n\t\t\t\tstates.mouseDownClientY = e.clientY;\n\t\t\t\tstates.mouseDownCursorX = states.pointerCanvasPos[0];\n\t\t\t\tstates.mouseDownCursorY = states.pointerCanvasPos[1];\n\t\t\t\tif (!configs.firstPerson && configs.followPointer) {\n\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\t\t\tpickController.schedulePickSurface = true;\n\t\t\t\t\tpickController.update();\n\t\t\t\t}\n\t\t\t\tconst pickResult = pickController.pickResult;\n\t\t\t\tif (pickResult) {\n\t\t\t\t\tcameraControl.fire(\"doublePicked\", pickController.pickResult, true);\n\n\t\t\t\t\tif (pickController.pickedSurface) {\n\t\t\t\t\t\tcameraControl.fire(\"doublePickedSurface\", pickController.pickResult, true);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcameraControl.fire(\n\t\t\t\t\t\t\"doublePickedNothing\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcanvasPos: states.pointerCanvasPos\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttrue\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mousedown\",\n\t\t\t(this._canvasMouseDownHandler = (e) => {\n\t\t\t\tif (e.which === 1) {\n\t\t\t\t\tleftDown = true;\n\t\t\t\t}\n\n\t\t\t\tif (e.which === 3) {\n\t\t\t\t\trightDown = true;\n\t\t\t\t}\n\n\t\t\t\tconst leftButtonDown = e.which === 1;\n\n\t\t\t\tif (!leftButtonDown) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Left mouse button down to start pivoting\n\n\t\t\t\tstates.mouseDownClientX = e.clientX;\n\t\t\t\tstates.mouseDownClientY = e.clientY;\n\t\t\t\tstates.mouseDownCursorX = states.pointerCanvasPos[0];\n\t\t\t\tstates.mouseDownCursorY = states.pointerCanvasPos[1];\n\n\t\t\t\tif (!configs.firstPerson && configs.followPointer) {\n\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\t\t\tpickController.schedulePickSurface = true;\n\n\t\t\t\t\tpickController.update();\n\n\t\t\t\t\tif (e.which === 1) {\n\t\t\t\t\t\t// Left button\n\t\t\t\t\t\tconst pickResult = pickController.pickResult;\n\n\t\t\t\t\t\tif (pickResult && pickResult.worldPos) {\n\t\t\t\t\t\t\tpivotController.setCanvasPivotPos(states.pointerCanvasPos);\n\t\t\t\t\t\t\tcameraControl.fire(\"mouseDownEntity\", pickController.pickResult, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (configs.smartPivot) {\n\t\t\t\t\t\t\t\tpivotController.setCanvasPivotPos(states.pointerCanvasPos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tpivotController.setPivotPos(scene.camera.look);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpivotController.startPivot();\n\t\t\t\t\t\t\tcameraControl.fire(\"mouseDownNothing\", pickController.pickResult, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tdocument.addEventListener(\n\t\t\t\"mouseup\",\n\t\t\t(this._documentMouseUpHandler = (e) => {\n\t\t\t\tif (e.which === 1) {\n\t\t\t\t\tleftDown = false;\n\t\t\t\t}\n\n\t\t\t\tif (e.which === 3) {\n\t\t\t\t\trightDown = false;\n\t\t\t\t}\n\n\t\t\t\tif (pivotController.getPivoting()) {\n\t\t\t\t\tpivotController.endPivot();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"mouseup\",\n\t\t\t(this._canvasMouseUpHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst leftButtonUp = e.which === 1;\n\n\t\t\t\tif (!leftButtonUp) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Left mouse button up to possibly pick or double-pick\n\n\t\t\t\tpivotController.hidePivot();\n\n\t\t\t\tif (Math.abs(e.clientX - states.mouseDownClientX) > 3 || Math.abs(e.clientY - states.mouseDownClientY) > 3) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst pickedSubs = cameraControl.hasSubs(\"picked\");\n\t\t\t\tconst pickedNothingSubs = cameraControl.hasSubs(\"pickedNothing\");\n\t\t\t\tconst pickedSurfaceSubs = cameraControl.hasSubs(\"pickedSurface\");\n\t\t\t\tconst doublePickedSubs = cameraControl.hasSubs(\"doublePicked\");\n\t\t\t\tconst doublePickedSurfaceSubs = cameraControl.hasSubs(\"doublePickedSurface\");\n\t\t\t\tconst doublePickedNothingSubs = cameraControl.hasSubs(\"doublePickedNothing\");\n\n\t\t\t\tif (!configs.doublePickFlyTo && !doublePickedSubs && !doublePickedSurfaceSubs && !doublePickedNothingSubs) {\n\t\t\t\t\t// Avoid the single/double click differentiation timeout\n\n\t\t\t\t\tif (pickedSubs || pickedNothingSubs || pickedSurfaceSubs) {\n\t\t\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\t\t\t\tpickController.schedulePickEntity = true;\n\t\t\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\n\t\t\t\t\t\tpickController.update();\n\n\t\t\t\t\t\tif (pickController.pickResult) {\n\t\t\t\t\t\t\tcameraControl.fire(\"picked\", pickController.pickResult, true);\n\n\t\t\t\t\t\t\tif (pickController.pickedSurface) {\n\t\t\t\t\t\t\t\tcameraControl.fire(\"pickedSurface\", pickController.pickResult, true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcameraControl.fire(\n\t\t\t\t\t\t\t\t\"pickedNothing\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcanvasPos: states.pointerCanvasPos\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._clicks = 0;\n\t\t\t\t\tclickedEntity = null;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// this._clicks++;\n\n\t\t\t\t// if (this._clicks === 1) {\n\t\t\t\t// First click\n\n\t\t\t\tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\t\tpickController.schedulePickEntity = configs.doublePickFlyTo;\n\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\n\t\t\t\tpickController.update();\n\n\t\t\t\tconst firstClickPickResult = pickController.pickResult;\n\t\t\t\tconst firstClickPickSurface = pickController.pickedSurface;\n\n\t\t\t\tthis._timeout = setTimeout(() => {\n\t\t\t\t\tif (firstClickPickResult) {\n\t\t\t\t\t\tcameraControl.fire(\"picked\", firstClickPickResult, true);\n\n\t\t\t\t\t\tif (firstClickPickSurface) {\n\t\t\t\t\t\t\tcameraControl.fire(\"pickedSurface\", firstClickPickResult, true);\n\n\t\t\t\t\t\t\tif (!configs.firstPerson && configs.followPointer) {\n\t\t\t\t\t\t\t\tcontrollers.pivotController.setPivotPos(firstClickPickResult.worldPos);\n\t\t\t\t\t\t\t\tif (controllers.pivotController.startPivot()) {\n\t\t\t\t\t\t\t\t\tcontrollers.pivotController.showPivot();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcameraControl.fire(\n\t\t\t\t\t\t\t\"pickedNothing\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcanvasPos: states.pointerCanvasPos\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._clicks = 0;\n\t\t\t\t}, configs.doubleClickTimeFrame);\n\t\t\t\t// }\n\t\t\t\t// else {\n\t\t\t\t// \t// Second click\n\n\t\t\t\t// \tif (this._timeout !== null) {\n\t\t\t\t// \t\twindow.clearTimeout(this._timeout);\n\t\t\t\t// \t\tthis._timeout = null;\n\t\t\t\t// \t}\n\n\t\t\t\t// \tpickController.pickCursorPos = states.pointerCanvasPos;\n\t\t\t\t// \tpickController.schedulePickEntity = configs.doublePickFlyTo || doublePickedSubs || doublePickedSurfaceSubs;\n\t\t\t\t// \tpickController.schedulePickSurface = pickController.schedulePickEntity && doublePickedSurfaceSubs;\n\t\t\t\t// \tpickController.update();\n\n\t\t\t\t// \tif (pickController.pickResult) {\n\t\t\t\t// \t\tcameraControl.fire(\"doublePicked\", pickController.pickResult, true);\n\n\t\t\t\t// \t\tif (pickController.pickedSurface) {\n\t\t\t\t// \t\t\tcameraControl.fire(\"doublePickedSurface\", pickController.pickResult, true);\n\t\t\t\t// \t\t}\n\n\t\t\t\t// \t\tif (configs.doublePickFlyTo) {\n\t\t\t\t// \t\t\tflyCameraTo(pickController.pickResult);\n\n\t\t\t\t// \t\t\tif (!configs.firstPerson && configs.followPointer) {\n\t\t\t\t// \t\t\t\tconst pickedEntityAABB = pickController.pickResult.entity.aabb;\n\t\t\t\t// \t\t\t\tconst pickedEntityCenterPos = math.getAABB3Center(pickedEntityAABB);\n\n\t\t\t\t// \t\t\t\tcontrollers.pivotController.setPivotPos(pickedEntityCenterPos);\n\n\t\t\t\t// \t\t\t\tif (controllers.pivotController.startPivot()) {\n\t\t\t\t// \t\t\t\t\tcontrollers.pivotController.showPivot();\n\t\t\t\t// \t\t\t\t}\n\t\t\t\t// \t\t\t}\n\t\t\t\t// \t\t}\n\t\t\t\t// \t} else {\n\t\t\t\t// \t\tcameraControl.fire(\n\t\t\t\t// \t\t\t\"doublePickedNothing\",\n\t\t\t\t// \t\t\t{\n\t\t\t\t// \t\t\t\tcanvasPos: states.pointerCanvasPos\n\t\t\t\t// \t\t\t},\n\t\t\t\t// \t\t\ttrue\n\t\t\t\t// \t\t);\n\n\t\t\t\t// \t\tif (configs.doublePickFlyTo) {\n\t\t\t\t// \t\t\tflyCameraTo();\n\n\t\t\t\t// \t\t\tif (!configs.firstPerson && configs.followPointer) {\n\t\t\t\t// \t\t\t\tconst sceneAABB = scene.aabb;\n\t\t\t\t// \t\t\t\tconst sceneCenterPos = math.getAABB3Center(sceneAABB);\n\n\t\t\t\t// \t\t\t\tcontrollers.pivotController.setPivotPos(sceneCenterPos);\n\n\t\t\t\t// \t\t\t\tif (controllers.pivotController.startPivot()) {\n\t\t\t\t// \t\t\t\t\tcontrollers.pivotController.showPivot();\n\t\t\t\t// \t\t\t\t}\n\t\t\t\t// \t\t\t}\n\t\t\t\t// \t\t}\n\t\t\t\t// \t}\n\n\t\t\t\t// \tthis._clicks = 0;\n\t\t\t\t// }\n\t\t\t}),\n\t\t\tfalse\n\t\t);\n\t}\n\n\treset() {\n\t\tthis._clicks = 0;\n\t\tthis._lastPickedEntityId = null;\n\t\tif (this._timeout) {\n\t\t\twindow.clearTimeout(this._timeout);\n\t\t\tthis._timeout = null;\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tif (this.canvas != null) {\n\t\t\tthis.canvas.removeEventListener(\"mousemove\", this._canvasMouseMoveHandler);\n\t\t\tthis.canvas.removeEventListener(\"mousedown\", this._canvasMouseDownHandler);\n\t\t\tthis.canvas.removeEventListener(\"dblclick\", this._canvasDblClickHandler);\n\t\t\tthis.canvas.removeEventListener(\"mouseup\", this._canvasMouseUpHandler);\n\t\t}\n\t\tdocument.removeEventListener(\"mouseup\", this._documentMouseUpHandler);\n\t\tif (this._timeout) {\n\t\t\twindow.clearTimeout(this._timeout);\n\t\t\tthis._timeout = null;\n\t\t}\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js?");
|
|
2568
2568
|
|
|
2569
2569
|
/***/ }),
|
|
2570
2570
|
|
|
@@ -2574,7 +2574,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2574
2574
|
\**************************************************************************************/
|
|
2575
2575
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2576
2576
|
|
|
2577
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TouchPanRotateAndDollyHandler: () => (/* binding */ TouchPanRotateAndDollyHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\nconst getCanvasPosFromEvent = function (event, canvasPos) {\r\n\tif (!event) {\r\n\t\tevent = window.event;\r\n\t\tcanvasPos[0] = event.x;\r\n\t\tcanvasPos[1] = event.y;\r\n\t} else {\r\n\t\tlet element = event.target;\r\n\t\tlet totalOffsetLeft = 0;\r\n\t\tlet totalOffsetTop = 0;\r\n\t\twhile (element.offsetParent) {\r\n\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\telement = element.offsetParent;\r\n\t\t}\r\n\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t}\r\n\treturn canvasPos;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nclass TouchPanRotateAndDollyHandler {\r\n\tconstructor(scene, controllers, configs, states, updates) {\r\n\t\tthis._scene = scene;\r\n\r\n\t\tconst pickController = controllers.pickController;\r\n\t\tconst pivotController = controllers.pivotController;\r\n\r\n\t\tconst tapStartCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tconst tapCanvasPos0 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tconst tapCanvasPos1 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tconst touch0Vec = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\r\n\t\tconst lastCanvasTouchPosList = [];\r\n\t\tthis.canvas = this._scene.canvas.canvas;\r\n\r\n\t\tlet numTouches = 0;\r\n\t\tlet tapStartTime = -1;\r\n\t\tlet waitForTick = false;\r\n\r\n\t\tthis._onTick = scene.on(\"tick\", () => {\r\n\t\t\twaitForTick = false;\r\n\t\t});\r\n\r\n\t\tlet firstDragDeltaX = 0;\r\n\t\tlet firstDragDeltaY = 1;\r\n\t\tlet absorbTinyFirstDrag = false;\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"touchstart\",\r\n\t\t\t(this._canvasTouchStartHandler = (event) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (!event.isTrusted) return;\r\n\r\n\t\t\t\tevent.preventDefault();\r\n\r\n\t\t\t\tconst touches = event.touches;\r\n\t\t\t\tconst changedTouches = event.changedTouches;\r\n\r\n\t\t\t\tstates.touchStartTime = Date.now();\r\n\r\n\t\t\t\tif (touches.length === 1 && changedTouches.length === 1) {\r\n\t\t\t\t\ttapStartTime = states.touchStartTime;\r\n\r\n\t\t\t\t\tgetCanvasPosFromEvent(touches[0], tapStartCanvasPos);\r\n\r\n\t\t\t\t\tif (configs.followPointer) {\r\n\t\t\t\t\t\tpickController.pickCursorPos = tapStartCanvasPos;\r\n\t\t\t\t\t\tpickController.schedulePickSurface = true;\r\n\t\t\t\t\t\tpickController.update();\r\n\t\t\t\t\t\tpivotController.setPivotPos(scene.camera.look);\r\n\r\n\t\t\t\t\t\t// if (!configs.planView) {\r\n\t\t\t\t\t\t// \tif (\r\n\t\t\t\t\t\t// \t\tpickController.picked &&\r\n\t\t\t\t\t\t// \t\tpickController.pickedSurface &&\r\n\t\t\t\t\t\t// \t\tpickController.pickResult &&\r\n\t\t\t\t\t\t// \t\tpickController.pickResult.worldPos\r\n\t\t\t\t\t\t// \t) {\r\n\t\t\t\t\t\t// \t\t// pivotController.setPivotPos(pickController.pickResult.worldPos);\r\n\t\t\t\t\t\t// \t\tpivotController.setPivotPos(scene.camera.look);\r\n\t\t\t\t\t\t// \t\tif (!configs.firstPerson && pivotController.startPivot()) {\r\n\t\t\t\t\t\t// \t\t\t// pivotController.showPivot();\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\tif (configs.smartPivot) {\r\n\t\t\t\t\t\t// \t\t\tpivotController.setPivotPos(scene.camera.look);\r\n\t\t\t\t\t\t// \t\t\t// pivotController.setCanvasPivotPos(states.pointerCanvasPos);\r\n\t\t\t\t\t\t// \t\t} else {\r\n\t\t\t\t\t\t// \t\t\tpivotController.setPivotPos(scene.camera.look);\r\n\t\t\t\t\t\t// \t\t}\r\n\r\n\t\t\t\t\t\t// \t\tif (!configs.firstPerson && pivotController.startPivot()) {\r\n\t\t\t\t\t\t// \t\t\t// pivotController.showPivot();\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} else {\r\n\t\t\t\t\ttapStartTime = -1;\r\n\t\t\t\t}\r\n\r\n\t\t\t\twhile (lastCanvasTouchPosList.length < touches.length) {\r\n\t\t\t\t\tlastCanvasTouchPosList.push(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2());\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor (let i = 0, len = touches.length; i < len; ++i) {\r\n\t\t\t\t\tgetCanvasPosFromEvent(touches[i], lastCanvasTouchPosList[i]);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tnumTouches = touches.length;\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"touchend\",\r\n\t\t\t(this._canvasTouchEndHandler = () => {\r\n\t\t\t\tif (pivotController.getPivoting()) {\r\n\t\t\t\t\tpivotController.endPivot();\r\n\t\t\t\t\tpivotController.hidePivot();\r\n\t\t\t\t}\r\n\t\t\t\tfirstDragDeltaX = 0;\r\n\t\t\t\tfirstDragDeltaY = 0;\r\n\t\t\t\tabsorbTinyFirstDrag = true;\r\n\t\t\t})\r\n\t\t);\r\n\t\tthis.canvas.addEventListener(\"touchcancel\", this._canvasTouchEndHandler);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"touchmove\",\r\n\t\t\t(this._canvasTouchMoveHandler = (event) => {\r\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tevent.stopPropagation();\r\n\t\t\t\tevent.preventDefault();\r\n\r\n\t\t\t\tif (waitForTick) {\r\n\t\t\t\t\t// Limit changes detection to one per frame\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\twaitForTick = true;\r\n\r\n\t\t\t\t// Scaling drag-rotate to canvas boundary\r\n\r\n\t\t\t\tconst canvasBoundary = scene.canvas.boundary;\r\n\t\t\t\tconst canvasWidth = canvasBoundary[2];\r\n\t\t\t\tconst canvasHeight = canvasBoundary[3];\r\n\r\n\t\t\t\tconst touches = event.touches;\r\n\r\n\t\t\t\tif (event.touches.length !== numTouches) {\r\n\t\t\t\t\t// Two fingers were pressed, then one of them is removed\r\n\t\t\t\t\t// We don't want to rotate in this case (weird behavior)\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (numTouches === 1) {\r\n\t\t\t\t\tgetCanvasPosFromEvent(touches[0], tapCanvasPos0);\r\n\r\n\t\t\t\t\t//-----------------------------------------------------------------------------------------------\r\n\t\t\t\t\t// Drag rotation\r\n\t\t\t\t\t//-----------------------------------------------------------------------------------------------\r\n\r\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec2(tapCanvasPos0, lastCanvasTouchPosList[0], touch0Vec);\r\n\r\n\t\t\t\t\tconst xPanDelta = touch0Vec[0];\r\n\t\t\t\t\tconst yPanDelta = touch0Vec[1];\r\n\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\tstates.longTouchTimeout !== null &&\r\n\t\t\t\t\t\t(Math.abs(xPanDelta) > configs.longTapRadius || Math.abs(yPanDelta) > configs.longTapRadius)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tclearTimeout(states.longTouchTimeout);\r\n\t\t\t\t\t\tstates.longTouchTimeout = null;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (configs.planView) {\r\n\t\t\t\t\t\t// No rotating in plan-view mode\r\n\r\n\t\t\t\t\t\tconst camera = scene.camera;\r\n\r\n\t\t\t\t\t\t// We use only canvasHeight here so that aspect ratio does not distort speed\r\n\r\n\t\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\t\tconst touchPicked = false;\r\n\t\t\t\t\t\t\tconst pickedWorldPos = [0, 0, 0];\r\n\r\n\t\t\t\t\t\t\tconst depth = Math.abs(\r\n\t\t\t\t\t\t\t\ttouchPicked\r\n\t\t\t\t\t\t\t\t\t? _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(pickedWorldPos, scene.camera.eye, []))\r\n\t\t\t\t\t\t\t\t\t: scene.camera.eyeLookDist\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\tconst targetDistance = depth * Math.tan(((camera.perspective.fov / 2) * Math.PI) / 180.0);\r\n\r\n\t\t\t\t\t\t\tupdates.panDeltaX += ((xPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t\tupdates.panDeltaY += ((yPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tupdates.panDeltaX += 0.5 * camera.ortho.scale * (xPanDelta / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t\tupdates.panDeltaY += 0.5 * camera.ortho.scale * (yPanDelta / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t// if (!absorbTinyFirstDrag) {\r\n\t\t\t\t\t\tupdates.rotateDeltaY -= (xPanDelta / canvasWidth) * (configs.dragRotationRate * 1.0); // Full horizontal rotation\r\n\t\t\t\t\t\tupdates.rotateDeltaX += (yPanDelta / canvasHeight) * (configs.dragRotationRate * 1.5); // Half vertical rotation\r\n\t\t\t\t\t\t// } else {\r\n\t\t\t\t\t\t// firstDragDeltaY -= (xPanDelta / canvasWidth) * (configs.dragRotationRate * 1.0); // Full horizontal rotation\r\n\t\t\t\t\t\t// firstDragDeltaX += (yPanDelta / canvasHeight) * (configs.dragRotationRate * 1.5); // Half vertical rotation\r\n\t\t\t\t\t\t// if (Math.abs(firstDragDeltaX) > 5 || Math.abs(firstDragDeltaY) > 5) {\r\n\t\t\t\t\t\t// updates.rotateDeltaX += firstDragDeltaX;\r\n\t\t\t\t\t\t// updates.rotateDeltaY += firstDragDeltaY;\r\n\t\t\t\t\t\t// firstDragDeltaX = 0;\r\n\t\t\t\t\t\t// firstDragDeltaY = 0;\r\n\t\t\t\t\t\t// absorbTinyFirstDrag = false;\r\n\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} else if (numTouches === 2) {\r\n\t\t\t\t\tpivotController.hidePivot();\r\n\t\t\t\t\tconst touch0 = touches[0];\r\n\t\t\t\t\tconst touch1 = touches[1];\r\n\r\n\t\t\t\t\tgetCanvasPosFromEvent(touch0, tapCanvasPos0);\r\n\t\t\t\t\tgetCanvasPosFromEvent(touch1, tapCanvasPos1);\r\n\r\n\t\t\t\t\tconst lastMiddleTouch = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.geometricMeanVec2(lastCanvasTouchPosList[0], lastCanvasTouchPosList[1]);\r\n\t\t\t\t\tconst currentMiddleTouch = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.geometricMeanVec2(tapCanvasPos0, tapCanvasPos1);\r\n\r\n\t\t\t\t\tconst touchDelta = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\r\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec2(lastMiddleTouch, currentMiddleTouch, touchDelta);\r\n\r\n\t\t\t\t\tconst xPanDelta = touchDelta[0];\r\n\t\t\t\t\tconst yPanDelta = touchDelta[1];\r\n\r\n\t\t\t\t\tconst camera = scene.camera;\r\n\r\n\t\t\t\t\t// Dollying\r\n\r\n\t\t\t\t\tconst d1 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec2([touch0.pageX, touch0.pageY], [touch1.pageX, touch1.pageY]);\r\n\t\t\t\t\tconst d2 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec2(lastCanvasTouchPosList[0], lastCanvasTouchPosList[1]);\r\n\r\n\t\t\t\t\tconst dollyDelta = (d2 - d1) * configs.touchDollyRate;\r\n\r\n\t\t\t\t\tupdates.dollyDelta = dollyDelta;\r\n\r\n\t\t\t\t\tif (Math.abs(dollyDelta) < 1.0) {\r\n\t\t\t\t\t\t// We use only canvasHeight here so that aspect ratio does not distort speed\r\n\r\n\t\t\t\t\t\tif (camera.projection === \"perspective\") {\r\n\t\t\t\t\t\t\tconst pickedWorldPos = pickController.pickResult ? pickController.pickResult.worldPos : scene.center;\r\n\r\n\t\t\t\t\t\t\tconst depth = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(pickedWorldPos, scene.camera.eye, [])));\r\n\t\t\t\t\t\t\tconst targetDistance = depth * Math.tan(((camera.perspective.fov / 2) * Math.PI) / 180.0);\r\n\r\n\t\t\t\t\t\t\tupdates.panDeltaX -= ((xPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t\tupdates.panDeltaY -= ((yPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tupdates.panDeltaX -= 0.5 * camera.ortho.scale * (xPanDelta / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t\tupdates.panDeltaY -= 0.5 * camera.ortho.scale * (yPanDelta / canvasHeight) * configs.touchPanRate;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstates.pointerCanvasPos = currentMiddleTouch;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor (let i = 0; i < numTouches; ++i) {\r\n\t\t\t\t\tgetCanvasPosFromEvent(touches[i], lastCanvasTouchPosList[i]);\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\treset() {}\r\n\r\n\tdestroy() {\r\n\t\tif (this.canvas != null) {\r\n\t\t\tthis.canvas.removeEventListener(\"touchstart\", this._canvasTouchStartHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"touchend\", this._canvasTouchEndHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"touchcancel\", this._canvasTouchEndHandler);\r\n\t\t\tthis.canvas.removeEventListener(\"touchmove\", this._canvasTouchMoveHandler);\r\n\t\t}\r\n\t\tthis._scene.off(this._onTick);\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/TouchPanRotateAndDollyHandler.js?");
|
|
2577
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TouchPanRotateAndDollyHandler: () => (/* binding */ TouchPanRotateAndDollyHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\n\nconst getCanvasPosFromEvent = function (event, canvasPos) {\n\tif (!event) {\n\t\tevent = window.event;\n\t\tcanvasPos[0] = event.x;\n\t\tcanvasPos[1] = event.y;\n\t} else {\n\t\tlet element = event.target;\n\t\tlet totalOffsetLeft = 0;\n\t\tlet totalOffsetTop = 0;\n\t\twhile (element.offsetParent) {\n\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\telement = element.offsetParent;\n\t\t}\n\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t}\n\treturn canvasPos;\n};\n\n/**\n * @private\n */\nclass TouchPanRotateAndDollyHandler {\n\tconstructor(scene, controllers, configs, states, updates) {\n\t\tthis._scene = scene;\n\n\t\tconst pickController = controllers.pickController;\n\t\tconst pivotController = controllers.pivotController;\n\n\t\tconst tapStartCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\t\tconst tapCanvasPos0 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\t\tconst tapCanvasPos1 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\t\tconst touch0Vec = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\n\t\tconst lastCanvasTouchPosList = [];\n\t\tthis.canvas = this._scene.canvas.canvas;\n\n\t\tlet numTouches = 0;\n\t\tlet tapStartTime = -1;\n\t\tlet waitForTick = false;\n\n\t\tthis._onTick = scene.on(\"tick\", () => {\n\t\t\twaitForTick = false;\n\t\t});\n\n\t\tlet firstDragDeltaX = 0;\n\t\tlet firstDragDeltaY = 1;\n\t\tlet absorbTinyFirstDrag = false;\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"touchstart\",\n\t\t\t(this._canvasTouchStartHandler = (event) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!event.isTrusted) return;\n\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tconst touches = event.touches;\n\t\t\t\tconst changedTouches = event.changedTouches;\n\n\t\t\t\tstates.touchStartTime = Date.now();\n\n\t\t\t\tif (touches.length === 1 && changedTouches.length === 1) {\n\t\t\t\t\ttapStartTime = states.touchStartTime;\n\n\t\t\t\t\tgetCanvasPosFromEvent(touches[0], tapStartCanvasPos);\n\n\t\t\t\t\tif (configs.followPointer) {\n\t\t\t\t\t\tpickController.pickCursorPos = tapStartCanvasPos;\n\t\t\t\t\t\tpickController.schedulePickSurface = true;\n\t\t\t\t\t\tpickController.update();\n\t\t\t\t\t\tpivotController.setPivotPos(scene.camera.look);\n\n\t\t\t\t\t\t// if (!configs.planView) {\n\t\t\t\t\t\t// \tif (\n\t\t\t\t\t\t// \t\tpickController.picked &&\n\t\t\t\t\t\t// \t\tpickController.pickedSurface &&\n\t\t\t\t\t\t// \t\tpickController.pickResult &&\n\t\t\t\t\t\t// \t\tpickController.pickResult.worldPos\n\t\t\t\t\t\t// \t) {\n\t\t\t\t\t\t// \t\t// pivotController.setPivotPos(pickController.pickResult.worldPos);\n\t\t\t\t\t\t// \t\tpivotController.setPivotPos(scene.camera.look);\n\t\t\t\t\t\t// \t\tif (!configs.firstPerson && pivotController.startPivot()) {\n\t\t\t\t\t\t// \t\t\t// pivotController.showPivot();\n\t\t\t\t\t\t// \t\t}\n\t\t\t\t\t\t// \t} else {\n\t\t\t\t\t\t// \t\tif (configs.smartPivot) {\n\t\t\t\t\t\t// \t\t\tpivotController.setPivotPos(scene.camera.look);\n\t\t\t\t\t\t// \t\t\t// pivotController.setCanvasPivotPos(states.pointerCanvasPos);\n\t\t\t\t\t\t// \t\t} else {\n\t\t\t\t\t\t// \t\t\tpivotController.setPivotPos(scene.camera.look);\n\t\t\t\t\t\t// \t\t}\n\n\t\t\t\t\t\t// \t\tif (!configs.firstPerson && pivotController.startPivot()) {\n\t\t\t\t\t\t// \t\t\t// pivotController.showPivot();\n\t\t\t\t\t\t// \t\t}\n\t\t\t\t\t\t// \t}\n\t\t\t\t\t\t// }\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttapStartTime = -1;\n\t\t\t\t}\n\n\t\t\t\twhile (lastCanvasTouchPosList.length < touches.length) {\n\t\t\t\t\tlastCanvasTouchPosList.push(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2());\n\t\t\t\t}\n\n\t\t\t\tfor (let i = 0, len = touches.length; i < len; ++i) {\n\t\t\t\t\tgetCanvasPosFromEvent(touches[i], lastCanvasTouchPosList[i]);\n\t\t\t\t}\n\n\t\t\t\tnumTouches = touches.length;\n\t\t\t})\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"touchend\",\n\t\t\t(this._canvasTouchEndHandler = () => {\n\t\t\t\tif (pivotController.getPivoting()) {\n\t\t\t\t\tpivotController.endPivot();\n\t\t\t\t\tpivotController.hidePivot();\n\t\t\t\t}\n\t\t\t\tfirstDragDeltaX = 0;\n\t\t\t\tfirstDragDeltaY = 0;\n\t\t\t\tabsorbTinyFirstDrag = true;\n\t\t\t})\n\t\t);\n\t\tthis.canvas.addEventListener(\"touchcancel\", this._canvasTouchEndHandler);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"touchmove\",\n\t\t\t(this._canvasTouchMoveHandler = (event) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tif (waitForTick) {\n\t\t\t\t\t// Limit changes detection to one per frame\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\twaitForTick = true;\n\n\t\t\t\t// Scaling drag-rotate to canvas boundary\n\n\t\t\t\tconst canvasBoundary = scene.canvas.boundary;\n\t\t\t\tconst canvasWidth = canvasBoundary[2];\n\t\t\t\tconst canvasHeight = canvasBoundary[3];\n\n\t\t\t\tconst touches = event.touches;\n\n\t\t\t\tif (event.touches.length !== numTouches) {\n\t\t\t\t\t// Two fingers were pressed, then one of them is removed\n\t\t\t\t\t// We don't want to rotate in this case (weird behavior)\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (numTouches === 1) {\n\t\t\t\t\tgetCanvasPosFromEvent(touches[0], tapCanvasPos0);\n\n\t\t\t\t\t//-----------------------------------------------------------------------------------------------\n\t\t\t\t\t// Drag rotation\n\t\t\t\t\t//-----------------------------------------------------------------------------------------------\n\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec2(tapCanvasPos0, lastCanvasTouchPosList[0], touch0Vec);\n\n\t\t\t\t\tconst xPanDelta = touch0Vec[0];\n\t\t\t\t\tconst yPanDelta = touch0Vec[1];\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tstates.longTouchTimeout !== null &&\n\t\t\t\t\t\t(Math.abs(xPanDelta) > configs.longTapRadius || Math.abs(yPanDelta) > configs.longTapRadius)\n\t\t\t\t\t) {\n\t\t\t\t\t\tclearTimeout(states.longTouchTimeout);\n\t\t\t\t\t\tstates.longTouchTimeout = null;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (configs.planView) {\n\t\t\t\t\t\t// No rotating in plan-view mode\n\n\t\t\t\t\t\tconst camera = scene.camera;\n\n\t\t\t\t\t\t// We use only canvasHeight here so that aspect ratio does not distort speed\n\n\t\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\t\tconst touchPicked = false;\n\t\t\t\t\t\t\tconst pickedWorldPos = [0, 0, 0];\n\n\t\t\t\t\t\t\tconst depth = Math.abs(\n\t\t\t\t\t\t\t\ttouchPicked\n\t\t\t\t\t\t\t\t\t? _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(pickedWorldPos, scene.camera.eye, []))\n\t\t\t\t\t\t\t\t\t: scene.camera.eyeLookDist\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tconst targetDistance = depth * Math.tan(((camera.perspective.fov / 2) * Math.PI) / 180.0);\n\n\t\t\t\t\t\t\tupdates.panDeltaX += ((xPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t\tupdates.panDeltaY += ((yPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tupdates.panDeltaX += 0.5 * camera.ortho.scale * (xPanDelta / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t\tupdates.panDeltaY += 0.5 * camera.ortho.scale * (yPanDelta / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// if (!absorbTinyFirstDrag) {\n\t\t\t\t\t\tupdates.rotateDeltaY -= (xPanDelta / canvasWidth) * (configs.dragRotationRate * 1.0); // Full horizontal rotation\n\t\t\t\t\t\tupdates.rotateDeltaX += (yPanDelta / canvasHeight) * (configs.dragRotationRate * 1.5); // Half vertical rotation\n\t\t\t\t\t\t// } else {\n\t\t\t\t\t\t// firstDragDeltaY -= (xPanDelta / canvasWidth) * (configs.dragRotationRate * 1.0); // Full horizontal rotation\n\t\t\t\t\t\t// firstDragDeltaX += (yPanDelta / canvasHeight) * (configs.dragRotationRate * 1.5); // Half vertical rotation\n\t\t\t\t\t\t// if (Math.abs(firstDragDeltaX) > 5 || Math.abs(firstDragDeltaY) > 5) {\n\t\t\t\t\t\t// updates.rotateDeltaX += firstDragDeltaX;\n\t\t\t\t\t\t// updates.rotateDeltaY += firstDragDeltaY;\n\t\t\t\t\t\t// firstDragDeltaX = 0;\n\t\t\t\t\t\t// firstDragDeltaY = 0;\n\t\t\t\t\t\t// absorbTinyFirstDrag = false;\n\t\t\t\t\t\t// }\n\t\t\t\t\t\t// }\n\t\t\t\t\t}\n\t\t\t\t} else if (numTouches === 2) {\n\t\t\t\t\tpivotController.hidePivot();\n\t\t\t\t\tconst touch0 = touches[0];\n\t\t\t\t\tconst touch1 = touches[1];\n\n\t\t\t\t\tgetCanvasPosFromEvent(touch0, tapCanvasPos0);\n\t\t\t\t\tgetCanvasPosFromEvent(touch1, tapCanvasPos1);\n\n\t\t\t\t\tconst lastMiddleTouch = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.geometricMeanVec2(lastCanvasTouchPosList[0], lastCanvasTouchPosList[1]);\n\t\t\t\t\tconst currentMiddleTouch = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.geometricMeanVec2(tapCanvasPos0, tapCanvasPos1);\n\n\t\t\t\t\tconst touchDelta = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\n\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec2(lastMiddleTouch, currentMiddleTouch, touchDelta);\n\n\t\t\t\t\tconst xPanDelta = touchDelta[0];\n\t\t\t\t\tconst yPanDelta = touchDelta[1];\n\n\t\t\t\t\tconst camera = scene.camera;\n\n\t\t\t\t\t// Dollying\n\n\t\t\t\t\tconst d1 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec2([touch0.pageX, touch0.pageY], [touch1.pageX, touch1.pageY]);\n\t\t\t\t\tconst d2 = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec2(lastCanvasTouchPosList[0], lastCanvasTouchPosList[1]);\n\n\t\t\t\t\tconst dollyDelta = (d2 - d1) * configs.touchDollyRate;\n\n\t\t\t\t\tupdates.dollyDelta = dollyDelta;\n\n\t\t\t\t\tif (Math.abs(dollyDelta) < 1.0) {\n\t\t\t\t\t\t// We use only canvasHeight here so that aspect ratio does not distort speed\n\n\t\t\t\t\t\tif (camera.projection === \"perspective\") {\n\t\t\t\t\t\t\tconst pickedWorldPos = pickController.pickResult ? pickController.pickResult.worldPos : scene.center;\n\n\t\t\t\t\t\t\tconst depth = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(pickedWorldPos, scene.camera.eye, [])));\n\t\t\t\t\t\t\tconst targetDistance = depth * Math.tan(((camera.perspective.fov / 2) * Math.PI) / 180.0);\n\n\t\t\t\t\t\t\tupdates.panDeltaX -= ((xPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t\tupdates.panDeltaY -= ((yPanDelta * targetDistance) / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tupdates.panDeltaX -= 0.5 * camera.ortho.scale * (xPanDelta / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t\tupdates.panDeltaY -= 0.5 * camera.ortho.scale * (yPanDelta / canvasHeight) * configs.touchPanRate;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tstates.pointerCanvasPos = currentMiddleTouch;\n\t\t\t\t}\n\n\t\t\t\tfor (let i = 0; i < numTouches; ++i) {\n\t\t\t\t\tgetCanvasPosFromEvent(touches[i], lastCanvasTouchPosList[i]);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\treset() {}\n\n\tdestroy() {\n\t\tif (this.canvas != null) {\n\t\t\tthis.canvas.removeEventListener(\"touchstart\", this._canvasTouchStartHandler);\n\t\t\tthis.canvas.removeEventListener(\"touchend\", this._canvasTouchEndHandler);\n\t\t\tthis.canvas.removeEventListener(\"touchcancel\", this._canvasTouchEndHandler);\n\t\t\tthis.canvas.removeEventListener(\"touchmove\", this._canvasTouchMoveHandler);\n\t\t}\n\t\tthis._scene.off(this._onTick);\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/TouchPanRotateAndDollyHandler.js?");
|
|
2578
2578
|
|
|
2579
2579
|
/***/ }),
|
|
2580
2580
|
|
|
@@ -2584,7 +2584,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2584
2584
|
\*************************************************************************/
|
|
2585
2585
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2586
2586
|
|
|
2587
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TouchPickHandler: () => (/* binding */ TouchPickHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\
|
|
2587
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TouchPickHandler: () => (/* binding */ TouchPickHandler)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\n\nconst TAP_INTERVAL = 150;\nconst DBL_TAP_INTERVAL = 325;\nconst TAP_DISTANCE_THRESHOLD = 4;\n\nconst getCanvasPosFromEvent = function (event, canvasPos) {\n\tif (!event) {\n\t\tevent = window.event;\n\t\tcanvasPos[0] = event.x;\n\t\tcanvasPos[1] = event.y;\n\t} else {\n\t\tlet element = event.target;\n\t\tlet totalOffsetLeft = 0;\n\t\tlet totalOffsetTop = 0;\n\t\twhile (element.offsetParent) {\n\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\telement = element.offsetParent;\n\t\t}\n\t\tcanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\tcanvasPos[1] = event.pageY - totalOffsetTop;\n\t}\n\treturn canvasPos;\n};\n\n/**\n * @private\n */\nclass TouchPickHandler {\n\tconstructor(scene, controllers, configs, states, updates) {\n\t\tthis._scene = scene;\n\n\t\tconst pickController = controllers.pickController;\n\t\tconst cameraControl = controllers.cameraControl;\n\n\t\tlet touchStartTime;\n\t\tconst activeTouches = [];\n\t\tconst tapStartPos = new Float32Array(2);\n\t\tlet tapStartTime = -1;\n\t\tlet lastTapTime = -1;\n\n\t\tthis.canvas = this._scene.canvas.canvas;\n\n\t\tconst flyCameraTo = (pickResult) => {\n\t\t\tlet pos;\n\t\t\tif (pickResult && pickResult.worldPos) {\n\t\t\t\tpos = pickResult.worldPos;\n\t\t\t}\n\t\t\tconst aabb = pickResult ? pickResult.entity.aabb : scene.aabb;\n\t\t\tif (pos) {\n\t\t\t\t// Fly to look at point, don't change eye->look dist\n\t\t\t\tconst camera = scene.camera;\n\t\t\t\tconst diff = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, camera.look, []);\n\t\t\t\tcontrollers.cameraFlight.flyTo({\n\t\t\t\t\taabb: aabb\n\t\t\t\t});\n\t\t\t\t// TODO: Option to back off to fit AABB in view\n\t\t\t} else {\n\t\t\t\t// Fly to fit target boundary in view\n\t\t\t\tcontrollers.cameraFlight.flyTo({\n\t\t\t\t\taabb: aabb\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"touchstart\",\n\t\t\t(this._canvasTouchStartHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!e.isTrusted) return;\n\n\t\t\t\tif (states.longTouchTimeout !== null) {\n\t\t\t\t\tclearTimeout(states.longTouchTimeout);\n\t\t\t\t\tstates.longTouchTimeout = null;\n\t\t\t\t}\n\n\t\t\t\tconst touches = e.touches;\n\t\t\t\tconst changedTouches = e.changedTouches;\n\n\t\t\t\ttouchStartTime = Date.now();\n\n\t\t\t\tif (touches.length === 1 && changedTouches.length === 1) {\n\t\t\t\t\ttapStartTime = touchStartTime;\n\n\t\t\t\t\t// getCanvasPosFromEvent(touches[0], tapStartPos);\n\n\t\t\t\t\tconst rightClickClientX = tapStartPos[0];\n\t\t\t\t\tconst rightClickClientY = tapStartPos[1];\n\n\t\t\t\t\tconst rightClickPageX = touches[0].pageX;\n\t\t\t\t\tconst rightClickPageY = touches[0].pageY;\n\n\t\t\t\t\tstates.longTouchTimeout = setTimeout(() => {\n\t\t\t\t\t\tcontrollers.cameraControl.fire(\n\t\t\t\t\t\t\t\"rightClick\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// For context menus\n\t\t\t\t\t\t\t\tpagePos: [Math.round(rightClickPageX), Math.round(rightClickPageY)],\n\t\t\t\t\t\t\t\tcanvasPos: [Math.round(rightClickClientX), Math.round(rightClickClientY)],\n\t\t\t\t\t\t\t\tevent: e\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tstates.longTouchTimeout = null;\n\t\t\t\t\t}, configs.longTapTimeout);\n\n\t\t\t\t\t//////////\n\t\t\t\t\tconst pickedSurfaceSubs = cameraControl.hasSubs(\"pickedSurface\");\n\t\t\t\t\tgetCanvasPosFromEvent(touches[0], pickController.pickCursorPos);\n\t\t\t\t\tpickController.schedulePickEntity = true;\n\t\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\n\t\t\t\t\tpickController.update();\n\t\t\t\t\tif (pickController.pickResult) {\n\t\t\t\t\t\tcameraControl.fire(\"touchEntity\", pickController.pickResult);\n\n\t\t\t\t\t\tif (pickController.pickedSurface) {\n\t\t\t\t\t\t\tcameraControl.fire(\"touchSurface\", pickController.pickResult);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcameraControl.fire(\"touchNothing\");\n\t\t\t\t\t}\n\t\t\t\t\t// lastTapTime = currentTime;\n\t\t\t\t\ttapStartTime = -1;\n\t\t\t\t} else {\n\t\t\t\t\ttapStartTime = -1;\n\t\t\t\t}\n\t\t\t\t///////////\n\t\t\t\twhile (activeTouches.length < touches.length) {\n\t\t\t\t\tactiveTouches.push(new Float32Array(2));\n\t\t\t\t}\n\n\t\t\t\tfor (let i = 0, len = touches.length; i < len; ++i) {\n\t\t\t\t\tgetCanvasPosFromEvent(touches[i], activeTouches[i]);\n\t\t\t\t}\n\n\t\t\t\tactiveTouches.length = touches.length;\n\t\t\t}),\n\t\t\t{ passive: true }\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"touchend\",\n\t\t\t(this._canvasTouchEndHandler = (e) => {\n\t\t\t\tif (!(configs.active && configs.pointerEnabled)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst currentTime = Date.now();\n\t\t\t\tconst touches = e.touches;\n\t\t\t\tconst changedTouches = e.changedTouches;\n\n\t\t\t\tconst pickedSurfaceSubs = cameraControl.hasSubs(\"pickedSurface\");\n\n\t\t\t\tif (states.longTouchTimeout !== null) {\n\t\t\t\t\tclearTimeout(states.longTouchTimeout);\n\t\t\t\t\tstates.longTouchTimeout = null;\n\t\t\t\t}\n\n\t\t\t\t// process tap\n\n\t\t\t\tif (touches.length === 0 && changedTouches.length === 1) {\n\t\t\t\t\tif (tapStartTime > -1 && currentTime - tapStartTime < TAP_INTERVAL) {\n\t\t\t\t\t\tif (lastTapTime > -1 && tapStartTime - lastTapTime < DBL_TAP_INTERVAL) {\n\t\t\t\t\t\t\t// Double-tap\n\n\t\t\t\t\t\t\tgetCanvasPosFromEvent(changedTouches[0], pickController.pickCursorPos);\n\t\t\t\t\t\t\tpickController.schedulePickEntity = true;\n\t\t\t\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\n\n\t\t\t\t\t\t\tpickController.update();\n\n\t\t\t\t\t\t\tif (pickController.pickResult) {\n\t\t\t\t\t\t\t\tpickController.pickResult.touchInput = true;\n\n\t\t\t\t\t\t\t\tcameraControl.fire(\"doublePicked\", pickController.pickResult);\n\t\t\t\t\t\t\t\tcameraControl.fire(\"touchDoublePicked\", pickController.pickResult);\n\n\t\t\t\t\t\t\t\tif (pickController.pickedSurface) {\n\t\t\t\t\t\t\t\t\tcameraControl.fire(\"doublePickedSurface\", pickController.pickResult);\n\t\t\t\t\t\t\t\t\tcameraControl.fire(\"touchDoublePickedSurface\", pickController.pickResult);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (configs.doublePickFlyTo) {\n\t\t\t\t\t\t\t\t\tflyCameraTo(pickController.pickResult);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcameraControl.fire(\"doublePickedNothing\");\n\t\t\t\t\t\t\t\tcameraControl.fire(\"touchDoublePickedNothing\");\n\t\t\t\t\t\t\t\tif (configs.doublePickFlyTo) {\n\t\t\t\t\t\t\t\t\tflyCameraTo();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlastTapTime = -1;\n\t\t\t\t\t\t} else if (_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec2(activeTouches[0], tapStartPos) < TAP_DISTANCE_THRESHOLD) {\n\t\t\t\t\t\t\t// Single-tap\n\n\t\t\t\t\t\t\tgetCanvasPosFromEvent(changedTouches[0], pickController.pickCursorPos);\n\t\t\t\t\t\t\tpickController.schedulePickEntity = true;\n\t\t\t\t\t\t\tpickController.schedulePickSurface = pickedSurfaceSubs;\n\n\t\t\t\t\t\t\tpickController.update();\n\n\t\t\t\t\t\t\tif (pickController.pickResult) {\n\t\t\t\t\t\t\t\tpickController.pickResult.touchInput = true;\n\n\t\t\t\t\t\t\t\tcameraControl.fire(\"picked\", pickController.pickResult);\n\t\t\t\t\t\t\t\tcameraControl.fire(\"touchPicked\", pickController.pickResult);\n\n\t\t\t\t\t\t\t\tif (pickController.pickedSurface) {\n\t\t\t\t\t\t\t\t\tcameraControl.fire(\"pickedSurface\", pickController.pickResult);\n\t\t\t\t\t\t\t\t\tcameraControl.fire(\"touchPickedSurface\", pickController.pickResult);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcameraControl.fire(\"pickedNothing\");\n\t\t\t\t\t\t\t\tcameraControl.fire(\"touchPickedNothing\");\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlastTapTime = currentTime;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttapStartTime = -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tactiveTouches.length = touches.length;\n\n\t\t\t\tfor (let i = 0, len = touches.length; i < len; ++i) {\n\t\t\t\t\tactiveTouches[i][0] = touches[i].pageX;\n\t\t\t\t\tactiveTouches[i][1] = touches[i].pageY;\n\t\t\t\t}\n\n\t\t\t\t// e.stopPropagation();\n\t\t\t}),\n\t\t\t{ passive: true }\n\t\t);\n\n\t\tthis.canvas.addEventListener(\"touchcancel\", this._canvasTouchEndHandler);\n\t}\n\n\treset() {\n\t\t// TODO\n\t\t// tapStartTime = -1;\n\t\t// lastTapTime = -1;\n\t}\n\n\tdestroy() {\n\t\tif (this.canvas != null) {\n\t\t\tthis.canvas.removeEventListener(\"touchstart\", this._canvasTouchStartHandler);\n\t\t\tthis.canvas.removeEventListener(\"touchend\", this._canvasTouchEndHandler);\n\t\t\tthis.canvas.removeEventListener(\"touchcancel\", this._canvasTouchEndHandler);\n\t\t}\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/handlers/TouchPickHandler.js?");
|
|
2588
2588
|
|
|
2589
2589
|
/***/ }),
|
|
2590
2590
|
|
|
@@ -2594,7 +2594,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2594
2594
|
\***************************************/
|
|
2595
2595
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2596
2596
|
|
|
2597
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Component: () => (/* binding */ Component)\n/* harmony export */ });\n/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core.js */ \"./src/viewer/scene/core.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n\r\n\r\n\r\n\r\n/**\r\n * @desc Base class for all xeokit components.\r\n *\r\n * ## Component IDs\r\n *\r\n * Every Component has an ID that's unique within the parent {@link Scene}. xeokit generates\r\n * the IDs automatically by default, however you can also specify them yourself. In the example below, we're creating a\r\n * scene comprised of {@link Scene}, {@link Material}, {@link ReadableGeometry} and\r\n * {@link Mesh} components, while letting xeokit generate its own ID for\r\n * the {@link ReadableGeometry}:\r\n *\r\n *````JavaScript\r\n * import {Viewer, Mesh, buildTorusGeometry, ReadableGeometry, PhongMaterial, Texture, Fresnel} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [0, 0, 5];\r\n * viewer.scene.camera.look = [0, 0, 0];\r\n * viewer.scene.camera.up = [0, 1, 0];\r\n *\r\n * new Mesh(viewer.scene, {\r\n * geometry: new ReadableGeometry(viewer.scene, buildTorusGeometry({\r\n * center: [0, 0, 0],\r\n * radius: 1.5,\r\n * tube: 0.5,\r\n * radialSegments: 32,\r\n * tubeSegments: 24,\r\n * arc: Math.PI * 2.0\r\n * }),\r\n * material: new PhongMaterial(viewer.scene, {\r\n * id: \"myMaterial\",\r\n * ambient: [0.9, 0.3, 0.9],\r\n * shininess: 30,\r\n * diffuseMap: new Texture(viewer.scene, {\r\n * src: \"textures/diffuse/uvGrid2.jpg\"\r\n * }),\r\n * specularFresnel: new Fresnel(viewer.scene, {\r\n * leftColor: [1.0, 1.0, 1.0],\r\n * rightColor: [0.0, 0.0, 0.0],\r\n * power: 4\r\n * })\r\n * })\r\n * });\r\n *````\r\n *\r\n * We can then find those components like this:\r\n *\r\n * ````javascript\r\n * // Find the Material\r\n * var material = viewer.scene.components[\"myMaterial\"];\r\n *\r\n * // Find all PhongMaterials in the Scene\r\n * var phongMaterials = viewer.scene.types[\"PhongMaterial\"];\r\n *\r\n * // Find our Material within the PhongMaterials\r\n * var materialAgain = phongMaterials[\"myMaterial\"];\r\n * ````\r\n *\r\n * ## Restriction on IDs\r\n *\r\n * Auto-generated IDs are of the form ````\"__0\"````, ````\"__1\"````, ````\"__2\"```` ... and so on.\r\n *\r\n * Scene maintains a map of these IDs, along with a counter that it increments each time it generates a new ID.\r\n *\r\n * If Scene has created the IDs listed above, and we then destroy the ````Component```` with ID ````\"__1\"````,\r\n * Scene will mark that ID as available, and will reuse it for the next default ID.\r\n *\r\n * Therefore, two restrictions your on IDs:\r\n *\r\n * * don't use IDs that begin with two underscores, and\r\n * * don't reuse auto-generated IDs of destroyed Components.\r\n *\r\n * ## Logging\r\n *\r\n * Components have methods to log ID-prefixed messages to the JavaScript console:\r\n *\r\n * ````javascript\r\n * material.log(\"Everything is fine, situation normal.\");\r\n * material.warn(\"Wait, whats that red light?\");\r\n * material.error(\"Aw, snap!\");\r\n * ````\r\n *\r\n * The logged messages will look like this in the console:\r\n *\r\n * ````text\r\n * [LOG] myMaterial: Everything is fine, situation normal.\r\n * [WARN] myMaterial: Wait, whats that red light..\r\n * [ERROR] myMaterial: Aw, snap!\r\n * ````\r\n *\r\n * ## Destruction\r\n *\r\n * Get notification of destruction of Components:\r\n *\r\n * ````javascript\r\n * material.once(\"destroyed\", function() {\r\n * this.log(\"Component was destroyed: \" + this.id);\r\n * });\r\n * ````\r\n *\r\n * Or get notification of destruction of any Component within its {@link Scene}:\r\n *\r\n * ````javascript\r\n * scene.on(\"componentDestroyed\", function(component) {\r\n * this.log(\"Component was destroyed: \" + component.id);\r\n * });\r\n * ````\r\n *\r\n * Then destroy a component like this:\r\n *\r\n * ````javascript\r\n * material.destroy();\r\n * ````\r\n */\r\nclass Component {\r\n\t/**\r\n @private\r\n */\r\n\tget type() {\r\n\t\treturn \"Component\";\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tget isComponent() {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tconstructor(owner = null, cfg = {}) {\r\n\t\t/**\r\n\t\t * The parent {@link Scene} that contains this Component.\r\n\t\t *\r\n\t\t * @property scene\r\n\t\t * @type {Scene}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.scene = null;\r\n\r\n\t\tif (this.type === \"Scene\") {\r\n\t\t\tthis.scene = this;\r\n\t\t\t/**\r\n\t\t\t * The viewer that contains this Scene.\r\n\t\t\t * @property viewer\r\n\t\t\t * @type {Viewer}\r\n\t\t\t */\r\n\t\t\tthis.viewer = cfg.viewer;\r\n\t\t} else {\r\n\t\t\tif (owner.type === \"Scene\") {\r\n\t\t\t\tthis.scene = owner;\r\n\t\t\t} else if (owner instanceof Component) {\r\n\t\t\t\tthis.scene = owner.scene;\r\n\t\t\t} else {\r\n\t\t\t\tthrow \"Invalid param: owner must be a Component\";\r\n\t\t\t}\r\n\t\t\tthis._owner = owner;\r\n\t\t}\r\n\r\n\t\tthis._dontClear = !!cfg.dontClear; // Prevent Scene#clear from destroying this component\r\n\r\n\t\tthis._renderer = this.scene._renderer;\r\n\r\n\t\t/**\r\n Arbitrary, user-defined metadata on this component.\r\n\r\n @property metadata\r\n @type Object\r\n */\r\n\t\tthis.meta = cfg.meta || {};\r\n\r\n\t\t/**\r\n\t\t * ID of this Component, unique within the {@link Scene}.\r\n\t\t *\r\n\t\t * Components are mapped by this ID in {@link Scene#components}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = cfg.id; // Auto-generated by Scene by default\r\n\r\n\t\t/**\r\n True as soon as this Component has been destroyed\r\n\r\n @property destroyed\r\n @type {Boolean}\r\n */\r\n\t\tthis.destroyed = false;\r\n\r\n\t\tthis._attached = {}; // Attached components with names.\r\n\t\tthis._attachments = null; // Attached components keyed to IDs - lazy-instantiated\r\n\t\tthis._subIdMap = null; // Subscription subId pool\r\n\t\tthis._subIdEvents = null; // Subscription subIds mapped to event names\r\n\t\tthis._eventSubs = null; // Event names mapped to subscribers\r\n\t\tthis._eventSubsNum = null;\r\n\t\tthis._events = null; // Maps names to events\r\n\t\tthis._eventCallDepth = 0; // Helps us catch stack overflows from recursive events\r\n\t\tthis._ownedComponents = null; // // Components created with #create - lazy-instantiated\r\n\r\n\t\tif (this !== this.scene) {\r\n\t\t\t// Don't add scene to itself\r\n\t\t\tthis.scene._addComponent(this); // Assigns this component an automatic ID if not yet assigned\r\n\t\t}\r\n\r\n\t\tthis._updateScheduled = false; // True when #_update will be called on next tick\r\n\r\n\t\tif (owner) {\r\n\t\t\towner._own(this);\r\n\t\t}\r\n\t}\r\n\r\n\t// /**\r\n\t// * Unique ID for this Component within its {@link Scene}.\r\n\t// *\r\n\t// * @property\r\n\t// * @type {String}\r\n\t// */\r\n\t// get id() {\r\n\t// return this._id;\r\n\t// }\r\n\r\n\t/**\r\n Indicates that we need to redraw the scene.\r\n\r\n This is called by certain subclasses after they have made some sort of state update that requires the\r\n renderer to perform a redraw.\r\n\r\n For example: a {@link Mesh} calls this on itself whenever you update its\r\n {@link Mesh#layer} property, which manually controls its render order in\r\n relation to other Meshes.\r\n\r\n If this component has a ````castsShadow```` property that's set ````true````, then this will also indicate\r\n that the renderer needs to redraw shadow map associated with this component. Components like\r\n {@link DirLight} have that property set when they produce light that creates shadows, while\r\n components like {@link Mesh\"}}layer{{/crossLink}} have that property set when they cast shadows.\r\n\r\n @protected\r\n */\r\n\tglRedraw() {\r\n\t\tif (!this._renderer) {\r\n\t\t\t// Called from a constructor\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._renderer.imageDirty();\r\n\t\tif (this.castsShadow) {\r\n\t\t\t// Light source or object\r\n\t\t\tthis._renderer.shadowsDirty();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n Indicates that we need to re-sort the renderer's state-ordered drawables list.\r\n\r\n For efficiency, the renderer keeps its list of drawables ordered so that runs of the same state updates can be\r\n combined. This method is called by certain subclasses after they have made some sort of state update that would\r\n require re-ordering of the drawables list.\r\n\r\n For example: a {@link DirLight} calls this on itself whenever you update {@link DirLight#dir}.\r\n\r\n @protected\r\n */\r\n\tglResort() {\r\n\t\tif (!this._renderer) {\r\n\t\t\t// Called from a constructor\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._renderer.needStateSort();\r\n\t}\r\n\r\n\t/**\r\n\t * The {@link Component} that owns the lifecycle of this Component, if any.\r\n\t *\r\n\t * When that component is destroyed, this component will be automatically destroyed also.\r\n\t *\r\n\t * Will be null if this Component has no owner.\r\n\t *\r\n\t * @property owner\r\n\t * @type {Component}\r\n\t */\r\n\tget owner() {\r\n\t\treturn this._owner;\r\n\t}\r\n\r\n\t/**\r\n\t * Tests if this component is of the given type, or is a subclass of the given type.\r\n\t * @type {Boolean}\r\n\t */\r\n\tisType(type) {\r\n\t\treturn this.type === type;\r\n\t}\r\n\r\n\t/**\r\n\t * Fires an event on this component.\r\n\t *\r\n\t * Notifies existing subscribers to the event, optionally retains the event to give to\r\n\t * any subsequent notifications on the event as they are made.\r\n\t *\r\n\t * @param {String} event The event type name\r\n\t * @param {Object} value The event parameters\r\n\t * @param {Boolean} [forget=false] When true, does not retain for subsequent subscribers\r\n\t */\r\n\tfire(event, value, forget) {\r\n\t\tif (!this._events) {\r\n\t\t\tthis._events = {};\r\n\t\t}\r\n\t\tif (!this._eventSubs) {\r\n\t\t\tthis._eventSubs = {};\r\n\t\t\tthis._eventSubsNum = {};\r\n\t\t}\r\n\t\tif (forget !== true) {\r\n\t\t\tthis._events[event] = value || true; // Save notification\r\n\t\t}\r\n\t\tconst subs = this._eventSubs[event];\r\n\t\tlet sub;\r\n\t\tif (subs) {\r\n\t\t\t// Notify subscriptions\r\n\t\t\tfor (const subId in subs) {\r\n\t\t\t\tif (subs.hasOwnProperty(subId)) {\r\n\t\t\t\t\tsub = subs[subId];\r\n\t\t\t\t\tthis._eventCallDepth++;\r\n\t\t\t\t\tif (this._eventCallDepth < 300) {\r\n\t\t\t\t\t\tsub.callback.call(sub.scope, value);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.error(\"fire: potential stack overflow from recursive event '\" + event + \"' - dropping this event\");\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis._eventCallDepth--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Subscribes to an event on this component.\r\n\t *\r\n\t * The callback is be called with this component as scope.\r\n\t *\r\n\t * @param {String} event The event\r\n\t * @param {Function} callback Called fired on the event\r\n\t * @param {Object} [scope=this] Scope for the callback\r\n\t * @return {String} Handle to the subscription, which may be used to unsubscribe with {@link #off}.\r\n\t */\r\n\ton(event, callback, scope) {\r\n\t\tif (!this._events) {\r\n\t\t\tthis._events = {};\r\n\t\t}\r\n\t\tif (!this._subIdMap) {\r\n\t\t\tthis._subIdMap = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_2__.Map(); // Subscription subId pool\r\n\t\t}\r\n\t\tif (!this._subIdEvents) {\r\n\t\t\tthis._subIdEvents = {};\r\n\t\t}\r\n\t\tif (!this._eventSubs) {\r\n\t\t\tthis._eventSubs = {};\r\n\t\t}\r\n\t\tif (!this._eventSubsNum) {\r\n\t\t\tthis._eventSubsNum = {};\r\n\t\t}\r\n\t\tlet subs = this._eventSubs[event];\r\n\t\tif (!subs) {\r\n\t\t\tsubs = {};\r\n\t\t\tthis._eventSubs[event] = subs;\r\n\t\t\tthis._eventSubsNum[event] = 1;\r\n\t\t} else {\r\n\t\t\tthis._eventSubsNum[event]++;\r\n\t\t}\r\n\t\tconst subId = this._subIdMap.addItem(); // Create unique subId\r\n\t\tsubs[subId] = {\r\n\t\t\tcallback: callback,\r\n\t\t\tscope: scope || this\r\n\t\t};\r\n\t\tthis._subIdEvents[subId] = event;\r\n\t\tconst value = this._events[event];\r\n\t\tif (value !== undefined) {\r\n\t\t\t// A publication exists, notify callback immediately\r\n\t\t\tcallback.call(scope || this, value);\r\n\t\t}\r\n\t\treturn subId;\r\n\t}\r\n\r\n\t/**\r\n\t * Cancels an event subscription that was previously made with {@link Component#on} or {@link Component#once}.\r\n\t *\r\n\t * @param {String} subId Subscription ID\r\n\t */\r\n\toff(subId) {\r\n\t\tif (subId === undefined || subId === null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!this._subIdEvents) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst event = this._subIdEvents[subId];\r\n\t\tif (event) {\r\n\t\t\tdelete this._subIdEvents[subId];\r\n\t\t\tconst subs = this._eventSubs[event];\r\n\t\t\tif (subs) {\r\n\t\t\t\tdelete subs[subId];\r\n\t\t\t\tthis._eventSubsNum[event]--;\r\n\t\t\t}\r\n\t\t\tthis._subIdMap.removeItem(subId); // Release subId\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Subscribes to the next occurrence of the given event, then un-subscribes as soon as the event is subIdd.\r\n\t *\r\n\t * This is equivalent to calling {@link Component#on}, and then calling {@link Component#off} inside the callback function.\r\n\t *\r\n\t * @param {String} event Data event to listen to\r\n\t * @param {Function} callback Called when fresh data is available at the event\r\n\t * @param {Object} [scope=this] Scope for the callback\r\n\t */\r\n\tonce(event, callback, scope) {\r\n\t\tconst self = this;\r\n\t\tconst subId = this.on(\r\n\t\t\tevent,\r\n\t\t\tfunction (value) {\r\n\t\t\t\tself.off(subId);\r\n\t\t\t\tcallback.call(scope || this, value);\r\n\t\t\t},\r\n\t\t\tscope\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Returns true if there are any subscribers to the given event on this component.\r\n\t *\r\n\t * @param {String} event The event\r\n\t * @return {Boolean} True if there are any subscribers to the given event on this component.\r\n\t */\r\n\thasSubs(event) {\r\n\t\treturn this._eventSubsNum && this._eventSubsNum[event] > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Logs a console debugging message for this component.\r\n\t *\r\n\t * The console message will have this format: *````[LOG] [<component type> <component id>: <message>````*\r\n\t *\r\n\t * Also fires the message as a \"log\" event on the parent {@link Scene}.\r\n\t *\r\n\t * @param {String} message The message to log\r\n\t */\r\n\tlog(message) {\r\n\t\tmessage = \"[LOG]\" + this._message(message);\r\n\t\twindow.console.log(message);\r\n\t\tthis.scene.fire(\"log\", message);\r\n\t}\r\n\r\n\t_message(message) {\r\n\t\treturn \" [\" + this.type + \" \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(this.id) + \"]: \" + message;\r\n\t}\r\n\r\n\t/**\r\n\t * Logs a warning for this component to the JavaScript console.\r\n\t *\r\n\t * The console message will have this format: *````[WARN] [<component type> =<component id>: <message>````*\r\n\t *\r\n\t * Also fires the message as a \"warn\" event on the parent {@link Scene}.\r\n\t *\r\n\t * @param {String} message The message to log\r\n\t */\r\n\twarn(message) {\r\n\t\tmessage = \"[WARN]\" + this._message(message);\r\n\t\twindow.console.warn(message);\r\n\t\tthis.scene.fire(\"warn\", message);\r\n\t}\r\n\r\n\t/**\r\n\t * Logs an error for this component to the JavaScript console.\r\n\t *\r\n\t * The console message will have this format: *````[ERROR] [<component type> =<component id>: <message>````*\r\n\t *\r\n\t * Also fires the message as an \"error\" event on the parent {@link Scene}.\r\n\t *\r\n\t * @param {String} message The message to log\r\n\t */\r\n\terror(message) {\r\n\t\tmessage = \"[ERROR]\" + this._message(message);\r\n\t\twindow.console.error(message);\r\n\t\tthis.scene.fire(\"error\", message);\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a child component to this.\r\n\t *\r\n\t * When component not given, attaches the scene's default instance for the given name (if any).\r\n\t * Publishes the new child component on this component, keyed to the given name.\r\n\t *\r\n\t * @param {*} params\r\n\t * @param {String} params.name component name\r\n\t * @param {Component} [params.component] The component\r\n\t * @param {String} [params.type] Optional expected type of base type of the child; when supplied, will\r\n\t * cause an exception if the given child is not the same type or a subtype of this.\r\n\t * @param {Boolean} [params.sceneDefault=false]\r\n\t * @param {Boolean} [params.sceneSingleton=false]\r\n\t * @param {Function} [params.onAttached] Optional callback called when component attached\r\n\t * @param {Function} [params.onAttached.callback] Callback function\r\n\t * @param {Function} [params.onAttached.scope] Optional scope for callback\r\n\t * @param {Function} [params.onDetached] Optional callback called when component is detached\r\n\t * @param {Function} [params.onDetached.callback] Callback function\r\n\t * @param {Function} [params.onDetached.scope] Optional scope for callback\r\n\t * @param {{String:Function}} [params.on] Callbacks to subscribe to properties on component\r\n\t * @param {Boolean} [params.recompiles=true] When true, fires \"dirty\" events on this component\r\n\t * @private\r\n\t */\r\n\t_attach(params) {\r\n\t\tconst name = params.name;\r\n\r\n\t\tif (!name) {\r\n\t\t\tthis.error(\"Component 'name' expected\");\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet component = params.component;\r\n\t\tconst sceneDefault = params.sceneDefault;\r\n\t\tconst sceneSingleton = params.sceneSingleton;\r\n\t\tconst type = params.type;\r\n\t\tconst on = params.on;\r\n\t\tconst recompiles = params.recompiles !== false;\r\n\r\n\t\t// True when child given as config object, where parent manages its instantiation and destruction\r\n\t\tlet managingLifecycle = false;\r\n\r\n\t\tif (component) {\r\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isNumeric(component) || _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isString(component)) {\r\n\t\t\t\t// Component ID given\r\n\t\t\t\t// Both numeric and string IDs are supported\r\n\r\n\t\t\t\tconst id = component;\r\n\r\n\t\t\t\tcomponent = this.scene.components[id];\r\n\r\n\t\t\t\tif (!component) {\r\n\t\t\t\t\t// Quote string IDs in errors\r\n\r\n\t\t\t\t\tthis.error(\"Component not found: \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(id));\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!component) {\r\n\t\t\tif (sceneSingleton === true) {\r\n\t\t\t\t// Using the first instance of the component type we find\r\n\r\n\t\t\t\tconst instances = this.scene.types[type];\r\n\t\t\t\tfor (const id2 in instances) {\r\n\t\t\t\t\tif (instances.hasOwnProperty) {\r\n\t\t\t\t\t\tcomponent = instances[id2];\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!component) {\r\n\t\t\t\t\tthis.error(\"Scene has no default component for '\" + name + \"'\");\r\n\t\t\t\t\treturn null;\r\n\t\t\t\t}\r\n\t\t\t} else if (sceneDefault === true) {\r\n\t\t\t\t// Using a default scene component\r\n\r\n\t\t\t\tcomponent = this.scene[name];\r\n\r\n\t\t\t\tif (!component) {\r\n\t\t\t\t\tthis.error(\"Scene has no default component for '\" + name + \"'\");\r\n\t\t\t\t\treturn null;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (component) {\r\n\t\t\tif (component.scene.id !== this.scene.id) {\r\n\t\t\t\tthis.error(\"Not in same scene: \" + component.type + \" \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(component.id));\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (type) {\r\n\t\t\t\tif (!component.isType(type)) {\r\n\t\t\t\t\tthis.error(\"Expected a \" + type + \" type or subtype: \" + component.type + \" \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(component.id));\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!this._attachments) {\r\n\t\t\tthis._attachments = {};\r\n\t\t}\r\n\r\n\t\tconst oldComponent = this._attached[name];\r\n\t\tlet subs;\r\n\t\tlet i;\r\n\t\tlet len;\r\n\r\n\t\tif (oldComponent) {\r\n\t\t\tif (component && oldComponent.id === component.id) {\r\n\t\t\t\t// Reject attempt to reattach same component\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tconst oldAttachment = this._attachments[oldComponent.id];\r\n\r\n\t\t\t// Unsubscribe from events on old component\r\n\r\n\t\t\tsubs = oldAttachment.subs;\r\n\r\n\t\t\tfor (i = 0, len = subs.length; i < len; i++) {\r\n\t\t\t\toldComponent.off(subs[i]);\r\n\t\t\t}\r\n\r\n\t\t\tdelete this._attached[name];\r\n\t\t\tdelete this._attachments[oldComponent.id];\r\n\r\n\t\t\tconst onDetached = oldAttachment.params.onDetached;\r\n\t\t\tif (onDetached) {\r\n\t\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isFunction(onDetached)) {\r\n\t\t\t\t\tonDetached(oldComponent);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tonDetached.scope\r\n\t\t\t\t\t\t? onDetached.callback.call(onDetached.scope, oldComponent)\r\n\t\t\t\t\t\t: onDetached.callback(oldComponent);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (oldAttachment.managingLifecycle) {\r\n\t\t\t\t// Note that we just unsubscribed from all events fired by the child\r\n\t\t\t\t// component, so destroying it won't fire events back at us now.\r\n\r\n\t\t\t\toldComponent.destroy();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (component) {\r\n\t\t\t// Set and publish the new component on this component\r\n\r\n\t\t\tconst attachment = {\r\n\t\t\t\tparams: params,\r\n\t\t\t\tcomponent: component,\r\n\t\t\t\tsubs: [],\r\n\t\t\t\tmanagingLifecycle: managingLifecycle\r\n\t\t\t};\r\n\r\n\t\t\tattachment.subs.push(\r\n\t\t\t\tcomponent.once(\r\n\t\t\t\t\t\"destroyed\",\r\n\t\t\t\t\tfunction () {\r\n\t\t\t\t\t\tattachment.params.component = null;\r\n\t\t\t\t\t\tthis._attach(attachment.params);\r\n\t\t\t\t\t},\r\n\t\t\t\t\tthis\r\n\t\t\t\t)\r\n\t\t\t);\r\n\r\n\t\t\tif (recompiles) {\r\n\t\t\t\tattachment.subs.push(\r\n\t\t\t\t\tcomponent.on(\r\n\t\t\t\t\t\t\"dirty\",\r\n\t\t\t\t\t\tfunction () {\r\n\t\t\t\t\t\t\tthis.fire(\"dirty\", this);\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tthis\r\n\t\t\t\t\t)\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tthis._attached[name] = component;\r\n\t\t\tthis._attachments[component.id] = attachment;\r\n\r\n\t\t\t// Bind destruct listener to new component to remove it\r\n\t\t\t// from this component when destroyed\r\n\r\n\t\t\tconst onAttached = params.onAttached;\r\n\t\t\tif (onAttached) {\r\n\t\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isFunction(onAttached)) {\r\n\t\t\t\t\tonAttached(component);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tonAttached.scope ? onAttached.callback.call(onAttached.scope, component) : onAttached.callback(component);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (on) {\r\n\t\t\t\tlet event;\r\n\t\t\t\tlet subIdr;\r\n\t\t\t\tlet callback;\r\n\t\t\t\tlet scope;\r\n\r\n\t\t\t\tfor (event in on) {\r\n\t\t\t\t\tif (on.hasOwnProperty(event)) {\r\n\t\t\t\t\t\tsubIdr = on[event];\r\n\r\n\t\t\t\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isFunction(subIdr)) {\r\n\t\t\t\t\t\t\tcallback = subIdr;\r\n\t\t\t\t\t\t\tscope = null;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tcallback = subIdr.callback;\r\n\t\t\t\t\t\t\tscope = subIdr.scope;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif (!callback) {\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tattachment.subs.push(component.on(event, callback, scope));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (recompiles) {\r\n\t\t\tthis.fire(\"dirty\", this); // FIXME: May trigger spurous mesh recompilations unless able to limit with param?\r\n\t\t}\r\n\r\n\t\tthis.fire(name, component); // Component can be null\r\n\r\n\t\treturn component;\r\n\t}\r\n\r\n\t_checkComponent(expectedType, component) {\r\n\t\tif (!component.isComponent) {\r\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isID(component)) {\r\n\t\t\t\tconst id = component;\r\n\t\t\t\tcomponent = this.scene.components[id];\r\n\t\t\t\tif (!component) {\r\n\t\t\t\t\tthis.error(\"Component not found: \" + id);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthis.error(\"Expected a Component or ID\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (expectedType !== component.type) {\r\n\t\t\tthis.error(\"Expected a \" + expectedType + \" Component\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (component.scene.id !== this.scene.id) {\r\n\t\t\tthis.error(\"Not in same scene: \" + component.type);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\treturn component;\r\n\t}\r\n\r\n\t_checkComponent2(expectedTypes, component) {\r\n\t\tif (!component.isComponent) {\r\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isID(component)) {\r\n\t\t\t\tconst id = component;\r\n\t\t\t\tcomponent = this.scene.components[id];\r\n\t\t\t\tif (!component) {\r\n\t\t\t\t\tthis.error(\"Component not found: \" + id);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthis.error(\"Expected a Component or ID\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (component.scene.id !== this.scene.id) {\r\n\t\t\tthis.error(\"Not in same scene: \" + component.type);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (var i = 0, len = expectedTypes.length; i < len; i++) {\r\n\t\t\tif (expectedTypes[i] === component.type) {\r\n\t\t\t\treturn component;\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.error(\"Expected component types: \" + expectedTypes);\r\n\t\treturn null;\r\n\t}\r\n\r\n\t_own(component) {\r\n\t\tif (!this._ownedComponents) {\r\n\t\t\tthis._ownedComponents = {};\r\n\t\t}\r\n\t\tif (!this._ownedComponents[component.id]) {\r\n\t\t\tthis._ownedComponents[component.id] = component;\r\n\t\t}\r\n\t\tcomponent.once(\r\n\t\t\t\"destroyed\",\r\n\t\t\t() => {\r\n\t\t\t\tdelete this._ownedComponents[component.id];\r\n\t\t\t},\r\n\t\t\tthis\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Protected method, called by sub-classes to queue a call to _update().\r\n\t * @protected\r\n\t * @param {Number} [priority=1]\r\n\t */\r\n\t_needUpdate(priority) {\r\n\t\tif (!this._updateScheduled) {\r\n\t\t\tthis._updateScheduled = true;\r\n\t\t\tif (priority === 0) {\r\n\t\t\t\tthis._doUpdate();\r\n\t\t\t} else {\r\n\t\t\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(this._doUpdate, this);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\t_doUpdate() {\r\n\t\tif (this._updateScheduled) {\r\n\t\t\tthis._updateScheduled = false;\r\n\t\t\tif (this._update) {\r\n\t\t\t\tthis._update();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Schedule a task to perform on the next browser interval\r\n\t * @param task\r\n\t */\r\n\tscheduleTask(task) {\r\n\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(task, null);\r\n\t}\r\n\r\n\t/**\r\n\t * Protected virtual template method, optionally implemented\r\n\t * by sub-classes to perform a scheduled task.\r\n\t *\r\n\t * @protected\r\n\t */\r\n\t_update() {}\r\n\r\n\t/**\r\n\t * Destroys all {@link Component}s that are owned by this. These are Components that were instantiated with\r\n\t * this Component as their first constructor argument.\r\n\t */\r\n\tclear() {\r\n\t\tif (this._ownedComponents) {\r\n\t\t\tfor (var id in this._ownedComponents) {\r\n\t\t\t\tif (this._ownedComponents.hasOwnProperty(id)) {\r\n\t\t\t\t\tconst component = this._ownedComponents[id];\r\n\t\t\t\t\tcomponent.destroy();\r\n\t\t\t\t\tdelete this._ownedComponents[id];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this component.\r\n\t */\r\n\tdestroy(callback) {\r\n\t\tif (this.destroyed) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Fired when this Component is destroyed.\r\n\t\t * @event destroyed\r\n\t\t */\r\n\t\tthis.fire(\"destroyed\", (this.destroyed = true)); // Must fire before we blow away subscription maps, below\r\n\r\n\t\t// Unsubscribe from child components and destroy then\r\n\r\n\t\tlet id;\r\n\t\tlet attachment;\r\n\t\tlet component;\r\n\t\tlet subs;\r\n\t\tlet i;\r\n\t\tlet len;\r\n\r\n\t\tif (this._attachments) {\r\n\t\t\tfor (id in this._attachments) {\r\n\t\t\t\tif (this._attachments.hasOwnProperty(id)) {\r\n\t\t\t\t\tattachment = this._attachments[id];\r\n\t\t\t\t\tcomponent = attachment.component;\r\n\t\t\t\t\tsubs = attachment.subs;\r\n\t\t\t\t\tfor (i = 0, len = subs.length; i < len; i++) {\r\n\t\t\t\t\t\tcomponent.off(subs[i]);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (attachment.managingLifecycle) {\r\n\t\t\t\t\t\tcomponent.destroy();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (this._ownedComponents) {\r\n\t\t\tfor (id in this._ownedComponents) {\r\n\t\t\t\tif (this._ownedComponents.hasOwnProperty(id)) {\r\n\t\t\t\t\tcomponent = this._ownedComponents[id];\r\n\t\t\t\t\tcomponent.destroy();\r\n\t\t\t\t\tdelete this._ownedComponents[id];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.scene._removeComponent(this);\r\n\r\n\t\t// Memory leak avoidance\r\n\t\tthis._attached = {};\r\n\t\tthis._attachments = null;\r\n\t\tthis._subIdMap = null;\r\n\t\tthis._subIdEvents = null;\r\n\t\tthis._eventSubs = null;\r\n\t\tthis._events = null;\r\n\t\tthis._eventCallDepth = 0;\r\n\t\tthis._ownedComponents = null;\r\n\t\tthis._updateScheduled = false;\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/Component.js?");
|
|
2597
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Component: () => (/* binding */ Component)\n/* harmony export */ });\n/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core.js */ \"./src/viewer/scene/core.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n\n\n\n\n/**\n * @desc Base class for all xeokit components.\n *\n * ## Component IDs\n *\n * Every Component has an ID that's unique within the parent {@link Scene}. xeokit generates\n * the IDs automatically by default, however you can also specify them yourself. In the example below, we're creating a\n * scene comprised of {@link Scene}, {@link Material}, {@link ReadableGeometry} and\n * {@link Mesh} components, while letting xeokit generate its own ID for\n * the {@link ReadableGeometry}:\n *\n *````JavaScript\n * import {Viewer, Mesh, buildTorusGeometry, ReadableGeometry, PhongMaterial, Texture, Fresnel} from \"xeokit-sdk.es.js\";\n *\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\"\n * });\n *\n * viewer.scene.camera.eye = [0, 0, 5];\n * viewer.scene.camera.look = [0, 0, 0];\n * viewer.scene.camera.up = [0, 1, 0];\n *\n * new Mesh(viewer.scene, {\n * geometry: new ReadableGeometry(viewer.scene, buildTorusGeometry({\n * center: [0, 0, 0],\n * radius: 1.5,\n * tube: 0.5,\n * radialSegments: 32,\n * tubeSegments: 24,\n * arc: Math.PI * 2.0\n * }),\n * material: new PhongMaterial(viewer.scene, {\n * id: \"myMaterial\",\n * ambient: [0.9, 0.3, 0.9],\n * shininess: 30,\n * diffuseMap: new Texture(viewer.scene, {\n * src: \"textures/diffuse/uvGrid2.jpg\"\n * }),\n * specularFresnel: new Fresnel(viewer.scene, {\n * leftColor: [1.0, 1.0, 1.0],\n * rightColor: [0.0, 0.0, 0.0],\n * power: 4\n * })\n * })\n * });\n *````\n *\n * We can then find those components like this:\n *\n * ````javascript\n * // Find the Material\n * var material = viewer.scene.components[\"myMaterial\"];\n *\n * // Find all PhongMaterials in the Scene\n * var phongMaterials = viewer.scene.types[\"PhongMaterial\"];\n *\n * // Find our Material within the PhongMaterials\n * var materialAgain = phongMaterials[\"myMaterial\"];\n * ````\n *\n * ## Restriction on IDs\n *\n * Auto-generated IDs are of the form ````\"__0\"````, ````\"__1\"````, ````\"__2\"```` ... and so on.\n *\n * Scene maintains a map of these IDs, along with a counter that it increments each time it generates a new ID.\n *\n * If Scene has created the IDs listed above, and we then destroy the ````Component```` with ID ````\"__1\"````,\n * Scene will mark that ID as available, and will reuse it for the next default ID.\n *\n * Therefore, two restrictions your on IDs:\n *\n * * don't use IDs that begin with two underscores, and\n * * don't reuse auto-generated IDs of destroyed Components.\n *\n * ## Logging\n *\n * Components have methods to log ID-prefixed messages to the JavaScript console:\n *\n * ````javascript\n * material.log(\"Everything is fine, situation normal.\");\n * material.warn(\"Wait, whats that red light?\");\n * material.error(\"Aw, snap!\");\n * ````\n *\n * The logged messages will look like this in the console:\n *\n * ````text\n * [LOG] myMaterial: Everything is fine, situation normal.\n * [WARN] myMaterial: Wait, whats that red light..\n * [ERROR] myMaterial: Aw, snap!\n * ````\n *\n * ## Destruction\n *\n * Get notification of destruction of Components:\n *\n * ````javascript\n * material.once(\"destroyed\", function() {\n * this.log(\"Component was destroyed: \" + this.id);\n * });\n * ````\n *\n * Or get notification of destruction of any Component within its {@link Scene}:\n *\n * ````javascript\n * scene.on(\"componentDestroyed\", function(component) {\n * this.log(\"Component was destroyed: \" + component.id);\n * });\n * ````\n *\n * Then destroy a component like this:\n *\n * ````javascript\n * material.destroy();\n * ````\n */\nclass Component {\n\t/**\n @private\n */\n\tget type() {\n\t\treturn \"Component\";\n\t}\n\n\t/**\n\t * @private\n\t */\n\tget isComponent() {\n\t\treturn true;\n\t}\n\n\tconstructor(owner = null, cfg = {}) {\n\t\t/**\n\t\t * The parent {@link Scene} that contains this Component.\n\t\t *\n\t\t * @property scene\n\t\t * @type {Scene}\n\t\t * @final\n\t\t */\n\t\tthis.scene = null;\n\n\t\tif (this.type === \"Scene\") {\n\t\t\tthis.scene = this;\n\t\t\t/**\n\t\t\t * The viewer that contains this Scene.\n\t\t\t * @property viewer\n\t\t\t * @type {Viewer}\n\t\t\t */\n\t\t\tthis.viewer = cfg.viewer;\n\t\t} else {\n\t\t\tif (owner.type === \"Scene\") {\n\t\t\t\tthis.scene = owner;\n\t\t\t} else if (owner instanceof Component) {\n\t\t\t\tthis.scene = owner.scene;\n\t\t\t} else {\n\t\t\t\tthrow \"Invalid param: owner must be a Component\";\n\t\t\t}\n\t\t\tthis._owner = owner;\n\t\t}\n\n\t\tthis._dontClear = !!cfg.dontClear; // Prevent Scene#clear from destroying this component\n\n\t\tthis._renderer = this.scene._renderer;\n\n\t\t/**\n Arbitrary, user-defined metadata on this component.\n\n @property metadata\n @type Object\n */\n\t\tthis.meta = cfg.meta || {};\n\n\t\t/**\n\t\t * ID of this Component, unique within the {@link Scene}.\n\t\t *\n\t\t * Components are mapped by this ID in {@link Scene#components}.\n\t\t *\n\t\t * @property id\n\t\t * @type {String|Number}\n\t\t */\n\t\tthis.id = cfg.id; // Auto-generated by Scene by default\n\n\t\t/**\n True as soon as this Component has been destroyed\n\n @property destroyed\n @type {Boolean}\n */\n\t\tthis.destroyed = false;\n\n\t\tthis._attached = {}; // Attached components with names.\n\t\tthis._attachments = null; // Attached components keyed to IDs - lazy-instantiated\n\t\tthis._subIdMap = null; // Subscription subId pool\n\t\tthis._subIdEvents = null; // Subscription subIds mapped to event names\n\t\tthis._eventSubs = null; // Event names mapped to subscribers\n\t\tthis._eventSubsNum = null;\n\t\tthis._events = null; // Maps names to events\n\t\tthis._eventCallDepth = 0; // Helps us catch stack overflows from recursive events\n\t\tthis._ownedComponents = null; // // Components created with #create - lazy-instantiated\n\n\t\tif (this !== this.scene) {\n\t\t\t// Don't add scene to itself\n\t\t\tthis.scene._addComponent(this); // Assigns this component an automatic ID if not yet assigned\n\t\t}\n\n\t\tthis._updateScheduled = false; // True when #_update will be called on next tick\n\n\t\tif (owner) {\n\t\t\towner._own(this);\n\t\t}\n\t}\n\n\t// /**\n\t// * Unique ID for this Component within its {@link Scene}.\n\t// *\n\t// * @property\n\t// * @type {String}\n\t// */\n\t// get id() {\n\t// return this._id;\n\t// }\n\n\t/**\n Indicates that we need to redraw the scene.\n\n This is called by certain subclasses after they have made some sort of state update that requires the\n renderer to perform a redraw.\n\n For example: a {@link Mesh} calls this on itself whenever you update its\n {@link Mesh#layer} property, which manually controls its render order in\n relation to other Meshes.\n\n If this component has a ````castsShadow```` property that's set ````true````, then this will also indicate\n that the renderer needs to redraw shadow map associated with this component. Components like\n {@link DirLight} have that property set when they produce light that creates shadows, while\n components like {@link Mesh\"}}layer{{/crossLink}} have that property set when they cast shadows.\n\n @protected\n */\n\tglRedraw() {\n\t\tif (!this._renderer) {\n\t\t\t// Called from a constructor\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.imageDirty();\n\t\tif (this.castsShadow) {\n\t\t\t// Light source or object\n\t\t\tthis._renderer.shadowsDirty();\n\t\t}\n\t}\n\n\t/**\n Indicates that we need to re-sort the renderer's state-ordered drawables list.\n\n For efficiency, the renderer keeps its list of drawables ordered so that runs of the same state updates can be\n combined. This method is called by certain subclasses after they have made some sort of state update that would\n require re-ordering of the drawables list.\n\n For example: a {@link DirLight} calls this on itself whenever you update {@link DirLight#dir}.\n\n @protected\n */\n\tglResort() {\n\t\tif (!this._renderer) {\n\t\t\t// Called from a constructor\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.needStateSort();\n\t}\n\n\t/**\n\t * The {@link Component} that owns the lifecycle of this Component, if any.\n\t *\n\t * When that component is destroyed, this component will be automatically destroyed also.\n\t *\n\t * Will be null if this Component has no owner.\n\t *\n\t * @property owner\n\t * @type {Component}\n\t */\n\tget owner() {\n\t\treturn this._owner;\n\t}\n\n\t/**\n\t * Tests if this component is of the given type, or is a subclass of the given type.\n\t * @type {Boolean}\n\t */\n\tisType(type) {\n\t\treturn this.type === type;\n\t}\n\n\t/**\n\t * Fires an event on this component.\n\t *\n\t * Notifies existing subscribers to the event, optionally retains the event to give to\n\t * any subsequent notifications on the event as they are made.\n\t *\n\t * @param {String} event The event type name\n\t * @param {Object} value The event parameters\n\t * @param {Boolean} [forget=false] When true, does not retain for subsequent subscribers\n\t */\n\tfire(event, value, forget) {\n\t\tif (!this._events) {\n\t\t\tthis._events = {};\n\t\t}\n\t\tif (!this._eventSubs) {\n\t\t\tthis._eventSubs = {};\n\t\t\tthis._eventSubsNum = {};\n\t\t}\n\t\tif (forget !== true) {\n\t\t\tthis._events[event] = value || true; // Save notification\n\t\t}\n\t\tconst subs = this._eventSubs[event];\n\t\tlet sub;\n\t\tif (subs) {\n\t\t\t// Notify subscriptions\n\t\t\tfor (const subId in subs) {\n\t\t\t\tif (subs.hasOwnProperty(subId)) {\n\t\t\t\t\tsub = subs[subId];\n\t\t\t\t\tthis._eventCallDepth++;\n\t\t\t\t\tif (this._eventCallDepth < 300) {\n\t\t\t\t\t\tsub.callback.call(sub.scope, value);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.error(\"fire: potential stack overflow from recursive event '\" + event + \"' - dropping this event\");\n\t\t\t\t\t}\n\t\t\t\t\tthis._eventCallDepth--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Subscribes to an event on this component.\n\t *\n\t * The callback is be called with this component as scope.\n\t *\n\t * @param {String} event The event\n\t * @param {Function} callback Called fired on the event\n\t * @param {Object} [scope=this] Scope for the callback\n\t * @return {String} Handle to the subscription, which may be used to unsubscribe with {@link #off}.\n\t */\n\ton(event, callback, scope) {\n\t\tif (!this._events) {\n\t\t\tthis._events = {};\n\t\t}\n\t\tif (!this._subIdMap) {\n\t\t\tthis._subIdMap = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_2__.Map(); // Subscription subId pool\n\t\t}\n\t\tif (!this._subIdEvents) {\n\t\t\tthis._subIdEvents = {};\n\t\t}\n\t\tif (!this._eventSubs) {\n\t\t\tthis._eventSubs = {};\n\t\t}\n\t\tif (!this._eventSubsNum) {\n\t\t\tthis._eventSubsNum = {};\n\t\t}\n\t\tlet subs = this._eventSubs[event];\n\t\tif (!subs) {\n\t\t\tsubs = {};\n\t\t\tthis._eventSubs[event] = subs;\n\t\t\tthis._eventSubsNum[event] = 1;\n\t\t} else {\n\t\t\tthis._eventSubsNum[event]++;\n\t\t}\n\t\tconst subId = this._subIdMap.addItem(); // Create unique subId\n\t\tsubs[subId] = {\n\t\t\tcallback: callback,\n\t\t\tscope: scope || this\n\t\t};\n\t\tthis._subIdEvents[subId] = event;\n\t\tconst value = this._events[event];\n\t\tif (value !== undefined) {\n\t\t\t// A publication exists, notify callback immediately\n\t\t\tcallback.call(scope || this, value);\n\t\t}\n\t\treturn subId;\n\t}\n\n\t/**\n\t * Cancels an event subscription that was previously made with {@link Component#on} or {@link Component#once}.\n\t *\n\t * @param {String} subId Subscription ID\n\t */\n\toff(subId) {\n\t\tif (subId === undefined || subId === null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!this._subIdEvents) {\n\t\t\treturn;\n\t\t}\n\t\tconst event = this._subIdEvents[subId];\n\t\tif (event) {\n\t\t\tdelete this._subIdEvents[subId];\n\t\t\tconst subs = this._eventSubs[event];\n\t\t\tif (subs) {\n\t\t\t\tdelete subs[subId];\n\t\t\t\tthis._eventSubsNum[event]--;\n\t\t\t}\n\t\t\tthis._subIdMap.removeItem(subId); // Release subId\n\t\t}\n\t}\n\n\t/**\n\t * Subscribes to the next occurrence of the given event, then un-subscribes as soon as the event is subIdd.\n\t *\n\t * This is equivalent to calling {@link Component#on}, and then calling {@link Component#off} inside the callback function.\n\t *\n\t * @param {String} event Data event to listen to\n\t * @param {Function} callback Called when fresh data is available at the event\n\t * @param {Object} [scope=this] Scope for the callback\n\t */\n\tonce(event, callback, scope) {\n\t\tconst self = this;\n\t\tconst subId = this.on(\n\t\t\tevent,\n\t\t\tfunction (value) {\n\t\t\t\tself.off(subId);\n\t\t\t\tcallback.call(scope || this, value);\n\t\t\t},\n\t\t\tscope\n\t\t);\n\t}\n\n\t/**\n\t * Returns true if there are any subscribers to the given event on this component.\n\t *\n\t * @param {String} event The event\n\t * @return {Boolean} True if there are any subscribers to the given event on this component.\n\t */\n\thasSubs(event) {\n\t\treturn this._eventSubsNum && this._eventSubsNum[event] > 0;\n\t}\n\n\t/**\n\t * Logs a console debugging message for this component.\n\t *\n\t * The console message will have this format: *````[LOG] [<component type> <component id>: <message>````*\n\t *\n\t * Also fires the message as a \"log\" event on the parent {@link Scene}.\n\t *\n\t * @param {String} message The message to log\n\t */\n\tlog(message) {\n\t\tmessage = \"[LOG]\" + this._message(message);\n\t\twindow.console.log(message);\n\t\tthis.scene.fire(\"log\", message);\n\t}\n\n\t_message(message) {\n\t\treturn \" [\" + this.type + \" \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(this.id) + \"]: \" + message;\n\t}\n\n\t/**\n\t * Logs a warning for this component to the JavaScript console.\n\t *\n\t * The console message will have this format: *````[WARN] [<component type> =<component id>: <message>````*\n\t *\n\t * Also fires the message as a \"warn\" event on the parent {@link Scene}.\n\t *\n\t * @param {String} message The message to log\n\t */\n\twarn(message) {\n\t\tmessage = \"[WARN]\" + this._message(message);\n\t\twindow.console.warn(message);\n\t\tthis.scene.fire(\"warn\", message);\n\t}\n\n\t/**\n\t * Logs an error for this component to the JavaScript console.\n\t *\n\t * The console message will have this format: *````[ERROR] [<component type> =<component id>: <message>````*\n\t *\n\t * Also fires the message as an \"error\" event on the parent {@link Scene}.\n\t *\n\t * @param {String} message The message to log\n\t */\n\terror(message) {\n\t\tmessage = \"[ERROR]\" + this._message(message);\n\t\twindow.console.error(message);\n\t\tthis.scene.fire(\"error\", message);\n\t}\n\n\t/**\n\t * Adds a child component to this.\n\t *\n\t * When component not given, attaches the scene's default instance for the given name (if any).\n\t * Publishes the new child component on this component, keyed to the given name.\n\t *\n\t * @param {*} params\n\t * @param {String} params.name component name\n\t * @param {Component} [params.component] The component\n\t * @param {String} [params.type] Optional expected type of base type of the child; when supplied, will\n\t * cause an exception if the given child is not the same type or a subtype of this.\n\t * @param {Boolean} [params.sceneDefault=false]\n\t * @param {Boolean} [params.sceneSingleton=false]\n\t * @param {Function} [params.onAttached] Optional callback called when component attached\n\t * @param {Function} [params.onAttached.callback] Callback function\n\t * @param {Function} [params.onAttached.scope] Optional scope for callback\n\t * @param {Function} [params.onDetached] Optional callback called when component is detached\n\t * @param {Function} [params.onDetached.callback] Callback function\n\t * @param {Function} [params.onDetached.scope] Optional scope for callback\n\t * @param {{String:Function}} [params.on] Callbacks to subscribe to properties on component\n\t * @param {Boolean} [params.recompiles=true] When true, fires \"dirty\" events on this component\n\t * @private\n\t */\n\t_attach(params) {\n\t\tconst name = params.name;\n\n\t\tif (!name) {\n\t\t\tthis.error(\"Component 'name' expected\");\n\t\t\treturn;\n\t\t}\n\n\t\tlet component = params.component;\n\t\tconst sceneDefault = params.sceneDefault;\n\t\tconst sceneSingleton = params.sceneSingleton;\n\t\tconst type = params.type;\n\t\tconst on = params.on;\n\t\tconst recompiles = params.recompiles !== false;\n\n\t\t// True when child given as config object, where parent manages its instantiation and destruction\n\t\tlet managingLifecycle = false;\n\n\t\tif (component) {\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isNumeric(component) || _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isString(component)) {\n\t\t\t\t// Component ID given\n\t\t\t\t// Both numeric and string IDs are supported\n\n\t\t\t\tconst id = component;\n\n\t\t\t\tcomponent = this.scene.components[id];\n\n\t\t\t\tif (!component) {\n\t\t\t\t\t// Quote string IDs in errors\n\n\t\t\t\t\tthis.error(\"Component not found: \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(id));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!component) {\n\t\t\tif (sceneSingleton === true) {\n\t\t\t\t// Using the first instance of the component type we find\n\n\t\t\t\tconst instances = this.scene.types[type];\n\t\t\t\tfor (const id2 in instances) {\n\t\t\t\t\tif (instances.hasOwnProperty) {\n\t\t\t\t\t\tcomponent = instances[id2];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!component) {\n\t\t\t\t\tthis.error(\"Scene has no default component for '\" + name + \"'\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t} else if (sceneDefault === true) {\n\t\t\t\t// Using a default scene component\n\n\t\t\t\tcomponent = this.scene[name];\n\n\t\t\t\tif (!component) {\n\t\t\t\t\tthis.error(\"Scene has no default component for '\" + name + \"'\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (component) {\n\t\t\tif (component.scene.id !== this.scene.id) {\n\t\t\t\tthis.error(\"Not in same scene: \" + component.type + \" \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(component.id));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (type) {\n\t\t\t\tif (!component.isType(type)) {\n\t\t\t\t\tthis.error(\"Expected a \" + type + \" type or subtype: \" + component.type + \" \" + _utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.inQuotes(component.id));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!this._attachments) {\n\t\t\tthis._attachments = {};\n\t\t}\n\n\t\tconst oldComponent = this._attached[name];\n\t\tlet subs;\n\t\tlet i;\n\t\tlet len;\n\n\t\tif (oldComponent) {\n\t\t\tif (component && oldComponent.id === component.id) {\n\t\t\t\t// Reject attempt to reattach same component\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst oldAttachment = this._attachments[oldComponent.id];\n\n\t\t\t// Unsubscribe from events on old component\n\n\t\t\tsubs = oldAttachment.subs;\n\n\t\t\tfor (i = 0, len = subs.length; i < len; i++) {\n\t\t\t\toldComponent.off(subs[i]);\n\t\t\t}\n\n\t\t\tdelete this._attached[name];\n\t\t\tdelete this._attachments[oldComponent.id];\n\n\t\t\tconst onDetached = oldAttachment.params.onDetached;\n\t\t\tif (onDetached) {\n\t\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isFunction(onDetached)) {\n\t\t\t\t\tonDetached(oldComponent);\n\t\t\t\t} else {\n\t\t\t\t\tonDetached.scope\n\t\t\t\t\t\t? onDetached.callback.call(onDetached.scope, oldComponent)\n\t\t\t\t\t\t: onDetached.callback(oldComponent);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (oldAttachment.managingLifecycle) {\n\t\t\t\t// Note that we just unsubscribed from all events fired by the child\n\t\t\t\t// component, so destroying it won't fire events back at us now.\n\n\t\t\t\toldComponent.destroy();\n\t\t\t}\n\t\t}\n\n\t\tif (component) {\n\t\t\t// Set and publish the new component on this component\n\n\t\t\tconst attachment = {\n\t\t\t\tparams: params,\n\t\t\t\tcomponent: component,\n\t\t\t\tsubs: [],\n\t\t\t\tmanagingLifecycle: managingLifecycle\n\t\t\t};\n\n\t\t\tattachment.subs.push(\n\t\t\t\tcomponent.once(\n\t\t\t\t\t\"destroyed\",\n\t\t\t\t\tfunction () {\n\t\t\t\t\t\tattachment.params.component = null;\n\t\t\t\t\t\tthis._attach(attachment.params);\n\t\t\t\t\t},\n\t\t\t\t\tthis\n\t\t\t\t)\n\t\t\t);\n\n\t\t\tif (recompiles) {\n\t\t\t\tattachment.subs.push(\n\t\t\t\t\tcomponent.on(\n\t\t\t\t\t\t\"dirty\",\n\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\tthis.fire(\"dirty\", this);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tthis\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis._attached[name] = component;\n\t\t\tthis._attachments[component.id] = attachment;\n\n\t\t\t// Bind destruct listener to new component to remove it\n\t\t\t// from this component when destroyed\n\n\t\t\tconst onAttached = params.onAttached;\n\t\t\tif (onAttached) {\n\t\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isFunction(onAttached)) {\n\t\t\t\t\tonAttached(component);\n\t\t\t\t} else {\n\t\t\t\t\tonAttached.scope ? onAttached.callback.call(onAttached.scope, component) : onAttached.callback(component);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (on) {\n\t\t\t\tlet event;\n\t\t\t\tlet subIdr;\n\t\t\t\tlet callback;\n\t\t\t\tlet scope;\n\n\t\t\t\tfor (event in on) {\n\t\t\t\t\tif (on.hasOwnProperty(event)) {\n\t\t\t\t\t\tsubIdr = on[event];\n\n\t\t\t\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isFunction(subIdr)) {\n\t\t\t\t\t\t\tcallback = subIdr;\n\t\t\t\t\t\t\tscope = null;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcallback = subIdr.callback;\n\t\t\t\t\t\t\tscope = subIdr.scope;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!callback) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tattachment.subs.push(component.on(event, callback, scope));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (recompiles) {\n\t\t\tthis.fire(\"dirty\", this); // FIXME: May trigger spurous mesh recompilations unless able to limit with param?\n\t\t}\n\n\t\tthis.fire(name, component); // Component can be null\n\n\t\treturn component;\n\t}\n\n\t_checkComponent(expectedType, component) {\n\t\tif (!component.isComponent) {\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isID(component)) {\n\t\t\t\tconst id = component;\n\t\t\t\tcomponent = this.scene.components[id];\n\t\t\t\tif (!component) {\n\t\t\t\t\tthis.error(\"Component not found: \" + id);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.error(\"Expected a Component or ID\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (expectedType !== component.type) {\n\t\t\tthis.error(\"Expected a \" + expectedType + \" Component\");\n\t\t\treturn;\n\t\t}\n\t\tif (component.scene.id !== this.scene.id) {\n\t\t\tthis.error(\"Not in same scene: \" + component.type);\n\t\t\treturn;\n\t\t}\n\t\treturn component;\n\t}\n\n\t_checkComponent2(expectedTypes, component) {\n\t\tif (!component.isComponent) {\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_1__.utils.isID(component)) {\n\t\t\t\tconst id = component;\n\t\t\t\tcomponent = this.scene.components[id];\n\t\t\t\tif (!component) {\n\t\t\t\t\tthis.error(\"Component not found: \" + id);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.error(\"Expected a Component or ID\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (component.scene.id !== this.scene.id) {\n\t\t\tthis.error(\"Not in same scene: \" + component.type);\n\t\t\treturn;\n\t\t}\n\t\tfor (var i = 0, len = expectedTypes.length; i < len; i++) {\n\t\t\tif (expectedTypes[i] === component.type) {\n\t\t\t\treturn component;\n\t\t\t}\n\t\t}\n\t\tthis.error(\"Expected component types: \" + expectedTypes);\n\t\treturn null;\n\t}\n\n\t_own(component) {\n\t\tif (!this._ownedComponents) {\n\t\t\tthis._ownedComponents = {};\n\t\t}\n\t\tif (!this._ownedComponents[component.id]) {\n\t\t\tthis._ownedComponents[component.id] = component;\n\t\t}\n\t\tcomponent.once(\n\t\t\t\"destroyed\",\n\t\t\t() => {\n\t\t\t\tdelete this._ownedComponents[component.id];\n\t\t\t},\n\t\t\tthis\n\t\t);\n\t}\n\n\t/**\n\t * Protected method, called by sub-classes to queue a call to _update().\n\t * @protected\n\t * @param {Number} [priority=1]\n\t */\n\t_needUpdate(priority) {\n\t\tif (!this._updateScheduled) {\n\t\t\tthis._updateScheduled = true;\n\t\t\tif (priority === 0) {\n\t\t\t\tthis._doUpdate();\n\t\t\t} else {\n\t\t\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(this._doUpdate, this);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_doUpdate() {\n\t\tif (this._updateScheduled) {\n\t\t\tthis._updateScheduled = false;\n\t\t\tif (this._update) {\n\t\t\t\tthis._update();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Schedule a task to perform on the next browser interval\n\t * @param task\n\t */\n\tscheduleTask(task) {\n\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(task, null);\n\t}\n\n\t/**\n\t * Protected virtual template method, optionally implemented\n\t * by sub-classes to perform a scheduled task.\n\t *\n\t * @protected\n\t */\n\t_update() {}\n\n\t/**\n\t * Destroys all {@link Component}s that are owned by this. These are Components that were instantiated with\n\t * this Component as their first constructor argument.\n\t */\n\tclear() {\n\t\tif (this._ownedComponents) {\n\t\t\tfor (var id in this._ownedComponents) {\n\t\t\t\tif (this._ownedComponents.hasOwnProperty(id)) {\n\t\t\t\t\tconst component = this._ownedComponents[id];\n\t\t\t\t\tcomponent.destroy();\n\t\t\t\t\tdelete this._ownedComponents[id];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys this component.\n\t */\n\tdestroy(callback) {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t * Fired when this Component is destroyed.\n\t\t * @event destroyed\n\t\t */\n\t\tthis.fire(\"destroyed\", (this.destroyed = true)); // Must fire before we blow away subscription maps, below\n\n\t\t// Unsubscribe from child components and destroy then\n\n\t\tlet id;\n\t\tlet attachment;\n\t\tlet component;\n\t\tlet subs;\n\t\tlet i;\n\t\tlet len;\n\n\t\tif (this._attachments) {\n\t\t\tfor (id in this._attachments) {\n\t\t\t\tif (this._attachments.hasOwnProperty(id)) {\n\t\t\t\t\tattachment = this._attachments[id];\n\t\t\t\t\tcomponent = attachment.component;\n\t\t\t\t\tsubs = attachment.subs;\n\t\t\t\t\tfor (i = 0, len = subs.length; i < len; i++) {\n\t\t\t\t\t\tcomponent.off(subs[i]);\n\t\t\t\t\t}\n\t\t\t\t\tif (attachment.managingLifecycle) {\n\t\t\t\t\t\tcomponent.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this._ownedComponents) {\n\t\t\tfor (id in this._ownedComponents) {\n\t\t\t\tif (this._ownedComponents.hasOwnProperty(id)) {\n\t\t\t\t\tcomponent = this._ownedComponents[id];\n\t\t\t\t\tcomponent.destroy();\n\t\t\t\t\tdelete this._ownedComponents[id];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.scene._removeComponent(this);\n\n\t\t// Memory leak avoidance\n\t\tthis._attached = {};\n\t\tthis._attachments = null;\n\t\tthis._subIdMap = null;\n\t\tthis._subIdEvents = null;\n\t\tthis._eventSubs = null;\n\t\tthis._events = null;\n\t\tthis._eventCallDepth = 0;\n\t\tthis._ownedComponents = null;\n\t\tthis._updateScheduled = false;\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/Component.js?");
|
|
2598
2598
|
|
|
2599
2599
|
/***/ }),
|
|
2600
2600
|
|
|
@@ -2944,7 +2944,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2944
2944
|
\*****************************************/
|
|
2945
2945
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2946
2946
|
|
|
2947
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Input: () => (/* binding */ Input)\n/* harmony export */ });\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\n\r\n/**\r\n * @desc Meditates mouse, touch and keyboard events for various interaction controls.\r\n *\r\n * Ordinarily, you would only use this component as a utility to help manage input events and state for your\r\n * own custom input handlers.\r\n *\r\n * * Located at {@link Scene#input}\r\n * * Used by (at least) {@link CameraControl}\r\n *\r\n * ## Usage\r\n *\r\n * Subscribing to mouse events on the canvas:\r\n *\r\n * ````javascript\r\n * import {Viewer} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * const input = viewer.scene.input;\r\n *\r\n * const onMouseDown = input.on(\"mousedown\", (canvasCoords) => {\r\n * console.log(\"Mouse down at: x=\" + canvasCoords[0] + \", y=\" + coords[1]);\r\n * });\r\n *\r\n * const onMouseUp = input.on(\"mouseup\", (canvasCoords) => {\r\n * console.log(\"Mouse up at: x=\" + canvasCoords[0] + \", y=\" + canvasCoords[1]);\r\n * });\r\n *\r\n * const onMouseClicked = input.on(\"mouseclicked\", (canvasCoords) => {\r\n * console.log(\"Mouse clicked at: x=\" + canvasCoords[0] + \", y=\" + canvasCoords[1]);\r\n * });\r\n *\r\n * const onDblClick = input.on(\"dblclick\", (canvasCoords) => {\r\n * console.log(\"Double-click at: x=\" + canvasCoords[0] + \", y=\" + canvasCoords[1]);\r\n * });\r\n * ````\r\n *\r\n * Subscribing to keyboard events on the canvas:\r\n *\r\n * ````javascript\r\n * const onKeyDown = input.on(\"keydown\", (keyCode) => {\r\n * switch (keyCode) {\r\n * case this.KEY_A:\r\n * console.log(\"The 'A' key is down\");\r\n * break;\r\n *\r\n * case this.KEY_B:\r\n * console.log(\"The 'B' key is down\");\r\n * break;\r\n *\r\n * case this.KEY_C:\r\n * console.log(\"The 'C' key is down\");\r\n * break;\r\n *\r\n * default:\r\n * console.log(\"Some other key is down\");\r\n * }\r\n * });\r\n *\r\n * const onKeyUp = input.on(\"keyup\", (keyCode) => {\r\n * switch (keyCode) {\r\n * case this.KEY_A:\r\n * console.log(\"The 'A' key is up\");\r\n * break;\r\n *\r\n * case this.KEY_B:\r\n * console.log(\"The 'B' key is up\");\r\n * break;\r\n *\r\n * case this.KEY_C:\r\n * console.log(\"The 'C' key is up\");\r\n * break;\r\n *\r\n * default:\r\n * console.log(\"Some other key is up\");\r\n * }\r\n * });\r\n * ````\r\n *\r\n * Checking if keys are down:\r\n *\r\n * ````javascript\r\n * const isCtrlDown = input.ctrlDown;\r\n * const isAltDown = input.altDown;\r\n * const shiftDown = input.shiftDown;\r\n * //...\r\n *\r\n * const isAKeyDown = input.keyDown[input.KEY_A];\r\n * const isBKeyDown = input.keyDown[input.KEY_B];\r\n * const isShiftKeyDown = input.keyDown[input.KEY_SHIFT];\r\n * //...\r\n *\r\n * ````\r\n * Unsubscribing from events:\r\n *\r\n * ````javascript\r\n * input.off(onMouseDown);\r\n * input.off(onMouseUp);\r\n * //...\r\n * ````\r\n *\r\n * ## Disabling all events\r\n *\r\n * Event handling is enabled by default.\r\n *\r\n * To disable all events:\r\n *\r\n * ````javascript\r\n * myViewer.scene.input.setEnabled(false);\r\n * ````\r\n * To enable all events again:\r\n *\r\n * ````javascript\r\n * myViewer.scene.input.setEnabled(true);\r\n * ````\r\n *\r\n * ## Disabling keyboard input\r\n *\r\n * When the mouse is over the canvas, the canvas will consume keyboard events. Therefore, sometimes we need\r\n * to disable keyboard control, so that other UI elements can get those events.\r\n *\r\n * To disable keyboard events:\r\n *\r\n * ````javascript\r\n * myViewer.scene.input.setKeyboardEnabled(false);\r\n * ````\r\n *\r\n * To enable keyboard events again:\r\n *\r\n * ````javascript\r\n * myViewer.scene.input.setKeyboardEnabled(true)\r\n * ````\r\n */\r\nclass Input extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tconstructor(owner, cfg = {}) {\r\n\t\tsuper(owner, cfg);\r\n\r\n\t\t/**\r\n\t\t * Code for the BACKSPACE key.\r\n\t\t * @property KEY_BACKSPACE\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_BACKSPACE = 8;\r\n\r\n\t\t/**\r\n\t\t * Code for the TAB key.\r\n\t\t * @property KEY_TAB\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_TAB = 9;\r\n\r\n\t\t/**\r\n\t\t * Code for the ENTER key.\r\n\t\t * @property KEY_ENTER\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_ENTER = 13;\r\n\r\n\t\t/**\r\n\t\t * Code for the SHIFT key.\r\n\t\t * @property KEY_SHIFT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SHIFT = 16;\r\n\r\n\t\t/**\r\n\t\t * Code for the CTRL key.\r\n\t\t * @property KEY_CTRL\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_CTRL = 17;\r\n\r\n\t\t/**\r\n\t\t * Code for the ALT key.\r\n\t\t * @property KEY_ALT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_ALT = 18;\r\n\r\n\t\t/**\r\n\t\t * Code for the PAUSE_BREAK key.\r\n\t\t * @property KEY_PAUSE_BREAK\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_PAUSE_BREAK = 19;\r\n\r\n\t\t/**\r\n\t\t * Code for the CAPS_LOCK key.\r\n\t\t * @property KEY_CAPS_LOCK\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_CAPS_LOCK = 20;\r\n\r\n\t\t/**\r\n\t\t * Code for the ESCAPE key.\r\n\t\t * @property KEY_ESCAPE\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_ESCAPE = 27;\r\n\r\n\t\t/**\r\n\t\t * Code for the PAGE_UP key.\r\n\t\t * @property KEY_PAGE_UP\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_PAGE_UP = 33;\r\n\r\n\t\t/**\r\n\t\t * Code for the PAGE_DOWN key.\r\n\t\t * @property KEY_PAGE_DOWN\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_PAGE_DOWN = 34;\r\n\r\n\t\t/**\r\n\t\t * Code for the END key.\r\n\t\t * @property KEY_END\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_END = 35;\r\n\r\n\t\t/**\r\n\t\t * Code for the HOME key.\r\n\t\t * @property KEY_HOME\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_HOME = 36;\r\n\r\n\t\t/**\r\n\t\t * Code for the LEFT_ARROW key.\r\n\t\t * @property KEY_LEFT_ARROW\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_LEFT_ARROW = 37;\r\n\r\n\t\t/**\r\n\t\t * Code for the UP_ARROW key.\r\n\t\t * @property KEY_UP_ARROW\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_UP_ARROW = 38;\r\n\r\n\t\t/**\r\n\t\t * Code for the RIGHT_ARROW key.\r\n\t\t * @property KEY_RIGHT_ARROW\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_RIGHT_ARROW = 39;\r\n\r\n\t\t/**\r\n\t\t * Code for the DOWN_ARROW key.\r\n\t\t * @property KEY_DOWN_ARROW\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_DOWN_ARROW = 40;\r\n\r\n\t\t/**\r\n\t\t * Code for the INSERT key.\r\n\t\t * @property KEY_INSERT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_INSERT = 45;\r\n\r\n\t\t/**\r\n\t\t * Code for the DELETE key.\r\n\t\t * @property KEY_DELETE\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_DELETE = 46;\r\n\r\n\t\t/**\r\n\t\t * Code for the 0 key.\r\n\t\t * @property KEY_NUM_0\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_0 = 48;\r\n\r\n\t\t/**\r\n\t\t * Code for the 1 key.\r\n\t\t * @property KEY_NUM_1\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_1 = 49;\r\n\r\n\t\t/**\r\n\t\t * Code for the 2 key.\r\n\t\t * @property KEY_NUM_2\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_2 = 50;\r\n\r\n\t\t/**\r\n\t\t * Code for the 3 key.\r\n\t\t * @property KEY_NUM_3\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_3 = 51;\r\n\r\n\t\t/**\r\n\t\t * Code for the 4 key.\r\n\t\t * @property KEY_NUM_4\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_4 = 52;\r\n\r\n\t\t/**\r\n\t\t * Code for the 5 key.\r\n\t\t * @property KEY_NUM_5\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_5 = 53;\r\n\r\n\t\t/**\r\n\t\t * Code for the 6 key.\r\n\t\t * @property KEY_NUM_6\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_6 = 54;\r\n\r\n\t\t/**\r\n\t\t * Code for the 7 key.\r\n\t\t * @property KEY_NUM_7\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_7 = 55;\r\n\r\n\t\t/**\r\n\t\t * Code for the 8 key.\r\n\t\t * @property KEY_NUM_8\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_8 = 56;\r\n\r\n\t\t/**\r\n\t\t * Code for the 9 key.\r\n\t\t * @property KEY_NUM_9\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_9 = 57;\r\n\r\n\t\t/**\r\n\t\t * Code for the A key.\r\n\t\t * @property KEY_A\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_A = 65;\r\n\r\n\t\t/**\r\n\t\t * Code for the B key.\r\n\t\t * @property KEY_B\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_B = 66;\r\n\r\n\t\t/**\r\n\t\t * Code for the C key.\r\n\t\t * @property KEY_C\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_C = 67;\r\n\r\n\t\t/**\r\n\t\t * Code for the D key.\r\n\t\t * @property KEY_D\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_D = 68;\r\n\r\n\t\t/**\r\n\t\t * Code for the E key.\r\n\t\t * @property KEY_E\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_E = 69;\r\n\r\n\t\t/**\r\n\t\t * Code for the F key.\r\n\t\t * @property KEY_F\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F = 70;\r\n\r\n\t\t/**\r\n\t\t * Code for the G key.\r\n\t\t * @property KEY_G\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_G = 71;\r\n\r\n\t\t/**\r\n\t\t * Code for the H key.\r\n\t\t * @property KEY_H\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_H = 72;\r\n\r\n\t\t/**\r\n\t\t * Code for the I key.\r\n\t\t * @property KEY_I\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_I = 73;\r\n\r\n\t\t/**\r\n\t\t * Code for the J key.\r\n\t\t * @property KEY_J\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_J = 74;\r\n\r\n\t\t/**\r\n\t\t * Code for the K key.\r\n\t\t * @property KEY_K\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_K = 75;\r\n\r\n\t\t/**\r\n\t\t * Code for the L key.\r\n\t\t * @property KEY_L\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_L = 76;\r\n\r\n\t\t/**\r\n\t\t * Code for the M key.\r\n\t\t * @property KEY_M\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_M = 77;\r\n\r\n\t\t/**\r\n\t\t * Code for the N key.\r\n\t\t * @property KEY_N\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_N = 78;\r\n\r\n\t\t/**\r\n\t\t * Code for the O key.\r\n\t\t * @property KEY_O\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_O = 79;\r\n\r\n\t\t/**\r\n\t\t * Code for the P key.\r\n\t\t * @property KEY_P\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_P = 80;\r\n\r\n\t\t/**\r\n\t\t * Code for the Q key.\r\n\t\t * @property KEY_Q\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_Q = 81;\r\n\r\n\t\t/**\r\n\t\t * Code for the R key.\r\n\t\t * @property KEY_R\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_R = 82;\r\n\r\n\t\t/**\r\n\t\t * Code for the S key.\r\n\t\t * @property KEY_S\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_S = 83;\r\n\r\n\t\t/**\r\n\t\t * Code for the T key.\r\n\t\t * @property KEY_T\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_T = 84;\r\n\r\n\t\t/**\r\n\t\t * Code for the U key.\r\n\t\t * @property KEY_U\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_U = 85;\r\n\r\n\t\t/**\r\n\t\t * Code for the V key.\r\n\t\t * @property KEY_V\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_V = 86;\r\n\r\n\t\t/**\r\n\t\t * Code for the W key.\r\n\t\t * @property KEY_W\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_W = 87;\r\n\r\n\t\t/**\r\n\t\t * Code for the X key.\r\n\t\t * @property KEY_X\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_X = 88;\r\n\r\n\t\t/**\r\n\t\t * Code for the Y key.\r\n\t\t * @property KEY_Y\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_Y = 89;\r\n\r\n\t\t/**\r\n\t\t * Code for the Z key.\r\n\t\t * @property KEY_Z\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_Z = 90;\r\n\r\n\t\t/**\r\n\t\t * Code for the LEFT_WINDOW key.\r\n\t\t * @property KEY_LEFT_WINDOW\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_LEFT_WINDOW = 91;\r\n\r\n\t\t/**\r\n\t\t * Code for the RIGHT_WINDOW key.\r\n\t\t * @property KEY_RIGHT_WINDOW\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_RIGHT_WINDOW = 92;\r\n\r\n\t\t/**\r\n\t\t * Code for the SELECT key.\r\n\t\t * @property KEY_SELECT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SELECT_KEY = 93;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 0 key.\r\n\t\t * @property KEY_NUMPAD_0\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_0 = 96;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 1 key.\r\n\t\t * @property KEY_NUMPAD_1\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_1 = 97;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 2 key.\r\n\t\t * @property KEY_NUMPAD 2\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_2 = 98;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 3 key.\r\n\t\t * @property KEY_NUMPAD_3\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_3 = 99;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 4 key.\r\n\t\t * @property KEY_NUMPAD_4\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_4 = 100;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 5 key.\r\n\t\t * @property KEY_NUMPAD_5\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_5 = 101;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 6 key.\r\n\t\t * @property KEY_NUMPAD_6\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_6 = 102;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 7 key.\r\n\t\t * @property KEY_NUMPAD_7\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_7 = 103;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 8 key.\r\n\t\t * @property KEY_NUMPAD_8\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_8 = 104;\r\n\r\n\t\t/**\r\n\t\t * Code for the number pad 9 key.\r\n\t\t * @property KEY_NUMPAD_9\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUMPAD_9 = 105;\r\n\r\n\t\t/**\r\n\t\t * Code for the MULTIPLY key.\r\n\t\t * @property KEY_MULTIPLY\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_MULTIPLY = 106;\r\n\r\n\t\t/**\r\n\t\t * Code for the ADD key.\r\n\t\t * @property KEY_ADD\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_ADD = 107;\r\n\r\n\t\t/**\r\n\t\t * Code for the SUBTRACT key.\r\n\t\t * @property KEY_SUBTRACT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SUBTRACT = 109;\r\n\r\n\t\t/**\r\n\t\t * Code for the DECIMAL POINT key.\r\n\t\t * @property KEY_DECIMAL_POINT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_DECIMAL_POINT = 110;\r\n\r\n\t\t/**\r\n\t\t * Code for the DIVIDE key.\r\n\t\t * @property KEY_DIVIDE\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_DIVIDE = 111;\r\n\r\n\t\t/**\r\n\t\t * Code for the F1 key.\r\n\t\t * @property KEY_F1\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F1 = 112;\r\n\r\n\t\t/**\r\n\t\t * Code for the F2 key.\r\n\t\t * @property KEY_F2\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F2 = 113;\r\n\r\n\t\t/**\r\n\t\t * Code for the F3 key.\r\n\t\t * @property KEY_F3\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F3 = 114;\r\n\r\n\t\t/**\r\n\t\t * Code for the F4 key.\r\n\t\t * @property KEY_F4\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F4 = 115;\r\n\r\n\t\t/**\r\n\t\t * Code for the F5 key.\r\n\t\t * @property KEY_F5\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F5 = 116;\r\n\r\n\t\t/**\r\n\t\t * Code for the F6 key.\r\n\t\t * @property KEY_F6\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F6 = 117;\r\n\r\n\t\t/**\r\n\t\t * Code for the F7 key.\r\n\t\t * @property KEY_F7\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F7 = 118;\r\n\r\n\t\t/**\r\n\t\t * Code for the F8 key.\r\n\t\t * @property KEY_F8\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F8 = 119;\r\n\r\n\t\t/**\r\n\t\t * Code for the F9 key.\r\n\t\t * @property KEY_F9\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F9 = 120;\r\n\r\n\t\t/**\r\n\t\t * Code for the F10 key.\r\n\t\t * @property KEY_F10\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F10 = 121;\r\n\r\n\t\t/**\r\n\t\t * Code for the F11 key.\r\n\t\t * @property KEY_F11\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F11 = 122;\r\n\r\n\t\t/**\r\n\t\t * Code for the F12 key.\r\n\t\t * @property KEY_F12\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_F12 = 123;\r\n\r\n\t\t/**\r\n\t\t * Code for the NUM_LOCK key.\r\n\t\t * @property KEY_NUM_LOCK\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_NUM_LOCK = 144;\r\n\r\n\t\t/**\r\n\t\t * Code for the SCROLL_LOCK key.\r\n\t\t * @property KEY_SCROLL_LOCK\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SCROLL_LOCK = 145;\r\n\r\n\t\t/**\r\n\t\t * Code for the SEMI_COLON key.\r\n\t\t * @property KEY_SEMI_COLON\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SEMI_COLON = 186;\r\n\r\n\t\t/**\r\n\t\t * Code for the EQUAL_SIGN key.\r\n\t\t * @property KEY_EQUAL_SIGN\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_EQUAL_SIGN = 187;\r\n\r\n\t\t/**\r\n\t\t * Code for the COMMA key.\r\n\t\t * @property KEY_COMMA\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_COMMA = 188;\r\n\r\n\t\t/**\r\n\t\t * Code for the DASH key.\r\n\t\t * @property KEY_DASH\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_DASH = 189;\r\n\r\n\t\t/**\r\n\t\t * Code for the PERIOD key.\r\n\t\t * @property KEY_PERIOD\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_PERIOD = 190;\r\n\r\n\t\t/**\r\n\t\t * Code for the FORWARD_SLASH key.\r\n\t\t * @property KEY_FORWARD_SLASH\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_FORWARD_SLASH = 191;\r\n\r\n\t\t/**\r\n\t\t * Code for the GRAVE_ACCENT key.\r\n\t\t * @property KEY_GRAVE_ACCENT\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_GRAVE_ACCENT = 192;\r\n\r\n\t\t/**\r\n\t\t * Code for the OPEN_BRACKET key.\r\n\t\t * @property KEY_OPEN_BRACKET\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_OPEN_BRACKET = 219;\r\n\r\n\t\t/**\r\n\t\t * Code for the BACK_SLASH key.\r\n\t\t * @property KEY_BACK_SLASH\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_BACK_SLASH = 220;\r\n\r\n\t\t/**\r\n\t\t * Code for the CLOSE_BRACKET key.\r\n\t\t * @property KEY_CLOSE_BRACKET\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_CLOSE_BRACKET = 221;\r\n\r\n\t\t/**\r\n\t\t * Code for the SINGLE_QUOTE key.\r\n\t\t * @property KEY_SINGLE_QUOTE\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SINGLE_QUOTE = 222;\r\n\r\n\t\t/**\r\n\t\t * Code for the SPACE key.\r\n\t\t * @property KEY_SPACE\r\n\t\t * @final\r\n\t\t * @type {Number}\r\n\t\t */\r\n\t\tthis.KEY_SPACE = 32;\r\n\r\n\t\t/**\r\n\t\t * The canvas element that mouse and keyboards are bound to.\r\n\t\t *\r\n\t\t * @final\r\n\t\t * @type {HTMLCanvasElement}\r\n\t\t */\r\n\t\tthis.element = cfg.element;\r\n\r\n\t\t/** True whenever ALT key is down.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.altDown = false;\r\n\r\n\t\t/** True whenever CTRL key is down.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.ctrlDown = false;\r\n\r\n\t\t/** True whenever left mouse button is down.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.mouseDownLeft = false;\r\n\r\n\t\t/**\r\n\t\t * True whenever middle mouse button is down.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.mouseDownMiddle = false;\r\n\r\n\t\t/**\r\n\t\t * True whenever the right mouse button is down.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.mouseDownRight = false;\r\n\r\n\t\t/**\r\n\t\t * Flag for each key that's down.\r\n\t\t *\r\n\t\t * @type {boolean[]}\r\n\t\t */\r\n\t\tthis.keyDown = [];\r\n\r\n\t\t/** True while input enabled\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.enabled = true;\r\n\r\n\t\t/** True while keyboard input is enabled.\r\n\t\t *\r\n\t\t * Default value is ````true````.\r\n\t\t *\r\n\t\t * {@link CameraControl} will not respond to keyboard events while this is ````false````.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.keyboardEnabled = true;\r\n\r\n\t\t/** True while the mouse is over the canvas.\r\n\t\t *\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.mouseover = false;\r\n\r\n\t\t/**\r\n\t\t * Current mouse position within the canvas.\r\n\t\t * @type {Number[]}\r\n\t\t */\r\n\t\tthis.mouseCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec2();\r\n\t\tthis.touchCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec2();\r\n\r\n\t\tthis._keyboardEventsElement = cfg.keyboardEventsElement || document;\r\n\r\n\t\tthis._bindEvents();\r\n\t}\r\n\r\n\t_bindEvents() {\r\n\t\tif (this._eventsBound) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t//keydown\r\n\t\tthis._keyboardEventsElement.addEventListener(\r\n\t\t\t\"keydown\",\r\n\t\t\t(this._keyDownListener = (e) => {\r\n\t\t\t\tif (!this.enabled || !this.keyboardEnabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (e.target.tagName !== \"INPUT\" && e.target.tagName !== \"TEXTAREA\") {\r\n\t\t\t\t\tif (e.keyCode === this.KEY_CTRL) {\r\n\t\t\t\t\t\tthis.ctrlDown = true;\r\n\t\t\t\t\t} else if (e.keyCode === this.KEY_ALT) {\r\n\t\t\t\t\t\tthis.altDown = true;\r\n\t\t\t\t\t} else if (e.keyCode === this.KEY_SHIFT) {\r\n\t\t\t\t\t\tthis.shiftDown = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.keyDown[e.keyCode] = true;\r\n\t\t\t\t\tthis.fire(\"keydown\", e.keyCode, true);\r\n\t\t\t\t}\r\n\t\t\t}),\r\n\t\t\tfalse\r\n\t\t);\r\n\t\t//keyup\r\n\t\tthis._keyboardEventsElement.addEventListener(\r\n\t\t\t\"keyup\",\r\n\t\t\t(this._keyUpListener = (e) => {\r\n\t\t\t\tif (!this.enabled || !this.keyboardEnabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (e.target.tagName !== \"INPUT\" && e.target.tagName !== \"TEXTAREA\") {\r\n\t\t\t\t\tif (e.keyCode === this.KEY_CTRL) {\r\n\t\t\t\t\t\tthis.ctrlDown = false;\r\n\t\t\t\t\t} else if (e.keyCode === this.KEY_ALT) {\r\n\t\t\t\t\t\tthis.altDown = false;\r\n\t\t\t\t\t} else if (e.keyCode === this.KEY_SHIFT) {\r\n\t\t\t\t\t\tthis.shiftDown = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.keyDown[e.keyCode] = false;\r\n\t\t\t\t\tthis.fire(\"keyup\", e.keyCode, true);\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t\t//mouseenter\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"mouseenter\",\r\n\t\t\t(this._mouseEnterListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis.mouseover = true;\r\n\t\t\t\tthis._getMouseCanvasPos(e);\r\n\t\t\t\tthis.fire(\"mouseenter\", this.mouseCanvasPos, true);\r\n\t\t\t})\r\n\t\t);\r\n\t\t//mouseleave\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"mouseleave\",\r\n\t\t\t(this._mouseLeaveListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis.mouseover = false;\r\n\t\t\t\tthis._getMouseCanvasPos(e);\r\n\t\t\t\tthis.fire(\"mouseleave\", this.mouseCanvasPos, true);\r\n\t\t\t})\r\n\t\t);\r\n\t\t//click\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"click\",\r\n\t\t\t(this._clickListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\tthis.mouseDownLeft = false;\r\n\t\t\t\t\t\tthis.mouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\tthis.mouseDownMiddle = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tthis.mouseDownLeft = false;\r\n\t\t\t\t\t\tthis.mouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tif (\"touches\" in e) {\r\n\t\t\t\t\tthis._getTouchCanvasPos(e);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._getMouseCanvasPos(e);\r\n\t\t\t\t}\r\n\t\t\t\tthis.fire(\"click\", this.mouseCanvasPos, true);\r\n\t\t\t\tif (this.mouseover) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t\t//dblclick\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"dblclick\",\r\n\t\t\t(this._dblClickListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\tthis.mouseDownLeft = false;\r\n\t\t\t\t\t\tthis.mouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\tthis.mouseDownMiddle = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tthis.mouseDownLeft = false;\r\n\t\t\t\t\t\tthis.mouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tif (\"touches\" in e) {\r\n\t\t\t\t\tthis._getTouchCanvasPos(e);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._getMouseCanvasPos(e);\r\n\t\t\t\t}\r\n\t\t\t\tthis.fire(\"dblclick\", this.mouseCanvasPos, true);\r\n\t\t\t\tif (this.mouseover) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t\tconst tickifedMouseMoveFn = this.scene.tickify(() => this.fire(\"mousemove\", this.mouseCanvasPos, true));\r\n\t\tconst tickifedTouchMoveFn = this.scene.tickify(() => this.fire(\"touchmove\", this.touchCanvasPos, true));\r\n\t\t//mousemove\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"mousemove\",\r\n\t\t\t(this._mouseMoveListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis._getMouseCanvasPos(e);\r\n\t\t\t\ttickifedMouseMoveFn();\r\n\t\t\t\tif (this.mouseover) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t\tconst tickifiedMouseWheelFn = this.scene.tickify((delta) => {\r\n\t\t\tthis.fire(\"mousewheel\", delta, true);\r\n\t\t});\r\n\t\t//wheel\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"wheel\",\r\n\t\t\t(this._mouseWheelListener = (e, d) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tconst delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\r\n\t\t\t\ttickifiedMouseWheelFn(delta);\r\n\t\t\t}),\r\n\t\t\t{ passive: true }\r\n\t\t);\r\n\t\t//mousedown\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"mousedown\",\r\n\t\t\t(this._mouseDownListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\tthis.mouseDownLeft = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\tthis.mouseDownMiddle = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tthis.mouseDownRight = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tthis._getMouseCanvasPos(e);\r\n\t\t\t\tthis.element.focus();\r\n\t\t\t\tthis.fire(\"mousedown\", this.mouseCanvasPos, true);\r\n\t\t\t\tif (this.mouseover) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t\t//mouseup\r\n\t\tdocument.addEventListener(\r\n\t\t\t\"mouseup\",\r\n\t\t\t(this._mouseUpListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tswitch (e.which) {\r\n\t\t\t\t\tcase 1: // Left button\r\n\t\t\t\t\t\tthis.mouseDownLeft = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2: // Middle/both buttons\r\n\t\t\t\t\t\tthis.mouseDownMiddle = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3: // Right button\r\n\t\t\t\t\t\tthis.mouseDownRight = false;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tthis.fire(\"mouseup\", this.mouseCanvasPos, true);\r\n\t\t\t\tif (this.mouseover) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t}),\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t//touchstart\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"touchstart\",\r\n\t\t\t(this._touchDownListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tif (!e.isTrusted) return;\r\n\t\t\t\tif (e.touches.length == 1) {\r\n\t\t\t\t\tthis.touchDown = true;\r\n\t\t\t\t}\r\n\t\t\t\tthis._getTouchCanvasPos(e);\r\n\t\t\t\tthis.element.focus();\r\n\t\t\t\tthis.fire(\"touchstart\", this.mouseCanvasPos, true);\r\n\t\t\t\tif (this.mouseover) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\t\t//touchend\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"touchend\",\r\n\t\t\t(this._touchUpListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis.touchDown = false;\r\n\t\t\t\tthis.fire(\"touchend\", this.mouseCanvasPos, true);\r\n\t\t\t}),\r\n\t\t\ttrue\r\n\t\t);\r\n\t\t//touchcancel\r\n\t\tthis.element.addEventListener(\"touchcancel\", this._touchUpListener, true);\r\n\t\t//touchmove\r\n\t\tthis.element.addEventListener(\r\n\t\t\t\"touchmove\",\r\n\t\t\t(this._touchMoveListener = (e) => {\r\n\t\t\t\tif (!this.enabled) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis._getTouchCanvasPos(e);\r\n\t\t\t\t// tickifedTouchMoveFn();\r\n\t\t\t\ttickifedMouseMoveFn();\r\n\t\t\t})\r\n\t\t);\r\n\t\t// mouseclicked / touch\r\n\t\t{\r\n\t\t\tlet downX;\r\n\t\t\tlet downY;\r\n\t\t\t// Tolerance between down and up positions for a mouse click\r\n\t\t\tconst tolerance = 2;\r\n\t\t\tthis.on(\"mousedown\", (params) => {\r\n\t\t\t\tdownX = params[0];\r\n\t\t\t\tdownY = params[1];\r\n\t\t\t});\r\n\t\t\tthis.on(\"mouseup\", (params) => {\r\n\t\t\t\tif (\r\n\t\t\t\t\tdownX >= params[0] - tolerance &&\r\n\t\t\t\t\tdownX <= params[0] + tolerance &&\r\n\t\t\t\t\tdownY >= params[1] - tolerance &&\r\n\t\t\t\t\tdownY <= params[1] + tolerance\r\n\t\t\t\t) {\r\n\t\t\t\t\tthis.fire(\"mouseclicked\", params, true);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tthis.on(\"touchstart\", (params) => {\r\n\t\t\t\tdownX = params[0];\r\n\t\t\t\tdownY = params[1];\r\n\t\t\t});\r\n\t\t\tthis.on(\"touchend\", (params) => {\r\n\t\t\t\tif (\r\n\t\t\t\t\tdownX >= params[0] - tolerance &&\r\n\t\t\t\t\tdownX <= params[0] + tolerance &&\r\n\t\t\t\t\tdownY >= params[1] - tolerance &&\r\n\t\t\t\t\tdownY <= params[1] + tolerance\r\n\t\t\t\t) {\r\n\t\t\t\t\tthis.fire(\"touchclicked\", params, true);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tthis._eventsBound = true;\r\n\t}\r\n\r\n\t_unbindEvents() {\r\n\t\tif (!this._eventsBound) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._keyboardEventsElement.removeEventListener(\"keydown\", this._keyDownListener);\r\n\t\tthis._keyboardEventsElement.removeEventListener(\"keyup\", this._keyUpListener);\r\n\t\tthis.element.removeEventListener(\"mouseenter\", this._mouseEnterListener);\r\n\t\tthis.element.removeEventListener(\"mouseleave\", this._mouseLeaveListener);\r\n\t\tthis.element.removeEventListener(\"mousedown\", this._mouseDownListener);\r\n\t\tdocument.removeEventListener(\"mouseup\", this._mouseDownListener);\r\n\t\tdocument.removeEventListener(\"click\", this._clickListener);\r\n\t\tdocument.removeEventListener(\"dblclick\", this._dblClickListener);\r\n\t\tthis.element.removeEventListener(\"mousemove\", this._mouseMoveListener);\r\n\t\tthis.element.removeEventListener(\"wheel\", this._mouseWheelListener);\r\n\r\n\t\tthis.element.removeEventListener(\"touchstart\", this._touchDownListener);\r\n\t\tdocument.removeEventListener(\"touchend\", this._touchUpListener);\r\n\t\tdocument.removeEventListener(\"touchcancel\", this._touchUpListener);\r\n\t\tthis.element.removeEventListener(\"touchmove\", this._touchMoveListener);\r\n\r\n\t\tif (window.OrientationChangeEvent) {\r\n\t\t\twindow.removeEventListener(\"orientationchange\", this._orientationchangedListener);\r\n\t\t}\r\n\t\tif (window.DeviceMotionEvent) {\r\n\t\t\twindow.removeEventListener(\"devicemotion\", this._deviceMotionListener);\r\n\t\t}\r\n\t\tif (window.DeviceOrientationEvent) {\r\n\t\t\twindow.removeEventListener(\"deviceorientation\", this._deviceOrientListener);\r\n\t\t}\r\n\t\tthis._eventsBound = false;\r\n\t}\r\n\r\n\t_getMouseCanvasPos(event) {\r\n\t\tif (!event) {\r\n\t\t\tevent = window.event;\r\n\t\t\tthis.mouseCanvasPos[0] = event.x;\r\n\t\t\tthis.mouseCanvasPos[1] = event.y;\r\n\t\t} else {\r\n\t\t\tlet element = event.target;\r\n\t\t\tlet totalOffsetLeft = 0;\r\n\t\t\tlet totalOffsetTop = 0;\r\n\t\t\twhile (element.offsetParent) {\r\n\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\telement = element.offsetParent;\r\n\t\t\t}\r\n\t\t\tthis.mouseCanvasPos[0] = event.pageX - totalOffsetLeft;\r\n\t\t\tthis.mouseCanvasPos[1] = event.pageY - totalOffsetTop;\r\n\t\t}\r\n\t}\r\n\r\n\t_getTouchCanvasPos(event) {\r\n\t\tif (!event || !event.touches || event.touches.length === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst touch = event.touches[0]; // 获取第一个触摸点的信息\r\n\r\n\t\tlet element = event.target;\r\n\t\tlet totalOffsetLeft = 0;\r\n\t\tlet totalOffsetTop = 0;\r\n\t\twhile (element.offsetParent) {\r\n\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\telement = element.offsetParent;\r\n\t\t}\r\n\r\n\t\tthis.mouseCanvasPos[0] = touch.pageX - totalOffsetLeft;\r\n\t\tthis.mouseCanvasPos[1] = touch.pageY - totalOffsetTop;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether input handlers are enabled.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @param {Boolean} enable Indicates if input handlers are enabled.\r\n\t */\r\n\tsetEnabled(enable) {\r\n\t\tif (this.enabled !== enable) {\r\n\t\t\tthis.fire(\"enabled\", (this.enabled = enable));\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether input handlers are enabled.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @returns {Boolean} Indicates if input handlers are enabled.\r\n\t */\r\n\tgetEnabled() {\r\n\t\treturn this.enabled;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether or not keyboard input is enabled.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * {@link CameraControl} will not respond to keyboard events while this is set ````false````.\r\n\t *\r\n\t * @param {Boolean} value Indicates whether keyboard input is enabled.\r\n\t */\r\n\tsetKeyboardEnabled(value) {\r\n\t\tthis.keyboardEnabled = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether keyboard input is enabled.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * {@link CameraControl} will not respond to keyboard events while this is set ````false````.\r\n\t *\r\n\t * @returns {Boolean} Returns whether keyboard input is enabled.\r\n\t */\r\n\tgetKeyboardEnabled() {\r\n\t\treturn this.keyboardEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tdestroy() {\r\n\t\tsuper.destroy();\r\n\t\tthis._unbindEvents();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/input/Input.js?");
|
|
2947
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Input: () => (/* binding */ Input)\n/* harmony export */ });\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n\n\n\n/**\n * @desc Meditates mouse, touch and keyboard events for various interaction controls.\n *\n * Ordinarily, you would only use this component as a utility to help manage input events and state for your\n * own custom input handlers.\n *\n * * Located at {@link Scene#input}\n * * Used by (at least) {@link CameraControl}\n *\n * ## Usage\n *\n * Subscribing to mouse events on the canvas:\n *\n * ````javascript\n * import {Viewer} from \"xeokit-sdk.es.js\";\n *\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\"\n * });\n *\n * const input = viewer.scene.input;\n *\n * const onMouseDown = input.on(\"mousedown\", (canvasCoords) => {\n * console.log(\"Mouse down at: x=\" + canvasCoords[0] + \", y=\" + coords[1]);\n * });\n *\n * const onMouseUp = input.on(\"mouseup\", (canvasCoords) => {\n * console.log(\"Mouse up at: x=\" + canvasCoords[0] + \", y=\" + canvasCoords[1]);\n * });\n *\n * const onMouseClicked = input.on(\"mouseclicked\", (canvasCoords) => {\n * console.log(\"Mouse clicked at: x=\" + canvasCoords[0] + \", y=\" + canvasCoords[1]);\n * });\n *\n * const onDblClick = input.on(\"dblclick\", (canvasCoords) => {\n * console.log(\"Double-click at: x=\" + canvasCoords[0] + \", y=\" + canvasCoords[1]);\n * });\n * ````\n *\n * Subscribing to keyboard events on the canvas:\n *\n * ````javascript\n * const onKeyDown = input.on(\"keydown\", (keyCode) => {\n * switch (keyCode) {\n * case this.KEY_A:\n * console.log(\"The 'A' key is down\");\n * break;\n *\n * case this.KEY_B:\n * console.log(\"The 'B' key is down\");\n * break;\n *\n * case this.KEY_C:\n * console.log(\"The 'C' key is down\");\n * break;\n *\n * default:\n * console.log(\"Some other key is down\");\n * }\n * });\n *\n * const onKeyUp = input.on(\"keyup\", (keyCode) => {\n * switch (keyCode) {\n * case this.KEY_A:\n * console.log(\"The 'A' key is up\");\n * break;\n *\n * case this.KEY_B:\n * console.log(\"The 'B' key is up\");\n * break;\n *\n * case this.KEY_C:\n * console.log(\"The 'C' key is up\");\n * break;\n *\n * default:\n * console.log(\"Some other key is up\");\n * }\n * });\n * ````\n *\n * Checking if keys are down:\n *\n * ````javascript\n * const isCtrlDown = input.ctrlDown;\n * const isAltDown = input.altDown;\n * const shiftDown = input.shiftDown;\n * //...\n *\n * const isAKeyDown = input.keyDown[input.KEY_A];\n * const isBKeyDown = input.keyDown[input.KEY_B];\n * const isShiftKeyDown = input.keyDown[input.KEY_SHIFT];\n * //...\n *\n * ````\n * Unsubscribing from events:\n *\n * ````javascript\n * input.off(onMouseDown);\n * input.off(onMouseUp);\n * //...\n * ````\n *\n * ## Disabling all events\n *\n * Event handling is enabled by default.\n *\n * To disable all events:\n *\n * ````javascript\n * myViewer.scene.input.setEnabled(false);\n * ````\n * To enable all events again:\n *\n * ````javascript\n * myViewer.scene.input.setEnabled(true);\n * ````\n *\n * ## Disabling keyboard input\n *\n * When the mouse is over the canvas, the canvas will consume keyboard events. Therefore, sometimes we need\n * to disable keyboard control, so that other UI elements can get those events.\n *\n * To disable keyboard events:\n *\n * ````javascript\n * myViewer.scene.input.setKeyboardEnabled(false);\n * ````\n *\n * To enable keyboard events again:\n *\n * ````javascript\n * myViewer.scene.input.setKeyboardEnabled(true)\n * ````\n */\nclass Input extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\n\t/**\n\t * @private\n\t */\n\tconstructor(owner, cfg = {}) {\n\t\tsuper(owner, cfg);\n\n\t\t/**\n\t\t * Code for the BACKSPACE key.\n\t\t * @property KEY_BACKSPACE\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_BACKSPACE = 8;\n\n\t\t/**\n\t\t * Code for the TAB key.\n\t\t * @property KEY_TAB\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_TAB = 9;\n\n\t\t/**\n\t\t * Code for the ENTER key.\n\t\t * @property KEY_ENTER\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_ENTER = 13;\n\n\t\t/**\n\t\t * Code for the SHIFT key.\n\t\t * @property KEY_SHIFT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SHIFT = 16;\n\n\t\t/**\n\t\t * Code for the CTRL key.\n\t\t * @property KEY_CTRL\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_CTRL = 17;\n\n\t\t/**\n\t\t * Code for the ALT key.\n\t\t * @property KEY_ALT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_ALT = 18;\n\n\t\t/**\n\t\t * Code for the PAUSE_BREAK key.\n\t\t * @property KEY_PAUSE_BREAK\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_PAUSE_BREAK = 19;\n\n\t\t/**\n\t\t * Code for the CAPS_LOCK key.\n\t\t * @property KEY_CAPS_LOCK\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_CAPS_LOCK = 20;\n\n\t\t/**\n\t\t * Code for the ESCAPE key.\n\t\t * @property KEY_ESCAPE\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_ESCAPE = 27;\n\n\t\t/**\n\t\t * Code for the PAGE_UP key.\n\t\t * @property KEY_PAGE_UP\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_PAGE_UP = 33;\n\n\t\t/**\n\t\t * Code for the PAGE_DOWN key.\n\t\t * @property KEY_PAGE_DOWN\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_PAGE_DOWN = 34;\n\n\t\t/**\n\t\t * Code for the END key.\n\t\t * @property KEY_END\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_END = 35;\n\n\t\t/**\n\t\t * Code for the HOME key.\n\t\t * @property KEY_HOME\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_HOME = 36;\n\n\t\t/**\n\t\t * Code for the LEFT_ARROW key.\n\t\t * @property KEY_LEFT_ARROW\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_LEFT_ARROW = 37;\n\n\t\t/**\n\t\t * Code for the UP_ARROW key.\n\t\t * @property KEY_UP_ARROW\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_UP_ARROW = 38;\n\n\t\t/**\n\t\t * Code for the RIGHT_ARROW key.\n\t\t * @property KEY_RIGHT_ARROW\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_RIGHT_ARROW = 39;\n\n\t\t/**\n\t\t * Code for the DOWN_ARROW key.\n\t\t * @property KEY_DOWN_ARROW\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_DOWN_ARROW = 40;\n\n\t\t/**\n\t\t * Code for the INSERT key.\n\t\t * @property KEY_INSERT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_INSERT = 45;\n\n\t\t/**\n\t\t * Code for the DELETE key.\n\t\t * @property KEY_DELETE\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_DELETE = 46;\n\n\t\t/**\n\t\t * Code for the 0 key.\n\t\t * @property KEY_NUM_0\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_0 = 48;\n\n\t\t/**\n\t\t * Code for the 1 key.\n\t\t * @property KEY_NUM_1\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_1 = 49;\n\n\t\t/**\n\t\t * Code for the 2 key.\n\t\t * @property KEY_NUM_2\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_2 = 50;\n\n\t\t/**\n\t\t * Code for the 3 key.\n\t\t * @property KEY_NUM_3\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_3 = 51;\n\n\t\t/**\n\t\t * Code for the 4 key.\n\t\t * @property KEY_NUM_4\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_4 = 52;\n\n\t\t/**\n\t\t * Code for the 5 key.\n\t\t * @property KEY_NUM_5\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_5 = 53;\n\n\t\t/**\n\t\t * Code for the 6 key.\n\t\t * @property KEY_NUM_6\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_6 = 54;\n\n\t\t/**\n\t\t * Code for the 7 key.\n\t\t * @property KEY_NUM_7\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_7 = 55;\n\n\t\t/**\n\t\t * Code for the 8 key.\n\t\t * @property KEY_NUM_8\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_8 = 56;\n\n\t\t/**\n\t\t * Code for the 9 key.\n\t\t * @property KEY_NUM_9\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_9 = 57;\n\n\t\t/**\n\t\t * Code for the A key.\n\t\t * @property KEY_A\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_A = 65;\n\n\t\t/**\n\t\t * Code for the B key.\n\t\t * @property KEY_B\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_B = 66;\n\n\t\t/**\n\t\t * Code for the C key.\n\t\t * @property KEY_C\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_C = 67;\n\n\t\t/**\n\t\t * Code for the D key.\n\t\t * @property KEY_D\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_D = 68;\n\n\t\t/**\n\t\t * Code for the E key.\n\t\t * @property KEY_E\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_E = 69;\n\n\t\t/**\n\t\t * Code for the F key.\n\t\t * @property KEY_F\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F = 70;\n\n\t\t/**\n\t\t * Code for the G key.\n\t\t * @property KEY_G\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_G = 71;\n\n\t\t/**\n\t\t * Code for the H key.\n\t\t * @property KEY_H\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_H = 72;\n\n\t\t/**\n\t\t * Code for the I key.\n\t\t * @property KEY_I\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_I = 73;\n\n\t\t/**\n\t\t * Code for the J key.\n\t\t * @property KEY_J\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_J = 74;\n\n\t\t/**\n\t\t * Code for the K key.\n\t\t * @property KEY_K\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_K = 75;\n\n\t\t/**\n\t\t * Code for the L key.\n\t\t * @property KEY_L\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_L = 76;\n\n\t\t/**\n\t\t * Code for the M key.\n\t\t * @property KEY_M\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_M = 77;\n\n\t\t/**\n\t\t * Code for the N key.\n\t\t * @property KEY_N\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_N = 78;\n\n\t\t/**\n\t\t * Code for the O key.\n\t\t * @property KEY_O\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_O = 79;\n\n\t\t/**\n\t\t * Code for the P key.\n\t\t * @property KEY_P\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_P = 80;\n\n\t\t/**\n\t\t * Code for the Q key.\n\t\t * @property KEY_Q\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_Q = 81;\n\n\t\t/**\n\t\t * Code for the R key.\n\t\t * @property KEY_R\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_R = 82;\n\n\t\t/**\n\t\t * Code for the S key.\n\t\t * @property KEY_S\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_S = 83;\n\n\t\t/**\n\t\t * Code for the T key.\n\t\t * @property KEY_T\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_T = 84;\n\n\t\t/**\n\t\t * Code for the U key.\n\t\t * @property KEY_U\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_U = 85;\n\n\t\t/**\n\t\t * Code for the V key.\n\t\t * @property KEY_V\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_V = 86;\n\n\t\t/**\n\t\t * Code for the W key.\n\t\t * @property KEY_W\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_W = 87;\n\n\t\t/**\n\t\t * Code for the X key.\n\t\t * @property KEY_X\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_X = 88;\n\n\t\t/**\n\t\t * Code for the Y key.\n\t\t * @property KEY_Y\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_Y = 89;\n\n\t\t/**\n\t\t * Code for the Z key.\n\t\t * @property KEY_Z\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_Z = 90;\n\n\t\t/**\n\t\t * Code for the LEFT_WINDOW key.\n\t\t * @property KEY_LEFT_WINDOW\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_LEFT_WINDOW = 91;\n\n\t\t/**\n\t\t * Code for the RIGHT_WINDOW key.\n\t\t * @property KEY_RIGHT_WINDOW\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_RIGHT_WINDOW = 92;\n\n\t\t/**\n\t\t * Code for the SELECT key.\n\t\t * @property KEY_SELECT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SELECT_KEY = 93;\n\n\t\t/**\n\t\t * Code for the number pad 0 key.\n\t\t * @property KEY_NUMPAD_0\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_0 = 96;\n\n\t\t/**\n\t\t * Code for the number pad 1 key.\n\t\t * @property KEY_NUMPAD_1\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_1 = 97;\n\n\t\t/**\n\t\t * Code for the number pad 2 key.\n\t\t * @property KEY_NUMPAD 2\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_2 = 98;\n\n\t\t/**\n\t\t * Code for the number pad 3 key.\n\t\t * @property KEY_NUMPAD_3\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_3 = 99;\n\n\t\t/**\n\t\t * Code for the number pad 4 key.\n\t\t * @property KEY_NUMPAD_4\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_4 = 100;\n\n\t\t/**\n\t\t * Code for the number pad 5 key.\n\t\t * @property KEY_NUMPAD_5\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_5 = 101;\n\n\t\t/**\n\t\t * Code for the number pad 6 key.\n\t\t * @property KEY_NUMPAD_6\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_6 = 102;\n\n\t\t/**\n\t\t * Code for the number pad 7 key.\n\t\t * @property KEY_NUMPAD_7\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_7 = 103;\n\n\t\t/**\n\t\t * Code for the number pad 8 key.\n\t\t * @property KEY_NUMPAD_8\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_8 = 104;\n\n\t\t/**\n\t\t * Code for the number pad 9 key.\n\t\t * @property KEY_NUMPAD_9\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUMPAD_9 = 105;\n\n\t\t/**\n\t\t * Code for the MULTIPLY key.\n\t\t * @property KEY_MULTIPLY\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_MULTIPLY = 106;\n\n\t\t/**\n\t\t * Code for the ADD key.\n\t\t * @property KEY_ADD\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_ADD = 107;\n\n\t\t/**\n\t\t * Code for the SUBTRACT key.\n\t\t * @property KEY_SUBTRACT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SUBTRACT = 109;\n\n\t\t/**\n\t\t * Code for the DECIMAL POINT key.\n\t\t * @property KEY_DECIMAL_POINT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_DECIMAL_POINT = 110;\n\n\t\t/**\n\t\t * Code for the DIVIDE key.\n\t\t * @property KEY_DIVIDE\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_DIVIDE = 111;\n\n\t\t/**\n\t\t * Code for the F1 key.\n\t\t * @property KEY_F1\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F1 = 112;\n\n\t\t/**\n\t\t * Code for the F2 key.\n\t\t * @property KEY_F2\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F2 = 113;\n\n\t\t/**\n\t\t * Code for the F3 key.\n\t\t * @property KEY_F3\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F3 = 114;\n\n\t\t/**\n\t\t * Code for the F4 key.\n\t\t * @property KEY_F4\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F4 = 115;\n\n\t\t/**\n\t\t * Code for the F5 key.\n\t\t * @property KEY_F5\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F5 = 116;\n\n\t\t/**\n\t\t * Code for the F6 key.\n\t\t * @property KEY_F6\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F6 = 117;\n\n\t\t/**\n\t\t * Code for the F7 key.\n\t\t * @property KEY_F7\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F7 = 118;\n\n\t\t/**\n\t\t * Code for the F8 key.\n\t\t * @property KEY_F8\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F8 = 119;\n\n\t\t/**\n\t\t * Code for the F9 key.\n\t\t * @property KEY_F9\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F9 = 120;\n\n\t\t/**\n\t\t * Code for the F10 key.\n\t\t * @property KEY_F10\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F10 = 121;\n\n\t\t/**\n\t\t * Code for the F11 key.\n\t\t * @property KEY_F11\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F11 = 122;\n\n\t\t/**\n\t\t * Code for the F12 key.\n\t\t * @property KEY_F12\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_F12 = 123;\n\n\t\t/**\n\t\t * Code for the NUM_LOCK key.\n\t\t * @property KEY_NUM_LOCK\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_NUM_LOCK = 144;\n\n\t\t/**\n\t\t * Code for the SCROLL_LOCK key.\n\t\t * @property KEY_SCROLL_LOCK\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SCROLL_LOCK = 145;\n\n\t\t/**\n\t\t * Code for the SEMI_COLON key.\n\t\t * @property KEY_SEMI_COLON\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SEMI_COLON = 186;\n\n\t\t/**\n\t\t * Code for the EQUAL_SIGN key.\n\t\t * @property KEY_EQUAL_SIGN\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_EQUAL_SIGN = 187;\n\n\t\t/**\n\t\t * Code for the COMMA key.\n\t\t * @property KEY_COMMA\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_COMMA = 188;\n\n\t\t/**\n\t\t * Code for the DASH key.\n\t\t * @property KEY_DASH\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_DASH = 189;\n\n\t\t/**\n\t\t * Code for the PERIOD key.\n\t\t * @property KEY_PERIOD\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_PERIOD = 190;\n\n\t\t/**\n\t\t * Code for the FORWARD_SLASH key.\n\t\t * @property KEY_FORWARD_SLASH\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_FORWARD_SLASH = 191;\n\n\t\t/**\n\t\t * Code for the GRAVE_ACCENT key.\n\t\t * @property KEY_GRAVE_ACCENT\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_GRAVE_ACCENT = 192;\n\n\t\t/**\n\t\t * Code for the OPEN_BRACKET key.\n\t\t * @property KEY_OPEN_BRACKET\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_OPEN_BRACKET = 219;\n\n\t\t/**\n\t\t * Code for the BACK_SLASH key.\n\t\t * @property KEY_BACK_SLASH\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_BACK_SLASH = 220;\n\n\t\t/**\n\t\t * Code for the CLOSE_BRACKET key.\n\t\t * @property KEY_CLOSE_BRACKET\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_CLOSE_BRACKET = 221;\n\n\t\t/**\n\t\t * Code for the SINGLE_QUOTE key.\n\t\t * @property KEY_SINGLE_QUOTE\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SINGLE_QUOTE = 222;\n\n\t\t/**\n\t\t * Code for the SPACE key.\n\t\t * @property KEY_SPACE\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.KEY_SPACE = 32;\n\n\t\t/**\n\t\t * The canvas element that mouse and keyboards are bound to.\n\t\t *\n\t\t * @final\n\t\t * @type {HTMLCanvasElement}\n\t\t */\n\t\tthis.element = cfg.element;\n\n\t\t/** True whenever ALT key is down.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.altDown = false;\n\n\t\t/** True whenever CTRL key is down.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.ctrlDown = false;\n\n\t\t/** True whenever left mouse button is down.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.mouseDownLeft = false;\n\n\t\t/**\n\t\t * True whenever middle mouse button is down.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.mouseDownMiddle = false;\n\n\t\t/**\n\t\t * True whenever the right mouse button is down.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.mouseDownRight = false;\n\n\t\t/**\n\t\t * Flag for each key that's down.\n\t\t *\n\t\t * @type {boolean[]}\n\t\t */\n\t\tthis.keyDown = [];\n\n\t\t/** True while input enabled\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.enabled = true;\n\n\t\t/** True while keyboard input is enabled.\n\t\t *\n\t\t * Default value is ````true````.\n\t\t *\n\t\t * {@link CameraControl} will not respond to keyboard events while this is ````false````.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.keyboardEnabled = true;\n\n\t\t/** True while the mouse is over the canvas.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.mouseover = false;\n\n\t\t/**\n\t\t * Current mouse position within the canvas.\n\t\t * @type {Number[]}\n\t\t */\n\t\tthis.mouseCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec2();\n\t\tthis.touchCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec2();\n\n\t\tthis._keyboardEventsElement = cfg.keyboardEventsElement || document;\n\n\t\tthis._bindEvents();\n\t}\n\n\t_bindEvents() {\n\t\tif (this._eventsBound) {\n\t\t\treturn;\n\t\t}\n\t\t//keydown\n\t\tthis._keyboardEventsElement.addEventListener(\n\t\t\t\"keydown\",\n\t\t\t(this._keyDownListener = (e) => {\n\t\t\t\tif (!this.enabled || !this.keyboardEnabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (e.target.tagName !== \"INPUT\" && e.target.tagName !== \"TEXTAREA\") {\n\t\t\t\t\tif (e.keyCode === this.KEY_CTRL) {\n\t\t\t\t\t\tthis.ctrlDown = true;\n\t\t\t\t\t} else if (e.keyCode === this.KEY_ALT) {\n\t\t\t\t\t\tthis.altDown = true;\n\t\t\t\t\t} else if (e.keyCode === this.KEY_SHIFT) {\n\t\t\t\t\t\tthis.shiftDown = true;\n\t\t\t\t\t}\n\t\t\t\t\tthis.keyDown[e.keyCode] = true;\n\t\t\t\t\tthis.fire(\"keydown\", e.keyCode, true);\n\t\t\t\t}\n\t\t\t}),\n\t\t\tfalse\n\t\t);\n\t\t//keyup\n\t\tthis._keyboardEventsElement.addEventListener(\n\t\t\t\"keyup\",\n\t\t\t(this._keyUpListener = (e) => {\n\t\t\t\tif (!this.enabled || !this.keyboardEnabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (e.target.tagName !== \"INPUT\" && e.target.tagName !== \"TEXTAREA\") {\n\t\t\t\t\tif (e.keyCode === this.KEY_CTRL) {\n\t\t\t\t\t\tthis.ctrlDown = false;\n\t\t\t\t\t} else if (e.keyCode === this.KEY_ALT) {\n\t\t\t\t\t\tthis.altDown = false;\n\t\t\t\t\t} else if (e.keyCode === this.KEY_SHIFT) {\n\t\t\t\t\t\tthis.shiftDown = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis.keyDown[e.keyCode] = false;\n\t\t\t\t\tthis.fire(\"keyup\", e.keyCode, true);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\t//mouseenter\n\t\tthis.element.addEventListener(\n\t\t\t\"mouseenter\",\n\t\t\t(this._mouseEnterListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.mouseover = true;\n\t\t\t\tthis._getMouseCanvasPos(e);\n\t\t\t\tthis.fire(\"mouseenter\", this.mouseCanvasPos, true);\n\t\t\t})\n\t\t);\n\t\t//mouseleave\n\t\tthis.element.addEventListener(\n\t\t\t\"mouseleave\",\n\t\t\t(this._mouseLeaveListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.mouseover = false;\n\t\t\t\tthis._getMouseCanvasPos(e);\n\t\t\t\tthis.fire(\"mouseleave\", this.mouseCanvasPos, true);\n\t\t\t})\n\t\t);\n\t\t//click\n\t\tdocument.addEventListener(\n\t\t\t\"click\",\n\t\t\t(this._clickListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\tthis.mouseDownLeft = false;\n\t\t\t\t\t\tthis.mouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\tthis.mouseDownMiddle = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tthis.mouseDownLeft = false;\n\t\t\t\t\t\tthis.mouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (\"touches\" in e) {\n\t\t\t\t\tthis._getTouchCanvasPos(e);\n\t\t\t\t} else {\n\t\t\t\t\tthis._getMouseCanvasPos(e);\n\t\t\t\t}\n\t\t\t\tthis.fire(\"click\", this.mouseCanvasPos, true);\n\t\t\t\tif (this.mouseover) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\t//dblclick\n\t\tdocument.addEventListener(\n\t\t\t\"dblclick\",\n\t\t\t(this._dblClickListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\tthis.mouseDownLeft = false;\n\t\t\t\t\t\tthis.mouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\tthis.mouseDownMiddle = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tthis.mouseDownLeft = false;\n\t\t\t\t\t\tthis.mouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (\"touches\" in e) {\n\t\t\t\t\tthis._getTouchCanvasPos(e);\n\t\t\t\t} else {\n\t\t\t\t\tthis._getMouseCanvasPos(e);\n\t\t\t\t}\n\t\t\t\tthis.fire(\"dblclick\", this.mouseCanvasPos, true);\n\t\t\t\tif (this.mouseover) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\tconst tickifedMouseMoveFn = this.scene.tickify(() => this.fire(\"mousemove\", this.mouseCanvasPos, true));\n\t\tconst tickifedTouchMoveFn = this.scene.tickify(() => this.fire(\"touchmove\", this.touchCanvasPos, true));\n\t\t//mousemove\n\t\tthis.element.addEventListener(\n\t\t\t\"mousemove\",\n\t\t\t(this._mouseMoveListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._getMouseCanvasPos(e);\n\t\t\t\ttickifedMouseMoveFn();\n\t\t\t\tif (this.mouseover) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\tconst tickifiedMouseWheelFn = this.scene.tickify((delta) => {\n\t\t\tthis.fire(\"mousewheel\", delta, true);\n\t\t});\n\t\t//wheel\n\t\tthis.element.addEventListener(\n\t\t\t\"wheel\",\n\t\t\t(this._mouseWheelListener = (e, d) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst delta = Math.max(-1, Math.min(1, -e.deltaY * 40));\n\t\t\t\ttickifiedMouseWheelFn(delta);\n\t\t\t}),\n\t\t\t{ passive: true }\n\t\t);\n\t\t//mousedown\n\t\tthis.element.addEventListener(\n\t\t\t\"mousedown\",\n\t\t\t(this._mouseDownListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\tthis.mouseDownLeft = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\tthis.mouseDownMiddle = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tthis.mouseDownRight = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis._getMouseCanvasPos(e);\n\t\t\t\tthis.element.focus();\n\t\t\t\tthis.fire(\"mousedown\", this.mouseCanvasPos, true);\n\t\t\t\tif (this.mouseover) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\t//mouseup\n\t\tdocument.addEventListener(\n\t\t\t\"mouseup\",\n\t\t\t(this._mouseUpListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (e.which) {\n\t\t\t\t\tcase 1: // Left button\n\t\t\t\t\t\tthis.mouseDownLeft = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2: // Middle/both buttons\n\t\t\t\t\t\tthis.mouseDownMiddle = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3: // Right button\n\t\t\t\t\t\tthis.mouseDownRight = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis.fire(\"mouseup\", this.mouseCanvasPos, true);\n\t\t\t\tif (this.mouseover) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}\n\t\t\t}),\n\t\t\ttrue\n\t\t);\n\t\t//touchstart\n\t\tthis.element.addEventListener(\n\t\t\t\"touchstart\",\n\t\t\t(this._touchDownListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!e.isTrusted) return;\n\t\t\t\tif (e.touches.length == 1) {\n\t\t\t\t\tthis.touchDown = true;\n\t\t\t\t}\n\t\t\t\tthis._getTouchCanvasPos(e);\n\t\t\t\tthis.element.focus();\n\t\t\t\tthis.fire(\"touchstart\", this.mouseCanvasPos, true);\n\t\t\t\tif (this.mouseover) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\t//touchend\n\t\tthis.element.addEventListener(\n\t\t\t\"touchend\",\n\t\t\t(this._touchUpListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.touchDown = false;\n\t\t\t\tthis.fire(\"touchend\", this.mouseCanvasPos, true);\n\t\t\t}),\n\t\t\ttrue\n\t\t);\n\t\t//touchcancel\n\t\tthis.element.addEventListener(\"touchcancel\", this._touchUpListener, true);\n\t\t//touchmove\n\t\tthis.element.addEventListener(\n\t\t\t\"touchmove\",\n\t\t\t(this._touchMoveListener = (e) => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._getTouchCanvasPos(e);\n\t\t\t\t// tickifedTouchMoveFn();\n\t\t\t\ttickifedMouseMoveFn();\n\t\t\t})\n\t\t);\n\t\t// mouseclicked / touch\n\t\t{\n\t\t\tlet downX;\n\t\t\tlet downY;\n\t\t\t// Tolerance between down and up positions for a mouse click\n\t\t\tconst tolerance = 2;\n\t\t\tthis.on(\"mousedown\", (params) => {\n\t\t\t\tdownX = params[0];\n\t\t\t\tdownY = params[1];\n\t\t\t});\n\t\t\tthis.on(\"mouseup\", (params) => {\n\t\t\t\tif (\n\t\t\t\t\tdownX >= params[0] - tolerance &&\n\t\t\t\t\tdownX <= params[0] + tolerance &&\n\t\t\t\t\tdownY >= params[1] - tolerance &&\n\t\t\t\t\tdownY <= params[1] + tolerance\n\t\t\t\t) {\n\t\t\t\t\tthis.fire(\"mouseclicked\", params, true);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.on(\"touchstart\", (params) => {\n\t\t\t\tdownX = params[0];\n\t\t\t\tdownY = params[1];\n\t\t\t});\n\t\t\tthis.on(\"touchend\", (params) => {\n\t\t\t\tif (\n\t\t\t\t\tdownX >= params[0] - tolerance &&\n\t\t\t\t\tdownX <= params[0] + tolerance &&\n\t\t\t\t\tdownY >= params[1] - tolerance &&\n\t\t\t\t\tdownY <= params[1] + tolerance\n\t\t\t\t) {\n\t\t\t\t\tthis.fire(\"touchclicked\", params, true);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tthis._eventsBound = true;\n\t}\n\n\t_unbindEvents() {\n\t\tif (!this._eventsBound) {\n\t\t\treturn;\n\t\t}\n\t\tthis._keyboardEventsElement.removeEventListener(\"keydown\", this._keyDownListener);\n\t\tthis._keyboardEventsElement.removeEventListener(\"keyup\", this._keyUpListener);\n\t\tthis.element.removeEventListener(\"mouseenter\", this._mouseEnterListener);\n\t\tthis.element.removeEventListener(\"mouseleave\", this._mouseLeaveListener);\n\t\tthis.element.removeEventListener(\"mousedown\", this._mouseDownListener);\n\t\tdocument.removeEventListener(\"mouseup\", this._mouseDownListener);\n\t\tdocument.removeEventListener(\"click\", this._clickListener);\n\t\tdocument.removeEventListener(\"dblclick\", this._dblClickListener);\n\t\tthis.element.removeEventListener(\"mousemove\", this._mouseMoveListener);\n\t\tthis.element.removeEventListener(\"wheel\", this._mouseWheelListener);\n\n\t\tthis.element.removeEventListener(\"touchstart\", this._touchDownListener);\n\t\tdocument.removeEventListener(\"touchend\", this._touchUpListener);\n\t\tdocument.removeEventListener(\"touchcancel\", this._touchUpListener);\n\t\tthis.element.removeEventListener(\"touchmove\", this._touchMoveListener);\n\n\t\tif (window.OrientationChangeEvent) {\n\t\t\twindow.removeEventListener(\"orientationchange\", this._orientationchangedListener);\n\t\t}\n\t\tif (window.DeviceMotionEvent) {\n\t\t\twindow.removeEventListener(\"devicemotion\", this._deviceMotionListener);\n\t\t}\n\t\tif (window.DeviceOrientationEvent) {\n\t\t\twindow.removeEventListener(\"deviceorientation\", this._deviceOrientListener);\n\t\t}\n\t\tthis._eventsBound = false;\n\t}\n\n\t_getMouseCanvasPos(event) {\n\t\tif (!event) {\n\t\t\tevent = window.event;\n\t\t\tthis.mouseCanvasPos[0] = event.x;\n\t\t\tthis.mouseCanvasPos[1] = event.y;\n\t\t} else {\n\t\t\tlet element = event.target;\n\t\t\tlet totalOffsetLeft = 0;\n\t\t\tlet totalOffsetTop = 0;\n\t\t\twhile (element.offsetParent) {\n\t\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\t\telement = element.offsetParent;\n\t\t\t}\n\t\t\tthis.mouseCanvasPos[0] = event.pageX - totalOffsetLeft;\n\t\t\tthis.mouseCanvasPos[1] = event.pageY - totalOffsetTop;\n\t\t}\n\t}\n\n\t_getTouchCanvasPos(event) {\n\t\tif (!event || !event.touches || event.touches.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst touch = event.touches[0]; // 获取第一个触摸点的信息\n\n\t\tlet element = event.target;\n\t\tlet totalOffsetLeft = 0;\n\t\tlet totalOffsetTop = 0;\n\t\twhile (element.offsetParent) {\n\t\t\ttotalOffsetLeft += element.offsetLeft;\n\t\t\ttotalOffsetTop += element.offsetTop;\n\t\t\telement = element.offsetParent;\n\t\t}\n\n\t\tthis.mouseCanvasPos[0] = touch.pageX - totalOffsetLeft;\n\t\tthis.mouseCanvasPos[1] = touch.pageY - totalOffsetTop;\n\t}\n\n\t/**\n\t * Sets whether input handlers are enabled.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @param {Boolean} enable Indicates if input handlers are enabled.\n\t */\n\tsetEnabled(enable) {\n\t\tif (this.enabled !== enable) {\n\t\t\tthis.fire(\"enabled\", (this.enabled = enable));\n\t\t}\n\t}\n\n\t/**\n\t * Gets whether input handlers are enabled.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @returns {Boolean} Indicates if input handlers are enabled.\n\t */\n\tgetEnabled() {\n\t\treturn this.enabled;\n\t}\n\n\t/**\n\t * Sets whether or not keyboard input is enabled.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * {@link CameraControl} will not respond to keyboard events while this is set ````false````.\n\t *\n\t * @param {Boolean} value Indicates whether keyboard input is enabled.\n\t */\n\tsetKeyboardEnabled(value) {\n\t\tthis.keyboardEnabled = value;\n\t}\n\n\t/**\n\t * Gets whether keyboard input is enabled.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * {@link CameraControl} will not respond to keyboard events while this is set ````false````.\n\t *\n\t * @returns {Boolean} Returns whether keyboard input is enabled.\n\t */\n\tgetKeyboardEnabled() {\n\t\treturn this.keyboardEnabled;\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\t\tthis._unbindEvents();\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/input/Input.js?");
|
|
2948
2948
|
|
|
2949
2949
|
/***/ }),
|
|
2950
2950
|
|
|
@@ -2954,7 +2954,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2954
2954
|
\**************************************/
|
|
2955
2955
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2956
2956
|
|
|
2957
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ K3D: () => (/* binding */ K3D)\n/* harmony export */ });\n/**\r\n * @private\r\n */\r\nvar K3D = {};\r\n\r\nK3D.load = function(path, resp)\r\n{\r\n var request = new XMLHttpRequest();\r\n request.open(\"GET\", path, true);\r\n request.responseType = \"arraybuffer\";\r\n request.onload = function(e){resp(e.target.response);};\r\n request.send();\r\n}\r\n\r\nK3D.save = function(buff, path)\r\n{\r\n var dataURI = \"data:application/octet-stream;base64,\" + btoa(K3D.parse._buffToStr(buff));\r\n window.location.href = dataURI;\r\n}\r\n\r\nK3D.clone = function(o)\r\n{\r\n return JSON.parse(JSON.stringify(o));\r\n}\r\n\r\n\r\n\r\nK3D.bin = {};\r\n\r\nK3D.bin.f = new Float32Array(1);\r\nK3D.bin.fb = new Uint8Array(K3D.bin.f.buffer);\r\n\r\nK3D.bin.rf\t\t= function(buff, off) { var f = K3D.bin.f, fb = K3D.bin.fb; for(var i=0; i<4; i++) fb[i] = buff[off+i]; return f[0]; }\r\nK3D.bin.rsl\t\t= function(buff, off) { return buff[off] | buff[off+1]<<8; }\r\nK3D.bin.ril\t\t= function(buff, off) { return buff[off] | buff[off+1]<<8 | buff[off+2]<<16 | buff[off+3]<<24; }\r\nK3D.bin.rASCII0 = function(buff, off) { var s = \"\"; while(buff[off]!=0) s += String.fromCharCode(buff[off++]); return s; }\r\n\r\n\r\nK3D.bin.wf\t\t= function(buff, off, v) { var f=new Float32Array(buff.buffer, off, 1); f[0]=v; }\r\nK3D.bin.wsl\t\t= function(buff, off, v) { buff[off]=v; buff[off+1]=v>>8; }\r\nK3D.bin.wil\t\t= function(buff, off, v) { buff[off]=v; buff[off+1]=v>>8; buff[off+2]=v>>16; buff[off+3]>>24; }\r\nK3D.parse = {};\r\n\r\nK3D.parse._buffToStr = function(buff)\r\n{\r\n var a = new Uint8Array(buff);\r\n var s = \"\";\r\n for(var i=0; i<a.length; i++) s = s.concat(String.fromCharCode(a[i]));\r\n return s;\r\n}\r\n\r\nK3D.parse._strToBuff = function(str)\r\n{\r\n var buf = new ArrayBuffer(str.length);\r\n var bufView = new Uint8Array(buf);\r\n for (var i=0; i<str.length; i++) bufView[i] = str.charCodeAt(i);\r\n return buf;\r\n}\r\n\r\nK3D.parse._readLine = function(a, off)\t// Uint8Array, offset\r\n{\r\n var s = \"\";\r\n while(a[off] != 10) s += String.fromCharCode(a[off++]);\r\n return s;\r\n}\r\nK3D.parse.fromJSON = function(buff)\r\n{\r\n var json = JSON.parse(K3D.parse._buffToStr(buff));\r\n return json;\r\n}\r\n\r\nK3D.parse.toJSON = function(object)\r\n{\r\n var str = JSON.stringify(object);\r\n return K3D.parse._strToBuff(str);\r\n}\r\n\r\nK3D.parse.fromOBJ = function(buff)\r\n{\r\n var res = {};\r\n res.groups = {};\r\n\r\n res.c_verts = [];\r\n res.c_uvt\t= [];\r\n res.c_norms = [];\r\n\r\n res.i_verts = [];\r\n res.i_uvt = [];\r\n res.i_norms = [];\r\n\r\n var cg = {from: 0, to:0};\t// current group\r\n var off = 0;\r\n var a = new Uint8Array(buff);\r\n\r\n while(off < a.length)\r\n {\r\n var line = K3D.parse._readLine(a, off);\r\n off += line.length + 1;\r\n line = line.replace(/ +(?= )/g,'');\r\n line = line.replace(/(^\\s+|\\s+$)/g, '');\r\n var cds = line.split(\" \");\r\n if(cds[0] == \"g\")\r\n {\r\n cg.to = res.i_verts.length;\r\n if(res.groups[cds[1]] == null) res.groups[cds[1]] = {from:res.i_verts.length, to:0};\r\n cg = res.groups[cds[1]];\r\n }\r\n if(cds[0] == \"v\")\r\n {\r\n var x = parseFloat(cds[1]);\r\n var y = parseFloat(cds[2]);\r\n var z = parseFloat(cds[3]);\r\n res.c_verts.push(x,y,z);\r\n }\r\n if(cds[0] == \"vt\")\r\n {\r\n var x = parseFloat(cds[1]);\r\n var y = 1-parseFloat(cds[2]);\r\n res.c_uvt.push(x,y);\r\n }\r\n if(cds[0] == \"vn\")\r\n {\r\n var x = parseFloat(cds[1]);\r\n var y = parseFloat(cds[2]);\r\n var z = parseFloat(cds[3]);\r\n res.c_norms.push(x,y,z);\r\n }\r\n if(cds[0] == \"f\")\r\n {\r\n var v0a = cds[1].split(\"/\"), v1a = cds[2].split(\"/\"), v2a = cds[3].split(\"/\");\r\n var vi0 = parseInt(v0a[0])-1, vi1 = parseInt(v1a[0])-1, vi2 = parseInt(v2a[0])-1;\r\n var ui0 = parseInt(v0a[1])-1, ui1 = parseInt(v1a[1])-1, ui2 = parseInt(v2a[1])-1;\r\n var ni0 = parseInt(v0a[2])-1, ni1 = parseInt(v1a[2])-1, ni2 = parseInt(v2a[2])-1;\r\n\r\n var vlen = res.c_verts.length/3, ulen = res.c_uvt.length/2, nlen = res.c_norms.length/3;\r\n if(vi0<0) vi0 = vlen + vi0+1; if(vi1<0) vi1 = vlen + vi1+1;\tif(vi2<0) vi2 = vlen + vi2+1;\r\n if(ui0<0) ui0 = ulen + ui0+1; if(ui1<0) ui1 = ulen + ui1+1;\tif(ui2<0) ui2 = ulen + ui2+1;\r\n if(ni0<0) ni0 = nlen + ni0+1; if(ni1<0) ni1 = nlen + ni1+1;\tif(ni2<0) ni2 = nlen + ni2+1;\r\n\r\n res.i_verts.push(vi0, vi1, vi2); //cg.i_verts.push(vi0, vi1, vi2)\r\n res.i_uvt .push(ui0, ui1, ui2); //cg.i_uvt .push(ui0, ui1, ui2);\r\n res.i_norms.push(ni0, ni1, ni2); //cg.i_norms.push(ni0, ni1, ni2);\r\n if(cds.length == 5)\r\n {\r\n var v3a = cds[4].split(\"/\");\r\n var vi3 = parseInt(v3a[0])-1, ui3 = parseInt(v3a[1])-1, ni3 = parseInt(v3a[2])-1;\r\n if(vi3<0) vi3 = vlen + vi3+1;\r\n if(ui3<0) ui3 = ulen + ui3+1;\r\n if(ni3<0) ni3 = nlen + ni3+1;\r\n res.i_verts.push(vi0, vi2, vi3); //cg.i_verts.push(vi0, vi2, vi3);\r\n res.i_uvt .push(ui0, ui2, ui3); //cg.i_uvt .push(ui0, ui2, ui3);\r\n res.i_norms.push(ni0, ni2, ni3); //cg.i_norms.push(ni0, ni2, ni3);\r\n }\r\n }\r\n }\r\n cg.to = res.i_verts.length;\r\n\r\n return res;\r\n}\r\n\r\n\r\nK3D.parse.fromMD2 = function(buff)\r\n{\r\n buff = new Uint8Array(buff);\r\n var res = {};\r\n var head = {};\r\n //res.head = head;\r\n head.ident\t\t\t= K3D.bin.ril(buff, 0); /* magic number: \"IDP2\" */\r\n head.version\t\t= K3D.bin.ril(buff, 4); /* version: must be 8 */\r\n\r\n head.skinwidth\t\t= K3D.bin.ril(buff, 8); /* texture width */\r\n head.skinheight\t\t= K3D.bin.ril(buff, 12); /* texture height */\r\n\r\n head.framesize\t\t= K3D.bin.ril(buff, 16); /* size in bytes of a frame */\r\n\r\n head.num_skins\t\t= K3D.bin.ril(buff, 20); /* number of skins */\r\n head.num_vertices\t= K3D.bin.ril(buff, 24); /* number of vertices per frame */\r\n head.num_st\t\t\t= K3D.bin.ril(buff, 28); /* number of texture coordinates */\r\n head.num_tris\t\t= K3D.bin.ril(buff, 32); /* number of triangles */\r\n head.num_glcmds\t\t= K3D.bin.ril(buff, 36); /* number of opengl commands */\r\n head.num_frames\t\t= K3D.bin.ril(buff, 40); /* number of frames */\r\n\r\n head.offset_skins\t= K3D.bin.ril(buff, 44); /* offset skin data */\r\n head.offset_st\t\t= K3D.bin.ril(buff, 48); /* offset texture coordinate data */\r\n head.offset_tris\t= K3D.bin.ril(buff, 52); /* offset triangle data */\r\n head.offset_frames\t= K3D.bin.ril(buff, 56); /* offset frame data */\r\n head.offset_glcmds\t= K3D.bin.ril(buff, 60); /* offset OpenGL command data */\r\n head.offset_end\t\t= K3D.bin.ril(buff, 64); /* offset end of file */\r\n\r\n var off = head.offset_st;\r\n res.c_uvt = [];\r\n for(var i=0; i<head.num_st; i++)\r\n {\r\n var x = K3D.bin.rsl(buff, off )/head.skinwidth;\r\n var y = K3D.bin.rsl(buff, off+2)/head.skinheight;\r\n res.c_uvt.push(x,y); off += 4;\r\n }\r\n\r\n var off = head.offset_tris;\r\n var vi = [], ti = [];\r\n res.i_verts = vi;\r\n res.i_uvt = ti;\r\n //res.tris = {i_verts : vi, i_uvt : ti};\r\n for(var i=0; i<head.num_tris; i++)\r\n {\r\n vi.push(K3D.bin.rsl(buff, off ), K3D.bin.rsl(buff, off+2), K3D.bin.rsl(buff, off+4 ));\r\n ti.push(K3D.bin.rsl(buff, off+6), K3D.bin.rsl(buff, off+8), K3D.bin.rsl(buff, off+10));\r\n off += 12;\r\n }\r\n\r\n var off = head.offset_skins;\r\n res.skins = [];\r\n for(var i=0; i<head.num_skins; i++)\r\n {\r\n res.skins.push(K3D.bin.rASCII0(buff, off));\r\n off += 64;\r\n }\r\n\r\n var off = head.offset_frames;\r\n res.frames = [];\r\n var nms = K3D.parse.fromMD2._normals;\r\n for(var i=0; i<head.num_frames; i++)\r\n {\r\n var fr = {};\r\n var sx = K3D.bin.rf(buff, off), sy = K3D.bin.rf(buff, off+4), sz = K3D.bin.rf(buff, off+8); off += 12;\r\n var tx = K3D.bin.rf(buff, off), ty = K3D.bin.rf(buff, off+4), tz = K3D.bin.rf(buff, off+8); off += 12;\r\n fr.name\t\t = K3D.bin.rASCII0(buff, off); off += 16;\r\n fr.verts\t = [];\r\n fr.norms\t = [];\r\n\r\n for(var j=0; j<head.num_vertices; j++)\r\n {\r\n fr.verts.push(buff[off]*sx+tx, buff[off+1]*sy+ty, buff[off+2]*sz+tz);\r\n fr.norms.push(nms[3*buff[off+3]], nms[3*buff[off+3]+1], nms[3*buff[off+3]+2]);\r\n off += 4;\r\n }\r\n res.frames.push(fr);\r\n }\r\n return res;\r\n}\r\n\r\n\r\n\r\n/*\r\n static MD2 normals\r\n */\r\n\r\nK3D.parse.fromMD2._normals =\r\n [\r\n -0.525731, 0.000000, 0.850651,\r\n -0.442863, 0.238856, 0.864188,\r\n -0.295242, 0.000000, 0.955423,\r\n -0.309017, 0.500000, 0.809017,\r\n -0.162460, 0.262866, 0.951056,\r\n 0.000000, 0.000000, 1.000000,\r\n 0.000000, 0.850651, 0.525731,\r\n -0.147621, 0.716567, 0.681718,\r\n 0.147621, 0.716567, 0.681718,\r\n 0.000000, 0.525731, 0.850651,\r\n 0.309017, 0.500000, 0.809017,\r\n 0.525731, 0.000000, 0.850651,\r\n 0.295242, 0.000000, 0.955423,\r\n 0.442863, 0.238856, 0.864188,\r\n 0.162460, 0.262866, 0.951056,\r\n -0.681718, 0.147621, 0.716567,\r\n -0.809017, 0.309017, 0.500000,\r\n -0.587785, 0.425325, 0.688191,\r\n -0.850651, 0.525731, 0.000000,\r\n -0.864188, 0.442863, 0.238856,\r\n -0.716567, 0.681718, 0.147621,\r\n -0.688191, 0.587785, 0.425325,\r\n -0.500000, 0.809017, 0.309017,\r\n -0.238856, 0.864188, 0.442863,\r\n -0.425325, 0.688191, 0.587785,\r\n -0.716567, 0.681718, -0.147621,\r\n -0.500000, 0.809017, -0.309017,\r\n -0.525731, 0.850651, 0.000000,\r\n 0.000000, 0.850651, -0.525731,\r\n -0.238856, 0.864188, -0.442863,\r\n 0.000000, 0.955423, -0.295242,\r\n -0.262866, 0.951056, -0.162460,\r\n 0.000000, 1.000000, 0.000000,\r\n 0.000000, 0.955423, 0.295242,\r\n -0.262866, 0.951056, 0.162460,\r\n 0.238856, 0.864188, 0.442863,\r\n 0.262866, 0.951056, 0.162460,\r\n 0.500000, 0.809017, 0.309017,\r\n 0.238856, 0.864188, -0.442863,\r\n 0.262866, 0.951056, -0.162460,\r\n 0.500000, 0.809017, -0.309017,\r\n 0.850651, 0.525731, 0.000000,\r\n 0.716567, 0.681718, 0.147621,\r\n 0.716567, 0.681718, -0.147621,\r\n 0.525731, 0.850651, 0.000000,\r\n 0.425325, 0.688191, 0.587785,\r\n 0.864188, 0.442863, 0.238856,\r\n 0.688191, 0.587785, 0.425325,\r\n 0.809017, 0.309017, 0.500000,\r\n 0.681718, 0.147621, 0.716567,\r\n 0.587785, 0.425325, 0.688191,\r\n 0.955423, 0.295242, 0.000000,\r\n 1.000000, 0.000000, 0.000000,\r\n 0.951056, 0.162460, 0.262866,\r\n 0.850651, -0.525731, 0.000000,\r\n 0.955423, -0.295242, 0.000000,\r\n 0.864188, -0.442863, 0.238856,\r\n 0.951056, -0.162460, 0.262866,\r\n 0.809017, -0.309017, 0.500000,\r\n 0.681718, -0.147621, 0.716567,\r\n 0.850651, 0.000000, 0.525731,\r\n 0.864188, 0.442863, -0.238856,\r\n 0.809017, 0.309017, -0.500000,\r\n 0.951056, 0.162460, -0.262866,\r\n 0.525731, 0.000000, -0.850651,\r\n 0.681718, 0.147621, -0.716567,\r\n 0.681718, -0.147621, -0.716567,\r\n 0.850651, 0.000000, -0.525731,\r\n 0.809017, -0.309017, -0.500000,\r\n 0.864188, -0.442863, -0.238856,\r\n 0.951056, -0.162460, -0.262866,\r\n 0.147621, 0.716567, -0.681718,\r\n 0.309017, 0.500000, -0.809017,\r\n 0.425325, 0.688191, -0.587785,\r\n 0.442863, 0.238856, -0.864188,\r\n 0.587785, 0.425325, -0.688191,\r\n 0.688191, 0.587785, -0.425325,\r\n -0.147621, 0.716567, -0.681718,\r\n -0.309017, 0.500000, -0.809017,\r\n 0.000000, 0.525731, -0.850651,\r\n -0.525731, 0.000000, -0.850651,\r\n -0.442863, 0.238856, -0.864188,\r\n -0.295242, 0.000000, -0.955423,\r\n -0.162460, 0.262866, -0.951056,\r\n 0.000000, 0.000000, -1.000000,\r\n 0.295242, 0.000000, -0.955423,\r\n 0.162460, 0.262866, -0.951056,\r\n -0.442863, -0.238856, -0.864188,\r\n -0.309017, -0.500000, -0.809017,\r\n -0.162460, -0.262866, -0.951056,\r\n 0.000000, -0.850651, -0.525731,\r\n -0.147621, -0.716567, -0.681718,\r\n 0.147621, -0.716567, -0.681718,\r\n 0.000000, -0.525731, -0.850651,\r\n 0.309017, -0.500000, -0.809017,\r\n 0.442863, -0.238856, -0.864188,\r\n 0.162460, -0.262866, -0.951056,\r\n 0.238856, -0.864188, -0.442863,\r\n 0.500000, -0.809017, -0.309017,\r\n 0.425325, -0.688191, -0.587785,\r\n 0.716567, -0.681718, -0.147621,\r\n 0.688191, -0.587785, -0.425325,\r\n 0.587785, -0.425325, -0.688191,\r\n 0.000000, -0.955423, -0.295242,\r\n 0.000000, -1.000000, 0.000000,\r\n 0.262866, -0.951056, -0.162460,\r\n 0.000000, -0.850651, 0.525731,\r\n 0.000000, -0.955423, 0.295242,\r\n 0.238856, -0.864188, 0.442863,\r\n 0.262866, -0.951056, 0.162460,\r\n 0.500000, -0.809017, 0.309017,\r\n 0.716567, -0.681718, 0.147621,\r\n 0.525731, -0.850651, 0.000000,\r\n -0.238856, -0.864188, -0.442863,\r\n -0.500000, -0.809017, -0.309017,\r\n -0.262866, -0.951056, -0.162460,\r\n -0.850651, -0.525731, 0.000000,\r\n -0.716567, -0.681718, -0.147621,\r\n -0.716567, -0.681718, 0.147621,\r\n -0.525731, -0.850651, 0.000000,\r\n -0.500000, -0.809017, 0.309017,\r\n -0.238856, -0.864188, 0.442863,\r\n -0.262866, -0.951056, 0.162460,\r\n -0.864188, -0.442863, 0.238856,\r\n -0.809017, -0.309017, 0.500000,\r\n -0.688191, -0.587785, 0.425325,\r\n -0.681718, -0.147621, 0.716567,\r\n -0.442863, -0.238856, 0.864188,\r\n -0.587785, -0.425325, 0.688191,\r\n -0.309017, -0.500000, 0.809017,\r\n -0.147621, -0.716567, 0.681718,\r\n -0.425325, -0.688191, 0.587785,\r\n -0.162460, -0.262866, 0.951056,\r\n 0.442863, -0.238856, 0.864188,\r\n 0.162460, -0.262866, 0.951056,\r\n 0.309017, -0.500000, 0.809017,\r\n 0.147621, -0.716567, 0.681718,\r\n 0.000000, -0.525731, 0.850651,\r\n 0.425325, -0.688191, 0.587785,\r\n 0.587785, -0.425325, 0.688191,\r\n 0.688191, -0.587785, 0.425325,\r\n -0.955423, 0.295242, 0.000000,\r\n -0.951056, 0.162460, 0.262866,\r\n -1.000000, 0.000000, 0.000000,\r\n -0.850651, 0.000000, 0.525731,\r\n -0.955423, -0.295242, 0.000000,\r\n -0.951056, -0.162460, 0.262866,\r\n -0.864188, 0.442863, -0.238856,\r\n -0.951056, 0.162460, -0.262866,\r\n -0.809017, 0.309017, -0.500000,\r\n -0.864188, -0.442863, -0.238856,\r\n -0.951056, -0.162460, -0.262866,\r\n -0.809017, -0.309017, -0.500000,\r\n -0.681718, 0.147621, -0.716567,\r\n -0.681718, -0.147621, -0.716567,\r\n -0.850651, 0.000000, -0.525731,\r\n -0.688191, 0.587785, -0.425325,\r\n -0.587785, 0.425325, -0.688191,\r\n -0.425325, 0.688191, -0.587785,\r\n -0.425325, -0.688191, -0.587785,\r\n -0.587785, -0.425325, -0.688191,\r\n -0.688191, -0.587785, -0.425325\r\n ];\r\n\r\nK3D.parse.fromCollada = function(buff)\r\n{\r\n var str = K3D.parse._buffToStr(buff);\r\n var xml = new DOMParser().parseFromString(str,\"text/xml\");\r\n xml = xml.childNodes[0];\r\n var resp = {};\r\n\r\n //console.log(xml);\r\n\r\n var ass = xml.getElementsByTagName(\"asset\" )[0];\r\n var geo = xml.getElementsByTagName(\"library_geometries\")[0];\r\n var ima = xml.getElementsByTagName(\"library_images\" )[0];\r\n var mat = xml.getElementsByTagName(\"library_materials\" )[0];\r\n var eff = xml.getElementsByTagName(\"library_effects\" )[0];\r\n\r\n //console.log(xml);\r\n if(ass) resp.asset \t\t= K3D.parse.fromCollada._asset (ass);\r\n if(geo) resp.geometries = K3D.parse.fromCollada._libGeometries(geo);\r\n if(ima) resp.images = K3D.parse.fromCollada._libImages (ima);\r\n if(mat) resp.materials = K3D.parse.fromCollada._libMaterials (mat);\r\n if(eff) resp.effects = K3D.parse.fromCollada._libEffects (eff);\r\n return resp;\r\n}\r\n\r\nK3D.parse.fromCollada._asset = function(xml)\r\n{\r\n //console.log(xml);\r\n return {\r\n created : xml.getElementsByTagName(\"created\" )[0].textContent,\r\n modified: xml.getElementsByTagName(\"modified\")[0].textContent,\r\n up_axis : xml.getElementsByTagName(\"up_axis\" )[0].textContent\r\n };\r\n}\r\n\r\nK3D.parse.fromCollada._libGeometries = function(xml)\r\n{\r\n xml = xml.getElementsByTagName(\"geometry\");\r\n var res = [];\r\n for(var i=0; i<xml.length; i++)\r\n {\r\n var g = xml[i];\r\n var o = K3D.parse.fromCollada._getMesh(g.getElementsByTagName(\"mesh\")[0]);\r\n res.push(o);\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.fromCollada._getMesh = function(mesh)\r\n{\r\n //console.log(mesh);\r\n var res = {};\r\n var ss = mesh.getElementsByTagName(\"source\");\r\n var sources = res.sources = {};\r\n for(var i=0; i<ss.length; i++)\r\n {\r\n var farr = ss[i].getElementsByTagName(\"float_array\")[0].textContent.split(\" \");\r\n var fl = farr.length - (farr[farr.length-1] == \"\" ? 1 : 0);\r\n var arr = new Array(fl);\r\n for(var j=0; j<fl; j++) arr[j] = parseFloat(farr[j]);\r\n sources[ss[i].getAttribute(\"id\")] = arr;\r\n }\r\n\r\n res.triangles = [];\r\n var tgs = mesh.getElementsByTagName(\"triangles\");\r\n if(tgs == null) return res;\r\n for(var i=0; i<tgs.length; i++)\r\n {\r\n var t = {};\r\n var tnode = tgs[i];\r\n t.material = tnode.getAttribute(\"material\");\r\n var inputs = tnode.getElementsByTagName(\"input\");\r\n var inds = [];\r\n for(var j=0; j<inputs.length; j++)\r\n {\r\n var inp = inputs[j], arr = [];\r\n inds[parseInt(inp.getAttribute(\"offset\"))] = arr;\r\n var par = inp.getAttribute(\"semantic\");\r\n t[\"s_\"+par] = (par == \"VERTEX\") ?\r\n mesh.getElementsByTagName(\"vertices\")[0].getElementsByTagName(\"input\")[0].getAttribute(\"source\").substring(1)\r\n : inp.getAttribute(\"source\").substring(1);\r\n\r\n t[\"i_\"+par] = arr;\r\n var psrc = sources[t[\"s_\"+par]];\r\n }\r\n var indices = tnode.getElementsByTagName(\"p\")[0].textContent.split(\" \");\r\n var inum = 3*Math.floor(indices.length/3);\r\n for(var j=0; j<inum; j++) inds[j%inputs.length].push(parseInt(indices[j]));\r\n\r\n /*\r\n if(t.s_VERTEX ) t.u_VERTEX = K3D.edit.unwrap(t.i_VERTEX , sources[t.s_VERTEX ], 3);\r\n if(t.s_TEXCOORD) t.u_TEXCOORD = K3D.edit.unwrap(t.i_TEXCOORD, sources[t.s_TEXCOORD], 2);\r\n if(t.s_NORMAL ) t.u_NORMAL = K3D.edit.unwrap(t.i_NORMAL , sources[t.s_NORMAL ], 3);\r\n //*/\r\n //if(t.s_TEXCOORD) for(var j=1; j<t.u_TEXCOORD.length; j+=2) t.u_TEXCOORD[j] = 1 - t.u_TEXCOORD[j];\r\n\r\n /*\r\n t.u_INDEX = new Array(t.i_VERTEX.length);\r\n for(var j=0; j<t.i_VERTEX.length; j++) t.u_INDEX[j] = j;\r\n */\r\n\r\n res.triangles.push(t);\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.fromCollada._libImages = function(xml)\r\n{\r\n xml = xml.getElementsByTagName(\"image\");\r\n var res = {};\r\n for(var i=0; i<xml.length; i++)\r\n {\r\n res[xml[i].getAttribute(\"id\")] = xml[i].getElementsByTagName(\"init_from\")[0].textContent;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.fromCollada._libMaterials = function(xml)\r\n{\r\n xml = xml.getElementsByTagName(\"material\");\r\n var res = {};\r\n for(var i=0; i<xml.length; i++)\r\n {\r\n res[xml[i].getAttribute(\"name\")] = xml[i].getElementsByTagName(\"instance_effect\")[0].getAttribute(\"url\").substring(1);\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.fromCollada._libEffects = function(xml)\r\n{\r\n xml = xml.getElementsByTagName(\"effect\");\r\n var res = {};\r\n for(var i=0; i<xml.length; i++)\r\n {\r\n var eff = {};\r\n var params = xml[i].getElementsByTagName(\"newparam\");\r\n for(var j=0; j<params.length; j++)\r\n {\r\n var srf = params[j].getElementsByTagName(\"surface\")[0];\r\n if(srf) eff.surface = srf.getElementsByTagName(\"init_from\")[0].textContent;\r\n }\r\n res[xml[i].getAttribute(\"id\")] = eff;\r\n }\r\n return res;\r\n}\r\n\r\n\r\n\r\n\r\n\r\nK3D.parse.from3DS = function(buff)\r\n{\r\n buff = new Uint8Array(buff);\r\n var res = {};\r\n if(K3D.bin.rsl(buff, 0) != 0x4d4d) return null;\r\n var lim = K3D.bin.ril(buff, 2);\r\n\r\n var off = 6;\r\n while(off < lim)\r\n {\r\n var cid = K3D.bin.rsl(buff, off);\r\n var lng = K3D.bin.ril(buff, off+2);\r\n //console.log(cid.toString(16), lng);\r\n\r\n if(cid == 0x3d3d) res.edit = K3D.parse.from3DS._edit3ds(buff, off, lng);\r\n if(cid == 0xb000) res.keyf = K3D.parse.from3DS._keyf3ds(buff, off, lng);\r\n\r\n off += lng;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._edit3ds = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n while(off < coff+clng)\r\n {\r\n var cid = K3D.bin.rsl(buff, off);\r\n var lng = K3D.bin.ril(buff, off+2);\r\n //console.log(\"\\t\", cid.toString(16), lng);\r\n\r\n if(cid == 0x4000) { if(res.objects==null) res.objects = []; res.objects.push(K3D.parse.from3DS._edit_object(buff, off, lng)); }\r\n //if(cid == 0xb000) res.KEYF3DS = K3D.parse.from3DS._keyf3ds(buff, off, lng);\r\n\r\n off += lng;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._keyf3ds = function(buff, coff, clng)\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n while(off < coff+clng)\r\n {\r\n var cid = K3D.bin.rsl(buff, off);\r\n var lng = K3D.bin.ril(buff, off+2);\r\n //console.log(\"\\t\\t\", cid.toString(16), lng);\r\n\r\n //if(cid == 0x4000) { res.objects.push(K3D.parse.from3DS._edit_object(buff, off, lng)); }\r\n if(cid == 0xb002) { if(res.desc==null) res.desc = []; res.desc.push(K3D.parse.from3DS._keyf_objdes(buff, off, lng)); }\r\n\r\n off += lng;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._keyf_objdes = function(buff, coff, clng)\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n while(off < coff+clng)\r\n {\r\n var cid = K3D.bin.rsl(buff, off);\r\n var lng = K3D.bin.ril(buff, off+2);\r\n //console.log(\"\\t\\t\\t\", cid.toString(16), lng);\r\n\r\n if(cid == 0xb010) res.hierarchy = K3D.parse.from3DS._keyf_objhierarch(buff, off, lng);\r\n if(cid == 0xb011) res.dummy_name = K3D.bin.rASCII0(buff, off+6);\r\n off += lng;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._keyf_objhierarch = function(buff, coff, clng)\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n res.name = K3D.bin.rASCII0(buff, off); off += res.name.length+1;\r\n res.hierarchy = K3D.bin.rsl(buff, off+4);\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._edit_object = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n res.name = K3D.bin.rASCII0(buff, off); off += res.name.length+1;\r\n //console.log(res.name);\r\n while(off < coff+clng)\r\n {\r\n var cid = K3D.bin.rsl(buff, off);\r\n var lng = K3D.bin.ril(buff, off+2);\r\n //console.log(\"\\t\\t\", cid.toString(16), lng);\r\n\r\n if(cid == 0x4100) res.mesh = K3D.parse.from3DS._obj_trimesh(buff, off, lng);\r\n //if(cid == 0xb000) res.KEYF3DS = K3D.parse.from3DS._keyf3ds(buff, off, lng);\r\n\r\n off += lng;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._obj_trimesh = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n\r\n while(off < coff+clng)\r\n {\r\n var cid = K3D.bin.rsl(buff, off);\r\n var lng = K3D.bin.ril(buff, off+2);\r\n //console.log(\"\\t\\t\\t\", cid.toString(16), lng);\r\n\r\n if(cid == 0x4110) res.vertices = K3D.parse.from3DS._tri_vertexl (buff, off, lng);\r\n if(cid == 0x4120) res.indices = K3D.parse.from3DS._tri_facel1 (buff, off, lng);\r\n if(cid == 0x4140) res.uvt\t\t\t= K3D.parse.from3DS._tri_mappingcoors(buff, off, lng);\r\n if(cid == 0x4160) res.local\t\t = K3D.parse.from3DS._tri_local (buff, off, lng);\r\n off += lng;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._tri_vertexl = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = [];\r\n var off = coff+6;\r\n var n = K3D.bin.rsl(buff, off); off += 2;\r\n for(var i=0; i<n; i++)\r\n {\r\n res.push(K3D.bin.rf(buff, off ));\tres.push(K3D.bin.rf(buff, off+4));\tres.push(K3D.bin.rf(buff, off+8));\r\n off += 12;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._tri_facel1 = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = [];\r\n var off = coff+6;\r\n var n = K3D.bin.rsl(buff, off); off += 2;\r\n for(var i=0; i<n; i++)\r\n {\r\n res.push(K3D.bin.rsl(buff, off ));\r\n res.push(K3D.bin.rsl(buff, off+2));\r\n res.push(K3D.bin.rsl(buff, off+4));\r\n off += 8;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._tri_mappingcoors = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = [];\r\n var off = coff+6;\r\n var n = K3D.bin.rsl(buff, off); off += 2;\r\n for(var i=0; i<n; i++)\r\n {\r\n res.push( K3D.bin.rf(buff, off ));\r\n res.push(1-K3D.bin.rf(buff, off+4));\r\n off += 8;\r\n }\r\n return res;\r\n}\r\n\r\nK3D.parse.from3DS._tri_local = function(buff, coff, clng)\t// buffer, chunk offset, length\r\n{\r\n var res = {};\r\n var off = coff+6;\r\n res.X = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\r\n res.Y = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\r\n res.Z = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\r\n res.C = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\r\n return res;\r\n}\r\n\r\nK3D.parse.fromBIV = function(buff)\r\n{\r\n buff = new Uint8Array(buff);\r\n var res = {};\r\n\r\n var head = {};\r\n\r\n head.id\t\t= K3D.bin.ril(buff, 0);\r\n\r\n head.verS\t= K3D.bin.ril(buff, 4);\r\n head.texS\t= K3D.bin.ril(buff, 8);\r\n head.indS\t= K3D.bin.ril(buff, 12);\r\n\r\n head.verO\t= K3D.bin.ril(buff, 16);\r\n head.verL\t= K3D.bin.ril(buff, 20);\r\n head.texO\t= K3D.bin.ril(buff, 24);\r\n head.texL\t= K3D.bin.ril(buff, 28);\r\n head.indO\t= K3D.bin.ril(buff, 32);\r\n head.indL\t= K3D.bin.ril(buff, 36);\r\n\r\n if(head.verO != 0) res.vertices = K3D.parse.fromBIV._readFloats(buff, head.verO, head.verL);\r\n if(head.texO != 0) res.uvt = K3D.parse.fromBIV._readFloats(buff, head.texO, head.texL);\r\n if(head.indO != 0) res.indices = K3D.parse.fromBIV._readInts (buff, head.indO, head.indL, head.indS);\r\n\r\n return res;\r\n}\r\n\r\nK3D.parse.toBIV = function(obj)\r\n{\r\n var maxi = 0;\r\n for(var i=0; i<obj.indices.length; i++)\tmaxi = Math.max(maxi, obj.indices[i]);\r\n\r\n var indS = 32;\r\n if(maxi<=0xffff) indS = 16;\r\n\r\n var len = 40;\r\n if(obj.vertices) len+=obj.vertices.length*4;\r\n if(obj.uvt ) len+=obj.uvt .length*4;\r\n if(obj.indices ) len+=obj.indices .length*indS/8;\r\n\r\n\r\n var buff = new Uint8Array(len);\r\n\r\n K3D.bin.wil(buff, 0, 0x6976616e);\r\n\r\n K3D.bin.wil(buff, 4, 32);\r\n K3D.bin.wil(buff, 8, 32);\r\n K3D.bin.wil(buff, 12, indS);\r\n\r\n var off = 40;\r\n if(obj.vertices)\r\n {\r\n K3D.bin.wil(buff, 16, off);\r\n K3D.bin.wil(buff, 20, 4*obj.vertices.length);\r\n K3D.parse.fromBIV._writeFloats(buff, off, obj.vertices);\r\n off += 4*obj.vertices.length;\r\n }\r\n if(obj.uvt)\r\n {\r\n K3D.bin.wil(buff, 24, off);\r\n K3D.bin.wil(buff, 28, 4*obj.uvt.length);\r\n K3D.parse.fromBIV._writeFloats(buff, off, obj.uvt);\r\n off += 4*obj.uvt.length;\r\n }\r\n if(obj.indices)\r\n {\r\n K3D.bin.wil(buff, 32, off);\r\n K3D.bin.wil(buff, 36, 4*obj.indices.length);\r\n K3D.parse.fromBIV._writeInts (buff, off, obj.indices, indS);\r\n }\r\n return buff.buffer;\r\n}\r\n\r\nK3D.parse.fromBIV._readFloats = function(buff, off, len)\r\n{\r\n var arr = [];\r\n for(var i=0; i<len/4; i++) arr.push( K3D.bin.rf(buff, off+4*i));\r\n return arr;\r\n}\r\n\r\nK3D.parse.fromBIV._writeFloats = function(buff, off, arr)\r\n{\r\n for(var i=0; i<arr.length; i++) K3D.bin.wf(buff, off+4*i, arr[i]);\r\n}\r\n\r\nK3D.parse.fromBIV._readInts = function(buff, off, len, cs)\r\n{\r\n var arr = [];\r\n for(var i=0; i<len/4; i++)\r\n {\r\n if(cs==16) arr.push( K3D.bin.rsl(buff, off+2*i));\r\n if(cs==32) arr.push( K3D.bin.ril(buff, off+4*i));\r\n }\r\n return arr;\r\n}\r\n\r\nK3D.parse.fromBIV._writeInts = function(buff, off, arr, cs)\r\n{\r\n for(var i=0; i<arr.length; i++)\r\n {\r\n if(cs==16) K3D.bin.wsl(buff, off+2*i, arr[i]);\r\n if(cs==32) K3D.bin.wil(buff, off+4*i, arr[i]);\r\n }\r\n}\r\nK3D.gen = {};\r\n\r\nK3D.gen.Plane = function(sw, sh, tsw, tsh)\r\n{\r\n if(!tsw) tsw = 1;\r\n if(!tsh) tsh = 1;\r\n var r = {verts:[], inds:[], uvt:[]};\r\n var ssw = sw+1, ssh = sh+1\r\n for(var i=0; i<ssh; i++)\r\n {\r\n for(var j=0; j<ssw; j++)\r\n {\r\n var x = -1 + j*(2/sw);\r\n var y = -1 + i*(2/sh);\r\n r.verts.push(x, y, 0);\r\n r.uvt.push(tsw*j/sw, tsh*i/sh);\r\n if(i<sh && j<sw)\r\n r.inds.push(i*ssw+j, i*ssw+j+1, (i+1)*ssw+j, i*ssw+j+1, (i+1)*ssw+j, (i+1)*ssw+j+1);\r\n }\r\n }\r\n return r;\r\n}\r\nK3D.gen.Cube = function()\r\n{\r\n var r = {\r\n verts:[\t-1, 1,-1, 1, 1,-1, -1,-1,-1, 1,-1,-1, // front\r\n -1, 1, 1, 1, 1, 1, -1,-1, 1, 1,-1, 1, // back\r\n\r\n -1, 1, 1, -1, 1,-1, -1,-1, 1, -1,-1,-1, // left\r\n 1, 1, 1, 1, 1,-1, 1,-1, 1, 1,-1,-1, // right\r\n\r\n -1, 1,-1, 1, 1,-1, -1, 1, 1, 1, 1, 1, // top\r\n -1,-1,-1, 1,-1,-1, -1,-1, 1, 1,-1, 1 // bottom\r\n ],\r\n inds:[\t0,1,2, 1,2,3, 4,5,6, 5,6,7,\r\n 8,9,10, 9,10,11, 12,13,14, 13,14,15,\r\n 16,17,18, 17,18,19, 20,21,22, 21,22,23\r\n ],\r\n uvt:[\r\n 1/4,1/4, 2/4,1/4, 1/4,2/4, 2/4,2/4, // front\r\n 4/4,1/4, 3/4,1/4, 4/4,2/4, 3/4,2/4, // back\r\n\r\n 0/4,1/4, 1/4,1/4, 0/4,2/4, 1/4,2/4, // left\r\n 3/4,1/4, 2/4,1/4, 3/4,2/4, 2/4,2/4, // right\r\n\r\n 1/4,1/4, 2/4,1/4, 1/4,0/4, 2/4,0/4, // top\r\n 1/4,2/4, 2/4,2/4, 1/4,3/4, 2/4,3/4, // bottom\r\n ]\r\n };\r\n return r;\r\n};\r\n\r\nK3D.gen.Sphere = function(sx, sy){\r\n var r = {verts:[], inds:[], uvt:[]};\r\n\r\n var dx = 2*Math.PI/sx;\r\n var dy = Math.PI/sy;\r\n var nx = sx+1, ny = sy+1;\r\n for(var i=0; i<ny; i++)\t// rows\r\n {\r\n for(var j=0; j<nx; j++) // cols\r\n {\r\n var lat = -Math.PI/2 + i*Math.PI/sy;\r\n var lon = j*2*Math.PI/sx;\r\n var x = Math.cos(lat) * Math.cos(lon);\r\n var y = Math.sin(lat);\r\n var z = Math.cos(lat) * Math.sin(lon);\r\n\r\n r.verts.push(x,y,z);\r\n r.uvt.push(j/sx, i/sy);\r\n if(i<sy && j<sx) // 6 indices for 2 triangles\r\n r.inds.push(nx*i+j, nx*i+j+1, nx*(i+1)+j, nx*i+j+1, nx*(i+1)+j, nx*(i+1)+j+1);\r\n }\r\n }\r\n return r;\r\n};\r\n\r\nK3D.mat = {};\r\n\r\nK3D.mat.scale = function(x,y,z){\r\n return [\r\n x,0,0,0,\r\n 0,y,0,0,\r\n 0,0,z,0,\r\n 0,0,0,1\r\n ];\r\n};\r\n\r\nK3D.mat.translate = function(x,y,z){\r\n return [\r\n 1,0,0,0,\r\n 0,1,0,0,\r\n 0,0,1,0,\r\n x,y,z,1\r\n ];\r\n};\r\n\r\nK3D.mat.rotateDeg = function(x,y,z){\r\n var r = Math.PI/180;\r\n return K3D.mat.rotate(x*r, y*r, z*r);\r\n};\r\n\r\nK3D.mat.rotate = function(x,y,z){\r\n var m = [\r\n 1,0,0,0,\r\n 0,1,0,0,\r\n 0,0,1,0,\r\n 0,0,0,1\r\n ];\r\n var a = x;\t// alpha\r\n var b = y;\t// beta\r\n var g = z;\t// gama\r\n\r\n var ca = Math.cos(a), cb = Math.cos(b), cg = Math.cos(g);\r\n var sa = Math.sin(a), sb = Math.sin(b), sg = Math.sin(g);\r\n\r\n m[0] = cb*cg;\t\t\t\tm[1] = -cb*sg;\t\t\t\t\tm[2 ] = sb;\r\n m[4] = (ca*sg+sa*sb*cg);\tm[5] = (ca*cg-sa*sb*sg);\t\tm[6 ] = -sa*cb;\r\n m[8] = (sa*sg-ca*sb*cg);\tm[9] = (sa*cg+ca*sb*sg);\t\tm[10] = ca*cb;\r\n\r\n return m;\r\n};\r\n\r\n\r\nK3D.edit = {};\r\n\r\nK3D.edit.interpolate = function(a, b, d, t){\r\n for(var i=0; i<a.length; i++) d[i] = a[i] + t*(b[i] - a[i]);\r\n};\r\n\r\n\r\nK3D.edit.transform = function(a, m){\r\n for(var i=0; i<a.length; i+=3) {\r\n var x = a[i], y = a[i+1], z = a[i+2];\r\n a[i+0] = m[0]*x + m[4]*y + m[8 ]*z + m[12];\r\n a[i+1] = m[1]*x + m[5]*y + m[9 ]*z + m[13];\r\n a[i+2] = m[2]*x + m[6]*y + m[10]*z + m[14];\r\n }\r\n};\r\n\r\n// starting indices, starting coordinates, coordinates per index\r\n\r\nK3D.edit.unwrap = function(ind, crd, cpi){\r\n var ncrd = new Array(Math.floor(ind.length/3)*cpi);\r\n for(var i=0; i<ind.length; i++)\r\n {\r\n for(var j=0; j<cpi; j++)\r\n {\r\n ncrd[i*cpi+j] = crd[ind[i]*cpi+j];\r\n }\r\n }\r\n return ncrd;\r\n};\r\n\r\n// current indices, new indices, current array, coordinates per vertex\r\n\r\nK3D.edit.remap = function(ind, nind, arr, cpi){\r\n var ncrd = new Array(arr.length);\r\n for(var i=0; i<ind.length; i++)\r\n {\r\n for(var j=0; j<cpi; j++)\r\n {\r\n ncrd[nind[i]*cpi+j] = arr[ind[i]*cpi+j];\r\n }\r\n }\r\n return ncrd;\r\n};\r\n\r\nK3D.utils = {};\r\n\r\nK3D.utils.getAABB = function(vts)\r\n{\r\n var minx, miny, minz, maxx, maxy, maxz;\r\n minx = miny = minz = 999999999;\r\n maxx = maxy = maxz = -minx;\r\n\r\n for(var i=0; i<vts.length; i+=3)\r\n {\r\n var vx = vts[i+0];\r\n var vy = vts[i+1];\r\n var vz = vts[i+2];\r\n if(vx<minx) minx = vx; if(vx>maxx) maxx = vx;\r\n if(vy<miny) miny = vy; if(vy>maxy) maxy = vy;\r\n if(vz<minz) minz = vz; if(vy>maxz) maxz = vz;\r\n }\r\n return {min:{x:minx, y:miny, z:minz}, max:{x:maxx, y:maxy, z:maxz}};\r\n};\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/libs/k3d.js?");
|
|
2957
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ K3D: () => (/* binding */ K3D)\n/* harmony export */ });\n/**\n * @private\n */\nvar K3D = {};\n\nK3D.load = function(path, resp)\n{\n var request = new XMLHttpRequest();\n request.open(\"GET\", path, true);\n request.responseType = \"arraybuffer\";\n request.onload = function(e){resp(e.target.response);};\n request.send();\n}\n\nK3D.save = function(buff, path)\n{\n var dataURI = \"data:application/octet-stream;base64,\" + btoa(K3D.parse._buffToStr(buff));\n window.location.href = dataURI;\n}\n\nK3D.clone = function(o)\n{\n return JSON.parse(JSON.stringify(o));\n}\n\n\n\nK3D.bin = {};\n\nK3D.bin.f = new Float32Array(1);\nK3D.bin.fb = new Uint8Array(K3D.bin.f.buffer);\n\nK3D.bin.rf\t\t= function(buff, off) { var f = K3D.bin.f, fb = K3D.bin.fb; for(var i=0; i<4; i++) fb[i] = buff[off+i]; return f[0]; }\nK3D.bin.rsl\t\t= function(buff, off) { return buff[off] | buff[off+1]<<8; }\nK3D.bin.ril\t\t= function(buff, off) { return buff[off] | buff[off+1]<<8 | buff[off+2]<<16 | buff[off+3]<<24; }\nK3D.bin.rASCII0 = function(buff, off) { var s = \"\"; while(buff[off]!=0) s += String.fromCharCode(buff[off++]); return s; }\n\n\nK3D.bin.wf\t\t= function(buff, off, v) { var f=new Float32Array(buff.buffer, off, 1); f[0]=v; }\nK3D.bin.wsl\t\t= function(buff, off, v) { buff[off]=v; buff[off+1]=v>>8; }\nK3D.bin.wil\t\t= function(buff, off, v) { buff[off]=v; buff[off+1]=v>>8; buff[off+2]=v>>16; buff[off+3]>>24; }\nK3D.parse = {};\n\nK3D.parse._buffToStr = function(buff)\n{\n var a = new Uint8Array(buff);\n var s = \"\";\n for(var i=0; i<a.length; i++) s = s.concat(String.fromCharCode(a[i]));\n return s;\n}\n\nK3D.parse._strToBuff = function(str)\n{\n var buf = new ArrayBuffer(str.length);\n var bufView = new Uint8Array(buf);\n for (var i=0; i<str.length; i++) bufView[i] = str.charCodeAt(i);\n return buf;\n}\n\nK3D.parse._readLine = function(a, off)\t// Uint8Array, offset\n{\n var s = \"\";\n while(a[off] != 10) s += String.fromCharCode(a[off++]);\n return s;\n}\nK3D.parse.fromJSON = function(buff)\n{\n var json = JSON.parse(K3D.parse._buffToStr(buff));\n return json;\n}\n\nK3D.parse.toJSON = function(object)\n{\n var str = JSON.stringify(object);\n return K3D.parse._strToBuff(str);\n}\n\nK3D.parse.fromOBJ = function(buff)\n{\n var res = {};\n res.groups = {};\n\n res.c_verts = [];\n res.c_uvt\t= [];\n res.c_norms = [];\n\n res.i_verts = [];\n res.i_uvt = [];\n res.i_norms = [];\n\n var cg = {from: 0, to:0};\t// current group\n var off = 0;\n var a = new Uint8Array(buff);\n\n while(off < a.length)\n {\n var line = K3D.parse._readLine(a, off);\n off += line.length + 1;\n line = line.replace(/ +(?= )/g,'');\n line = line.replace(/(^\\s+|\\s+$)/g, '');\n var cds = line.split(\" \");\n if(cds[0] == \"g\")\n {\n cg.to = res.i_verts.length;\n if(res.groups[cds[1]] == null) res.groups[cds[1]] = {from:res.i_verts.length, to:0};\n cg = res.groups[cds[1]];\n }\n if(cds[0] == \"v\")\n {\n var x = parseFloat(cds[1]);\n var y = parseFloat(cds[2]);\n var z = parseFloat(cds[3]);\n res.c_verts.push(x,y,z);\n }\n if(cds[0] == \"vt\")\n {\n var x = parseFloat(cds[1]);\n var y = 1-parseFloat(cds[2]);\n res.c_uvt.push(x,y);\n }\n if(cds[0] == \"vn\")\n {\n var x = parseFloat(cds[1]);\n var y = parseFloat(cds[2]);\n var z = parseFloat(cds[3]);\n res.c_norms.push(x,y,z);\n }\n if(cds[0] == \"f\")\n {\n var v0a = cds[1].split(\"/\"), v1a = cds[2].split(\"/\"), v2a = cds[3].split(\"/\");\n var vi0 = parseInt(v0a[0])-1, vi1 = parseInt(v1a[0])-1, vi2 = parseInt(v2a[0])-1;\n var ui0 = parseInt(v0a[1])-1, ui1 = parseInt(v1a[1])-1, ui2 = parseInt(v2a[1])-1;\n var ni0 = parseInt(v0a[2])-1, ni1 = parseInt(v1a[2])-1, ni2 = parseInt(v2a[2])-1;\n\n var vlen = res.c_verts.length/3, ulen = res.c_uvt.length/2, nlen = res.c_norms.length/3;\n if(vi0<0) vi0 = vlen + vi0+1; if(vi1<0) vi1 = vlen + vi1+1;\tif(vi2<0) vi2 = vlen + vi2+1;\n if(ui0<0) ui0 = ulen + ui0+1; if(ui1<0) ui1 = ulen + ui1+1;\tif(ui2<0) ui2 = ulen + ui2+1;\n if(ni0<0) ni0 = nlen + ni0+1; if(ni1<0) ni1 = nlen + ni1+1;\tif(ni2<0) ni2 = nlen + ni2+1;\n\n res.i_verts.push(vi0, vi1, vi2); //cg.i_verts.push(vi0, vi1, vi2)\n res.i_uvt .push(ui0, ui1, ui2); //cg.i_uvt .push(ui0, ui1, ui2);\n res.i_norms.push(ni0, ni1, ni2); //cg.i_norms.push(ni0, ni1, ni2);\n if(cds.length == 5)\n {\n var v3a = cds[4].split(\"/\");\n var vi3 = parseInt(v3a[0])-1, ui3 = parseInt(v3a[1])-1, ni3 = parseInt(v3a[2])-1;\n if(vi3<0) vi3 = vlen + vi3+1;\n if(ui3<0) ui3 = ulen + ui3+1;\n if(ni3<0) ni3 = nlen + ni3+1;\n res.i_verts.push(vi0, vi2, vi3); //cg.i_verts.push(vi0, vi2, vi3);\n res.i_uvt .push(ui0, ui2, ui3); //cg.i_uvt .push(ui0, ui2, ui3);\n res.i_norms.push(ni0, ni2, ni3); //cg.i_norms.push(ni0, ni2, ni3);\n }\n }\n }\n cg.to = res.i_verts.length;\n\n return res;\n}\n\n\nK3D.parse.fromMD2 = function(buff)\n{\n buff = new Uint8Array(buff);\n var res = {};\n var head = {};\n //res.head = head;\n head.ident\t\t\t= K3D.bin.ril(buff, 0); /* magic number: \"IDP2\" */\n head.version\t\t= K3D.bin.ril(buff, 4); /* version: must be 8 */\n\n head.skinwidth\t\t= K3D.bin.ril(buff, 8); /* texture width */\n head.skinheight\t\t= K3D.bin.ril(buff, 12); /* texture height */\n\n head.framesize\t\t= K3D.bin.ril(buff, 16); /* size in bytes of a frame */\n\n head.num_skins\t\t= K3D.bin.ril(buff, 20); /* number of skins */\n head.num_vertices\t= K3D.bin.ril(buff, 24); /* number of vertices per frame */\n head.num_st\t\t\t= K3D.bin.ril(buff, 28); /* number of texture coordinates */\n head.num_tris\t\t= K3D.bin.ril(buff, 32); /* number of triangles */\n head.num_glcmds\t\t= K3D.bin.ril(buff, 36); /* number of opengl commands */\n head.num_frames\t\t= K3D.bin.ril(buff, 40); /* number of frames */\n\n head.offset_skins\t= K3D.bin.ril(buff, 44); /* offset skin data */\n head.offset_st\t\t= K3D.bin.ril(buff, 48); /* offset texture coordinate data */\n head.offset_tris\t= K3D.bin.ril(buff, 52); /* offset triangle data */\n head.offset_frames\t= K3D.bin.ril(buff, 56); /* offset frame data */\n head.offset_glcmds\t= K3D.bin.ril(buff, 60); /* offset OpenGL command data */\n head.offset_end\t\t= K3D.bin.ril(buff, 64); /* offset end of file */\n\n var off = head.offset_st;\n res.c_uvt = [];\n for(var i=0; i<head.num_st; i++)\n {\n var x = K3D.bin.rsl(buff, off )/head.skinwidth;\n var y = K3D.bin.rsl(buff, off+2)/head.skinheight;\n res.c_uvt.push(x,y); off += 4;\n }\n\n var off = head.offset_tris;\n var vi = [], ti = [];\n res.i_verts = vi;\n res.i_uvt = ti;\n //res.tris = {i_verts : vi, i_uvt : ti};\n for(var i=0; i<head.num_tris; i++)\n {\n vi.push(K3D.bin.rsl(buff, off ), K3D.bin.rsl(buff, off+2), K3D.bin.rsl(buff, off+4 ));\n ti.push(K3D.bin.rsl(buff, off+6), K3D.bin.rsl(buff, off+8), K3D.bin.rsl(buff, off+10));\n off += 12;\n }\n\n var off = head.offset_skins;\n res.skins = [];\n for(var i=0; i<head.num_skins; i++)\n {\n res.skins.push(K3D.bin.rASCII0(buff, off));\n off += 64;\n }\n\n var off = head.offset_frames;\n res.frames = [];\n var nms = K3D.parse.fromMD2._normals;\n for(var i=0; i<head.num_frames; i++)\n {\n var fr = {};\n var sx = K3D.bin.rf(buff, off), sy = K3D.bin.rf(buff, off+4), sz = K3D.bin.rf(buff, off+8); off += 12;\n var tx = K3D.bin.rf(buff, off), ty = K3D.bin.rf(buff, off+4), tz = K3D.bin.rf(buff, off+8); off += 12;\n fr.name\t\t = K3D.bin.rASCII0(buff, off); off += 16;\n fr.verts\t = [];\n fr.norms\t = [];\n\n for(var j=0; j<head.num_vertices; j++)\n {\n fr.verts.push(buff[off]*sx+tx, buff[off+1]*sy+ty, buff[off+2]*sz+tz);\n fr.norms.push(nms[3*buff[off+3]], nms[3*buff[off+3]+1], nms[3*buff[off+3]+2]);\n off += 4;\n }\n res.frames.push(fr);\n }\n return res;\n}\n\n\n\n/*\n static MD2 normals\n */\n\nK3D.parse.fromMD2._normals =\n [\n -0.525731, 0.000000, 0.850651,\n -0.442863, 0.238856, 0.864188,\n -0.295242, 0.000000, 0.955423,\n -0.309017, 0.500000, 0.809017,\n -0.162460, 0.262866, 0.951056,\n 0.000000, 0.000000, 1.000000,\n 0.000000, 0.850651, 0.525731,\n -0.147621, 0.716567, 0.681718,\n 0.147621, 0.716567, 0.681718,\n 0.000000, 0.525731, 0.850651,\n 0.309017, 0.500000, 0.809017,\n 0.525731, 0.000000, 0.850651,\n 0.295242, 0.000000, 0.955423,\n 0.442863, 0.238856, 0.864188,\n 0.162460, 0.262866, 0.951056,\n -0.681718, 0.147621, 0.716567,\n -0.809017, 0.309017, 0.500000,\n -0.587785, 0.425325, 0.688191,\n -0.850651, 0.525731, 0.000000,\n -0.864188, 0.442863, 0.238856,\n -0.716567, 0.681718, 0.147621,\n -0.688191, 0.587785, 0.425325,\n -0.500000, 0.809017, 0.309017,\n -0.238856, 0.864188, 0.442863,\n -0.425325, 0.688191, 0.587785,\n -0.716567, 0.681718, -0.147621,\n -0.500000, 0.809017, -0.309017,\n -0.525731, 0.850651, 0.000000,\n 0.000000, 0.850651, -0.525731,\n -0.238856, 0.864188, -0.442863,\n 0.000000, 0.955423, -0.295242,\n -0.262866, 0.951056, -0.162460,\n 0.000000, 1.000000, 0.000000,\n 0.000000, 0.955423, 0.295242,\n -0.262866, 0.951056, 0.162460,\n 0.238856, 0.864188, 0.442863,\n 0.262866, 0.951056, 0.162460,\n 0.500000, 0.809017, 0.309017,\n 0.238856, 0.864188, -0.442863,\n 0.262866, 0.951056, -0.162460,\n 0.500000, 0.809017, -0.309017,\n 0.850651, 0.525731, 0.000000,\n 0.716567, 0.681718, 0.147621,\n 0.716567, 0.681718, -0.147621,\n 0.525731, 0.850651, 0.000000,\n 0.425325, 0.688191, 0.587785,\n 0.864188, 0.442863, 0.238856,\n 0.688191, 0.587785, 0.425325,\n 0.809017, 0.309017, 0.500000,\n 0.681718, 0.147621, 0.716567,\n 0.587785, 0.425325, 0.688191,\n 0.955423, 0.295242, 0.000000,\n 1.000000, 0.000000, 0.000000,\n 0.951056, 0.162460, 0.262866,\n 0.850651, -0.525731, 0.000000,\n 0.955423, -0.295242, 0.000000,\n 0.864188, -0.442863, 0.238856,\n 0.951056, -0.162460, 0.262866,\n 0.809017, -0.309017, 0.500000,\n 0.681718, -0.147621, 0.716567,\n 0.850651, 0.000000, 0.525731,\n 0.864188, 0.442863, -0.238856,\n 0.809017, 0.309017, -0.500000,\n 0.951056, 0.162460, -0.262866,\n 0.525731, 0.000000, -0.850651,\n 0.681718, 0.147621, -0.716567,\n 0.681718, -0.147621, -0.716567,\n 0.850651, 0.000000, -0.525731,\n 0.809017, -0.309017, -0.500000,\n 0.864188, -0.442863, -0.238856,\n 0.951056, -0.162460, -0.262866,\n 0.147621, 0.716567, -0.681718,\n 0.309017, 0.500000, -0.809017,\n 0.425325, 0.688191, -0.587785,\n 0.442863, 0.238856, -0.864188,\n 0.587785, 0.425325, -0.688191,\n 0.688191, 0.587785, -0.425325,\n -0.147621, 0.716567, -0.681718,\n -0.309017, 0.500000, -0.809017,\n 0.000000, 0.525731, -0.850651,\n -0.525731, 0.000000, -0.850651,\n -0.442863, 0.238856, -0.864188,\n -0.295242, 0.000000, -0.955423,\n -0.162460, 0.262866, -0.951056,\n 0.000000, 0.000000, -1.000000,\n 0.295242, 0.000000, -0.955423,\n 0.162460, 0.262866, -0.951056,\n -0.442863, -0.238856, -0.864188,\n -0.309017, -0.500000, -0.809017,\n -0.162460, -0.262866, -0.951056,\n 0.000000, -0.850651, -0.525731,\n -0.147621, -0.716567, -0.681718,\n 0.147621, -0.716567, -0.681718,\n 0.000000, -0.525731, -0.850651,\n 0.309017, -0.500000, -0.809017,\n 0.442863, -0.238856, -0.864188,\n 0.162460, -0.262866, -0.951056,\n 0.238856, -0.864188, -0.442863,\n 0.500000, -0.809017, -0.309017,\n 0.425325, -0.688191, -0.587785,\n 0.716567, -0.681718, -0.147621,\n 0.688191, -0.587785, -0.425325,\n 0.587785, -0.425325, -0.688191,\n 0.000000, -0.955423, -0.295242,\n 0.000000, -1.000000, 0.000000,\n 0.262866, -0.951056, -0.162460,\n 0.000000, -0.850651, 0.525731,\n 0.000000, -0.955423, 0.295242,\n 0.238856, -0.864188, 0.442863,\n 0.262866, -0.951056, 0.162460,\n 0.500000, -0.809017, 0.309017,\n 0.716567, -0.681718, 0.147621,\n 0.525731, -0.850651, 0.000000,\n -0.238856, -0.864188, -0.442863,\n -0.500000, -0.809017, -0.309017,\n -0.262866, -0.951056, -0.162460,\n -0.850651, -0.525731, 0.000000,\n -0.716567, -0.681718, -0.147621,\n -0.716567, -0.681718, 0.147621,\n -0.525731, -0.850651, 0.000000,\n -0.500000, -0.809017, 0.309017,\n -0.238856, -0.864188, 0.442863,\n -0.262866, -0.951056, 0.162460,\n -0.864188, -0.442863, 0.238856,\n -0.809017, -0.309017, 0.500000,\n -0.688191, -0.587785, 0.425325,\n -0.681718, -0.147621, 0.716567,\n -0.442863, -0.238856, 0.864188,\n -0.587785, -0.425325, 0.688191,\n -0.309017, -0.500000, 0.809017,\n -0.147621, -0.716567, 0.681718,\n -0.425325, -0.688191, 0.587785,\n -0.162460, -0.262866, 0.951056,\n 0.442863, -0.238856, 0.864188,\n 0.162460, -0.262866, 0.951056,\n 0.309017, -0.500000, 0.809017,\n 0.147621, -0.716567, 0.681718,\n 0.000000, -0.525731, 0.850651,\n 0.425325, -0.688191, 0.587785,\n 0.587785, -0.425325, 0.688191,\n 0.688191, -0.587785, 0.425325,\n -0.955423, 0.295242, 0.000000,\n -0.951056, 0.162460, 0.262866,\n -1.000000, 0.000000, 0.000000,\n -0.850651, 0.000000, 0.525731,\n -0.955423, -0.295242, 0.000000,\n -0.951056, -0.162460, 0.262866,\n -0.864188, 0.442863, -0.238856,\n -0.951056, 0.162460, -0.262866,\n -0.809017, 0.309017, -0.500000,\n -0.864188, -0.442863, -0.238856,\n -0.951056, -0.162460, -0.262866,\n -0.809017, -0.309017, -0.500000,\n -0.681718, 0.147621, -0.716567,\n -0.681718, -0.147621, -0.716567,\n -0.850651, 0.000000, -0.525731,\n -0.688191, 0.587785, -0.425325,\n -0.587785, 0.425325, -0.688191,\n -0.425325, 0.688191, -0.587785,\n -0.425325, -0.688191, -0.587785,\n -0.587785, -0.425325, -0.688191,\n -0.688191, -0.587785, -0.425325\n ];\n\nK3D.parse.fromCollada = function(buff)\n{\n var str = K3D.parse._buffToStr(buff);\n var xml = new DOMParser().parseFromString(str,\"text/xml\");\n xml = xml.childNodes[0];\n var resp = {};\n\n //console.log(xml);\n\n var ass = xml.getElementsByTagName(\"asset\" )[0];\n var geo = xml.getElementsByTagName(\"library_geometries\")[0];\n var ima = xml.getElementsByTagName(\"library_images\" )[0];\n var mat = xml.getElementsByTagName(\"library_materials\" )[0];\n var eff = xml.getElementsByTagName(\"library_effects\" )[0];\n\n //console.log(xml);\n if(ass) resp.asset \t\t= K3D.parse.fromCollada._asset (ass);\n if(geo) resp.geometries = K3D.parse.fromCollada._libGeometries(geo);\n if(ima) resp.images = K3D.parse.fromCollada._libImages (ima);\n if(mat) resp.materials = K3D.parse.fromCollada._libMaterials (mat);\n if(eff) resp.effects = K3D.parse.fromCollada._libEffects (eff);\n return resp;\n}\n\nK3D.parse.fromCollada._asset = function(xml)\n{\n //console.log(xml);\n return {\n created : xml.getElementsByTagName(\"created\" )[0].textContent,\n modified: xml.getElementsByTagName(\"modified\")[0].textContent,\n up_axis : xml.getElementsByTagName(\"up_axis\" )[0].textContent\n };\n}\n\nK3D.parse.fromCollada._libGeometries = function(xml)\n{\n xml = xml.getElementsByTagName(\"geometry\");\n var res = [];\n for(var i=0; i<xml.length; i++)\n {\n var g = xml[i];\n var o = K3D.parse.fromCollada._getMesh(g.getElementsByTagName(\"mesh\")[0]);\n res.push(o);\n }\n return res;\n}\n\nK3D.parse.fromCollada._getMesh = function(mesh)\n{\n //console.log(mesh);\n var res = {};\n var ss = mesh.getElementsByTagName(\"source\");\n var sources = res.sources = {};\n for(var i=0; i<ss.length; i++)\n {\n var farr = ss[i].getElementsByTagName(\"float_array\")[0].textContent.split(\" \");\n var fl = farr.length - (farr[farr.length-1] == \"\" ? 1 : 0);\n var arr = new Array(fl);\n for(var j=0; j<fl; j++) arr[j] = parseFloat(farr[j]);\n sources[ss[i].getAttribute(\"id\")] = arr;\n }\n\n res.triangles = [];\n var tgs = mesh.getElementsByTagName(\"triangles\");\n if(tgs == null) return res;\n for(var i=0; i<tgs.length; i++)\n {\n var t = {};\n var tnode = tgs[i];\n t.material = tnode.getAttribute(\"material\");\n var inputs = tnode.getElementsByTagName(\"input\");\n var inds = [];\n for(var j=0; j<inputs.length; j++)\n {\n var inp = inputs[j], arr = [];\n inds[parseInt(inp.getAttribute(\"offset\"))] = arr;\n var par = inp.getAttribute(\"semantic\");\n t[\"s_\"+par] = (par == \"VERTEX\") ?\n mesh.getElementsByTagName(\"vertices\")[0].getElementsByTagName(\"input\")[0].getAttribute(\"source\").substring(1)\n : inp.getAttribute(\"source\").substring(1);\n\n t[\"i_\"+par] = arr;\n var psrc = sources[t[\"s_\"+par]];\n }\n var indices = tnode.getElementsByTagName(\"p\")[0].textContent.split(\" \");\n var inum = 3*Math.floor(indices.length/3);\n for(var j=0; j<inum; j++) inds[j%inputs.length].push(parseInt(indices[j]));\n\n /*\n if(t.s_VERTEX ) t.u_VERTEX = K3D.edit.unwrap(t.i_VERTEX , sources[t.s_VERTEX ], 3);\n if(t.s_TEXCOORD) t.u_TEXCOORD = K3D.edit.unwrap(t.i_TEXCOORD, sources[t.s_TEXCOORD], 2);\n if(t.s_NORMAL ) t.u_NORMAL = K3D.edit.unwrap(t.i_NORMAL , sources[t.s_NORMAL ], 3);\n //*/\n //if(t.s_TEXCOORD) for(var j=1; j<t.u_TEXCOORD.length; j+=2) t.u_TEXCOORD[j] = 1 - t.u_TEXCOORD[j];\n\n /*\n t.u_INDEX = new Array(t.i_VERTEX.length);\n for(var j=0; j<t.i_VERTEX.length; j++) t.u_INDEX[j] = j;\n */\n\n res.triangles.push(t);\n }\n return res;\n}\n\nK3D.parse.fromCollada._libImages = function(xml)\n{\n xml = xml.getElementsByTagName(\"image\");\n var res = {};\n for(var i=0; i<xml.length; i++)\n {\n res[xml[i].getAttribute(\"id\")] = xml[i].getElementsByTagName(\"init_from\")[0].textContent;\n }\n return res;\n}\n\nK3D.parse.fromCollada._libMaterials = function(xml)\n{\n xml = xml.getElementsByTagName(\"material\");\n var res = {};\n for(var i=0; i<xml.length; i++)\n {\n res[xml[i].getAttribute(\"name\")] = xml[i].getElementsByTagName(\"instance_effect\")[0].getAttribute(\"url\").substring(1);\n }\n return res;\n}\n\nK3D.parse.fromCollada._libEffects = function(xml)\n{\n xml = xml.getElementsByTagName(\"effect\");\n var res = {};\n for(var i=0; i<xml.length; i++)\n {\n var eff = {};\n var params = xml[i].getElementsByTagName(\"newparam\");\n for(var j=0; j<params.length; j++)\n {\n var srf = params[j].getElementsByTagName(\"surface\")[0];\n if(srf) eff.surface = srf.getElementsByTagName(\"init_from\")[0].textContent;\n }\n res[xml[i].getAttribute(\"id\")] = eff;\n }\n return res;\n}\n\n\n\n\n\nK3D.parse.from3DS = function(buff)\n{\n buff = new Uint8Array(buff);\n var res = {};\n if(K3D.bin.rsl(buff, 0) != 0x4d4d) return null;\n var lim = K3D.bin.ril(buff, 2);\n\n var off = 6;\n while(off < lim)\n {\n var cid = K3D.bin.rsl(buff, off);\n var lng = K3D.bin.ril(buff, off+2);\n //console.log(cid.toString(16), lng);\n\n if(cid == 0x3d3d) res.edit = K3D.parse.from3DS._edit3ds(buff, off, lng);\n if(cid == 0xb000) res.keyf = K3D.parse.from3DS._keyf3ds(buff, off, lng);\n\n off += lng;\n }\n return res;\n}\n\nK3D.parse.from3DS._edit3ds = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = {};\n var off = coff+6;\n while(off < coff+clng)\n {\n var cid = K3D.bin.rsl(buff, off);\n var lng = K3D.bin.ril(buff, off+2);\n //console.log(\"\\t\", cid.toString(16), lng);\n\n if(cid == 0x4000) { if(res.objects==null) res.objects = []; res.objects.push(K3D.parse.from3DS._edit_object(buff, off, lng)); }\n //if(cid == 0xb000) res.KEYF3DS = K3D.parse.from3DS._keyf3ds(buff, off, lng);\n\n off += lng;\n }\n return res;\n}\n\nK3D.parse.from3DS._keyf3ds = function(buff, coff, clng)\n{\n var res = {};\n var off = coff+6;\n while(off < coff+clng)\n {\n var cid = K3D.bin.rsl(buff, off);\n var lng = K3D.bin.ril(buff, off+2);\n //console.log(\"\\t\\t\", cid.toString(16), lng);\n\n //if(cid == 0x4000) { res.objects.push(K3D.parse.from3DS._edit_object(buff, off, lng)); }\n if(cid == 0xb002) { if(res.desc==null) res.desc = []; res.desc.push(K3D.parse.from3DS._keyf_objdes(buff, off, lng)); }\n\n off += lng;\n }\n return res;\n}\n\nK3D.parse.from3DS._keyf_objdes = function(buff, coff, clng)\n{\n var res = {};\n var off = coff+6;\n while(off < coff+clng)\n {\n var cid = K3D.bin.rsl(buff, off);\n var lng = K3D.bin.ril(buff, off+2);\n //console.log(\"\\t\\t\\t\", cid.toString(16), lng);\n\n if(cid == 0xb010) res.hierarchy = K3D.parse.from3DS._keyf_objhierarch(buff, off, lng);\n if(cid == 0xb011) res.dummy_name = K3D.bin.rASCII0(buff, off+6);\n off += lng;\n }\n return res;\n}\n\nK3D.parse.from3DS._keyf_objhierarch = function(buff, coff, clng)\n{\n var res = {};\n var off = coff+6;\n res.name = K3D.bin.rASCII0(buff, off); off += res.name.length+1;\n res.hierarchy = K3D.bin.rsl(buff, off+4);\n return res;\n}\n\nK3D.parse.from3DS._edit_object = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = {};\n var off = coff+6;\n res.name = K3D.bin.rASCII0(buff, off); off += res.name.length+1;\n //console.log(res.name);\n while(off < coff+clng)\n {\n var cid = K3D.bin.rsl(buff, off);\n var lng = K3D.bin.ril(buff, off+2);\n //console.log(\"\\t\\t\", cid.toString(16), lng);\n\n if(cid == 0x4100) res.mesh = K3D.parse.from3DS._obj_trimesh(buff, off, lng);\n //if(cid == 0xb000) res.KEYF3DS = K3D.parse.from3DS._keyf3ds(buff, off, lng);\n\n off += lng;\n }\n return res;\n}\n\nK3D.parse.from3DS._obj_trimesh = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = {};\n var off = coff+6;\n\n while(off < coff+clng)\n {\n var cid = K3D.bin.rsl(buff, off);\n var lng = K3D.bin.ril(buff, off+2);\n //console.log(\"\\t\\t\\t\", cid.toString(16), lng);\n\n if(cid == 0x4110) res.vertices = K3D.parse.from3DS._tri_vertexl (buff, off, lng);\n if(cid == 0x4120) res.indices = K3D.parse.from3DS._tri_facel1 (buff, off, lng);\n if(cid == 0x4140) res.uvt\t\t\t= K3D.parse.from3DS._tri_mappingcoors(buff, off, lng);\n if(cid == 0x4160) res.local\t\t = K3D.parse.from3DS._tri_local (buff, off, lng);\n off += lng;\n }\n return res;\n}\n\nK3D.parse.from3DS._tri_vertexl = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = [];\n var off = coff+6;\n var n = K3D.bin.rsl(buff, off); off += 2;\n for(var i=0; i<n; i++)\n {\n res.push(K3D.bin.rf(buff, off ));\tres.push(K3D.bin.rf(buff, off+4));\tres.push(K3D.bin.rf(buff, off+8));\n off += 12;\n }\n return res;\n}\n\nK3D.parse.from3DS._tri_facel1 = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = [];\n var off = coff+6;\n var n = K3D.bin.rsl(buff, off); off += 2;\n for(var i=0; i<n; i++)\n {\n res.push(K3D.bin.rsl(buff, off ));\n res.push(K3D.bin.rsl(buff, off+2));\n res.push(K3D.bin.rsl(buff, off+4));\n off += 8;\n }\n return res;\n}\n\nK3D.parse.from3DS._tri_mappingcoors = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = [];\n var off = coff+6;\n var n = K3D.bin.rsl(buff, off); off += 2;\n for(var i=0; i<n; i++)\n {\n res.push( K3D.bin.rf(buff, off ));\n res.push(1-K3D.bin.rf(buff, off+4));\n off += 8;\n }\n return res;\n}\n\nK3D.parse.from3DS._tri_local = function(buff, coff, clng)\t// buffer, chunk offset, length\n{\n var res = {};\n var off = coff+6;\n res.X = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\n res.Y = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\n res.Z = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\n res.C = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;\n return res;\n}\n\nK3D.parse.fromBIV = function(buff)\n{\n buff = new Uint8Array(buff);\n var res = {};\n\n var head = {};\n\n head.id\t\t= K3D.bin.ril(buff, 0);\n\n head.verS\t= K3D.bin.ril(buff, 4);\n head.texS\t= K3D.bin.ril(buff, 8);\n head.indS\t= K3D.bin.ril(buff, 12);\n\n head.verO\t= K3D.bin.ril(buff, 16);\n head.verL\t= K3D.bin.ril(buff, 20);\n head.texO\t= K3D.bin.ril(buff, 24);\n head.texL\t= K3D.bin.ril(buff, 28);\n head.indO\t= K3D.bin.ril(buff, 32);\n head.indL\t= K3D.bin.ril(buff, 36);\n\n if(head.verO != 0) res.vertices = K3D.parse.fromBIV._readFloats(buff, head.verO, head.verL);\n if(head.texO != 0) res.uvt = K3D.parse.fromBIV._readFloats(buff, head.texO, head.texL);\n if(head.indO != 0) res.indices = K3D.parse.fromBIV._readInts (buff, head.indO, head.indL, head.indS);\n\n return res;\n}\n\nK3D.parse.toBIV = function(obj)\n{\n var maxi = 0;\n for(var i=0; i<obj.indices.length; i++)\tmaxi = Math.max(maxi, obj.indices[i]);\n\n var indS = 32;\n if(maxi<=0xffff) indS = 16;\n\n var len = 40;\n if(obj.vertices) len+=obj.vertices.length*4;\n if(obj.uvt ) len+=obj.uvt .length*4;\n if(obj.indices ) len+=obj.indices .length*indS/8;\n\n\n var buff = new Uint8Array(len);\n\n K3D.bin.wil(buff, 0, 0x6976616e);\n\n K3D.bin.wil(buff, 4, 32);\n K3D.bin.wil(buff, 8, 32);\n K3D.bin.wil(buff, 12, indS);\n\n var off = 40;\n if(obj.vertices)\n {\n K3D.bin.wil(buff, 16, off);\n K3D.bin.wil(buff, 20, 4*obj.vertices.length);\n K3D.parse.fromBIV._writeFloats(buff, off, obj.vertices);\n off += 4*obj.vertices.length;\n }\n if(obj.uvt)\n {\n K3D.bin.wil(buff, 24, off);\n K3D.bin.wil(buff, 28, 4*obj.uvt.length);\n K3D.parse.fromBIV._writeFloats(buff, off, obj.uvt);\n off += 4*obj.uvt.length;\n }\n if(obj.indices)\n {\n K3D.bin.wil(buff, 32, off);\n K3D.bin.wil(buff, 36, 4*obj.indices.length);\n K3D.parse.fromBIV._writeInts (buff, off, obj.indices, indS);\n }\n return buff.buffer;\n}\n\nK3D.parse.fromBIV._readFloats = function(buff, off, len)\n{\n var arr = [];\n for(var i=0; i<len/4; i++) arr.push( K3D.bin.rf(buff, off+4*i));\n return arr;\n}\n\nK3D.parse.fromBIV._writeFloats = function(buff, off, arr)\n{\n for(var i=0; i<arr.length; i++) K3D.bin.wf(buff, off+4*i, arr[i]);\n}\n\nK3D.parse.fromBIV._readInts = function(buff, off, len, cs)\n{\n var arr = [];\n for(var i=0; i<len/4; i++)\n {\n if(cs==16) arr.push( K3D.bin.rsl(buff, off+2*i));\n if(cs==32) arr.push( K3D.bin.ril(buff, off+4*i));\n }\n return arr;\n}\n\nK3D.parse.fromBIV._writeInts = function(buff, off, arr, cs)\n{\n for(var i=0; i<arr.length; i++)\n {\n if(cs==16) K3D.bin.wsl(buff, off+2*i, arr[i]);\n if(cs==32) K3D.bin.wil(buff, off+4*i, arr[i]);\n }\n}\nK3D.gen = {};\n\nK3D.gen.Plane = function(sw, sh, tsw, tsh)\n{\n if(!tsw) tsw = 1;\n if(!tsh) tsh = 1;\n var r = {verts:[], inds:[], uvt:[]};\n var ssw = sw+1, ssh = sh+1\n for(var i=0; i<ssh; i++)\n {\n for(var j=0; j<ssw; j++)\n {\n var x = -1 + j*(2/sw);\n var y = -1 + i*(2/sh);\n r.verts.push(x, y, 0);\n r.uvt.push(tsw*j/sw, tsh*i/sh);\n if(i<sh && j<sw)\n r.inds.push(i*ssw+j, i*ssw+j+1, (i+1)*ssw+j, i*ssw+j+1, (i+1)*ssw+j, (i+1)*ssw+j+1);\n }\n }\n return r;\n}\nK3D.gen.Cube = function()\n{\n var r = {\n verts:[\t-1, 1,-1, 1, 1,-1, -1,-1,-1, 1,-1,-1, // front\n -1, 1, 1, 1, 1, 1, -1,-1, 1, 1,-1, 1, // back\n\n -1, 1, 1, -1, 1,-1, -1,-1, 1, -1,-1,-1, // left\n 1, 1, 1, 1, 1,-1, 1,-1, 1, 1,-1,-1, // right\n\n -1, 1,-1, 1, 1,-1, -1, 1, 1, 1, 1, 1, // top\n -1,-1,-1, 1,-1,-1, -1,-1, 1, 1,-1, 1 // bottom\n ],\n inds:[\t0,1,2, 1,2,3, 4,5,6, 5,6,7,\n 8,9,10, 9,10,11, 12,13,14, 13,14,15,\n 16,17,18, 17,18,19, 20,21,22, 21,22,23\n ],\n uvt:[\n 1/4,1/4, 2/4,1/4, 1/4,2/4, 2/4,2/4, // front\n 4/4,1/4, 3/4,1/4, 4/4,2/4, 3/4,2/4, // back\n\n 0/4,1/4, 1/4,1/4, 0/4,2/4, 1/4,2/4, // left\n 3/4,1/4, 2/4,1/4, 3/4,2/4, 2/4,2/4, // right\n\n 1/4,1/4, 2/4,1/4, 1/4,0/4, 2/4,0/4, // top\n 1/4,2/4, 2/4,2/4, 1/4,3/4, 2/4,3/4, // bottom\n ]\n };\n return r;\n};\n\nK3D.gen.Sphere = function(sx, sy){\n var r = {verts:[], inds:[], uvt:[]};\n\n var dx = 2*Math.PI/sx;\n var dy = Math.PI/sy;\n var nx = sx+1, ny = sy+1;\n for(var i=0; i<ny; i++)\t// rows\n {\n for(var j=0; j<nx; j++) // cols\n {\n var lat = -Math.PI/2 + i*Math.PI/sy;\n var lon = j*2*Math.PI/sx;\n var x = Math.cos(lat) * Math.cos(lon);\n var y = Math.sin(lat);\n var z = Math.cos(lat) * Math.sin(lon);\n\n r.verts.push(x,y,z);\n r.uvt.push(j/sx, i/sy);\n if(i<sy && j<sx) // 6 indices for 2 triangles\n r.inds.push(nx*i+j, nx*i+j+1, nx*(i+1)+j, nx*i+j+1, nx*(i+1)+j, nx*(i+1)+j+1);\n }\n }\n return r;\n};\n\nK3D.mat = {};\n\nK3D.mat.scale = function(x,y,z){\n return [\n x,0,0,0,\n 0,y,0,0,\n 0,0,z,0,\n 0,0,0,1\n ];\n};\n\nK3D.mat.translate = function(x,y,z){\n return [\n 1,0,0,0,\n 0,1,0,0,\n 0,0,1,0,\n x,y,z,1\n ];\n};\n\nK3D.mat.rotateDeg = function(x,y,z){\n var r = Math.PI/180;\n return K3D.mat.rotate(x*r, y*r, z*r);\n};\n\nK3D.mat.rotate = function(x,y,z){\n var m = [\n 1,0,0,0,\n 0,1,0,0,\n 0,0,1,0,\n 0,0,0,1\n ];\n var a = x;\t// alpha\n var b = y;\t// beta\n var g = z;\t// gama\n\n var ca = Math.cos(a), cb = Math.cos(b), cg = Math.cos(g);\n var sa = Math.sin(a), sb = Math.sin(b), sg = Math.sin(g);\n\n m[0] = cb*cg;\t\t\t\tm[1] = -cb*sg;\t\t\t\t\tm[2 ] = sb;\n m[4] = (ca*sg+sa*sb*cg);\tm[5] = (ca*cg-sa*sb*sg);\t\tm[6 ] = -sa*cb;\n m[8] = (sa*sg-ca*sb*cg);\tm[9] = (sa*cg+ca*sb*sg);\t\tm[10] = ca*cb;\n\n return m;\n};\n\n\nK3D.edit = {};\n\nK3D.edit.interpolate = function(a, b, d, t){\n for(var i=0; i<a.length; i++) d[i] = a[i] + t*(b[i] - a[i]);\n};\n\n\nK3D.edit.transform = function(a, m){\n for(var i=0; i<a.length; i+=3) {\n var x = a[i], y = a[i+1], z = a[i+2];\n a[i+0] = m[0]*x + m[4]*y + m[8 ]*z + m[12];\n a[i+1] = m[1]*x + m[5]*y + m[9 ]*z + m[13];\n a[i+2] = m[2]*x + m[6]*y + m[10]*z + m[14];\n }\n};\n\n// starting indices, starting coordinates, coordinates per index\n\nK3D.edit.unwrap = function(ind, crd, cpi){\n var ncrd = new Array(Math.floor(ind.length/3)*cpi);\n for(var i=0; i<ind.length; i++)\n {\n for(var j=0; j<cpi; j++)\n {\n ncrd[i*cpi+j] = crd[ind[i]*cpi+j];\n }\n }\n return ncrd;\n};\n\n// current indices, new indices, current array, coordinates per vertex\n\nK3D.edit.remap = function(ind, nind, arr, cpi){\n var ncrd = new Array(arr.length);\n for(var i=0; i<ind.length; i++)\n {\n for(var j=0; j<cpi; j++)\n {\n ncrd[nind[i]*cpi+j] = arr[ind[i]*cpi+j];\n }\n }\n return ncrd;\n};\n\nK3D.utils = {};\n\nK3D.utils.getAABB = function(vts)\n{\n var minx, miny, minz, maxx, maxy, maxz;\n minx = miny = minz = 999999999;\n maxx = maxy = maxz = -minx;\n\n for(var i=0; i<vts.length; i+=3)\n {\n var vx = vts[i+0];\n var vy = vts[i+1];\n var vz = vts[i+2];\n if(vx<minx) minx = vx; if(vx>maxx) maxx = vx;\n if(vy<miny) miny = vy; if(vy>maxy) maxy = vy;\n if(vz<minz) minz = vz; if(vy>maxz) maxz = vz;\n }\n return {min:{x:minx, y:miny, z:minz}, max:{x:maxx, y:maxy, z:maxz}};\n};\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/libs/k3d.js?");
|
|
2958
2958
|
|
|
2959
2959
|
/***/ }),
|
|
2960
2960
|
|
|
@@ -3044,7 +3044,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3044
3044
|
\*************************************/
|
|
3045
3045
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3046
3046
|
|
|
3047
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LOD: () => (/* binding */ LOD)\n/* harmony export */ });\n/* harmony import */ var _Component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _LODCullingManager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LODCullingManager */ \"./src/viewer/scene/lod/LODCullingManager.js\");\n\
|
|
3047
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LOD: () => (/* binding */ LOD)\n/* harmony export */ });\n/* harmony import */ var _Component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _LODCullingManager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LODCullingManager */ \"./src/viewer/scene/lod/LODCullingManager.js\");\n\n\n\n/**\n * Manages LOD culling for {@link SceneModel} implementations.\n */\nclass LOD extends _Component__WEBPACK_IMPORTED_MODULE_0__.Component {\n\t/** @private */\n\tconstructor(scene, cfg = {}) {\n\t\tsuper(scene, cfg);\n\n\t\tthis._scene = scene;\n\t\tthis._lodLevels = [2000, 600, 150, 80, 20];\n\t\tthis._lodManagers = {};\n\t\tthis._lodManagerList = [];\n\n\t\tthis.enabled = cfg.enabled;\n\t\tthis.targetFPS = cfg.targetFPS;\n\n\t\tthis._init();\n\t}\n\n\t_init() {\n\t\tconst MAX_NUM_TICKS = 4;\n\t\tconst tickTimeArray = new Array(MAX_NUM_TICKS);\n\n\t\tlet numTick = 0;\n\t\tlet currentFPS = -1;\n\t\tlet preRenderTime = Date.now();\n\t\tlet deltaTime = 0;\n\t\tlet sceneTick = 0;\n\t\tlet lastTickCameraMoved = sceneTick;\n\n\t\tthis._scene.on(\"rendering\", () => {\n\t\t\t// Apply LOD-culling before rendering the scene\n\t\t\tif (currentFPS === -1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (let i = 0, len = this._lodManagerList.length; i < len; i++) {\n\t\t\t\tthis._lodManagerList[i].applyLodCulling(currentFPS);\n\t\t\t}\n\t\t});\n\n\t\tthis._scene.on(\"rendered\", () => {\n\t\t\tpreRenderTime = Date.now();\n\t\t\twindow.requestAnimationFrame(() => {\n\t\t\t\tnumTick++;\n\t\t\t\tconst newTime = Date.now();\n\t\t\t\tdeltaTime = newTime - preRenderTime;\n\t\t\t\tpreRenderTime = newTime;\n\t\t\t\ttickTimeArray[numTick % MAX_NUM_TICKS] = deltaTime;\n\t\t\t\tlet sumTickTimes = 0;\n\t\t\t\tif (numTick > MAX_NUM_TICKS) {\n\t\t\t\t\tfor (let i = 0; i < MAX_NUM_TICKS; i++) {\n\t\t\t\t\t\tsumTickTimes += tickTimeArray[i];\n\t\t\t\t\t}\n\t\t\t\t\tcurrentFPS = (MAX_NUM_TICKS / sumTickTimes) * 1000;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tthis._scene.camera.on(\"matrix\", () => {\n\t\t\tlastTickCameraMoved = sceneTick;\n\t\t});\n\n\t\tthis._scene.on(\"tick\", () => {\n\t\t\tif (sceneTick - lastTickCameraMoved > 3) {\n\t\t\t\tfor (let i = 0, len = this._lodManagerList.length; i < len; i++) {\n\t\t\t\t\t// Call LOD-culling tasks\n\t\t\t\t\tthis._lodManagerList[i].resetLodCulling();\n\t\t\t\t}\n\t\t\t}\n\t\t\tsceneTick++;\n\t\t});\n\t}\n\n\t/**\n\t * Sets whether LOD is enabled for the {@link Scene}.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset enabled(value) {\n\t\tvalue = !!value;\n\t\tif (this._enabled === value) {\n\t\t\treturn;\n\t\t}\n\t\tthis._enabled = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether LOD is enabled for the {@link Scene}.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget enabled() {\n\t\treturn this._enabled;\n\t}\n\n\t/**\n\t * Sets the maximum area that LOD takes into account when checking for possible occlusion for each fragment.\n\t *\n\t * Default value is ````30.0````.\n\t *\n\t * @type {Number}\n\t */\n\tset targetFPS(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 30.0;\n\t\t}\n\t\tif (this._targetFPS === value) {\n\t\t\treturn;\n\t\t}\n\t\tthis._targetFPS = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the maximum area that LOD takes into account when checking for possible occlusion for each fragment.\n\t *\n\t * Default value is ````30.0````.\n\t *\n\t * @type {Number}\n\t */\n\tget targetFPS() {\n\t\treturn this._targetFPS;\n\t}\n\n\t/**\n\t * Called within SceneModel constructors\n\t * @private\n\t */\n\tgetLODManager(sceneModel) {\n\t\tconst lodManager = new _LODCullingManager__WEBPACK_IMPORTED_MODULE_1__.LODCullingManager(this.scene, sceneModel, this._lodLevels, this._targetFPS);\n\t\tthis._lodManagers[lodManager.id] = lodManager;\n\t\tthis._lodManagerList = Object.values(this._lodManagers);\n\t\treturn lodManager;\n\t}\n\n\t/**\n\t * Called within SceneModel destructors\n\t * @private\n\t */\n\tputLODManager(lodManager) {\n\t\tdelete this._lodManagers[lodManager.id];\n\t\tthis._lodManagerList = Object.values(this._lodManagers);\n\t}\n\n\t/**\n\t * Destroys this component.\n\t *\n\t * @private\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\t}\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/lod/LOD.js?");
|
|
3048
3048
|
|
|
3049
3049
|
/***/ }),
|
|
3050
3050
|
|
|
@@ -3244,7 +3244,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3244
3244
|
\***********************************************************/
|
|
3245
3245
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3246
3246
|
|
|
3247
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ geometryCompressionUtils: () => (/* binding */ geometryCompressionUtils)\n/* harmony export */ });\n/* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math.js */ \"./src/viewer/scene/math/math.js\");\n/**\r\n * Private geometry compression and decompression utilities.\r\n */\r\n\r\n\r\n\r\n/**\r\n * @private\r\n * @param array\r\n * @returns {{min: Float32Array, max: Float32Array}}\r\n */\r\nfunction getPositionsBounds(array) {\r\n const min = new Float32Array(3);\r\n const max = new Float32Array(3);\r\n let i, j;\r\n for (i = 0; i < 3; i++) {\r\n min[i] = Number.MAX_VALUE;\r\n max[i] = -Number.MAX_VALUE;\r\n }\r\n for (i = 0; i < array.length; i += 3) {\r\n for (j = 0; j < 3; j++) {\r\n min[j] = Math.min(min[j], array[i + j]);\r\n max[j] = Math.max(max[j], array[i + j]);\r\n }\r\n }\r\n return {\r\n min: min,\r\n max: max\r\n };\r\n}\r\n\r\nconst createPositionsDecodeMatrix = (function () {\r\n const translate = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n const scale = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n return function (aabb, positionsDecodeMatrix) {\r\n positionsDecodeMatrix = positionsDecodeMatrix || _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n const xmin = aabb[0];\r\n const ymin = aabb[1];\r\n const zmin = aabb[2];\r\n const xwid = aabb[3] - xmin;\r\n const ywid = aabb[4] - ymin;\r\n const zwid = aabb[5] - zmin;\r\n const maxInt = 65535;\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(translate);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.translationMat4v(aabb, translate);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(scale);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.scalingMat4v([xwid / maxInt, ywid / maxInt, zwid / maxInt], scale);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, positionsDecodeMatrix);\r\n return positionsDecodeMatrix;\r\n };\r\n})();\r\n\r\n/**\r\n * @private\r\n */\r\nvar compressPositions = (function () { // http://cg.postech.ac.kr/research/mesh_comp_mobile/mesh_comp_mobile_conference.pdf\r\n const translate = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n const scale = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\r\n return function (array, min, max) {\r\n const quantized = new Uint16Array(array.length);\r\n const multiplier = new Float32Array([\r\n max[0] !== min[0] ? 65535 / (max[0] - min[0]) : 0,\r\n max[1] !== min[1] ? 65535 / (max[1] - min[1]) : 0,\r\n max[2] !== min[2] ? 65535 / (max[2] - min[2]) : 0\r\n ]);\r\n let i;\r\n for (i = 0; i < array.length; i += 3) {\r\n quantized[i + 0] = Math.max(0, Math.min(65535, Math.floor((array[i + 0] - min[0]) * multiplier[0])));\r\n quantized[i + 1] = Math.max(0, Math.min(65535, Math.floor((array[i + 1] - min[1]) * multiplier[1])));\r\n quantized[i + 2] = Math.max(0, Math.min(65535, Math.floor((array[i + 2] - min[2]) * multiplier[2])));\r\n }\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(translate);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.translationMat4v(min, translate);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(scale);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.scalingMat4v([\r\n (max[0] - min[0]) / 65535,\r\n (max[1] - min[1]) / 65535,\r\n (max[2] - min[2]) / 65535\r\n ], scale);\r\n const decodeMat = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\r\n return {\r\n quantized: quantized,\r\n decodeMatrix: decodeMat\r\n };\r\n };\r\n})();\r\n\r\nfunction compressPosition(p, aabb, q) {\r\n const multiplier = new Float32Array([\r\n aabb[3] !== aabb[0] ? 65535 / (aabb[3] - aabb[0]) : 0,\r\n aabb[4] !== aabb[1] ? 65535 / (aabb[4] - aabb[1]) : 0,\r\n aabb[5] !== aabb[2] ? 65535 / (aabb[5] - aabb[2]) : 0\r\n ]);\r\n q[0] = Math.max(0, Math.min(65535, Math.floor((p[0] - aabb[0]) * multiplier[0])));\r\n q[1] = Math.max(0, Math.min(65535, Math.floor((p[1] - aabb[1]) * multiplier[1])));\r\n q[2] = Math.max(0, Math.min(65535, Math.floor((p[2] - aabb[2]) * multiplier[2])));\r\n}\r\n\r\nfunction decompressPosition(position, decodeMatrix, dest) {\r\n dest[0] = position[0] * decodeMatrix[0] + decodeMatrix[12];\r\n dest[1] = position[1] * decodeMatrix[5] + decodeMatrix[13];\r\n dest[2] = position[2] * decodeMatrix[10] + decodeMatrix[14];\r\n return dest;\r\n}\r\n\r\nfunction decompressAABB(aabb, decodeMatrix, dest = aabb) {\r\n dest[0] = aabb[0] * decodeMatrix[0] + decodeMatrix[12];\r\n dest[1] = aabb[1] * decodeMatrix[5] + decodeMatrix[13];\r\n dest[2] = aabb[2] * decodeMatrix[10] + decodeMatrix[14];\r\n dest[3] = aabb[3] * decodeMatrix[0] + decodeMatrix[12];\r\n dest[4] = aabb[4] * decodeMatrix[5] + decodeMatrix[13];\r\n dest[5] = aabb[5] * decodeMatrix[10] + decodeMatrix[14];\r\n return dest;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction decompressPositions(positions, decodeMatrix, dest = new Float32Array(positions.length)) {\r\n for (let i = 0, len = positions.length; i < len; i += 3) {\r\n dest[i + 0] = positions[i + 0] * decodeMatrix[0] + decodeMatrix[12];\r\n dest[i + 1] = positions[i + 1] * decodeMatrix[5] + decodeMatrix[13];\r\n dest[i + 2] = positions[i + 2] * decodeMatrix[10] + decodeMatrix[14];\r\n }\r\n return dest;\r\n}\r\n\r\n//--------------- UVs --------------------------------------------------------------------------------------------------\r\n\r\n/**\r\n * @private\r\n * @param array\r\n * @returns {{min: Float32Array, max: Float32Array}}\r\n */\r\nfunction getUVBounds(array) {\r\n const min = new Float32Array(2);\r\n const max = new Float32Array(2);\r\n let i, j;\r\n for (i = 0; i < 2; i++) {\r\n min[i] = Number.MAX_VALUE;\r\n max[i] = -Number.MAX_VALUE;\r\n }\r\n for (i = 0; i < array.length; i += 2) {\r\n for (j = 0; j < 2; j++) {\r\n min[j] = Math.min(min[j], array[i + j]);\r\n max[j] = Math.max(max[j], array[i + j]);\r\n }\r\n }\r\n return {\r\n min: min,\r\n max: max\r\n };\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nvar compressUVs = (function () {\r\n const translate = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat3();\r\n const scale = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat3();\r\n return function (array, min, max) {\r\n const quantized = new Uint16Array(array.length);\r\n const multiplier = new Float32Array([\r\n 65535 / (max[0] - min[0]),\r\n 65535 / (max[1] - min[1])\r\n ]);\r\n let i;\r\n for (i = 0; i < array.length; i += 2) {\r\n quantized[i + 0] = Math.max(0, Math.min(65535, Math.floor((array[i + 0] - min[0]) * multiplier[0])));\r\n quantized[i + 1] = Math.max(0, Math.min(65535, Math.floor((array[i + 1] - min[1]) * multiplier[1])));\r\n }\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat3(translate);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.translationMat3v(min, translate);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat3(scale);\r\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.scalingMat3v([\r\n (max[0] - min[0]) / 65535,\r\n (max[1] - min[1]) / 65535\r\n ], scale);\r\n const decodeMat = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat3(translate, scale, _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat3());\r\n return {\r\n quantized: quantized,\r\n decodeMatrix: decodeMat\r\n };\r\n };\r\n})();\r\n\r\n\r\n//--------------- Normals ----------------------------------------------------------------------------------------------\r\n\r\n/**\r\n * @private\r\n */\r\nfunction compressNormals(array) { // http://jcgt.org/published/0003/02/01/\r\n\r\n // Note: three elements for each encoded normal, in which the last element in each triplet is redundant.\r\n // This is to work around a mysterious WebGL issue where 2-element normals just wouldn't work in the shader :/\r\n\r\n const encoded = new Int8Array(array.length);\r\n let oct, dec, best, currentCos, bestCos;\r\n for (let i = 0; i < array.length; i += 3) {\r\n // Test various combinations of ceil and floor\r\n // to minimize rounding errors\r\n best = oct = octEncodeVec3(array, i, \"floor\", \"floor\");\r\n dec = octDecodeVec2(oct);\r\n currentCos = bestCos = dot(array, i, dec);\r\n oct = octEncodeVec3(array, i, \"ceil\", \"floor\");\r\n dec = octDecodeVec2(oct);\r\n currentCos = dot(array, i, dec);\r\n if (currentCos > bestCos) {\r\n best = oct;\r\n bestCos = currentCos;\r\n }\r\n oct = octEncodeVec3(array, i, \"floor\", \"ceil\");\r\n dec = octDecodeVec2(oct);\r\n currentCos = dot(array, i, dec);\r\n if (currentCos > bestCos) {\r\n best = oct;\r\n bestCos = currentCos;\r\n }\r\n oct = octEncodeVec3(array, i, \"ceil\", \"ceil\");\r\n dec = octDecodeVec2(oct);\r\n currentCos = dot(array, i, dec);\r\n if (currentCos > bestCos) {\r\n best = oct;\r\n bestCos = currentCos;\r\n }\r\n encoded[i] = best[0];\r\n encoded[i + 1] = best[1];\r\n }\r\n return encoded;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction octEncodeVec3(array, i, xfunc, yfunc) { // Oct-encode single normal vector in 2 bytes\r\n let x = array[i] / (Math.abs(array[i]) + Math.abs(array[i + 1]) + Math.abs(array[i + 2]));\r\n let y = array[i + 1] / (Math.abs(array[i]) + Math.abs(array[i + 1]) + Math.abs(array[i + 2]));\r\n if (array[i + 2] < 0) {\r\n let tempx = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\r\n let tempy = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\r\n x = tempx;\r\n y = tempy;\r\n }\r\n return new Int8Array([\r\n Math[xfunc](x * 127.5 + (x < 0 ? -1 : 0)),\r\n Math[yfunc](y * 127.5 + (y < 0 ? -1 : 0))\r\n ]);\r\n}\r\n\r\n/**\r\n * Decode an oct-encoded normal\r\n */\r\nfunction octDecodeVec2(oct) {\r\n let x = oct[0];\r\n let y = oct[1];\r\n x /= x < 0 ? 127 : 128;\r\n y /= y < 0 ? 127 : 128;\r\n const z = 1 - Math.abs(x) - Math.abs(y);\r\n if (z < 0) {\r\n x = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\r\n y = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\r\n }\r\n const length = Math.sqrt(x * x + y * y + z * z);\r\n return [\r\n x / length,\r\n y / length,\r\n z / length\r\n ];\r\n}\r\n\r\n/**\r\n * Dot product of a normal in an array against a candidate decoding\r\n * @private\r\n */\r\nfunction dot(array, i, vec3) {\r\n return array[i] * vec3[0] + array[i + 1] * vec3[1] + array[i + 2] * vec3[2];\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction decompressUV(uv, decodeMatrix, dest) {\r\n dest[0] = uv[0] * decodeMatrix[0] + decodeMatrix[6];\r\n dest[1] = uv[1] * decodeMatrix[4] + decodeMatrix[7];\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction decompressUVs(uvs, decodeMatrix, dest = new Float32Array(uvs.length)) {\r\n for (let i = 0, len = uvs.length; i < len; i += 3) {\r\n dest[i + 0] = uvs[i + 0] * decodeMatrix[0] + decodeMatrix[6];\r\n dest[i + 1] = uvs[i + 1] * decodeMatrix[4] + decodeMatrix[7];\r\n }\r\n return dest;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction decompressNormal(oct, result) {\r\n let x = oct[0];\r\n let y = oct[1];\r\n x = (2 * x + 1) / 255;\r\n y = (2 * y + 1) / 255;\r\n const z = 1 - Math.abs(x) - Math.abs(y);\r\n if (z < 0) {\r\n x = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\r\n y = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\r\n }\r\n const length = Math.sqrt(x * x + y * y + z * z);\r\n result[0] = x / length;\r\n result[1] = y / length;\r\n result[2] = z / length;\r\n return result;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction decompressNormals(octs, result) {\r\n for (let i = 0, j = 0, len = octs.length; i < len; i += 2) {\r\n let x = octs[i + 0];\r\n let y = octs[i + 1];\r\n x = (2 * x + 1) / 255;\r\n y = (2 * y + 1) / 255;\r\n const z = 1 - Math.abs(x) - Math.abs(y);\r\n if (z < 0) {\r\n x = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\r\n y = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\r\n }\r\n const length = Math.sqrt(x * x + y * y + z * z);\r\n result[j + 0] = x / length;\r\n result[j + 1] = y / length;\r\n result[j + 2] = z / length;\r\n j += 3;\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nconst geometryCompressionUtils = {\r\n\r\n getPositionsBounds: getPositionsBounds,\r\n createPositionsDecodeMatrix: createPositionsDecodeMatrix,\r\n compressPositions: compressPositions,\r\n compressPosition:compressPosition,\r\n decompressPositions: decompressPositions,\r\n decompressPosition: decompressPosition,\r\n decompressAABB: decompressAABB,\r\n\r\n getUVBounds: getUVBounds,\r\n compressUVs: compressUVs,\r\n decompressUVs: decompressUVs,\r\n decompressUV: decompressUV,\r\n\r\n compressNormals: compressNormals,\r\n decompressNormals: decompressNormals,\r\n decompressNormal: decompressNormal\r\n};\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/math/geometryCompressionUtils.js?");
|
|
3247
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ geometryCompressionUtils: () => (/* binding */ geometryCompressionUtils)\n/* harmony export */ });\n/* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math.js */ \"./src/viewer/scene/math/math.js\");\n/**\n * Private geometry compression and decompression utilities.\n */\n\n\n\n/**\n * @private\n * @param array\n * @returns {{min: Float32Array, max: Float32Array}}\n */\nfunction getPositionsBounds(array) {\n const min = new Float32Array(3);\n const max = new Float32Array(3);\n let i, j;\n for (i = 0; i < 3; i++) {\n min[i] = Number.MAX_VALUE;\n max[i] = -Number.MAX_VALUE;\n }\n for (i = 0; i < array.length; i += 3) {\n for (j = 0; j < 3; j++) {\n min[j] = Math.min(min[j], array[i + j]);\n max[j] = Math.max(max[j], array[i + j]);\n }\n }\n return {\n min: min,\n max: max\n };\n}\n\nconst createPositionsDecodeMatrix = (function () {\n const translate = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n const scale = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n return function (aabb, positionsDecodeMatrix) {\n positionsDecodeMatrix = positionsDecodeMatrix || _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n const xmin = aabb[0];\n const ymin = aabb[1];\n const zmin = aabb[2];\n const xwid = aabb[3] - xmin;\n const ywid = aabb[4] - ymin;\n const zwid = aabb[5] - zmin;\n const maxInt = 65535;\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(translate);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.translationMat4v(aabb, translate);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(scale);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.scalingMat4v([xwid / maxInt, ywid / maxInt, zwid / maxInt], scale);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, positionsDecodeMatrix);\n return positionsDecodeMatrix;\n };\n})();\n\n/**\n * @private\n */\nvar compressPositions = (function () { // http://cg.postech.ac.kr/research/mesh_comp_mobile/mesh_comp_mobile_conference.pdf\n const translate = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n const scale = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4();\n return function (array, min, max) {\n const quantized = new Uint16Array(array.length);\n const multiplier = new Float32Array([\n max[0] !== min[0] ? 65535 / (max[0] - min[0]) : 0,\n max[1] !== min[1] ? 65535 / (max[1] - min[1]) : 0,\n max[2] !== min[2] ? 65535 / (max[2] - min[2]) : 0\n ]);\n let i;\n for (i = 0; i < array.length; i += 3) {\n quantized[i + 0] = Math.max(0, Math.min(65535, Math.floor((array[i + 0] - min[0]) * multiplier[0])));\n quantized[i + 1] = Math.max(0, Math.min(65535, Math.floor((array[i + 1] - min[1]) * multiplier[1])));\n quantized[i + 2] = Math.max(0, Math.min(65535, Math.floor((array[i + 2] - min[2]) * multiplier[2])));\n }\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(translate);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.translationMat4v(min, translate);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4(scale);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.scalingMat4v([\n (max[0] - min[0]) / 65535,\n (max[1] - min[1]) / 65535,\n (max[2] - min[2]) / 65535\n ], scale);\n const decodeMat = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat4(translate, scale, _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat4());\n return {\n quantized: quantized,\n decodeMatrix: decodeMat\n };\n };\n})();\n\nfunction compressPosition(p, aabb, q) {\n const multiplier = new Float32Array([\n aabb[3] !== aabb[0] ? 65535 / (aabb[3] - aabb[0]) : 0,\n aabb[4] !== aabb[1] ? 65535 / (aabb[4] - aabb[1]) : 0,\n aabb[5] !== aabb[2] ? 65535 / (aabb[5] - aabb[2]) : 0\n ]);\n q[0] = Math.max(0, Math.min(65535, Math.floor((p[0] - aabb[0]) * multiplier[0])));\n q[1] = Math.max(0, Math.min(65535, Math.floor((p[1] - aabb[1]) * multiplier[1])));\n q[2] = Math.max(0, Math.min(65535, Math.floor((p[2] - aabb[2]) * multiplier[2])));\n}\n\nfunction decompressPosition(position, decodeMatrix, dest) {\n dest[0] = position[0] * decodeMatrix[0] + decodeMatrix[12];\n dest[1] = position[1] * decodeMatrix[5] + decodeMatrix[13];\n dest[2] = position[2] * decodeMatrix[10] + decodeMatrix[14];\n return dest;\n}\n\nfunction decompressAABB(aabb, decodeMatrix, dest = aabb) {\n dest[0] = aabb[0] * decodeMatrix[0] + decodeMatrix[12];\n dest[1] = aabb[1] * decodeMatrix[5] + decodeMatrix[13];\n dest[2] = aabb[2] * decodeMatrix[10] + decodeMatrix[14];\n dest[3] = aabb[3] * decodeMatrix[0] + decodeMatrix[12];\n dest[4] = aabb[4] * decodeMatrix[5] + decodeMatrix[13];\n dest[5] = aabb[5] * decodeMatrix[10] + decodeMatrix[14];\n return dest;\n}\n\n/**\n * @private\n */\nfunction decompressPositions(positions, decodeMatrix, dest = new Float32Array(positions.length)) {\n for (let i = 0, len = positions.length; i < len; i += 3) {\n dest[i + 0] = positions[i + 0] * decodeMatrix[0] + decodeMatrix[12];\n dest[i + 1] = positions[i + 1] * decodeMatrix[5] + decodeMatrix[13];\n dest[i + 2] = positions[i + 2] * decodeMatrix[10] + decodeMatrix[14];\n }\n return dest;\n}\n\n//--------------- UVs --------------------------------------------------------------------------------------------------\n\n/**\n * @private\n * @param array\n * @returns {{min: Float32Array, max: Float32Array}}\n */\nfunction getUVBounds(array) {\n const min = new Float32Array(2);\n const max = new Float32Array(2);\n let i, j;\n for (i = 0; i < 2; i++) {\n min[i] = Number.MAX_VALUE;\n max[i] = -Number.MAX_VALUE;\n }\n for (i = 0; i < array.length; i += 2) {\n for (j = 0; j < 2; j++) {\n min[j] = Math.min(min[j], array[i + j]);\n max[j] = Math.max(max[j], array[i + j]);\n }\n }\n return {\n min: min,\n max: max\n };\n}\n\n/**\n * @private\n */\nvar compressUVs = (function () {\n const translate = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat3();\n const scale = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat3();\n return function (array, min, max) {\n const quantized = new Uint16Array(array.length);\n const multiplier = new Float32Array([\n 65535 / (max[0] - min[0]),\n 65535 / (max[1] - min[1])\n ]);\n let i;\n for (i = 0; i < array.length; i += 2) {\n quantized[i + 0] = Math.max(0, Math.min(65535, Math.floor((array[i + 0] - min[0]) * multiplier[0])));\n quantized[i + 1] = Math.max(0, Math.min(65535, Math.floor((array[i + 1] - min[1]) * multiplier[1])));\n }\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat3(translate);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.translationMat3v(min, translate);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat3(scale);\n _math_js__WEBPACK_IMPORTED_MODULE_0__.math.scalingMat3v([\n (max[0] - min[0]) / 65535,\n (max[1] - min[1]) / 65535\n ], scale);\n const decodeMat = _math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulMat3(translate, scale, _math_js__WEBPACK_IMPORTED_MODULE_0__.math.identityMat3());\n return {\n quantized: quantized,\n decodeMatrix: decodeMat\n };\n };\n})();\n\n\n//--------------- Normals ----------------------------------------------------------------------------------------------\n\n/**\n * @private\n */\nfunction compressNormals(array) { // http://jcgt.org/published/0003/02/01/\n\n // Note: three elements for each encoded normal, in which the last element in each triplet is redundant.\n // This is to work around a mysterious WebGL issue where 2-element normals just wouldn't work in the shader :/\n\n const encoded = new Int8Array(array.length);\n let oct, dec, best, currentCos, bestCos;\n for (let i = 0; i < array.length; i += 3) {\n // Test various combinations of ceil and floor\n // to minimize rounding errors\n best = oct = octEncodeVec3(array, i, \"floor\", \"floor\");\n dec = octDecodeVec2(oct);\n currentCos = bestCos = dot(array, i, dec);\n oct = octEncodeVec3(array, i, \"ceil\", \"floor\");\n dec = octDecodeVec2(oct);\n currentCos = dot(array, i, dec);\n if (currentCos > bestCos) {\n best = oct;\n bestCos = currentCos;\n }\n oct = octEncodeVec3(array, i, \"floor\", \"ceil\");\n dec = octDecodeVec2(oct);\n currentCos = dot(array, i, dec);\n if (currentCos > bestCos) {\n best = oct;\n bestCos = currentCos;\n }\n oct = octEncodeVec3(array, i, \"ceil\", \"ceil\");\n dec = octDecodeVec2(oct);\n currentCos = dot(array, i, dec);\n if (currentCos > bestCos) {\n best = oct;\n bestCos = currentCos;\n }\n encoded[i] = best[0];\n encoded[i + 1] = best[1];\n }\n return encoded;\n}\n\n/**\n * @private\n */\nfunction octEncodeVec3(array, i, xfunc, yfunc) { // Oct-encode single normal vector in 2 bytes\n let x = array[i] / (Math.abs(array[i]) + Math.abs(array[i + 1]) + Math.abs(array[i + 2]));\n let y = array[i + 1] / (Math.abs(array[i]) + Math.abs(array[i + 1]) + Math.abs(array[i + 2]));\n if (array[i + 2] < 0) {\n let tempx = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\n let tempy = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\n x = tempx;\n y = tempy;\n }\n return new Int8Array([\n Math[xfunc](x * 127.5 + (x < 0 ? -1 : 0)),\n Math[yfunc](y * 127.5 + (y < 0 ? -1 : 0))\n ]);\n}\n\n/**\n * Decode an oct-encoded normal\n */\nfunction octDecodeVec2(oct) {\n let x = oct[0];\n let y = oct[1];\n x /= x < 0 ? 127 : 128;\n y /= y < 0 ? 127 : 128;\n const z = 1 - Math.abs(x) - Math.abs(y);\n if (z < 0) {\n x = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\n y = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\n }\n const length = Math.sqrt(x * x + y * y + z * z);\n return [\n x / length,\n y / length,\n z / length\n ];\n}\n\n/**\n * Dot product of a normal in an array against a candidate decoding\n * @private\n */\nfunction dot(array, i, vec3) {\n return array[i] * vec3[0] + array[i + 1] * vec3[1] + array[i + 2] * vec3[2];\n}\n\n/**\n * @private\n */\nfunction decompressUV(uv, decodeMatrix, dest) {\n dest[0] = uv[0] * decodeMatrix[0] + decodeMatrix[6];\n dest[1] = uv[1] * decodeMatrix[4] + decodeMatrix[7];\n}\n\n/**\n * @private\n */\nfunction decompressUVs(uvs, decodeMatrix, dest = new Float32Array(uvs.length)) {\n for (let i = 0, len = uvs.length; i < len; i += 3) {\n dest[i + 0] = uvs[i + 0] * decodeMatrix[0] + decodeMatrix[6];\n dest[i + 1] = uvs[i + 1] * decodeMatrix[4] + decodeMatrix[7];\n }\n return dest;\n}\n\n/**\n * @private\n */\nfunction decompressNormal(oct, result) {\n let x = oct[0];\n let y = oct[1];\n x = (2 * x + 1) / 255;\n y = (2 * y + 1) / 255;\n const z = 1 - Math.abs(x) - Math.abs(y);\n if (z < 0) {\n x = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\n y = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\n }\n const length = Math.sqrt(x * x + y * y + z * z);\n result[0] = x / length;\n result[1] = y / length;\n result[2] = z / length;\n return result;\n}\n\n/**\n * @private\n */\nfunction decompressNormals(octs, result) {\n for (let i = 0, j = 0, len = octs.length; i < len; i += 2) {\n let x = octs[i + 0];\n let y = octs[i + 1];\n x = (2 * x + 1) / 255;\n y = (2 * y + 1) / 255;\n const z = 1 - Math.abs(x) - Math.abs(y);\n if (z < 0) {\n x = (1 - Math.abs(y)) * (x >= 0 ? 1 : -1);\n y = (1 - Math.abs(x)) * (y >= 0 ? 1 : -1);\n }\n const length = Math.sqrt(x * x + y * y + z * z);\n result[j + 0] = x / length;\n result[j + 1] = y / length;\n result[j + 2] = z / length;\n j += 3;\n }\n return result;\n}\n\n/**\n * @private\n */\nconst geometryCompressionUtils = {\n\n getPositionsBounds: getPositionsBounds,\n createPositionsDecodeMatrix: createPositionsDecodeMatrix,\n compressPositions: compressPositions,\n compressPosition:compressPosition,\n decompressPositions: decompressPositions,\n decompressPosition: decompressPosition,\n decompressAABB: decompressAABB,\n\n getUVBounds: getUVBounds,\n compressUVs: compressUVs,\n decompressUVs: decompressUVs,\n decompressUV: decompressUV,\n\n compressNormals: compressNormals,\n decompressNormals: decompressNormals,\n decompressNormal: decompressNormal\n};\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/math/geometryCompressionUtils.js?");
|
|
3248
3248
|
|
|
3249
3249
|
/***/ }),
|
|
3250
3250
|
|
|
@@ -3524,7 +3524,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3524
3524
|
\**********************************************/
|
|
3525
3525
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3526
3526
|
|
|
3527
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SceneModel: () => (/* binding */ SceneModel)\n/* harmony export */ });\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../math/buildEdgeIndices.js */ \"./src/viewer/scene/math/buildEdgeIndices.js\");\n/* harmony import */ var _SceneModelMesh_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SceneModelMesh.js */ \"./src/viewer/scene/model/SceneModelMesh.js\");\n/* harmony import */ var _vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./vbo/ScratchMemory.js */ \"./src/viewer/scene/model/vbo/ScratchMemory.js\");\n/* harmony import */ var _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./vbo/batching/triangles/VBOBatchingTrianglesLayer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js\");\n/* harmony import */ var _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./vbo/instancing/triangles/VBOInstancingTrianglesLayer.js */ \"./src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js\");\n/* harmony import */ var _vbo_batching_lines_VBOBatchingLinesLayer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./vbo/batching/lines/VBOBatchingLinesLayer.js */ \"./src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js\");\n/* harmony import */ var _vbo_instancing_lines_VBOInstancingLinesLayer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./vbo/instancing/lines/VBOInstancingLinesLayer.js */ \"./src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js\");\n/* harmony import */ var _vbo_batching_points_VBOBatchingPointsLayer_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./vbo/batching/points/VBOBatchingPointsLayer.js */ \"./src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js\");\n/* harmony import */ var _vbo_instancing_points_VBOInstancingPointsLayer_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./vbo/instancing/points/VBOInstancingPointsLayer.js */ \"./src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js\");\n/* harmony import */ var _dtx_lines_DTXLinesLayer_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./dtx/lines/DTXLinesLayer.js */ \"./src/viewer/scene/model/dtx/lines/DTXLinesLayer.js\");\n/* harmony import */ var _dtx_triangles_DTXTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./dtx/triangles/DTXTrianglesLayer.js */ \"./src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js\");\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _webgl_RenderFlags_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../webgl/RenderFlags.js */ \"./src/viewer/scene/webgl/RenderFlags.js\");\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n/* harmony import */ var _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./SceneModelTextureSet.js */ \"./src/viewer/scene/model/SceneModelTextureSet.js\");\n/* harmony import */ var _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./SceneModelTexture.js */ \"./src/viewer/scene/model/SceneModelTexture.js\");\n/* harmony import */ var _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../webgl/Texture2D.js */ \"./src/viewer/scene/webgl/Texture2D.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _utils_textureTranscoders_KTX2TextureTranscoder_KTX2TextureTranscoder_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../utils/textureTranscoders/KTX2TextureTranscoder/KTX2TextureTranscoder.js */ \"./src/viewer/scene/utils/textureTranscoders/KTX2TextureTranscoder/KTX2TextureTranscoder.js\");\n/* harmony import */ var _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../constants/constants.js */ \"./src/viewer/scene/constants/constants.js\");\n/* harmony import */ var _compression_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./compression.js */ \"./src/viewer/scene/model/compression.js\");\n/* harmony import */ var _calculateUniquePositions_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./calculateUniquePositions.js */ \"./src/viewer/scene/model/calculateUniquePositions.js\");\n/* harmony import */ var _rebucketPositions_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./rebucketPositions.js */ \"./src/viewer/scene/model/rebucketPositions.js\");\n/* harmony import */ var _SceneModelEntity_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./SceneModelEntity.js */ \"./src/viewer/scene/model/SceneModelEntity.js\");\n/* harmony import */ var _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../math/geometryCompressionUtils.js */ \"./src/viewer/scene/math/geometryCompressionUtils.js\");\n/* harmony import */ var _SceneModelTransform_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./SceneModelTransform.js */ \"./src/viewer/scene/model/SceneModelTransform.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\n\r\n\r\n\r\n\r\n\r\n\r\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 tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\r\nconst tempOBB3 = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3();\r\n\r\nconst DEFAULT_SCALE = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3([1, 1, 1]);\r\nconst DEFAULT_POSITION = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3([0, 0, 0]);\r\nconst DEFAULT_ROTATION = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3([0, 0, 0]);\r\nconst DEFAULT_QUATERNION = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.identityQuaternion();\r\nconst DEFAULT_MATRIX = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.identityMat4();\r\n\r\nconst DEFAULT_COLOR_TEXTURE_ID = \"defaultColorTexture\";\r\nconst DEFAULT_METAL_ROUGH_TEXTURE_ID = \"defaultMetalRoughTexture\";\r\nconst DEFAULT_NORMALS_TEXTURE_ID = \"defaultNormalsTexture\";\r\nconst DEFAULT_EMISSIVE_TEXTURE_ID = \"defaultEmissiveTexture\";\r\nconst DEFAULT_OCCLUSION_TEXTURE_ID = \"defaultOcclusionTexture\";\r\nconst DEFAULT_TEXTURE_SET_ID = \"defaultTextureSet\";\r\n\r\nconst defaultCompressedColor = new Uint8Array([255, 255, 255]);\r\n\r\nconst VBO_INSTANCED = 0;\r\nconst VBO_BATCHED = 1;\r\nconst DTX = 2;\r\n\r\n/**\r\n * @desc A high-performance model representation for efficient rendering and low memory usage.\r\n *\r\n * # Examples\r\n *\r\n * Internally, SceneModel uses a combination of several different techniques to render and represent\r\n * the different parts of a typical model. Each of the live examples at these links is designed to \"unit test\" one of these\r\n * techniques, in isolation. If some bug occurs in SceneModel, we use these tests to debug, but they also\r\n * serve to demonstrate how to use the capabilities of SceneModel programmatically.\r\n *\r\n * * [Loading building models into SceneModels](/examples/buildings)\r\n * * [Loading city models into SceneModels](/examples/cities)\r\n * * [Loading LiDAR scans into SceneModels](/examples/lidar)\r\n * * [Loading CAD models into SceneModels](/examples/cad)\r\n * * [SceneModel feature tests](/examples/scenemodel)\r\n *\r\n * # Overview\r\n *\r\n * While xeokit's standard [scene graph](https://github.com/xeokit/xeokit-sdk/wiki/Scene-Graphs) is great for gizmos and medium-sized models, it doesn't scale up to millions of objects in terms of memory and rendering efficiency.\r\n *\r\n * For huge models, we have the ````SceneModel```` representation, which is optimized to pack large amounts of geometry into memory and render it efficiently using WebGL.\r\n *\r\n * ````SceneModel```` is the default model representation loaded by (at least) {@link GLTFLoaderPlugin}, {@link XKTLoaderPlugin} and {@link WebIFCLoaderPlugin}.\r\n *\r\n * In this tutorial you'll learn how to use ````SceneModel```` to create high-detail content programmatically. Ordinarily you'd be learning about ````SceneModel```` if you were writing your own model loader plugins.\r\n *\r\n * # Contents\r\n *\r\n * - [SceneModel](#DataTextureSceneModel)\r\n * - [GPU-Resident Geometry](#gpu-resident-geometry)\r\n * - [Picking](#picking)\r\n * - [Example 1: Geometry Instancing](#example-1--geometry-instancing)\r\n * - [Finalizing a SceneModel](#finalizing-a-DataTextureSceneModel)\r\n * - [Finding Entities](#finding-entities)\r\n * - [Example 2: Geometry Batching](#example-2--geometry-batching)\r\n * - [Classifying with Metadata](#classifying-with-metadata)\r\n * - [Querying Metadata](#querying-metadata)\r\n * - [Metadata Structure](#metadata-structure)\r\n * - [RTC Coordinates](#rtc-coordinates-for-double-precision)\r\n * - [Example 3: RTC Coordinates with Geometry Instancing](#example-2--rtc-coordinates-with-geometry-instancing)\r\n * - [Example 4: RTC Coordinates with Geometry Batching](#example-2--rtc-coordinates-with-geometry-batching)\r\n *\r\n * ## SceneModel\r\n *\r\n * ````SceneModel```` uses two rendering techniques internally:\r\n *\r\n * 1. ***Geometry batching*** for unique geometries, combining those into a single WebGL geometry buffer, to render in one draw call, and\r\n * 2. ***geometry instancing*** for geometries that are shared by multiple meshes, rendering all instances of each shared geometry in one draw call.\r\n *\r\n * <br>\r\n * These techniques come with certain limitations:\r\n *\r\n * * Non-realistic rendering - while scene graphs can use xeokit's full set of material workflows, ````SceneModel```` uses simple Lambertian shading without textures.\r\n * * Static transforms - transforms within a ````SceneModel```` are static and cannot be dynamically translated, rotated and scaled the way {@link Node}s and {@link Mesh}es in scene graphs can.\r\n * * Immutable model representation - while scene graph {@link Node}s and\r\n * {@link Mesh}es can be dynamically plugged together, ````SceneModel```` is immutable,\r\n * since it packs its geometries into buffers and instanced arrays.\r\n *\r\n * ````SceneModel````'s API allows us to exploit batching and instancing, while exposing its elements as\r\n * abstract {@link Entity} types.\r\n *\r\n * {@link Entity} is the abstract base class for\r\n * the various xeokit components that represent models, objects, or anonymous visible elements. An Entity has a unique ID and can be\r\n * individually shown, hidden, selected, highlighted, ghosted, culled, picked and clipped, and has its own World-space boundary.\r\n *\r\n * * A ````SceneModel```` is an {@link Entity} that represents a model.\r\n * * A ````SceneModel```` represents each of its objects with an {@link Entity}.\r\n * * Each {@link Entity} has one or more meshes that define its shape.\r\n * * Each mesh has either its own unique geometry, or shares a geometry with other meshes.\r\n *\r\n * ## GPU-Resident Geometry\r\n *\r\n * For a low memory footprint, ````SceneModel```` stores its geometries in GPU memory only, compressed (quantized) as integers. Unfortunately, GPU-resident geometry is\r\n * not readable by JavaScript.\r\n *\r\n *\r\n * ## Example 1: Geometry Instancing\r\n *\r\n * In the example below, we'll use a ````SceneModel````\r\n * to build a simple table model using geometry instancing.\r\n *\r\n * We'll start by adding a reusable box-shaped geometry to our ````SceneModel````.\r\n *\r\n * Then, for each object in our model we'll add an {@link Entity}\r\n * that has a mesh that instances our box geometry, transforming and coloring the instance.\r\n *\r\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_instancing)\r\n *\r\n * ````javascript\r\n * import {Viewer, SceneModel} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\r\n * viewer.scene.camera.look = [0, -5.75, 0];\r\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\r\n *\r\n * // Build a SceneModel representing a table\r\n * // with four legs, using geometry instancing\r\n *\r\n * const sceneModel = new SceneModel(viewer.scene, {\r\n * id: \"table\",\r\n * isModel: true, // <--- Registers SceneModel in viewer.scene.models\r\n * position: [0, 0, 0],\r\n * scale: [1, 1, 1],\r\n * rotation: [0, 0, 0]\r\n * });\r\n *\r\n * // Create a reusable geometry within the SceneModel\r\n * // We'll instance this geometry by five meshes\r\n *\r\n * sceneModel.createGeometry({\r\n *\r\n * id: \"myBoxGeometry\",\r\n *\r\n * // The primitive type - allowed values are \"points\", \"lines\" and \"triangles\".\r\n * // See the OpenGL/WebGL specification docs\r\n * // for how the coordinate arrays are supposed to be laid out.\r\n * primitive: \"triangles\",\r\n *\r\n * // The vertices - eight for our cube, each\r\n * // one spanning three array elements for X,Y and Z\r\n * positions: [\r\n * 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front\r\n * 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right\r\n * 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top\r\n * -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left\r\n * -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, // v7-v4-v3-v2 bottom\r\n * 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back\r\n * ],\r\n *\r\n * // Normal vectors, one for each vertex\r\n * normals: [\r\n * 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2-v3 front\r\n * 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right\r\n * 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0-v5-v6-v1 top\r\n * -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1-v6-v7-v2 left\r\n * 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, // v7-v4-v3-v2 bottom\r\n * 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 // v4-v7-v6-v5 back\r\n * ],\r\n *\r\n * // Indices - these organise the positions and and normals\r\n * // into geometric primitives in accordance with the \"primitive\" parameter,\r\n * // in this case a set of three indices for each triangle.\r\n * //\r\n * // Note that each triangle is specified in counter-clockwise winding order.\r\n * //\r\n * indices: [\r\n * 0, 1, 2, 0, 2, 3, // front\r\n * 4, 5, 6, 4, 6, 7, // right\r\n * 8, 9, 10, 8, 10, 11, // top\r\n * 12, 13, 14, 12, 14, 15, // left\r\n * 16, 17, 18, 16, 18, 19, // bottom\r\n * 20, 21, 22, 20, 22, 23\r\n * ]\r\n * });\r\n *\r\n * // Red table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"redLegMesh\",\r\n * geometryId: \"myBoxGeometry\",\r\n * position: [-4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1, 0.3, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"redLeg\",\r\n * meshIds: [\"redLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Green table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"greenLegMesh\",\r\n * geometryId: \"myBoxGeometry\",\r\n * position: [4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 1.0, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"greenLeg\",\r\n * meshIds: [\"greenLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Blue table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"blueLegMesh\",\r\n * geometryId: \"myBoxGeometry\",\r\n * position: [4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"blueLeg\",\r\n * meshIds: [\"blueLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Yellow table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"yellowLegMesh\",\r\n * geometryId: \"myBoxGeometry\",\r\n * position: [-4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 1.0, 0.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"yellowLeg\",\r\n * meshIds: [\"yellowLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Purple table top\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"purpleTableTopMesh\",\r\n * geometryId: \"myBoxGeometry\",\r\n * position: [0, -3, 0],\r\n * scale: [6, 0.5, 6],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"purpleTableTop\",\r\n * meshIds: [\"purpleTableTopMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n * ````\r\n *\r\n * ## Finalizing a SceneModel\r\n *\r\n * Before we can view and interact with our ````SceneModel````, we need to **finalize** it. Internally, this causes the ````SceneModel```` to build the\r\n * vertex buffer objects (VBOs) that support our geometry instances. When using geometry batching (see next example),\r\n * this causes ````SceneModel```` to build the VBOs that combine the batched geometries. Note that you can do both instancing and\r\n * batching within the same ````SceneModel````.\r\n *\r\n * Once finalized, we can't add anything more to our ````SceneModel````.\r\n *\r\n * ```` javascript\r\n * SceneModel.finalize();\r\n * ````\r\n *\r\n * ## Finding Entities\r\n *\r\n * As mentioned earlier, {@link Entity} is\r\n * the abstract base class for components that represent models, objects, or just\r\n * anonymous visible elements.\r\n *\r\n * Since we created configured our ````SceneModel```` with ````isModel: true````,\r\n * we're able to find it as an Entity by ID in ````viewer.scene.models````. Likewise, since\r\n * we configured each of its Entities with ````isObject: true````, we're able to\r\n * find them in ````viewer.scene.objects````.\r\n *\r\n *\r\n * ````javascript\r\n * // Get the whole table model Entity\r\n * const table = viewer.scene.models[\"table\"];\r\n *\r\n * // Get some leg object Entities\r\n * const redLeg = viewer.scene.objects[\"redLeg\"];\r\n * const greenLeg = viewer.scene.objects[\"greenLeg\"];\r\n * const blueLeg = viewer.scene.objects[\"blueLeg\"];\r\n * ````\r\n *\r\n * ## Example 2: Geometry Batching\r\n *\r\n * Let's once more use a ````SceneModel````\r\n * to build the simple table model, this time exploiting geometry batching.\r\n *\r\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_batching)\r\n *\r\n * ````javascript\r\n * import {Viewer, SceneModel} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\r\n * viewer.scene.camera.look = [0, -5.75, 0];\r\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\r\n *\r\n * // Create a SceneModel representing a table with four legs, using geometry batching\r\n * const sceneModel = new SceneModel(viewer.scene, {\r\n * id: \"table\",\r\n * isModel: true, // <--- Registers SceneModel in viewer.scene.models\r\n * position: [0, 0, 0],\r\n * scale: [1, 1, 1],\r\n * rotation: [0, 0, 0]\r\n * });\r\n *\r\n * // Red table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"redLegMesh\",\r\n *\r\n * // Geometry arrays are same as for the earlier batching example\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [-4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1, 0.3, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"redLeg\",\r\n * meshIds: [\"redLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Green table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"greenLegMesh\",\r\n * primitive: \"triangles\",\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 1.0, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"greenLeg\",\r\n * meshIds: [\"greenLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Blue table leg\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"blueLegMesh\",\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"blueLeg\",\r\n * meshIds: [\"blueLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Yellow table leg object\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"yellowLegMesh\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [-4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 1.0, 0.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"yellowLeg\",\r\n * meshIds: [\"yellowLegMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Purple table top\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"purpleTableTopMesh\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [0, -3, 0],\r\n * scale: [6, 0.5, 6],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"purpleTableTop\",\r\n * meshIds: [\"purpleTableTopMesh\"],\r\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\r\n * });\r\n *\r\n * // Finalize the SceneModel.\r\n *\r\n * SceneModel.finalize();\r\n *\r\n * // Find BigModelNodes by their model and object IDs\r\n *\r\n * // Get the whole table model\r\n * const table = viewer.scene.models[\"table\"];\r\n *\r\n * // Get some leg objects\r\n * const redLeg = viewer.scene.objects[\"redLeg\"];\r\n * const greenLeg = viewer.scene.objects[\"greenLeg\"];\r\n * const blueLeg = viewer.scene.objects[\"blueLeg\"];\r\n * ````\r\n *\r\n * ## Classifying with Metadata\r\n *\r\n * In the previous examples, we used ````SceneModel```` to build\r\n * two versions of the same table model, to demonstrate geometry batching and geometry instancing.\r\n *\r\n * We'll now classify our {@link Entity}s with metadata. This metadata\r\n * will work the same for both our examples, since they create the exact same structure of {@link Entity}s\r\n * to represent their models and objects. The abstract Entity type is, after all, intended to provide an abstract interface through which differently-implemented scene content can be accessed uniformly.\r\n *\r\n * To create the metadata, we'll create a {@link MetaModel} for our model,\r\n * with a {@link MetaObject} for each of it's objects. The MetaModel and MetaObjects\r\n * get the same IDs as the {@link Entity}s that represent their model and objects within our scene.\r\n *\r\n * ```` javascript\r\n * const furnitureMetaModel = viewer.metaScene.createMetaModel(\"furniture\", { // Creates a MetaModel in the MetaScene\r\n *\r\n * \"projectId\": \"myTableProject\",\r\n * \"revisionId\": \"V1.0\",\r\n *\r\n * \"metaObjects\": [\r\n * { // Creates a MetaObject in the MetaModel\r\n * \"id\": \"table\",\r\n * \"name\": \"Table\", // Same ID as an object Entity\r\n * \"type\": \"furniture\", // Arbitrary type, could be IFC type\r\n * \"properties\": { // Arbitrary properties, could be IfcPropertySet\r\n * \"cost\": \"200\"\r\n * }\r\n * },\r\n * {\r\n * \"id\": \"redLeg\",\r\n * \"name\": \"Red table Leg\",\r\n * \"type\": \"leg\",\r\n * \"parent\": \"table\", // References first MetaObject as parent\r\n * \"properties\": {\r\n * \"material\": \"wood\"\r\n * }\r\n * },\r\n * {\r\n * \"id\": \"greenLeg\", // Node with corresponding id does not need to exist\r\n * \"name\": \"Green table leg\", // and MetaObject does not need to exist for Node with an id\r\n * \"type\": \"leg\",\r\n * \"parent\": \"table\",\r\n * \"properties\": {\r\n * \"material\": \"wood\"\r\n * }\r\n * },\r\n * {\r\n * \"id\": \"blueLeg\",\r\n * \"name\": \"Blue table leg\",\r\n * \"type\": \"leg\",\r\n * \"parent\": \"table\",\r\n * \"properties\": {\r\n * \"material\": \"wood\"\r\n * }\r\n * },\r\n * {\r\n * \"id\": \"yellowLeg\",\r\n * \"name\": \"Yellow table leg\",\r\n * \"type\": \"leg\",\r\n * \"parent\": \"table\",\r\n * \"properties\": {\r\n * \"material\": \"wood\"\r\n * }\r\n * },\r\n * {\r\n * \"id\": \"tableTop\",\r\n * \"name\": \"Purple table top\",\r\n * \"type\": \"surface\",\r\n * \"parent\": \"table\",\r\n * \"properties\": {\r\n * \"material\": \"formica\",\r\n * \"width\": \"60\",\r\n * \"depth\": \"60\",\r\n * \"thickness\": \"5\"\r\n * }\r\n * }\r\n * ]\r\n * });\r\n * ````\r\n *\r\n * ## Querying Metadata\r\n *\r\n * Having created and classified our model (either the instancing or batching example), we can now find the {@link MetaModel}\r\n * and {@link MetaObject}s using the IDs of their\r\n * corresponding {@link Entity}s.\r\n *\r\n * ````JavaScript\r\n * const furnitureMetaModel = scene.metaScene.metaModels[\"furniture\"];\r\n *\r\n * const redLegMetaObject = scene.metaScene.metaObjects[\"redLeg\"];\r\n * ````\r\n *\r\n * In the snippet below, we'll log metadata on each {@link Entity} we click on:\r\n *\r\n * ````JavaScript\r\n * viewer.scene.input.on(\"mouseclicked\", function (coords) {\r\n *\r\n * const hit = viewer.scene.pick({\r\n * canvasPos: coords\r\n * });\r\n *\r\n * if (hit) {\r\n * const entity = hit.entity;\r\n * const metaObject = viewer.metaScene.metaObjects[entity.id];\r\n * if (metaObject) {\r\n * console.log(JSON.stringify(metaObject.getJSON(), null, \"\\t\"));\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * ## Metadata Structure\r\n *\r\n * The {@link MetaModel}\r\n * organizes its {@link MetaObject}s in\r\n * a tree that describes their structural composition:\r\n *\r\n * ````JavaScript\r\n * // Get metadata on the root object\r\n * const tableMetaObject = furnitureMetaModel.rootMetaObject;\r\n *\r\n * // Get metadata on the leg objects\r\n * const redLegMetaObject = tableMetaObject.children[0];\r\n * const greenLegMetaObject = tableMetaObject.children[1];\r\n * const blueLegMetaObject = tableMetaObject.children[2];\r\n * const yellowLegMetaObject = tableMetaObject.children[3];\r\n * ````\r\n *\r\n * Given an {@link Entity}, we can find the object or model of which it is a part, or the objects that comprise it. We can also generate UI\r\n * components from the metadata, such as the tree view demonstrated in [this demo](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_glTF_OTCConferenceCenter).\r\n *\r\n * This hierarchy allows us to express the hierarchical structure of a model while representing it in\r\n * various ways in the 3D scene (such as with ````SceneModel````, which\r\n * has a non-hierarchical scene representation).\r\n *\r\n * Note also that a {@link MetaObject} does not need to have a corresponding\r\n * {@link Entity} and vice-versa.\r\n *\r\n * # RTC Coordinates for Double Precision\r\n *\r\n * ````SceneModel```` can emulate 64-bit precision on GPUs using relative-to-center (RTC) coordinates.\r\n *\r\n * Consider a model that contains many small objects, but with such large spatial extents that 32 bits of GPU precision (accurate to ~7 digits) will not be sufficient to render all of the the objects without jittering.\r\n *\r\n * To prevent jittering, we could spatially subdivide the objects into \"tiles\". Each tile would have a center position, and the positions of the objects within the tile would be relative to that center (\"RTC coordinates\").\r\n *\r\n * While the center positions of the tiles would be 64-bit values, the object positions only need to be 32-bit.\r\n *\r\n * Internally, when rendering an object with RTC coordinates, xeokit first temporarily translates the camera viewing matrix by the object's tile's RTC center, on the CPU, using 64-bit math.\r\n *\r\n * Then xeokit loads the viewing matrix into its WebGL shaders, where math happens at 32-bit precision. Within the shaders, the matrix is effectively down-cast to 32-bit precision, and the object's 32-bit vertex positions are transformed by the matrix.\r\n *\r\n * We see no jittering, because with RTC a detectable loss of GPU accuracy only starts happening to objects as they become very distant from the camera viewpoint, at which point they are too small to be discernible anyway.\r\n *\r\n * ## RTC Coordinates with Geometry Instancing\r\n *\r\n * To use RTC with ````SceneModel```` geometry instancing, we specify an RTC center for the geometry via its ````origin```` parameter. Then ````SceneModel```` assumes that all meshes that instance that geometry are within the same RTC coordinate system, ie. the meshes ````position```` and ````rotation```` properties are assumed to be relative to the geometry's ````origin````.\r\n *\r\n * For simplicity, our example's meshes all instance the same geometry. Therefore, our example model has only one RTC center.\r\n *\r\n * Note that the axis-aligned World-space boundary (AABB) of our model is ````[ -6, -9, -6, 1000000006, -2.5, 1000000006]````.\r\n *\r\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_batching)\r\n *\r\n * ````javascript\r\n * const origin = [100000000, 0, 100000000];\r\n *\r\n * sceneModel.createGeometry({\r\n * id: \"box\",\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg1\",\r\n * geometryId: \"box\",\r\n * position: [-4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1, 0.3, 0.3],\r\n * origin: origin\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg1\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg2\",\r\n * geometryId: \"box\",\r\n * position: [4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 1.0, 0.3],\r\n * origin: origin\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg2\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg3\",\r\n * geometryId: \"box\",\r\n * position: [4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 0.3, 1.0],\r\n * origin: origin\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg3\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg4\",\r\n * geometryId: \"box\",\r\n * position: [-4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 1.0, 0.0],\r\n * origin: origin\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg4\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"top\",\r\n * geometryId: \"box\",\r\n * position: [0, -3, 0],\r\n * scale: [6, 0.5, 6],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 0.3, 1.0],\r\n * origin: origin\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"top\"],\r\n * isObject: true\r\n * });\r\n * ````\r\n *\r\n * ## RTC Coordinates with Geometry Batching\r\n *\r\n * To use RTC with ````SceneModel```` geometry batching, we specify an RTC center (````origin````) for each mesh. For performance, we try to have as many meshes share the same value for ````origin```` as possible. Each mesh's ````positions````, ````position```` and ````rotation```` properties are assumed to be relative to ````origin````.\r\n *\r\n * For simplicity, the meshes in our example all share the same RTC center.\r\n *\r\n * The axis-aligned World-space boundary (AABB) of our model is ````[ -6, -9, -6, 1000000006, -2.5, 1000000006]````.\r\n *\r\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_batching)\r\n *\r\n * ````javascript\r\n * const origin = [100000000, 0, 100000000];\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg1\",\r\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [-4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1, 0.3, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg1\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg2\",\r\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 1.0, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg2\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg3\",\r\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg3\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg4\",\r\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [-4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 1.0, 0.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg4\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"top\",\r\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * position: [0, -3, 0],\r\n * scale: [6, 0.5, 6],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"top\"],\r\n * isObject: true\r\n * });\r\n * ````\r\n *\r\n * ## Positioning at World-space coordinates\r\n *\r\n * To position a SceneModel at given double-precision World coordinates, we can\r\n * configure the ````origin```` of the SceneModel itself. The ````origin```` is a double-precision\r\n * 3D World-space position at which the SceneModel will be located.\r\n *\r\n * Note that ````position```` is a single-precision offset relative to ````origin````.\r\n *\r\n * ````javascript\r\n * const origin = [100000000, 0, 100000000];\r\n *\r\n * const sceneModel = new SceneModel(viewer.scene, {\r\n * id: \"table\",\r\n * isModel: true,\r\n * origin: origin, // Everything in this SceneModel is relative to this RTC center\r\n * position: [0, 0, 0],\r\n * scale: [1, 1, 1],\r\n * rotation: [0, 0, 0]\r\n * });\r\n *\r\n * sceneModel.createGeometry({\r\n * id: \"box\",\r\n * primitive: \"triangles\",\r\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\r\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\r\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg1\",\r\n * geometryId: \"box\",\r\n * position: [-4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1, 0.3, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg1\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg2\",\r\n * geometryId: \"box\",\r\n * position: [4, -6, -4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 1.0, 0.3]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg2\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg3\",\r\n * geometryId: \"box\",\r\n * position: [4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [0.3, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg3\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"leg4\",\r\n * geometryId: \"box\",\r\n * position: [-4, -6, 4],\r\n * scale: [1, 3, 1],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 1.0, 0.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"leg4\"],\r\n * isObject: true\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"top\",\r\n * geometryId: \"box\",\r\n * position: [0, -3, 0],\r\n * scale: [6, 0.5, 6],\r\n * rotation: [0, 0, 0],\r\n * color: [1.0, 0.3, 1.0]\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * meshIds: [\"top\"],\r\n * isObject: true\r\n * });\r\n * ````\r\n *\r\n * # Textures\r\n *\r\n * ## Loading KTX2 Texture Files into a SceneModel\r\n *\r\n * A {@link SceneModel} that is configured with a {@link KTX2TextureTranscoder} will\r\n * allow us to load textures into it from KTX2 buffers or files.\r\n *\r\n * In the example below, we'll create a {@link Viewer}, containing a {@link SceneModel} configured with a\r\n * {@link KTX2TextureTranscoder}. We'll then programmatically create a simple object within the SceneModel, consisting of\r\n * a single mesh with a texture loaded from a KTX2 file, which our SceneModel internally transcodes, using\r\n * its {@link KTX2TextureTranscoder}. Note how we configure our {@link KTX2TextureTranscoder} with a path to the Basis Universal\r\n * transcoder WASM module.\r\n *\r\n * ````javascript\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\r\n * viewer.scene.camera.look = [0, -5.75, 0];\r\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\r\n *\r\n * const textureTranscoder = new KTX2TextureTranscoder({\r\n * viewer,\r\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to BasisU transcoder module\r\n * });\r\n *\r\n * const sceneModel = new SceneModel(viewer.scene, {\r\n * id: \"myModel\",\r\n * textureTranscoder // <<-------------------- Configure model with our transcoder\r\n * });\r\n *\r\n * sceneModel.createTexture({\r\n * id: \"myColorTexture\",\r\n * src: \"../assets/textures/compressed/sample_uastc_zstd.ktx2\" // <<----- KTX2 texture asset\r\n * });\r\n *\r\n * sceneModel.createTexture({\r\n * id: \"myMetallicRoughnessTexture\",\r\n * src: \"../assets/textures/alpha/crosshatchAlphaMap.jpg\" // <<----- JPEG texture asset\r\n * });\r\n *\r\n * sceneModel.createTextureSet({\r\n * id: \"myTextureSet\",\r\n * colorTextureId: \"myColorTexture\",\r\n * metallicRoughnessTextureId: \"myMetallicRoughnessTexture\"\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"myMesh\",\r\n * textureSetId: \"myTextureSet\",\r\n * primitive: \"triangles\",\r\n * positions: [1, 1, 1, ...],\r\n * normals: [0, 0, 1, 0, ...],\r\n * uv: [1, 0, 0, ...],\r\n * indices: [0, 1, 2, ...],\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"myEntity\",\r\n * meshIds: [\"myMesh\"]\r\n * });\r\n *\r\n * sceneModel.finalize();\r\n * ````\r\n *\r\n * ## Loading KTX2 Textures from ArrayBuffers into a SceneModel\r\n *\r\n * A SceneModel that is configured with a {@link KTX2TextureTranscoder} will allow us to load textures into\r\n * it from KTX2 ArrayBuffers.\r\n *\r\n * In the example below, we'll create a {@link Viewer}, containing a {@link SceneModel} configured with a\r\n * {@link KTX2TextureTranscoder}. We'll then programmatically create a simple object within the SceneModel, consisting of\r\n * a single mesh with a texture loaded from a KTX2 ArrayBuffer, which our SceneModel internally transcodes, using\r\n * its {@link KTX2TextureTranscoder}.\r\n *\r\n * ````javascript\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\r\n * viewer.scene.camera.look = [0, -5.75, 0];\r\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\r\n *\r\n * const textureTranscoder = new KTX2TextureTranscoder({\r\n * viewer,\r\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to BasisU transcoder module\r\n * });\r\n *\r\n * const sceneModel = new SceneModel(viewer.scene, {\r\n * id: \"myModel\",\r\n * textureTranscoder // <<-------------------- Configure model with our transcoder\r\n * });\r\n *\r\n * utils.loadArraybuffer(\"../assets/textures/compressed/sample_uastc_zstd.ktx2\",(arrayBuffer) => {\r\n *\r\n * sceneModel.createTexture({\r\n * id: \"myColorTexture\",\r\n * buffers: [arrayBuffer] // <<----- KTX2 texture asset\r\n * });\r\n *\r\n * sceneModel.createTexture({\r\n * id: \"myMetallicRoughnessTexture\",\r\n * src: \"../assets/textures/alpha/crosshatchAlphaMap.jpg\" // <<----- JPEG texture asset\r\n * });\r\n *\r\n * sceneModel.createTextureSet({\r\n * id: \"myTextureSet\",\r\n * colorTextureId: \"myColorTexture\",\r\n * metallicRoughnessTextureId: \"myMetallicRoughnessTexture\"\r\n * });\r\n *\r\n * sceneModel.createMesh({\r\n * id: \"myMesh\",\r\n * textureSetId: \"myTextureSet\",\r\n * primitive: \"triangles\",\r\n * positions: [1, 1, 1, ...],\r\n * normals: [0, 0, 1, 0, ...],\r\n * uv: [1, 0, 0, ...],\r\n * indices: [0, 1, 2, ...],\r\n * });\r\n *\r\n * sceneModel.createEntity({\r\n * id: \"myEntity\",\r\n * meshIds: [\"myMesh\"]\r\n * });\r\n *\r\n * sceneModel.finalize();\r\n * });\r\n * ````\r\n *\r\n * @implements {Entity}\r\n */\r\nclass SceneModel extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\r\n\r\n /**\r\n * @constructor\r\n * @param {Component} owner Owner component. When destroyed, the owner will destroy this component as well.\r\n * @param {*} [cfg] Configs\r\n * @param {String} [cfg.id] Optional ID, unique among all components in the parent scene, generated automatically when omitted.\r\n * @param {Boolean} [cfg.isModel] Specify ````true```` if this SceneModel represents a model, in which case the SceneModel will be registered by {@link SceneModel#id} in {@link Scene#models} and may also have a corresponding {@link MetaModel} with matching {@link MetaModel#id}, registered by that ID in {@link MetaScene#metaModels}.\r\n * @param {Number[]} [cfg.origin=[0,0,0]] World-space double-precision 3D origin.\r\n * @param {Number[]} [cfg.position=[0,0,0]] Local, single-precision 3D position, relative to the origin parameter.\r\n * @param {Number[]} [cfg.scale=[1,1,1]] Local scale.\r\n * @param {Number[]} [cfg.rotation=[0,0,0]] Local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\r\n * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] Local modelling transform matrix. Overrides the position, scale and rotation parameters.\r\n * @param {Boolean} [cfg.visible=true] Indicates if the SceneModel is initially visible.\r\n * @param {Boolean} [cfg.culled=false] Indicates if the SceneModel is initially culled from view.\r\n * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModel is initially pickable.\r\n * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModel is initially clippable.\r\n * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModel is initially included in boundary calculations.\r\n * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModel is initially xrayed.\r\n * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModel is initially highlighted.\r\n * @param {Boolean} [cfg.selected=false] Indicates if the SceneModel is initially selected.\r\n * @param {Boolean} [cfg.edges=false] Indicates if the SceneModel's edges are initially emphasized.\r\n * @param {Number[]} [cfg.colorize=[1.0,1.0,1.0]] SceneModel's initial RGB colorize color, multiplies by the rendered fragment colors.\r\n * @param {Number} [cfg.opacity=1.0] SceneModel's initial opacity factor, multiplies by the rendered fragment alpha.\r\n * @param {Number} [cfg.backfaces=false] When we set this ````true````, then we force rendering of backfaces for this SceneModel. When\r\n * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\r\n * Viewer will hide backfaces on watertight meshes, show backfaces on open meshes, and always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\r\n * @param {Boolean} [cfg.saoEnabled=true] Indicates if Scalable Ambient Obscurance (SAO) will apply to this SceneModel. SAO is configured by the Scene's {@link SAO} component.\r\n * @param {Boolean} [cfg.pbrEnabled=true] Indicates if physically-based rendering (PBR) will apply to the SceneModel when {@link Scene#pbrEnabled} is ````true````.\r\n * @param {Boolean} [cfg.colorTextureEnabled=true] Indicates if base color textures will be rendered for the SceneModel when {@link Scene#colorTextureEnabled} is ````true````.\r\n * @param {Number} [cfg.edgeThreshold=10] When xraying, highlighting, selecting or edging, this is the threshold angle between normals of adjacent triangles, below which their shared wireframe edge is not drawn.\r\n * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\r\n * to limit the size of the batched geometry arrays that SceneModel internally creates for batched geometries.\r\n * A lower value means less heap allocation/de-allocation while creating/loading batched geometries, but more draw calls and\r\n * slower rendering speed. A high value means larger heap allocation/de-allocation while creating/loading, but less draw calls\r\n * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\r\n * @param {TextureTranscoder} [cfg.textureTranscoder] Transcoder that will be used internally by {@link SceneModel#createTexture}\r\n * to convert transcoded texture data. Only required when we'll be providing transcoded data\r\n * to {@link SceneModel#createTexture}. We assume that all transcoded texture data added to a ````SceneModel````\r\n * will then in a format supported by this transcoder.\r\n * @param {Boolean} [cfg.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\r\n * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\r\n * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\r\n * primitives. Only works while {@link DTX#enabled} is also ````true````.\r\n */\r\n constructor(owner, cfg = {}) {\r\n\r\n super(owner, cfg);\r\n\r\n this._dtxEnabled = this.scene.dtxEnabled && (cfg.dtxEnabled !== false);\r\n\r\n this._enableVertexWelding = false; // Not needed for most objects, and very expensive, so disabled\r\n this._enableIndexBucketing = false; // Until fixed: https://github.com/xeokit/xeokit-sdk/issues/1204\r\n\r\n this._vboBatchingLayerScratchMemory = (0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.getScratchMemory)();\r\n this._textureTranscoder = cfg.textureTranscoder || (0,_utils_textureTranscoders_KTX2TextureTranscoder_KTX2TextureTranscoder_js__WEBPACK_IMPORTED_MODULE_20__.getKTX2TextureTranscoder)(this.scene.viewer);\r\n\r\n this._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\r\n\r\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n this._aabbDirty = true;\r\n\r\n this._quantizationRanges = {};\r\n\r\n this._vboInstancingLayers = {};\r\n this._vboBatchingLayers = {};\r\n this._dtxLayers = {};\r\n\r\n this.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second\r\n this._entityList = [];\r\n\r\n this._geometries = {};\r\n this._dtxBuckets = {}; // Geometries with optimizations used for data texture representation\r\n this._textures = {};\r\n this._textureSets = {};\r\n this._transforms = {};\r\n this._meshes = {};\r\n this._entities = {};\r\n\r\n this._scheduledMeshes = {};\r\n this._meshesCfgsBeforeMeshCreation = {};\r\n\r\n /** @private **/\r\n this.renderFlags = new _webgl_RenderFlags_js__WEBPACK_IMPORTED_MODULE_14__.RenderFlags();\r\n\r\n /**\r\n * @private\r\n */\r\n this.numGeometries = 0; // Number of geometries created with createGeometry()\r\n\r\n // These counts are used to avoid unnecessary render passes\r\n // They are incremented or decremented exclusively by BatchingLayer and InstancingLayer\r\n\r\n /**\r\n * @private\r\n */\r\n this.numPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numVisibleLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numTransparentLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numXRayedLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numHighlightedLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numSelectedLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numEdgesLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numPickableLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numClippableLayerPortions = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.numCulledLayerPortions = 0;\r\n\r\n this.numEntities = 0;\r\n this._numTriangles = 0;\r\n this._numLines = 0;\r\n this._numPoints = 0;\r\n\r\n this._edgeThreshold = cfg.edgeThreshold || 10;\r\n\r\n // Build static matrix\r\n\r\n this._origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin || [0, 0, 0]);\r\n this._position = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.position || [0, 0, 0]);\r\n this._rotation = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.rotation || [0, 0, 0]);\r\n this._quaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\r\n this._conjugateQuaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\r\n\r\n if (cfg.rotation) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\r\n }\r\n this._scale = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.scale || [1, 1, 1]);\r\n\r\n this._worldRotationMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n this._worldRotationMatrixConjugate = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n this._matrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n this._matrixDirty = true;\r\n\r\n this._rebuildMatrices();\r\n\r\n this._worldNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._matrix, this._worldNormalMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._worldNormalMatrix);\r\n\r\n if (cfg.matrix || cfg.position || cfg.rotation || cfg.scale || cfg.quaternion) {\r\n this._viewMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n this._viewNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n this._viewMatrixDirty = true;\r\n this._matrixNonIdentity = true;\r\n }\r\n\r\n this._opacity = 1.0;\r\n this._colorize = [1, 1, 1];\r\n\r\n this._saoEnabled = (cfg.saoEnabled !== false);\r\n this._pbrEnabled = (cfg.pbrEnabled !== false);\r\n this._colorTextureEnabled = (cfg.colorTextureEnabled !== false);\r\n\r\n this._isModel = cfg.isModel;\r\n if (this._isModel) {\r\n this.scene._registerModel(this);\r\n }\r\n\r\n this._onCameraViewMatrix = this.scene.camera.on(\"matrix\", () => {\r\n this._viewMatrixDirty = true;\r\n });\r\n\r\n this._meshesWithDirtyMatrices = [];\r\n this._numMeshesWithDirtyMatrices = 0;\r\n\r\n this._onTick = this.scene.on(\"tick\", () => {\r\n while (this._numMeshesWithDirtyMatrices > 0) {\r\n this._meshesWithDirtyMatrices[--this._numMeshesWithDirtyMatrices]._updateMatrix();\r\n }\r\n });\r\n\r\n this._createDefaultTextureSet();\r\n\r\n this.visible = cfg.visible;\r\n this.culled = cfg.culled;\r\n this.pickable = cfg.pickable;\r\n this.clippable = cfg.clippable;\r\n this.collidable = cfg.collidable;\r\n this.castsShadow = cfg.castsShadow;\r\n this.receivesShadow = cfg.receivesShadow;\r\n this.xrayed = cfg.xrayed;\r\n this.highlighted = cfg.highlighted;\r\n this.selected = cfg.selected;\r\n this.edges = cfg.edges;\r\n this.colorize = cfg.colorize;\r\n this.opacity = cfg.opacity;\r\n this.backfaces = cfg.backfaces;\r\n }\r\n\r\n _meshMatrixDirty(mesh) {\r\n this._meshesWithDirtyMatrices[this._numMeshesWithDirtyMatrices++] = mesh;\r\n }\r\n\r\n _createDefaultTextureSet() {\r\n // Every SceneModelMesh gets at least the default TextureSet,\r\n // which contains empty default textures filled with color\r\n const defaultColorTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\r\n id: DEFAULT_COLOR_TEXTURE_ID,\r\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\r\n gl: this.scene.canvas.gl,\r\n preloadColor: [1, 1, 1, 1] // [r, g, b, a]})\r\n })\r\n });\r\n const defaultMetalRoughTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\r\n id: DEFAULT_METAL_ROUGH_TEXTURE_ID,\r\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\r\n gl: this.scene.canvas.gl,\r\n preloadColor: [0, 1, 1, 1] // [unused, roughness, metalness, unused]\r\n })\r\n });\r\n const defaultNormalsTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\r\n id: DEFAULT_NORMALS_TEXTURE_ID,\r\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\r\n gl: this.scene.canvas.gl,\r\n preloadColor: [0, 0, 0, 0] // [x, y, z, unused] - these must be zeros\r\n })\r\n });\r\n const defaultEmissiveTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\r\n id: DEFAULT_EMISSIVE_TEXTURE_ID,\r\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\r\n gl: this.scene.canvas.gl,\r\n preloadColor: [0, 0, 0, 1] // [x, y, z, unused]\r\n })\r\n });\r\n const defaultOcclusionTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\r\n id: DEFAULT_OCCLUSION_TEXTURE_ID,\r\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\r\n gl: this.scene.canvas.gl,\r\n preloadColor: [1, 1, 1, 1] // [x, y, z, unused]\r\n })\r\n });\r\n this._textures[DEFAULT_COLOR_TEXTURE_ID] = defaultColorTexture;\r\n this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID] = defaultMetalRoughTexture;\r\n this._textures[DEFAULT_NORMALS_TEXTURE_ID] = defaultNormalsTexture;\r\n this._textures[DEFAULT_EMISSIVE_TEXTURE_ID] = defaultEmissiveTexture;\r\n this._textures[DEFAULT_OCCLUSION_TEXTURE_ID] = defaultOcclusionTexture;\r\n this._textureSets[DEFAULT_TEXTURE_SET_ID] = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\r\n id: DEFAULT_TEXTURE_SET_ID,\r\n model: this,\r\n colorTexture: defaultColorTexture,\r\n metallicRoughnessTexture: defaultMetalRoughTexture,\r\n normalsTexture: defaultNormalsTexture,\r\n emissiveTexture: defaultEmissiveTexture,\r\n occlusionTexture: defaultOcclusionTexture\r\n });\r\n }\r\n\r\n //------------------------------------------------------------------------------------------------------------------\r\n // SceneModel members\r\n //------------------------------------------------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns true to indicate that this Component is a SceneModel.\r\n * @type {Boolean}\r\n */\r\n get isPerformanceModel() {\r\n return true;\r\n }\r\n\r\n /**\r\n * The {@link SceneModelTransform}s in this SceneModel.\r\n *\r\n * Each {#link SceneModelTransform} is stored here against its {@link SceneModelTransform.id}.\r\n *\r\n * @returns {*|{}}\r\n */\r\n get transforms() {\r\n return this._transforms;\r\n }\r\n\r\n /**\r\n * The {@link SceneModelTexture}s in this SceneModel.\r\n *\r\n * * Each {@link SceneModelTexture} is created with {@link SceneModel.createTexture}.\r\n * * Each {@link SceneModelTexture} is stored here against its {@link SceneModelTexture.id}.\r\n *\r\n * @returns {*|{}}\r\n */\r\n get textures() {\r\n return this._textures;\r\n }\r\n\r\n /**\r\n * The {@link SceneModelTextureSet}s in this SceneModel.\r\n *\r\n * Each {@link SceneModelTextureSet} is stored here against its {@link SceneModelTextureSet.id}.\r\n *\r\n * @returns {*|{}}\r\n */\r\n get textureSets() {\r\n return this._textureSets;\r\n }\r\n\r\n /**\r\n * The {@link SceneModelMesh}es in this SceneModel.\r\n *\r\n * Each {@SceneModelMesh} is stored here against its {@link SceneModelMesh.id}.\r\n *\r\n * @returns {*|{}}\r\n */\r\n get meshes() {\r\n return this._meshes;\r\n }\r\n\r\n /**\r\n * The {@link SceneModelEntity}s in this SceneModel.\r\n *\r\n * Each {#link SceneModelEntity} in this SceneModel that represents an object is\r\n * stored here against its {@link SceneModelTransform.id}.\r\n *\r\n * @returns {*|{}}\r\n */\r\n get objects() {\r\n return this._entities;\r\n }\r\n\r\n /**\r\n * Gets the 3D World-space origin for this SceneModel.\r\n *\r\n * Each {@link SceneModelMesh.origin}, if supplied, is relative to this origin.\r\n *\r\n * Default value is ````[0,0,0]````.\r\n *\r\n * @type {Float64Array}\r\n */\r\n get origin() {\r\n return this._origin;\r\n }\r\n\r\n /**\r\n * Sets the SceneModel's local translation.\r\n *\r\n * Default value is ````[0,0,0]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n set position(value) {\r\n this._position.set(value || [0, 0, 0]);\r\n this._setWorldMatrixDirty();\r\n this._sceneModelDirty();\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's local translation.\r\n *\r\n * Default value is ````[0,0,0]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n get position() {\r\n return this._position;\r\n }\r\n\r\n /**\r\n * Sets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\r\n *\r\n * Default value is ````[0,0,0]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n set rotation(value) {\r\n this._rotation.set(value || [0, 0, 0]);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\r\n this._setWorldMatrixDirty();\r\n this._sceneModelDirty();\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\r\n *\r\n * Default value is ````[0,0,0]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n get rotation() {\r\n return this._rotation;\r\n }\r\n\r\n /**\r\n * Sets the SceneModel's local rotation quaternion.\r\n *\r\n * Default value is ````[0,0,0,1]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n set quaternion(value) {\r\n this._quaternion.set(value || [0, 0, 0, 1]);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToEuler(this._quaternion, \"XYZ\", this._rotation);\r\n this._setWorldMatrixDirty();\r\n this._sceneModelDirty();\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's local rotation quaternion.\r\n *\r\n * Default value is ````[0,0,0,1]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n get quaternion() {\r\n return this._quaternion;\r\n }\r\n\r\n /**\r\n * Sets the SceneModel's local scale.\r\n *\r\n * Default value is ````[1,1,1]````.\r\n *\r\n * @type {Number[]}\r\n * @deprecated\r\n */\r\n set scale(value) {\r\n // NOP - deprecated\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's local scale.\r\n *\r\n * Default value is ````[1,1,1]````.\r\n *\r\n * @type {Number[]}\r\n * @deprecated\r\n */\r\n get scale() {\r\n return this._scale;\r\n }\r\n\r\n /**\r\n * Sets the SceneModel's local modeling transform matrix.\r\n *\r\n * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n set matrix(value) {\r\n this._matrix.set(value || DEFAULT_MATRIX);\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\r\n this._matrix.set(this._worldRotationMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\r\n\r\n this._matrixDirty = false;\r\n this._setWorldMatrixDirty();\r\n this._sceneModelDirty();\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's local modeling transform matrix.\r\n *\r\n * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n get matrix() {\r\n if (this._matrixDirty) {\r\n this._rebuildMatrices();\r\n }\r\n return this._matrix;\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's local modeling rotation transform matrix.\r\n *\r\n * @type {Number[]}\r\n */\r\n get rotationMatrix() {\r\n if (this._matrixDirty) {\r\n this._rebuildMatrices();\r\n }\r\n return this._worldRotationMatrix;\r\n }\r\n\r\n _rebuildMatrices() {\r\n if (this._matrixDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\r\n this._matrix.set(this._worldRotationMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\r\n this._matrixDirty = false;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the conjugate of the SceneModel's local modeling rotation transform matrix.\r\n *\r\n * This is used for RTC view matrix management in renderers.\r\n *\r\n * @type {Number[]}\r\n */\r\n get rotationMatrixConjugate() {\r\n if (this._matrixDirty) {\r\n this._rebuildMatrices();\r\n }\r\n return this._worldRotationMatrixConjugate;\r\n }\r\n\r\n _setWorldMatrixDirty() {\r\n this._matrixDirty = true;\r\n this._aabbDirty = true;\r\n }\r\n\r\n _transformDirty() {\r\n this._matrixDirty = true;\r\n this._aabbDirty = true;\r\n this.scene._aabbDirty = true;\r\n }\r\n\r\n _sceneModelDirty() {\r\n this.scene._aabbDirty = true;\r\n this._aabbDirty = true;\r\n this.scene._aabbDirty = true;\r\n this._matrixDirty = true;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i]._sceneModelDirty(); // Entities need to retransform their World AABBs by SceneModel's worldMatrix\r\n }\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's World matrix.\r\n *\r\n * @property worldMatrix\r\n * @type {Number[]}\r\n */\r\n get worldMatrix() {\r\n return this.matrix;\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's World normal matrix.\r\n *\r\n * @type {Number[]}\r\n */\r\n get worldNormalMatrix() {\r\n return this._worldNormalMatrix;\r\n }\r\n\r\n /**\r\n * Called by private renderers in ./lib, returns the view matrix with which to\r\n * render this SceneModel. The view matrix is the concatenation of the\r\n * Camera view matrix with the Performance model's world (modeling) matrix.\r\n *\r\n * @private\r\n */\r\n get viewMatrix() {\r\n if (!this._viewMatrix) {\r\n return this.scene.camera.viewMatrix;\r\n }\r\n if (this._matrixDirty) {\r\n this._rebuildMatrices();\r\n this._viewMatrixDirty = true;\r\n }\r\n if (this._viewMatrixDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\r\n this._viewMatrixDirty = false;\r\n }\r\n return this._viewMatrix;\r\n }\r\n\r\n /**\r\n * Called by private renderers in ./lib, returns the view normal matrix with which to render this SceneModel.\r\n *\r\n * @private\r\n */\r\n get viewNormalMatrix() {\r\n if (!this._viewNormalMatrix) {\r\n return this.scene.camera.viewNormalMatrix;\r\n }\r\n if (this._matrixDirty) {\r\n this._rebuildMatrices();\r\n this._viewMatrixDirty = true;\r\n }\r\n if (this._viewMatrixDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\r\n this._viewMatrixDirty = false;\r\n }\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\r\n return this._viewNormalMatrix;\r\n }\r\n\r\n /**\r\n * Sets if backfaces are rendered for this SceneModel.\r\n *\r\n * Default is ````false````.\r\n *\r\n * @type {Boolean}\r\n */\r\n get backfaces() {\r\n return this._backfaces;\r\n }\r\n\r\n /**\r\n * Sets if backfaces are rendered for this SceneModel.\r\n *\r\n * Default is ````false````.\r\n *\r\n * When we set this ````true````, then backfaces are always rendered for this SceneModel.\r\n *\r\n * When we set this ````false````, then we allow the Viewer to decide whether to render backfaces. In this case,\r\n * the Viewer will:\r\n *\r\n * * hide backfaces on watertight meshes,\r\n * * show backfaces on open meshes, and\r\n * * always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\r\n *\r\n * @type {Boolean}\r\n */\r\n set backfaces(backfaces) {\r\n backfaces = !!backfaces;\r\n this._backfaces = backfaces;\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets the list of {@link SceneModelEntity}s within this SceneModel.\r\n *\r\n * @returns {SceneModelEntity[]}\r\n */\r\n get entityList() {\r\n return this._entityList;\r\n }\r\n\r\n /**\r\n * Returns true to indicate that SceneModel is an {@link Entity}.\r\n * @type {Boolean}\r\n */\r\n get isEntity() {\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns ````true```` if this SceneModel represents a model.\r\n *\r\n * When ````true```` the SceneModel will be registered by {@link SceneModel#id} in\r\n * {@link Scene#models} and may also have a {@link MetaObject} with matching {@link MetaObject#id}.\r\n *\r\n * @type {Boolean}\r\n */\r\n get isModel() {\r\n return this._isModel;\r\n }\r\n\r\n //------------------------------------------------------------------------------------------------------------------\r\n // SceneModel members\r\n //------------------------------------------------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns ````false```` to indicate that SceneModel never represents an object.\r\n *\r\n * @type {Boolean}\r\n */\r\n get isObject() {\r\n return false;\r\n }\r\n\r\n /**\r\n * Gets the SceneModel's World-space 3D axis-aligned bounding box.\r\n *\r\n * Represented by a six-element Float64Array containing the min/max extents of the\r\n * axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n get aabb() {\r\n if (this._aabbDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3(this._aabb);\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3(this._aabb, this._entityList[i].aabb);\r\n }\r\n this._aabbDirty = false;\r\n }\r\n return this._aabb;\r\n }\r\n\r\n /**\r\n * The approximate number of triangle primitives in this SceneModel.\r\n *\r\n * @type {Number}\r\n */\r\n get numTriangles() {\r\n return this._numTriangles;\r\n }\r\n\r\n //------------------------------------------------------------------------------------------------------------------\r\n // Entity members\r\n //------------------------------------------------------------------------------------------------------------------\r\n\r\n /**\r\n * The approximate number of line primitives in this SceneModel.\r\n *\r\n * @type {Number}\r\n */\r\n get numLines() {\r\n return this._numLines;\r\n }\r\n\r\n /**\r\n * The approximate number of point primitives in this SceneModel.\r\n *\r\n * @type {Number}\r\n */\r\n get numPoints() {\r\n return this._numPoints;\r\n }\r\n\r\n /**\r\n * Gets if any {@link SceneModelEntity}s in this SceneModel are visible.\r\n *\r\n * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\r\n *\r\n * @type {Boolean}\r\n */\r\n get visible() {\r\n return (this.numVisibleLayerPortions > 0);\r\n }\r\n\r\n /**\r\n * Sets if this SceneModel is visible.\r\n *\r\n * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\r\n **\r\n * @type {Boolean}\r\n */\r\n set visible(visible) {\r\n visible = visible !== false;\r\n this._visible = visible;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].visible = visible;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if any {@link SceneModelEntity}s in this SceneModel are xrayed.\r\n *\r\n * @type {Boolean}\r\n */\r\n get xrayed() {\r\n return (this.numXRayedLayerPortions > 0);\r\n }\r\n\r\n /**\r\n * Sets if all {@link SceneModelEntity}s in this SceneModel are xrayed.\r\n *\r\n * @type {Boolean}\r\n */\r\n set xrayed(xrayed) {\r\n xrayed = !!xrayed;\r\n this._xrayed = xrayed;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].xrayed = xrayed;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if any {@link SceneModelEntity}s in this SceneModel are highlighted.\r\n *\r\n * @type {Boolean}\r\n */\r\n get highlighted() {\r\n return (this.numHighlightedLayerPortions > 0);\r\n }\r\n\r\n /**\r\n * Sets if all {@link SceneModelEntity}s in this SceneModel are highlighted.\r\n *\r\n * @type {Boolean}\r\n */\r\n set highlighted(highlighted) {\r\n highlighted = !!highlighted;\r\n this._highlighted = highlighted;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].highlighted = highlighted;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if any {@link SceneModelEntity}s in this SceneModel are selected.\r\n *\r\n * @type {Boolean}\r\n */\r\n get selected() {\r\n return (this.numSelectedLayerPortions > 0);\r\n }\r\n\r\n /**\r\n * Sets if all {@link SceneModelEntity}s in this SceneModel are selected.\r\n *\r\n * @type {Boolean}\r\n */\r\n set selected(selected) {\r\n selected = !!selected;\r\n this._selected = selected;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].selected = selected;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if any {@link SceneModelEntity}s in this SceneModel have edges emphasised.\r\n *\r\n * @type {Boolean}\r\n */\r\n get edges() {\r\n return (this.numEdgesLayerPortions > 0);\r\n }\r\n\r\n /**\r\n * Sets if all {@link SceneModelEntity}s in this SceneModel have edges emphasised.\r\n *\r\n * @type {Boolean}\r\n */\r\n set edges(edges) {\r\n edges = !!edges;\r\n this._edges = edges;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].edges = edges;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if this SceneModel is culled from view.\r\n *\r\n * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\r\n *\r\n * @type {Boolean}\r\n */\r\n get culled() {\r\n return this._culled;\r\n }\r\n\r\n /**\r\n * Sets if this SceneModel is culled from view.\r\n *\r\n * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\r\n *\r\n * @type {Boolean}\r\n */\r\n set culled(culled) {\r\n culled = !!culled;\r\n this._culled = culled;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].culled = culled;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if {@link SceneModelEntity}s in this SceneModel are clippable.\r\n *\r\n * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\r\n *\r\n * @type {Boolean}\r\n */\r\n get clippable() {\r\n return this._clippable;\r\n }\r\n\r\n /**\r\n * Sets if {@link SceneModelEntity}s in this SceneModel are clippable.\r\n *\r\n * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\r\n *\r\n * @type {Boolean}\r\n */\r\n set clippable(clippable) {\r\n clippable = clippable !== false;\r\n this._clippable = clippable;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].clippable = clippable;\r\n }\r\n this.glRedraw();\r\n }\r\n\r\n /**\r\n * Gets if this SceneModel is collidable.\r\n *\r\n * @type {Boolean}\r\n */\r\n get collidable() {\r\n return this._collidable;\r\n }\r\n\r\n /**\r\n * Sets if {@link SceneModelEntity}s in this SceneModel are collidable.\r\n *\r\n * @type {Boolean}\r\n */\r\n set collidable(collidable) {\r\n collidable = collidable !== false;\r\n this._collidable = collidable;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].collidable = collidable;\r\n }\r\n }\r\n\r\n /**\r\n * Gets if this SceneModel is pickable.\r\n *\r\n * Picking is done via calls to {@link Scene#pick}.\r\n *\r\n * @type {Boolean}\r\n */\r\n get pickable() {\r\n return (this.numPickableLayerPortions > 0);\r\n }\r\n\r\n /**\r\n * Sets if {@link SceneModelEntity}s in this SceneModel are pickable.\r\n *\r\n * Picking is done via calls to {@link Scene#pick}.\r\n *\r\n * @type {Boolean}\r\n */\r\n set pickable(pickable) {\r\n pickable = pickable !== false;\r\n this._pickable = pickable;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].pickable = pickable;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the RGB colorize color for this SceneModel.\r\n *\r\n * Each element of the color is in range ````[0..1]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n get colorize() {\r\n return this._colorize;\r\n }\r\n\r\n /**\r\n * Sets the RGB colorize color for this SceneModel.\r\n *\r\n * Multiplies by rendered fragment colors.\r\n *\r\n * Each element of the color is in range ````[0..1]````.\r\n *\r\n * @type {Number[]}\r\n */\r\n set colorize(colorize) {\r\n this._colorize = colorize;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].colorize = colorize;\r\n }\r\n }\r\n\r\n /**\r\n * Gets this SceneModel's opacity factor.\r\n *\r\n * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\r\n *\r\n * @type {Number}\r\n */\r\n get opacity() {\r\n return this._opacity;\r\n }\r\n\r\n /**\r\n * Sets the opacity factor for this SceneModel.\r\n *\r\n * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\r\n *\r\n * @type {Number}\r\n */\r\n set opacity(opacity) {\r\n this._opacity = opacity;\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i].opacity = opacity;\r\n }\r\n }\r\n\r\n /**\r\n * Gets if this SceneModel casts a shadow.\r\n *\r\n * @type {Boolean}\r\n */\r\n get castsShadow() {\r\n return this._castsShadow;\r\n }\r\n\r\n /**\r\n * Sets if this SceneModel casts a shadow.\r\n *\r\n * @type {Boolean}\r\n */\r\n set castsShadow(castsShadow) {\r\n castsShadow = (castsShadow !== false);\r\n if (castsShadow !== this._castsShadow) {\r\n this._castsShadow = castsShadow;\r\n this.glRedraw();\r\n }\r\n }\r\n\r\n /**\r\n * Sets if this SceneModel can have shadow cast upon it.\r\n *\r\n * @type {Boolean}\r\n */\r\n get receivesShadow() {\r\n return this._receivesShadow;\r\n }\r\n\r\n /**\r\n * Sets if this SceneModel can have shadow cast upon it.\r\n *\r\n * @type {Boolean}\r\n */\r\n set receivesShadow(receivesShadow) {\r\n receivesShadow = (receivesShadow !== false);\r\n if (receivesShadow !== this._receivesShadow) {\r\n this._receivesShadow = receivesShadow;\r\n this.glRedraw();\r\n }\r\n }\r\n\r\n /**\r\n * Gets if Scalable Ambient Obscurance (SAO) will apply to this SceneModel.\r\n *\r\n * SAO is configured by the Scene's {@link SAO} component.\r\n *\r\n * Only works when {@link SAO#enabled} is also true.\r\n *\r\n * @type {Boolean}\r\n */\r\n get saoEnabled() {\r\n return this._saoEnabled;\r\n }\r\n\r\n /**\r\n * Gets if physically-based rendering (PBR) is enabled for this SceneModel.\r\n *\r\n * Only works when {@link Scene#pbrEnabled} is also true.\r\n *\r\n * @type {Boolean}\r\n */\r\n get pbrEnabled() {\r\n return this._pbrEnabled;\r\n }\r\n\r\n /**\r\n * Gets if color textures are enabled for this SceneModel.\r\n *\r\n * Only works when {@link Scene#colorTextureEnabled} is also true.\r\n *\r\n * @type {Boolean}\r\n */\r\n get colorTextureEnabled() {\r\n return this._colorTextureEnabled;\r\n }\r\n\r\n /**\r\n * Returns true to indicate that SceneModel is implements {@link Drawable}.\r\n *\r\n * @type {Boolean}\r\n */\r\n get isDrawable() {\r\n return true;\r\n }\r\n\r\n /** @private */\r\n get isStateSortable() {\r\n return false\r\n }\r\n\r\n /**\r\n * Configures the appearance of xrayed {@link SceneModelEntity}s within this SceneModel.\r\n *\r\n * This is the {@link Scene#xrayMaterial}.\r\n *\r\n * @type {EmphasisMaterial}\r\n */\r\n get xrayMaterial() {\r\n return this.scene.xrayMaterial;\r\n }\r\n\r\n /**\r\n * Configures the appearance of highlighted {@link SceneModelEntity}s within this SceneModel.\r\n *\r\n * This is the {@link Scene#highlightMaterial}.\r\n *\r\n * @type {EmphasisMaterial}\r\n */\r\n get highlightMaterial() {\r\n return this.scene.highlightMaterial;\r\n }\r\n\r\n /**\r\n * Configures the appearance of selected {@link SceneModelEntity}s within this SceneModel.\r\n *\r\n * This is the {@link Scene#selectedMaterial}.\r\n *\r\n * @type {EmphasisMaterial}\r\n */\r\n get selectedMaterial() {\r\n return this.scene.selectedMaterial;\r\n }\r\n\r\n /**\r\n * Configures the appearance of edges of {@link SceneModelEntity}s within this SceneModel.\r\n *\r\n * This is the {@link Scene#edgeMaterial}.\r\n *\r\n * @type {EdgeMaterial}\r\n */\r\n get edgeMaterial() {\r\n return this.scene.edgeMaterial;\r\n }\r\n\r\n //------------------------------------------------------------------------------------------------------------------\r\n // Drawable members\r\n //------------------------------------------------------------------------------------------------------------------\r\n\r\n /**\r\n * Called by private renderers in ./lib, returns the picking view matrix with which to\r\n * ray-pick on this SceneModel.\r\n *\r\n * @private\r\n */\r\n getPickViewMatrix(pickViewMatrix) {\r\n if (!this._viewMatrix) {\r\n return pickViewMatrix;\r\n }\r\n return this._viewMatrix;\r\n }\r\n\r\n /**\r\n *\r\n * @param cfg\r\n */\r\n createQuantizationRange(cfg) {\r\n if (cfg.id === undefined || cfg.id === null) {\r\n this.error(\"[createQuantizationRange] Config missing: id\");\r\n return;\r\n }\r\n if (cfg.aabb) {\r\n this.error(\"[createQuantizationRange] Config missing: aabb\");\r\n return;\r\n }\r\n if (this._quantizationRanges[cfg.id]) {\r\n this.error(\"[createQuantizationRange] QuantizationRange already created: \" + cfg.id);\r\n return;\r\n }\r\n this._quantizationRanges[cfg.id] = {\r\n id: cfg.id,\r\n aabb: cfg.aabb,\r\n matrix: (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.aabb, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4())\r\n }\r\n }\r\n\r\n /**\r\n * Creates a reusable geometry within this SceneModel.\r\n *\r\n * We can then supply the geometry ID to {@link SceneModel#createMesh} when we want to create meshes that\r\n * instance the geometry.\r\n *\r\n * @param {*} cfg Geometry properties.\r\n * @param {String|Number} cfg.id Mandatory ID for the geometry, to refer to with {@link SceneModel#createMesh}.\r\n * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\r\n * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\r\n * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\r\n * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\r\n * @param {Number[]} [cfg.normals] Flat array of normal vectors. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\r\n * @param {Number[]} [cfg.normalsCompressed] Flat array of oct-encoded normal vectors. Overrides ````normals````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\r\n * @param {Number[]} [cfg.colors] Flat array of uncompressed RGBA vertex colors, as float values in range ````[0..1]````. Ignored when ````geometryId```` is given. Overridden by ````color```` and ````colorsCompressed````.\r\n * @param {Number[]} [cfg.colorsCompressed] Flat array of compressed RGBA vertex colors, as unsigned short integers in range ````[0..255]````. Ignored when ````geometryId```` is given. Overrides ````colors```` and is overridden by ````color````.\r\n * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\r\n * @param {Number[]} [cfg.uvCompressed] Flat array of compressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Overrides ````uv````. Must be accompanied by ````uvDecodeMatrix````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\r\n * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\r\n * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\r\n * @param {Number[]} [cfg.edgeIndices] Array of edge line indices. Used only with 'triangles', 'solid' and 'surface' primitives. Automatically generated internally if not supplied, using the optional ````edgeThreshold```` given to the ````SceneModel```` constructor.\r\n */\r\n createGeometry(cfg) {\r\n if (cfg.id === undefined || cfg.id === null) {\r\n this.error(\"[createGeometry] Config missing: id\");\r\n return;\r\n }\r\n if (this._geometries[cfg.id]) {\r\n this.error(\"[createGeometry] Geometry already created: \" + cfg.id);\r\n return;\r\n }\r\n if (cfg.primitive === undefined || cfg.primitive === null) {\r\n cfg.primitive = \"triangles\";\r\n }\r\n if (cfg.primitive !== \"points\" && cfg.primitive !== \"lines\" && cfg.primitive !== \"triangles\" && cfg.primitive !== \"solid\" && cfg.primitive !== \"surface\") {\r\n this.error(`[createGeometry] Unsupported value for 'primitive': '${cfg.primitive}' - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'. Defaulting to 'triangles'.`);\r\n return;\r\n }\r\n if (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\r\n this.error(\"[createGeometry] Param expected: `positions`, `positionsCompressed' or 'buckets\");\r\n return null;\r\n }\r\n if (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\r\n this.error(\"[createGeometry] Param expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\");\r\n return null;\r\n }\r\n if (cfg.positionsDecodeMatrix && cfg.positionsDecodeBoundary) {\r\n this.error(\"[createGeometry] Only one of these params expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\");\r\n return null;\r\n }\r\n if (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\r\n this.error(\"[createGeometry] Param expected: `uvDecodeMatrix` (required for `uvCompressed')\");\r\n return null;\r\n }\r\n if (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\r\n this.error(`[createGeometry] Param expected: indices (required for '${cfg.primitive}' primitive type)`);\r\n return null;\r\n }\r\n if (cfg.positionsDecodeBoundary) {\r\n cfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\r\n }\r\n if (cfg.positions) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n cfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\r\n cfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\r\n cfg.aabb = aabb;\r\n } else if (cfg.positionsCompressed) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n cfg.positionsDecodeMatrix = new Float64Array(cfg.positionsDecodeMatrix);\r\n cfg.positionsCompressed = new Uint16Array(cfg.positionsCompressed);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\r\n cfg.aabb = aabb;\r\n } else if (cfg.buckets) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n this._dtxBuckets[cfg.id] = cfg.buckets;\r\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\r\n const bucket = cfg.buckets[i];\r\n if (bucket.positions) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\r\n } else if (bucket.positionsCompressed) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\r\n }\r\n }\r\n if (cfg.positionsDecodeMatrix) {\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\r\n }\r\n cfg.aabb = aabb;\r\n }\r\n if (cfg.colorsCompressed && cfg.colorsCompressed.length > 0) {\r\n cfg.colorsCompressed = new Uint8Array(cfg.colorsCompressed);\r\n } else if (cfg.colors && cfg.colors.length > 0) {\r\n const colors = cfg.colors;\r\n const colorsCompressed = new Uint8Array(colors.length);\r\n for (let i = 0, len = colors.length; i < len; i++) {\r\n colorsCompressed[i] = colors[i] * 255;\r\n }\r\n cfg.colorsCompressed = colorsCompressed;\r\n }\r\n if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")) {\r\n if (cfg.positions) {\r\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 5.0);\r\n } else {\r\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\r\n }\r\n }\r\n if (cfg.uv) {\r\n const bounds = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.getUVBounds(cfg.uv);\r\n const result = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.compressUVs(cfg.uv, bounds.min, bounds.max);\r\n cfg.uvCompressed = result.quantized;\r\n cfg.uvDecodeMatrix = result.decodeMatrix;\r\n } else if (cfg.uvCompressed) {\r\n cfg.uvCompressed = new Uint16Array(cfg.uvCompressed);\r\n cfg.uvDecodeMatrix = new Float64Array(cfg.uvDecodeMatrix);\r\n }\r\n if (cfg.normals) { // HACK\r\n cfg.normals = null;\r\n }\r\n this._geometries [cfg.id] = cfg;\r\n this._numTriangles += (cfg.indices ? Math.round(cfg.indices.length / 3) : 0);\r\n this.numGeometries++;\r\n }\r\n\r\n /**\r\n * Creates a texture within this SceneModel.\r\n *\r\n * We can then supply the texture ID to {@link SceneModel#createTextureSet} when we want to create texture sets that use the texture.\r\n *\r\n * @param {*} cfg Texture properties.\r\n * @param {String|Number} cfg.id Mandatory ID for the texture, to refer to with {@link SceneModel#createTextureSet}.\r\n * @param {String} [cfg.src] Image file for the texture. Assumed to be transcoded if not having a recognized image file\r\n * extension (jpg, jpeg, png etc.). If transcoded, then assumes ````SceneModel```` is configured with a {@link TextureTranscoder}.\r\n * @param {ArrayBuffer[]} [cfg.buffers] Transcoded texture data. Assumes ````SceneModel```` is\r\n * configured with a {@link TextureTranscoder}. This parameter is given as an array of buffers so we can potentially support multi-image textures, such as cube maps.\r\n * @param {HTMLImageElement} [cfg.image] HTML Image object to load into this texture. Overrides ````src```` and ````buffers````. Never transcoded.\r\n * @param {Number} [cfg.minFilter=LinearMipmapLinearFilter] How the texture is sampled when a texel covers less than one pixel.\r\n * Supported values are {@link LinearMipmapLinearFilter}, {@link LinearMipMapNearestFilter}, {@link NearestMipMapNearestFilter}, {@link NearestMipMapLinearFilter} and {@link LinearMipMapLinearFilter}.\r\n * @param {Number} [cfg.magFilter=LinearFilter] How the texture is sampled when a texel covers more than one pixel. Supported values are {@link LinearFilter} and {@link NearestFilter}.\r\n * @param {Number} [cfg.wrapS=RepeatWrapping] Wrap parameter for texture coordinate *S*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\r\n * @param {Number} [cfg.wrapT=RepeatWrapping] Wrap parameter for texture coordinate *T*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}..\r\n * @param {Number} [cfg.wrapR=RepeatWrapping] Wrap parameter for texture coordinate *R*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\r\n * @param {Boolean} [cfg.flipY=false] Flips this Texture's source data along its vertical axis when ````true````.\r\n * @param {Number} [cfg.encoding=LinearEncoding] Encoding format. Supported values are {@link LinearEncoding} and {@link sRGBEncoding}.\r\n */\r\n createTexture(cfg) {\r\n const textureId = cfg.id;\r\n if (textureId === undefined || textureId === null) {\r\n this.error(\"[createTexture] Config missing: id\");\r\n return;\r\n }\r\n if (this._textures[textureId]) {\r\n this.error(\"[createTexture] Texture already created: \" + textureId);\r\n return;\r\n }\r\n if (!cfg.src && !cfg.image && !cfg.buffers) {\r\n this.error(\"[createTexture] Param expected: `src`, `image' or 'buffers'\");\r\n return null;\r\n }\r\n let minFilter = cfg.minFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\r\n if (minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter &&\r\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipMapNearestFilter &&\r\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter &&\r\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapLinearFilter &&\r\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapNearestFilter) {\r\n this.error(`[createTexture] Unsupported value for 'minFilter' - \r\n supported values are LinearFilter, LinearMipMapNearestFilter, NearestMipMapNearestFilter, \r\n NearestMipMapLinearFilter and LinearMipmapLinearFilter. Defaulting to LinearMipmapLinearFilter.`);\r\n minFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\r\n }\r\n let magFilter = cfg.magFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\r\n if (magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter && magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestFilter) {\r\n this.error(`[createTexture] Unsupported value for 'magFilter' - supported values are LinearFilter and NearestFilter. Defaulting to LinearFilter.`);\r\n magFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\r\n }\r\n let wrapS = cfg.wrapS || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\r\n if (wrapS !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.ClampToEdgeWrapping && wrapS !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.MirroredRepeatWrapping && wrapS !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping) {\r\n this.error(`[createTexture] Unsupported value for 'wrapS' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`);\r\n wrapS = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\r\n }\r\n let wrapT = cfg.wrapT || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\r\n if (wrapT !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.ClampToEdgeWrapping && wrapT !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.MirroredRepeatWrapping && wrapT !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping) {\r\n this.error(`[createTexture] Unsupported value for 'wrapT' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`);\r\n wrapT = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\r\n }\r\n let wrapR = cfg.wrapR || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\r\n if (wrapR !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.ClampToEdgeWrapping && wrapR !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.MirroredRepeatWrapping && wrapR !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping) {\r\n this.error(`[createTexture] Unsupported value for 'wrapR' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`);\r\n wrapR = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\r\n }\r\n let encoding = cfg.encoding || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\r\n if (encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding && encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.sRGBEncoding) {\r\n this.error(\"[createTexture] Unsupported value for 'encoding' - supported values are LinearEncoding and sRGBEncoding. Defaulting to LinearEncoding.\");\r\n encoding = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\r\n }\r\n const texture = new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\r\n gl: this.scene.canvas.gl,\r\n minFilter,\r\n magFilter,\r\n wrapS,\r\n wrapT,\r\n wrapR,\r\n // flipY: cfg.flipY,\r\n encoding\r\n });\r\n if (cfg.preloadColor) {\r\n texture.setPreloadColor(cfg.preloadColor);\r\n }\r\n if (cfg.image) { // Ignore transcoder for Images\r\n const image = cfg.image;\r\n image.crossOrigin = \"Anonymous\";\r\n texture.setImage(image, {minFilter, magFilter, wrapS, wrapT, wrapR, flipY: cfg.flipY, encoding});\r\n } else if (cfg.src) {\r\n const ext = cfg.src.split('.').pop();\r\n switch (ext) { // Don't transcode recognized image file types\r\n case \"jpeg\":\r\n case \"jpg\":\r\n case \"png\":\r\n case \"gif\":\r\n const image = new Image();\r\n image.onload = () => {\r\n texture.setImage(image, {\r\n minFilter,\r\n magFilter,\r\n wrapS,\r\n wrapT,\r\n wrapR,\r\n flipY: cfg.flipY,\r\n encoding\r\n });\r\n this.glRedraw();\r\n };\r\n image.src = cfg.src; // URL or Base64 string\r\n break;\r\n default: // Assume other file types need transcoding\r\n if (!this._textureTranscoder) {\r\n this.error(`[createTexture] Can't create texture from 'src' - SceneModel needs to be configured with a TextureTranscoder for this file type ('${ext}')`);\r\n } else {\r\n _utils_js__WEBPACK_IMPORTED_MODULE_19__.utils.loadArraybuffer(cfg.src, (arrayBuffer) => {\r\n if (!arrayBuffer.byteLength) {\r\n this.error(`[createTexture] Can't create texture from 'src': file data is zero length`);\r\n return;\r\n }\r\n this._textureTranscoder.transcode([arrayBuffer], texture).then(() => {\r\n this.glRedraw();\r\n });\r\n },\r\n function (errMsg) {\r\n this.error(`[createTexture] Can't create texture from 'src': ${errMsg}`);\r\n });\r\n }\r\n break;\r\n }\r\n } else if (cfg.buffers) { // Buffers implicitly require transcoding\r\n if (!this._textureTranscoder) {\r\n this.error(`[createTexture] Can't create texture from 'buffers' - SceneModel needs to be configured with a TextureTranscoder for this option`);\r\n } else {\r\n this._textureTranscoder.transcode(cfg.buffers, texture).then(() => {\r\n this.glRedraw();\r\n });\r\n }\r\n }\r\n this._textures[textureId] = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({id: textureId, texture});\r\n }\r\n\r\n /**\r\n * Creates a texture set within this SceneModel.\r\n *\r\n * * Stores the new {@link SceneModelTextureSet} in {@link SceneModel#textureSets}.\r\n *\r\n * A texture set is a collection of textures that can be shared among meshes. We can then supply the texture set\r\n * ID to {@link SceneModel#createMesh} when we want to create meshes that use the texture set.\r\n *\r\n * The textures can work as a texture atlas, where each mesh can have geometry UVs that index\r\n * a different part of the textures. This allows us to minimize the number of textures in our models, which\r\n * means faster rendering.\r\n *\r\n * @param {*} cfg Texture set properties.\r\n * @param {String|Number} cfg.id Mandatory ID for the texture set, to refer to with {@link SceneModel#createMesh}.\r\n * @param {*} [cfg.colorTextureId] ID of *RGBA* base color texture, with color in *RGB* and alpha in *A*.\r\n * @param {*} [cfg.metallicRoughnessTextureId] ID of *RGBA* metal-roughness texture, with the metallic factor in *R*, and roughness factor in *G*.\r\n * @param {*} [cfg.normalsTextureId] ID of *RGBA* normal map texture, with normal map vectors in *RGB*.\r\n * @param {*} [cfg.emissiveTextureId] ID of *RGBA* emissive map texture, with emissive color in *RGB*.\r\n * @param {*} [cfg.occlusionTextureId] ID of *RGBA* occlusion map texture, with occlusion factor in *R*.\r\n * @returns {SceneModelTransform} The new texture set.\r\n */\r\n createTextureSet(cfg) {\r\n const textureSetId = cfg.id;\r\n if (textureSetId === undefined || textureSetId === null) {\r\n this.error(\"[createTextureSet] Config missing: id\");\r\n return;\r\n }\r\n if (this._textureSets[textureSetId]) {\r\n this.error(`[createTextureSet] Texture set already created: ${textureSetId}`);\r\n return;\r\n }\r\n let colorTexture;\r\n if (cfg.colorTextureId !== undefined && cfg.colorTextureId !== null) {\r\n colorTexture = this._textures[cfg.colorTextureId];\r\n if (!colorTexture) {\r\n this.error(`[createTextureSet] Texture not found: ${cfg.colorTextureId} - ensure that you create it first with createTexture()`);\r\n return;\r\n }\r\n } else {\r\n colorTexture = this._textures[DEFAULT_COLOR_TEXTURE_ID];\r\n }\r\n let metallicRoughnessTexture;\r\n if (cfg.metallicRoughnessTextureId !== undefined && cfg.metallicRoughnessTextureId !== null) {\r\n metallicRoughnessTexture = this._textures[cfg.metallicRoughnessTextureId];\r\n if (!metallicRoughnessTexture) {\r\n this.error(`[createTextureSet] Texture not found: ${cfg.metallicRoughnessTextureId} - ensure that you create it first with createTexture()`);\r\n return;\r\n }\r\n } else {\r\n metallicRoughnessTexture = this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID];\r\n }\r\n let normalsTexture;\r\n if (cfg.normalsTextureId !== undefined && cfg.normalsTextureId !== null) {\r\n normalsTexture = this._textures[cfg.normalsTextureId];\r\n if (!normalsTexture) {\r\n this.error(`[createTextureSet] Texture not found: ${cfg.normalsTextureId} - ensure that you create it first with createTexture()`);\r\n return;\r\n }\r\n } else {\r\n normalsTexture = this._textures[DEFAULT_NORMALS_TEXTURE_ID];\r\n }\r\n let emissiveTexture;\r\n if (cfg.emissiveTextureId !== undefined && cfg.emissiveTextureId !== null) {\r\n emissiveTexture = this._textures[cfg.emissiveTextureId];\r\n if (!emissiveTexture) {\r\n this.error(`[createTextureSet] Texture not found: ${cfg.emissiveTextureId} - ensure that you create it first with createTexture()`);\r\n return;\r\n }\r\n } else {\r\n emissiveTexture = this._textures[DEFAULT_EMISSIVE_TEXTURE_ID];\r\n }\r\n let occlusionTexture;\r\n if (cfg.occlusionTextureId !== undefined && cfg.occlusionTextureId !== null) {\r\n occlusionTexture = this._textures[cfg.occlusionTextureId];\r\n if (!occlusionTexture) {\r\n this.error(`[createTextureSet] Texture not found: ${cfg.occlusionTextureId} - ensure that you create it first with createTexture()`);\r\n return;\r\n }\r\n } else {\r\n occlusionTexture = this._textures[DEFAULT_OCCLUSION_TEXTURE_ID];\r\n }\r\n const textureSet = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\r\n id: textureSetId,\r\n model: this,\r\n colorTexture,\r\n metallicRoughnessTexture,\r\n normalsTexture,\r\n emissiveTexture,\r\n occlusionTexture\r\n });\r\n this._textureSets[textureSetId] = textureSet;\r\n return textureSet;\r\n }\r\n\r\n /**\r\n * Creates a new {@link SceneModelTransform} within this SceneModel.\r\n *\r\n * * Stores the new {@link SceneModelTransform} in {@link SceneModel#transforms}.\r\n * * Can be connected into hierarchies\r\n * * Each {@link SceneModelTransform} can be used by unlimited {@link SceneModelMesh}es\r\n *\r\n * @param {*} cfg Transform creation parameters.\r\n * @param {String} cfg.id Mandatory ID for the new transform. Must not clash with any existing components within the {@link Scene}.\r\n * @param {String} [cfg.parentTransformId] ID of a parent transform, previously created with {@link SceneModel#createTextureSet}.\r\n * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\r\n * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the transform.\r\n * @param {Number[]} [cfg.rotation=[0,0,0]] Rotation of the transform as Euler angles given in degrees, for each of the X, Y and Z axis.\r\n * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] Modelling transform matrix. Overrides the ````position````, ````scale```` and ````rotation```` parameters.\r\n * @returns {SceneModelTransform} The new transform.\r\n */\r\n createTransform(cfg) {\r\n if (cfg.id === undefined || cfg.id === null) {\r\n this.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\r\n return;\r\n }\r\n if (this._transforms[cfg.id]) {\r\n this.error(`[createTransform] SceneModel already has a transform with this ID: ${cfg.id}`);\r\n return;\r\n }\r\n let parentTransform;\r\n if (this.parentTransformId) {\r\n parentTransform = this._transforms[cfg.parentTransformId];\r\n if (!parentTransform) {\r\n this.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\r\n return;\r\n }\r\n }\r\n const transform = new _SceneModelTransform_js__WEBPACK_IMPORTED_MODULE_27__.SceneModelTransform({\r\n id: cfg.id,\r\n model: this,\r\n parentTransform,\r\n matrix: cfg.matrix,\r\n position: cfg.position,\r\n scale: cfg.scale,\r\n rotation: cfg.rotation,\r\n quaternion: cfg.quaternion\r\n });\r\n this._transforms[transform.id] = transform;\r\n return transform;\r\n }\r\n\r\n /**\r\n * Creates a new {@link SceneModelMesh} within this SceneModel.\r\n *\r\n * * It prepares and saves data for a SceneModelMesh {@link SceneModel#meshes} creation. SceneModelMesh will be created only once the SceneModelEntity (which references this particular SceneModelMesh) will be created.\r\n * * The SceneModelMesh can either define its own geometry or share it with other SceneModelMeshes. To define own geometry, provide the\r\n * various geometry arrays to this method. To share a geometry, provide the ID of a geometry created earlier\r\n * with {@link SceneModel#createGeometry}.\r\n * * If you accompany the arrays with an ````origin````, then ````createMesh()```` will assume\r\n * that the geometry ````positions```` are in relative-to-center (RTC) coordinates, with ````origin```` being the\r\n * origin of their RTC coordinate system.\r\n *\r\n * @param {object} cfg Object properties.\r\n * @param {String} cfg.id Mandatory ID for the new mesh. Must not clash with any existing components within the {@link Scene}.\r\n * @param {String|Number} [cfg.textureSetId] ID of a {@link SceneModelTextureSet} previously created with {@link SceneModel#createTextureSet}.\r\n * @param {String|Number} [cfg.transformId] ID of a {@link SceneModelTransform} to instance, previously created with {@link SceneModel#createTransform}. Overrides all other transform parameters given to this method.\r\n * @param {String|Number} [cfg.geometryId] ID of a geometry to instance, previously created with {@link SceneModel#createGeometry}. Overrides all other geometry parameters given to this method.\r\n * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\r\n * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\r\n * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\r\n * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\r\n * @param {Number[]} [cfg.normals] Flat array of normal vectors. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\r\n * @param {Number[]} [cfg.normalsCompressed] Flat array of oct-encoded normal vectors. Overrides ````normals````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\r\n * @param {Number[]} [cfg.colors] Flat array of uncompressed RGBA vertex colors, as float values in range ````[0..1]````. Ignored when ````geometryId```` is given. Overridden by ````color```` and ````colorsCompressed````.\r\n * @param {Number[]} [cfg.colorsCompressed] Flat array of compressed RGBA vertex colors, as unsigned short integers in range ````[0..255]````. Ignored when ````geometryId```` is given. Overrides ````colors```` and is overridden by ````color````.\r\n * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\r\n * @param {Number[]} [cfg.uvCompressed] Flat array of compressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Overrides ````uv````. Must be accompanied by ````uvDecodeMatrix````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\r\n * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\r\n * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\r\n * @param {Number[]} [cfg.edgeIndices] Array of edge line indices. Used only with 'triangles', 'solid' and 'surface' primitives. Automatically generated internally if not supplied, using the optional ````edgeThreshold```` given to the ````SceneModel```` constructor.\r\n * @param {Number[]} [cfg.origin] Optional geometry origin, relative to {@link SceneModel#origin}. When this is given, then ````positions```` are assumed to be relative to this.\r\n * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\r\n * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.\r\n * @param {Number[]} [cfg.rotation=[0,0,0]] Rotation of the mesh as Euler angles given in degrees, for each of the X, Y and Z axis. Overridden by ````transformId````.\r\n * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] Mesh modelling transform matrix. Overrides the ````position````, ````scale```` and ````rotation```` parameters. Also overridden by ````transformId````.\r\n * @param {Number[]} [cfg.color=[1,1,1]] RGB color in range ````[0..1, 0..1, 0..1]````. Overridden by texture set ````colorTexture````. Overrides ````colors```` and ````colorsCompressed````.\r\n * @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.\r\n * @param {Number} [cfg.metallic=0] Metallic factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\r\n * @param {Number} [cfg.roughness=1] Roughness factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\r\n * @returns {Boolean} True = successfully mesh was created. False = error during creation of a mesh.\r\n */\r\n createMesh(cfg) {\r\n\r\n if (cfg.id === undefined || cfg.id === null) {\r\n this.error(\"[createMesh] SceneModel.createMesh() config missing: id\");\r\n return false;\r\n }\r\n\r\n if (this._scheduledMeshes[cfg.id]) {\r\n this.error(`[createMesh] SceneModel already has a mesh with this ID: ${cfg.id}`);\r\n return false;\r\n }\r\n\r\n const instancing = (cfg.geometryId !== undefined);\r\n const batching = !instancing;\r\n\r\n if (batching) {\r\n\r\n // Batched geometry\r\n\r\n if (cfg.primitive === undefined || cfg.primitive === null) {\r\n cfg.primitive = \"triangles\";\r\n }\r\n if (cfg.primitive !== \"points\" && cfg.primitive !== \"lines\" && cfg.primitive !== \"triangles\" && cfg.primitive !== \"solid\" && cfg.primitive !== \"surface\") {\r\n this.error(`Unsupported value for 'primitive': '${primitive}' ('geometryId' is absent) - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'.`);\r\n return false;\r\n }\r\n if (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\r\n this.error(\"Param expected: 'positions', 'positionsCompressed' or `buckets` ('geometryId' is absent)\");\r\n return false;\r\n }\r\n if (cfg.positions && (cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)) {\r\n this.error(\"Illegal params: 'positions' not expected with 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\");\r\n return false;\r\n }\r\n if (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\r\n this.error(\"Param expected: 'positionsCompressed' should be accompanied by 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\");\r\n return false;\r\n }\r\n if (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\r\n this.error(\"Param expected: 'uvCompressed' should be accompanied by `uvDecodeMatrix` ('geometryId' is absent)\");\r\n return false;\r\n }\r\n if (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\r\n this.error(`Param expected: indices (required for '${cfg.primitive}' primitive type)`);\r\n return false;\r\n }\r\n if ((cfg.matrix || cfg.position || cfg.rotation || cfg.scale) && (cfg.positionsCompressed || cfg.positionsDecodeBoundary)) {\r\n this.error(\"Unexpected params: 'matrix', 'rotation', 'scale', 'position' not allowed with 'positionsCompressed'\");\r\n return false;\r\n }\r\n\r\n const useDTX = (!!this._dtxEnabled && (cfg.primitive === \"triangles\"\r\n || cfg.primitive === \"solid\"\r\n || cfg.primitive === \"surface\"));\r\n\r\n cfg.origin = cfg.origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(this._origin, cfg.origin, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3()) : this._origin;\r\n\r\n // MATRIX - optional for batching\r\n\r\n if (cfg.matrix) {\r\n cfg.meshMatrix = cfg.matrix;\r\n } else if (cfg.scale || cfg.rotation || cfg.position) {\r\n const scale = cfg.scale || DEFAULT_SCALE;\r\n const position = cfg.position || DEFAULT_POSITION;\r\n const rotation = cfg.rotation || DEFAULT_ROTATION;\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\r\n cfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\r\n }\r\n\r\n if (cfg.positionsDecodeBoundary) {\r\n cfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\r\n }\r\n\r\n if (useDTX) {\r\n\r\n // DTX\r\n\r\n cfg.type = DTX;\r\n\r\n // NPR\r\n\r\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;\r\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\r\n\r\n // RTC\r\n\r\n if (cfg.positions) {\r\n const rtcCenter = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n const rtcPositions = [];\r\n const rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, rtcCenter);\r\n if (rtcNeeded) {\r\n cfg.positions = rtcPositions;\r\n cfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, rtcCenter, rtcCenter);\r\n }\r\n }\r\n\r\n // COMPRESSION\r\n\r\n if (cfg.positions) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n cfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\r\n cfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\r\n cfg.aabb = aabb;\r\n\r\n } else if (cfg.positionsCompressed) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\r\n cfg.aabb = aabb;\r\n\r\n }\r\n if (cfg.buckets) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\r\n const bucket = cfg.buckets[i];\r\n if (bucket.positions) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\r\n } else if (bucket.positionsCompressed) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\r\n }\r\n }\r\n if (cfg.positionsDecodeMatrix) {\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\r\n }\r\n cfg.aabb = aabb;\r\n }\r\n\r\n if (cfg.meshMatrix) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\r\n }\r\n\r\n // EDGES\r\n\r\n if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")) {\r\n if (cfg.positions) { // Faster\r\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\r\n } else {\r\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\r\n }\r\n }\r\n\r\n // BUCKETING\r\n\r\n if (!cfg.buckets) {\r\n cfg.buckets = createDTXBuckets(cfg, this._enableVertexWelding && this._enableIndexBucketing);\r\n }\r\n\r\n } else {\r\n\r\n // VBO\r\n\r\n cfg.type = VBO_BATCHED;\r\n\r\n // PBR\r\n\r\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : [255, 255, 255];\r\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\r\n cfg.metallic = (cfg.metallic !== undefined && cfg.metallic !== null) ? Math.floor(cfg.metallic * 255) : 0;\r\n cfg.roughness = (cfg.roughness !== undefined && cfg.roughness !== null) ? Math.floor(cfg.roughness * 255) : 255;\r\n\r\n // RTC\r\n\r\n if (cfg.positions) {\r\n const rtcPositions = [];\r\n const rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, tempVec3a);\r\n if (rtcNeeded) {\r\n cfg.positions = rtcPositions;\r\n cfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, tempVec3a, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3());\r\n }\r\n }\r\n\r\n if (cfg.positions) {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n if (cfg.meshMatrix) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPositions3(cfg.meshMatrix, cfg.positions, cfg.positions);\r\n cfg.meshMatrix = null; // Positions now baked, don't need any more\r\n }\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\r\n cfg.aabb = aabb;\r\n\r\n } else {\r\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\r\n cfg.aabb = aabb;\r\n }\r\n\r\n if (cfg.meshMatrix) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\r\n }\r\n\r\n // EDGES\r\n\r\n if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")) {\r\n if (cfg.positions) {\r\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\r\n } else {\r\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\r\n }\r\n }\r\n\r\n // TEXTURE\r\n\r\n // cfg.textureSetId = cfg.textureSetId || DEFAULT_TEXTURE_SET_ID;\r\n if (cfg.textureSetId) {\r\n cfg.textureSet = this._textureSets[cfg.textureSetId];\r\n if (!cfg.textureSet) {\r\n this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n } else {\r\n\r\n // INSTANCING\r\n\r\n if (cfg.positions || cfg.positionsCompressed || cfg.indices || cfg.edgeIndices || cfg.normals || cfg.normalsCompressed || cfg.uv || cfg.uvCompressed || cfg.positionsDecodeMatrix) {\r\n this.error(`Mesh geometry parameters not expected when instancing a geometry (not expected: positions, positionsCompressed, indices, edgeIndices, normals, normalsCompressed, uv, uvCompressed, positionsDecodeMatrix)`);\r\n return false;\r\n }\r\n\r\n cfg.geometry = this._geometries[cfg.geometryId];\r\n if (!cfg.geometry) {\r\n this.error(`[createMesh] Geometry not found: ${cfg.geometryId} - ensure that you create it first with createGeometry()`);\r\n return false;\r\n }\r\n\r\n cfg.origin = cfg.origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(this._origin, cfg.origin, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3()) : this._origin;\r\n cfg.positionsDecodeMatrix = cfg.geometry.positionsDecodeMatrix;\r\n\r\n if (cfg.transformId) {\r\n\r\n // TRANSFORM\r\n\r\n cfg.transform = this._transforms[cfg.transformId];\r\n\r\n if (!cfg.transform) {\r\n this.error(`[createMesh] Transform not found: ${cfg.transformId} - ensure that you create it first with createTransform()`);\r\n return false;\r\n }\r\n\r\n cfg.aabb = cfg.geometry.aabb;\r\n\r\n } else {\r\n\r\n // MATRIX\r\n\r\n if (cfg.matrix) {\r\n cfg.meshMatrix = cfg.matrix.slice();\r\n } else {\r\n const scale = cfg.scale || DEFAULT_SCALE;\r\n const position = cfg.position || DEFAULT_POSITION;\r\n const rotation = cfg.rotation || DEFAULT_ROTATION;\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\r\n cfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\r\n }\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\r\n cfg.aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3());\r\n }\r\n\r\n const useDTX = (!!this._dtxEnabled\r\n && (cfg.geometry.primitive === \"triangles\"\r\n || cfg.geometry.primitive === \"solid\"\r\n || cfg.geometry.primitive === \"surface\"));\r\n\r\n if (useDTX) {\r\n\r\n // DTX\r\n\r\n cfg.type = DTX;\r\n\r\n // NPR\r\n\r\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;\r\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\r\n\r\n // BUCKETING - lazy generated, reused\r\n\r\n let buckets = this._dtxBuckets[cfg.geometryId];\r\n if (!buckets) {\r\n buckets = createDTXBuckets(cfg.geometry, this._enableVertexWelding, this._enableIndexBucketing);\r\n this._dtxBuckets[cfg.geometryId] = buckets;\r\n }\r\n cfg.buckets = buckets;\r\n\r\n } else {\r\n\r\n // VBO\r\n\r\n cfg.type = VBO_INSTANCED;\r\n\r\n // PBR\r\n\r\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;\r\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\r\n cfg.metallic = (cfg.metallic !== undefined && cfg.metallic !== null) ? Math.floor(cfg.metallic * 255) : 0;\r\n cfg.roughness = (cfg.roughness !== undefined && cfg.roughness !== null) ? Math.floor(cfg.roughness * 255) : 255;\r\n\r\n // TEXTURE\r\n\r\n if (cfg.textureSetId) {\r\n cfg.textureSet = this._textureSets[cfg.textureSetId];\r\n // if (!cfg.textureSet) {\r\n // this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);\r\n // return false;\r\n // }\r\n }\r\n }\r\n }\r\n\r\n cfg.numPrimitives = this._getNumPrimitives(cfg);\r\n\r\n this._meshesCfgsBeforeMeshCreation[cfg.id] = cfg;\r\n\r\n return true;\r\n }\r\n\r\n _createMesh(cfg) {\r\n const mesh = new _SceneModelMesh_js__WEBPACK_IMPORTED_MODULE_3__.SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);\r\n mesh.pickId = this.scene._renderer.getPickID(mesh);\r\n const pickId = mesh.pickId;\r\n const a = pickId >> 24 & 0xFF;\r\n const b = pickId >> 16 & 0xFF;\r\n const g = pickId >> 8 & 0xFF;\r\n const r = pickId & 0xFF;\r\n cfg.pickColor = new Uint8Array([r, g, b, a]); // Quantized pick color\r\n cfg.solid = (cfg.primitive === \"solid\");\r\n mesh.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin);\r\n switch (cfg.type) {\r\n case DTX:\r\n mesh.layer = this._getDTXLayer(cfg);\r\n mesh.aabb = cfg.aabb;\r\n break;\r\n case VBO_BATCHED:\r\n mesh.layer = this._getVBOBatchingLayer(cfg);\r\n mesh.aabb = cfg.aabb;\r\n break;\r\n case VBO_INSTANCED:\r\n mesh.layer = this._getVBOInstancingLayer(cfg);\r\n mesh.aabb = cfg.aabb;\r\n break;\r\n }\r\n if (cfg.transform) {\r\n cfg.meshMatrix = cfg.transform.worldMatrix;\r\n }\r\n mesh.portionId = mesh.layer.createPortion(mesh, cfg);\r\n return mesh;\r\n }\r\n\r\n _getNumPrimitives(cfg) {\r\n let countIndices = 0;\r\n const primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\r\n switch (primitive) {\r\n case \"triangles\":\r\n case \"solid\":\r\n case \"surface\":\r\n switch (cfg.type) {\r\n case DTX:\r\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\r\n countIndices += cfg.buckets[i].indices.length;\r\n }\r\n break;\r\n case VBO_BATCHED:\r\n countIndices += cfg.indices.length;\r\n break;\r\n case VBO_INSTANCED:\r\n countIndices += cfg.geometry.indices.length;\r\n break;\r\n }\r\n return Math.round(countIndices / 3);\r\n case \"points\":\r\n switch (cfg.type) {\r\n case DTX:\r\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\r\n countIndices += cfg.buckets[i].positionsCompressed.length;\r\n }\r\n break;\r\n case VBO_BATCHED:\r\n countIndices += cfg.positions ? cfg.positions.length : cfg.positionsCompressed.length;\r\n break;\r\n case VBO_INSTANCED:\r\n const geometry = cfg.geometry;\r\n countIndices += geometry.positions ? geometry.positions.length : geometry.positionsCompressed.length;\r\n break;\r\n }\r\n return Math.round(countIndices);\r\n case \"lines\":\r\n case \"line-strip\":\r\n switch (cfg.type) {\r\n case DTX:\r\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\r\n countIndices += cfg.buckets[i].indices.length;\r\n }\r\n break;\r\n case VBO_BATCHED:\r\n countIndices += cfg.indices.length;\r\n break;\r\n case VBO_INSTANCED:\r\n countIndices += cfg.geometry.indices.length;\r\n break;\r\n }\r\n return Math.round(countIndices / 2);\r\n }\r\n return 0;\r\n }\r\n\r\n _getDTXLayer(cfg) {\r\n const origin = cfg.origin;\r\n const primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\r\n const layerId = `.${primitive}.${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}`;\r\n let dtxLayer = this._dtxLayers[layerId];\r\n if (dtxLayer) {\r\n if (!dtxLayer.canCreatePortion(cfg)) {\r\n dtxLayer.finalize();\r\n delete this._dtxLayers[layerId];\r\n dtxLayer = null;\r\n } else {\r\n return dtxLayer;\r\n }\r\n }\r\n switch (primitive) {\r\n case \"triangles\":\r\n case \"solid\":\r\n case \"surface\":\r\n dtxLayer = new _dtx_triangles_DTXTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_12__.DTXTrianglesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()\r\n break;\r\n case \"lines\":\r\n dtxLayer = new _dtx_lines_DTXLinesLayer_js__WEBPACK_IMPORTED_MODULE_11__.DTXLinesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()\r\n break;\r\n default:\r\n return;\r\n }\r\n this._dtxLayers[layerId] = dtxLayer;\r\n this.layerList.push(dtxLayer);\r\n return dtxLayer;\r\n }\r\n\r\n _getVBOBatchingLayer(cfg) {\r\n const model = this;\r\n const origin = cfg.origin;\r\n const positionsDecodeHash = cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary ?\r\n this._createHashStringFromMatrix(cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)\r\n : \"-\";\r\n const textureSetId = cfg.textureSetId || \"-\";\r\n const layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${cfg.primitive}.${positionsDecodeHash}.${textureSetId}`;\r\n let vboBatchingLayer = this._vboBatchingLayers[layerId];\r\n if (vboBatchingLayer) {\r\n return vboBatchingLayer;\r\n }\r\n let textureSet = cfg.textureSet;\r\n while (!vboBatchingLayer) {\r\n switch (cfg.primitive) {\r\n case \"triangles\":\r\n // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\r\n vboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\r\n model,\r\n textureSet,\r\n layerIndex: 0, // This is set in #finalize()\r\n scratchMemory: this._vboBatchingLayerScratchMemory,\r\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\r\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\r\n origin,\r\n maxGeometryBatchSize: this._maxGeometryBatchSize,\r\n solid: (cfg.primitive === \"solid\"),\r\n autoNormals: true\r\n });\r\n break;\r\n case \"solid\":\r\n // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\r\n vboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\r\n model,\r\n textureSet,\r\n layerIndex: 0, // This is set in #finalize()\r\n scratchMemory: this._vboBatchingLayerScratchMemory,\r\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\r\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\r\n origin,\r\n maxGeometryBatchSize: this._maxGeometryBatchSize,\r\n solid: (cfg.primitive === \"solid\"),\r\n autoNormals: true\r\n });\r\n break;\r\n case \"surface\":\r\n // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\r\n vboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\r\n model,\r\n textureSet,\r\n layerIndex: 0, // This is set in #finalize()\r\n scratchMemory: this._vboBatchingLayerScratchMemory,\r\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\r\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\r\n origin,\r\n maxGeometryBatchSize: this._maxGeometryBatchSize,\r\n solid: (cfg.primitive === \"solid\"),\r\n autoNormals: true\r\n });\r\n break;\r\n case \"lines\":\r\n // console.info(`[SceneModel ${this.id}]: creating VBOBatchingLinesLayer`);\r\n vboBatchingLayer = new _vbo_batching_lines_VBOBatchingLinesLayer_js__WEBPACK_IMPORTED_MODULE_7__.VBOBatchingLinesLayer({\r\n model,\r\n layerIndex: 0, // This is set in #finalize()\r\n scratchMemory: this._vboBatchingLayerScratchMemory,\r\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\r\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\r\n origin,\r\n maxGeometryBatchSize: this._maxGeometryBatchSize\r\n });\r\n break;\r\n case \"points\":\r\n // console.info(`[SceneModel ${this.id}]: creating VBOBatchingPointsLayer`);\r\n vboBatchingLayer = new _vbo_batching_points_VBOBatchingPointsLayer_js__WEBPACK_IMPORTED_MODULE_9__.VBOBatchingPointsLayer({\r\n model,\r\n layerIndex: 0, // This is set in #finalize()\r\n scratchMemory: this._vboBatchingLayerScratchMemory,\r\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\r\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\r\n origin,\r\n maxGeometryBatchSize: this._maxGeometryBatchSize\r\n });\r\n break;\r\n }\r\n const lenPositions = cfg.positionsCompressed ? cfg.positionsCompressed.length : cfg.positions.length;\r\n const canCreatePortion = (cfg.primitive === \"points\")\r\n ? vboBatchingLayer.canCreatePortion(lenPositions)\r\n : vboBatchingLayer.canCreatePortion(lenPositions, cfg.indices.length);\r\n if (!canCreatePortion) {\r\n vboBatchingLayer.finalize();\r\n delete this._vboBatchingLayers[layerId];\r\n vboBatchingLayer = null;\r\n }\r\n }\r\n this._vboBatchingLayers[layerId] = vboBatchingLayer;\r\n this.layerList.push(vboBatchingLayer);\r\n return vboBatchingLayer;\r\n }\r\n\r\n _createHashStringFromMatrix(matrix) {\r\n const matrixString = matrix.join('');\r\n let hash = 0;\r\n for (let i = 0; i < matrixString.length; i++) {\r\n const char = matrixString.charCodeAt(i);\r\n hash = (hash << 5) - hash + char;\r\n hash |= 0; // Convert to 32-bit integer\r\n }\r\n const hashString = (hash >>> 0).toString(16);\r\n return hashString;\r\n }\r\n\r\n _getVBOInstancingLayer(cfg) {\r\n const model = this;\r\n const origin = cfg.origin;\r\n const textureSetId = cfg.textureSetId || \"-\";\r\n const geometryId = cfg.geometryId;\r\n const layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${textureSetId}.${geometryId}`;\r\n let vboInstancingLayer = this._vboInstancingLayers[layerId];\r\n if (vboInstancingLayer) {\r\n return vboInstancingLayer;\r\n }\r\n let textureSet = cfg.textureSet;\r\n const geometry = cfg.geometry;\r\n while (!vboInstancingLayer) {\r\n switch (geometry.primitive) {\r\n case \"triangles\":\r\n // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\r\n vboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\r\n model,\r\n textureSet,\r\n geometry,\r\n origin,\r\n layerIndex: 0,\r\n solid: false\r\n });\r\n break;\r\n case \"solid\":\r\n // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\r\n vboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\r\n model,\r\n textureSet,\r\n geometry,\r\n origin,\r\n layerIndex: 0,\r\n solid: true\r\n });\r\n break;\r\n case \"surface\":\r\n // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\r\n vboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\r\n model,\r\n textureSet,\r\n geometry,\r\n origin,\r\n layerIndex: 0,\r\n solid: false\r\n });\r\n break;\r\n case \"lines\":\r\n // console.info(`[SceneModel ${this.id}]: creating VBOInstancingLinesLayer`);\r\n vboInstancingLayer = new _vbo_instancing_lines_VBOInstancingLinesLayer_js__WEBPACK_IMPORTED_MODULE_8__.VBOInstancingLinesLayer({\r\n model,\r\n textureSet,\r\n geometry,\r\n origin,\r\n layerIndex: 0\r\n });\r\n break;\r\n case \"points\":\r\n // console.info(`[SceneModel ${this.id}]: creating PointsInstancingLayer`);\r\n vboInstancingLayer = new _vbo_instancing_points_VBOInstancingPointsLayer_js__WEBPACK_IMPORTED_MODULE_10__.VBOInstancingPointsLayer({\r\n model,\r\n textureSet,\r\n geometry,\r\n origin,\r\n layerIndex: 0\r\n });\r\n break;\r\n }\r\n // const lenPositions = geometry.positionsCompressed.length;\r\n // if (!vboInstancingLayer.canCreatePortion(lenPositions, geometry.indices.length)) { // FIXME: indices should be optional\r\n // vboInstancingLayer.finalize();\r\n // delete this._vboInstancingLayers[layerId];\r\n // vboInstancingLayer = null;\r\n // }\r\n }\r\n this._vboInstancingLayers[layerId] = vboInstancingLayer;\r\n this.layerList.push(vboInstancingLayer);\r\n return vboInstancingLayer;\r\n }\r\n\r\n /**\r\n * Creates a {@link SceneModelEntity} within this SceneModel.\r\n *\r\n * * Gives the SceneModelEntity one or more {@link SceneModelMesh}es previously created with\r\n * {@link SceneModel#createMesh}. A SceneModelMesh can only belong to one SceneModelEntity, so you'll get an\r\n * error if you try to reuse a mesh among multiple SceneModelEntitys.\r\n * * The SceneModelEntity can have a {@link SceneModelTextureSet}, previously created with\r\n * {@link SceneModel#createTextureSet}. A SceneModelTextureSet can belong to multiple SceneModelEntitys.\r\n * * The SceneModelEntity can have a geometry, previously created with\r\n * {@link SceneModel#createTextureSet}. A geometry is a \"virtual component\" and can belong to multiple SceneModelEntitys.\r\n *\r\n * @param {Object} cfg SceneModelEntity configuration.\r\n * @param {String} cfg.id Optional ID for the new SceneModelEntity. Must not clash with any existing components within the {@link Scene}.\r\n * @param {String[]} cfg.meshIds IDs of one or more meshes created previously with {@link SceneModel@createMesh}.\r\n * @param {Boolean} [cfg.isObject] Set ````true```` if the {@link SceneModelEntity} represents an object, in which case it will be registered by {@link SceneModelEntity#id} in {@link Scene#objects} and can also have a corresponding {@link MetaObject} with matching {@link MetaObject#id}, registered by that ID in {@link MetaScene#metaObjects}.\r\n * @param {Boolean} [cfg.visible=true] Indicates if the SceneModelEntity is initially visible.\r\n * @param {Boolean} [cfg.culled=false] Indicates if the SceneModelEntity is initially culled from view.\r\n * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModelEntity is initially pickable.\r\n * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModelEntity is initially clippable.\r\n * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModelEntity is initially included in boundary calculations.\r\n * @param {Boolean} [cfg.castsShadow=true] Indicates if the SceneModelEntity initially casts shadows.\r\n * @param {Boolean} [cfg.receivesShadow=true] Indicates if the SceneModelEntity initially receives shadows.\r\n * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModelEntity is initially xrayed. XRayed appearance is configured by {@link SceneModel#xrayMaterial}.\r\n * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModelEntity is initially highlighted. Highlighted appearance is configured by {@link SceneModel#highlightMaterial}.\r\n * @param {Boolean} [cfg.selected=false] Indicates if the SceneModelEntity is initially selected. Selected appearance is configured by {@link SceneModel#selectedMaterial}.\r\n * @param {Boolean} [cfg.edges=false] Indicates if the SceneModelEntity's edges are initially emphasized. Edges appearance is configured by {@link SceneModel#edgeMaterial}.\r\n * @returns {SceneModelEntity} The new SceneModelEntity.\r\n */\r\n createEntity(cfg) {\r\n if (cfg.id === undefined) {\r\n cfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\r\n } else if (this.scene.components[cfg.id]) {\r\n this.error(`Scene already has a Component with this ID: ${cfg.id} - will assign random ID`);\r\n cfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\r\n }\r\n if (cfg.meshIds === undefined) {\r\n this.error(\"Config missing: meshIds\");\r\n return;\r\n }\r\n let flags = 0;\r\n if (this._visible && cfg.visible !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.VISIBLE;\r\n }\r\n if (this._pickable && cfg.pickable !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.PICKABLE;\r\n }\r\n if (this._culled && cfg.culled !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CULLED;\r\n }\r\n if (this._clippable && cfg.clippable !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CLIPPABLE;\r\n }\r\n if (this._collidable && cfg.collidable !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.COLLIDABLE;\r\n }\r\n if (this._edges && cfg.edges !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.EDGES;\r\n }\r\n if (this._xrayed && cfg.xrayed !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.XRAYED;\r\n }\r\n if (this._highlighted && cfg.highlighted !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.HIGHLIGHTED;\r\n }\r\n if (this._selected && cfg.selected !== false) {\r\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.SELECTED;\r\n }\r\n cfg.flags = flags;\r\n this._createEntity(cfg);\r\n }\r\n\r\n _createEntity(cfg) {\r\n let meshes = [];\r\n for (let i = 0, len = cfg.meshIds.length; i < len; i++) {\r\n const meshId = cfg.meshIds[i];\r\n let mesh = this._meshes[meshId]; // Trying to get already created mesh\r\n if (!mesh) { // Checks if there is already created mesh for this meshId\r\n let meshCfg = this._meshesCfgsBeforeMeshCreation[meshId]; // Trying to get already created cfg\r\n if (!meshCfg) { // Checks if there is already created cfg for this meshId\r\n this.error(`Mesh with this ID not found: \"${meshId}\" - ignoring this mesh`); // There is no such cfg\r\n continue;\r\n }\r\n mesh = this._createMesh(meshCfg) // There is no such mesh yet, but there is already created cfg, so it creates this mesh\r\n this._meshes[cfg.id] = mesh; // Now it will also add this mesh to dictionary of created meshes\r\n }\r\n if (mesh.parent) {\r\n this.error(`Mesh with ID \"${meshId}\" already belongs to object with ID \"${mesh.parent.id}\" - ignoring this mesh`);\r\n continue;\r\n }\r\n meshes.push(mesh);\r\n }\r\n const lodCullable = true;\r\n const entity = new _SceneModelEntity_js__WEBPACK_IMPORTED_MODULE_25__.SceneModelEntity(\r\n this,\r\n cfg.isObject,\r\n cfg.id,\r\n meshes,\r\n cfg.flags,\r\n lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel\r\n this._entityList.push(entity);\r\n this._entities[cfg.id] = entity;\r\n this.numEntities++;\r\n }\r\n\r\n /**\r\n * Finalizes this SceneModel.\r\n *\r\n * Once finalized, you can't add anything more to this SceneModel.\r\n */\r\n finalize() {\r\n if (this.destroyed) {\r\n return;\r\n }\r\n for (let i = 0, len = this.layerList.length; i < len; i++) {\r\n const layer = this.layerList[i];\r\n layer.finalize();\r\n }\r\n this._geometries = {};\r\n this._dtxBuckets = {};\r\n this._textures = {};\r\n this._textureSets = {};\r\n this._dtxLayers = {};\r\n this._vboInstancingLayers = {};\r\n this._vboBatchingLayers = {};\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n const entity = this._entityList[i];\r\n entity._finalize();\r\n }\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n const entity = this._entityList[i];\r\n entity._finalize2();\r\n }\r\n // Sort layers to reduce WebGL shader switching when rendering them\r\n this.layerList.sort((a, b) => {\r\n if (a.sortId < b.sortId) {\r\n return -1;\r\n }\r\n if (a.sortId > b.sortId) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n for (let i = 0, len = this.layerList.length; i < len; i++) {\r\n const layer = this.layerList[i];\r\n layer.layerIndex = i;\r\n }\r\n this.glRedraw();\r\n this.scene._aabbDirty = true;\r\n this._viewMatrixDirty = true;\r\n this._matrixDirty = true;\r\n this._aabbDirty = true;\r\n\r\n this._setWorldMatrixDirty();\r\n this._sceneModelDirty();\r\n\r\n this.position = this._position;\r\n }\r\n\r\n /** @private */\r\n stateSortCompare(drawable1, drawable2) {\r\n }\r\n\r\n /** @private */\r\n rebuildRenderFlags() {\r\n this.renderFlags.reset();\r\n this._updateRenderFlagsVisibleLayers();\r\n if (this.renderFlags.numLayers > 0 && this.renderFlags.numVisibleLayers === 0) {\r\n this.renderFlags.culled = true;\r\n return;\r\n }\r\n this._updateRenderFlags();\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n _updateRenderFlagsVisibleLayers() {\r\n const renderFlags = this.renderFlags;\r\n renderFlags.numLayers = this.layerList.length;\r\n renderFlags.numVisibleLayers = 0;\r\n for (let layerIndex = 0, len = this.layerList.length; layerIndex < len; layerIndex++) {\r\n const layer = this.layerList[layerIndex];\r\n const layerVisible = this._getActiveSectionPlanesForLayer(layer);\r\n if (layerVisible) {\r\n renderFlags.visibleLayers[renderFlags.numVisibleLayers++] = layerIndex;\r\n }\r\n }\r\n }\r\n\r\n _getActiveSectionPlanesForLayer(layer) {\r\n const renderFlags = this.renderFlags;\r\n const sectionPlanes = this.scene._sectionPlanesState.sectionPlanes;\r\n const numSectionPlanes = sectionPlanes.length;\r\n const baseIndex = layer.layerIndex * numSectionPlanes;\r\n if (numSectionPlanes > 0) {\r\n for (let i = 0; i < numSectionPlanes; i++) {\r\n const sectionPlane = sectionPlanes[i];\r\n if (!sectionPlane.active) {\r\n renderFlags.sectionPlanesActivePerLayer[baseIndex + i] = false;\r\n } else {\r\n renderFlags.sectionPlanesActivePerLayer[baseIndex + i] = true;\r\n renderFlags.sectioned = true;\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n _updateRenderFlags() {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n if (this.numCulledLayerPortions === this.numPortions) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n renderFlags.colorOpaque = (this.numTransparentLayerPortions < this.numPortions);\r\n if (this.numTransparentLayerPortions > 0) {\r\n renderFlags.colorTransparent = true;\r\n }\r\n if (this.numXRayedLayerPortions > 0) {\r\n const xrayMaterial = this.scene.xrayMaterial._state;\r\n if (xrayMaterial.fill) {\r\n if (xrayMaterial.fillAlpha < 1.0) {\r\n renderFlags.xrayedSilhouetteTransparent = true;\r\n } else {\r\n renderFlags.xrayedSilhouetteOpaque = true;\r\n }\r\n }\r\n if (xrayMaterial.edges) {\r\n if (xrayMaterial.edgeAlpha < 1.0) {\r\n renderFlags.xrayedEdgesTransparent = true;\r\n } else {\r\n renderFlags.xrayedEdgesOpaque = true;\r\n }\r\n }\r\n }\r\n if (this.numEdgesLayerPortions > 0) {\r\n const edgeMaterial = this.scene.edgeMaterial._state;\r\n if (edgeMaterial.edges) {\r\n renderFlags.edgesOpaque = (this.numTransparentLayerPortions < this.numPortions);\r\n if (this.numTransparentLayerPortions > 0) {\r\n renderFlags.edgesTransparent = true;\r\n }\r\n }\r\n }\r\n if (this.numSelectedLayerPortions > 0) {\r\n const selectedMaterial = this.scene.selectedMaterial._state;\r\n if (selectedMaterial.fill) {\r\n if (selectedMaterial.fillAlpha < 1.0) {\r\n renderFlags.selectedSilhouetteTransparent = true;\r\n } else {\r\n renderFlags.selectedSilhouetteOpaque = true;\r\n }\r\n }\r\n if (selectedMaterial.edges) {\r\n if (selectedMaterial.edgeAlpha < 1.0) {\r\n renderFlags.selectedEdgesTransparent = true;\r\n } else {\r\n renderFlags.selectedEdgesOpaque = true;\r\n }\r\n }\r\n }\r\n if (this.numHighlightedLayerPortions > 0) {\r\n const highlightMaterial = this.scene.highlightMaterial._state;\r\n if (highlightMaterial.fill) {\r\n if (highlightMaterial.fillAlpha < 1.0) {\r\n renderFlags.highlightedSilhouetteTransparent = true;\r\n } else {\r\n renderFlags.highlightedSilhouetteOpaque = true;\r\n }\r\n }\r\n if (highlightMaterial.edges) {\r\n if (highlightMaterial.edgeAlpha < 1.0) {\r\n renderFlags.highlightedEdgesTransparent = true;\r\n } else {\r\n renderFlags.highlightedEdgesOpaque = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // -------------- RENDERING ---------------------------------------------------------------------------------------\r\n\r\n /** @private */\r\n drawColorOpaque(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawColorOpaque(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawColorTransparent(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawColorTransparent(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawDepth(frameCtx) { // Dedicated to SAO because it skips transparent objects\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawDepth(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawNormals(frameCtx) { // Dedicated to SAO because it skips transparent objects\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawNormals(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawSilhouetteXRayed(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawSilhouetteXRayed(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawSilhouetteHighlighted(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawSilhouetteHighlighted(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawSilhouetteSelected(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawSilhouetteSelected(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawEdgesColorOpaque(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawEdgesColorOpaque(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawEdgesColorTransparent(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawEdgesColorTransparent(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawEdgesXRayed(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawEdgesXRayed(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawEdgesHighlighted(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawEdgesHighlighted(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n drawEdgesSelected(frameCtx) {\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawEdgesSelected(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n drawOcclusion(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawOcclusion(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n drawShadow(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawShadow(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /** @private */\r\n setPickMatrices(pickViewMatrix, pickProjMatrix) {\r\n if (this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n const layer = this.layerList[layerIndex];\r\n if (layer.setPickMatrices) {\r\n layer.setPickMatrices(pickViewMatrix, pickProjMatrix);\r\n }\r\n }\r\n }\r\n\r\n /** @private */\r\n drawPickMesh(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawPickMesh(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /**\r\n * Called by SceneModelMesh.drawPickDepths()\r\n * @private\r\n */\r\n drawPickDepths(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawPickDepths(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /**\r\n * Called by SceneModelMesh.drawPickNormals()\r\n * @private\r\n */\r\n drawPickNormals(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n this.layerList[layerIndex].drawPickNormals(renderFlags, frameCtx);\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n drawSnapInit(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n const layer = this.layerList[layerIndex];\r\n if (layer.drawSnapInit) {\r\n frameCtx.snapPickOrigin = [0, 0, 0];\r\n frameCtx.snapPickCoordinateScale = [1, 1, 1];\r\n frameCtx.snapPickLayerNumber++;\r\n layer.drawSnapInit(renderFlags, frameCtx);\r\n frameCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\r\n origin: frameCtx.snapPickOrigin.slice(),\r\n coordinateScale: frameCtx.snapPickCoordinateScale.slice(),\r\n };\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n drawSnap(frameCtx) {\r\n if (this.numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n const renderFlags = this.renderFlags;\r\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\r\n const layerIndex = renderFlags.visibleLayers[i];\r\n const layer = this.layerList[layerIndex];\r\n if (layer.drawSnap) {\r\n frameCtx.snapPickOrigin = [0, 0, 0];\r\n frameCtx.snapPickCoordinateScale = [1, 1, 1];\r\n frameCtx.snapPickLayerNumber++;\r\n layer.drawSnap(renderFlags, frameCtx);\r\n frameCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\r\n origin: frameCtx.snapPickOrigin.slice(),\r\n coordinateScale: frameCtx.snapPickCoordinateScale.slice(),\r\n };\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Destroys this SceneModel.\r\n */\r\n destroy() {\r\n for (let layerId in this._vboBatchingLayers) {\r\n if (this._vboBatchingLayers.hasOwnProperty(layerId)) {\r\n this._vboBatchingLayers[layerId].destroy();\r\n }\r\n }\r\n this._vboBatchingLayers = {};\r\n for (let layerId in this._vboInstancingLayers) {\r\n if (this._vboInstancingLayers.hasOwnProperty(layerId)) {\r\n this._vboInstancingLayers[layerId].destroy();\r\n }\r\n }\r\n this._vboInstancingLayers = {};\r\n this.scene.camera.off(this._onCameraViewMatrix);\r\n this.scene.off(this._onTick);\r\n for (let i = 0, len = this.layerList.length; i < len; i++) {\r\n this.layerList[i].destroy();\r\n }\r\n this.layerList = [];\r\n for (let i = 0, len = this._entityList.length; i < len; i++) {\r\n this._entityList[i]._destroy();\r\n }\r\n // Object.entries(this._geometries).forEach(([id, geometry]) => {\r\n // geometry.destroy();\r\n // });\r\n this._geometries = {};\r\n this._dtxBuckets = {};\r\n this._textures = {};\r\n this._textureSets = {};\r\n this._meshes = {};\r\n this._entities = {};\r\n this.scene._aabbDirty = true;\r\n if (this._isModel) {\r\n this.scene._deregisterModel(this);\r\n }\r\n (0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.putScratchMemory)();\r\n super.destroy();\r\n }\r\n}\r\n\r\n\r\n/**\r\n * This function applies two steps to the provided mesh geometry data:\r\n *\r\n * - 1st, it reduces its `.positions` to unique positions, thus removing duplicate vertices. It will adjust the `.indices` and `.edgeIndices` array accordingly to the unique `.positions`.\r\n *\r\n * - 2nd, it tries to do an optimization called `index rebucketting`\r\n *\r\n * _Rebucketting minimizes the amount of RAM usage for a given mesh geometry by trying do demote its needed index bitness._\r\n *\r\n * - _for 32 bit indices, will try to demote them to 16 bit indices_\r\n * - _for 16 bit indices, will try to demote them to 8 bits indices_\r\n * - _8 bits indices are kept as-is_\r\n *\r\n * The fact that 32/16/8 bits are needed for indices, depends on the number of maximumm indexable vertices within the mesh geometry: this is, the number of vertices in the mesh geometry.\r\n *\r\n * The function returns the same provided input `geometry`, enrichened with the additional key `.preparedBukets`.\r\n *\r\n * @param {object} geometry The mesh information containing `.positions`, `.indices`, `.edgeIndices` arrays.\r\n *\r\n * @param enableVertexWelding\r\n * @param enableIndexBucketing\r\n * @returns {object} The mesh information enrichened with `.buckets` key.\r\n */\r\nfunction createDTXBuckets(geometry, enableVertexWelding, enableIndexBucketing) {\r\n let uniquePositionsCompressed, uniqueIndices, uniqueEdgeIndices;\r\n if (enableVertexWelding || enableIndexBucketing) { // Expensive - careful!\r\n [\r\n uniquePositionsCompressed,\r\n uniqueIndices,\r\n uniqueEdgeIndices,\r\n ] = (0,_calculateUniquePositions_js__WEBPACK_IMPORTED_MODULE_23__.uniquifyPositions)({\r\n positionsCompressed: geometry.positionsCompressed,\r\n indices: geometry.indices,\r\n edgeIndices: geometry.edgeIndices\r\n });\r\n } else {\r\n uniquePositionsCompressed = geometry.positionsCompressed;\r\n uniqueIndices = geometry.indices;\r\n uniqueEdgeIndices = geometry.edgeIndices;\r\n }\r\n let buckets;\r\n if (enableIndexBucketing) {\r\n let numUniquePositions = uniquePositionsCompressed.length / 3;\r\n buckets = (0,_rebucketPositions_js__WEBPACK_IMPORTED_MODULE_24__.rebucketPositions)({\r\n positionsCompressed: uniquePositionsCompressed,\r\n indices: uniqueIndices,\r\n edgeIndices: uniqueEdgeIndices,\r\n },\r\n (numUniquePositions > (1 << 16)) ? 16 : 8,\r\n // true\r\n );\r\n } else {\r\n buckets = [{\r\n positionsCompressed: uniquePositionsCompressed,\r\n indices: uniqueIndices,\r\n edgeIndices: uniqueEdgeIndices,\r\n }];\r\n }\r\n return buckets;\r\n}\r\n\r\nfunction\r\n\r\ncreateGeometryOBB(geometry) {\r\n geometry.obb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3();\r\n if (geometry.positionsCompressed && geometry.positionsCompressed.length > 0) {\r\n const localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positionsCompressed);\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\r\n } else if (geometry.positions && geometry.positions.length > 0) {\r\n const localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positions);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\r\n } else if (geometry.buckets) {\r\n const localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\r\n for (let i = 0, len = geometry.buckets.length; i < len; i++) {\r\n const bucket = geometry.buckets[i];\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, bucket.positionsCompressed);\r\n }\r\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\r\n }\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/SceneModel.js?");
|
|
3527
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SceneModel: () => (/* binding */ SceneModel)\n/* harmony export */ });\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../math/buildEdgeIndices.js */ \"./src/viewer/scene/math/buildEdgeIndices.js\");\n/* harmony import */ var _SceneModelMesh_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SceneModelMesh.js */ \"./src/viewer/scene/model/SceneModelMesh.js\");\n/* harmony import */ var _vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./vbo/ScratchMemory.js */ \"./src/viewer/scene/model/vbo/ScratchMemory.js\");\n/* harmony import */ var _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./vbo/batching/triangles/VBOBatchingTrianglesLayer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js\");\n/* harmony import */ var _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./vbo/instancing/triangles/VBOInstancingTrianglesLayer.js */ \"./src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js\");\n/* harmony import */ var _vbo_batching_lines_VBOBatchingLinesLayer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./vbo/batching/lines/VBOBatchingLinesLayer.js */ \"./src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js\");\n/* harmony import */ var _vbo_instancing_lines_VBOInstancingLinesLayer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./vbo/instancing/lines/VBOInstancingLinesLayer.js */ \"./src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js\");\n/* harmony import */ var _vbo_batching_points_VBOBatchingPointsLayer_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./vbo/batching/points/VBOBatchingPointsLayer.js */ \"./src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js\");\n/* harmony import */ var _vbo_instancing_points_VBOInstancingPointsLayer_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./vbo/instancing/points/VBOInstancingPointsLayer.js */ \"./src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js\");\n/* harmony import */ var _dtx_lines_DTXLinesLayer_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./dtx/lines/DTXLinesLayer.js */ \"./src/viewer/scene/model/dtx/lines/DTXLinesLayer.js\");\n/* harmony import */ var _dtx_triangles_DTXTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./dtx/triangles/DTXTrianglesLayer.js */ \"./src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js\");\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _webgl_RenderFlags_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../webgl/RenderFlags.js */ \"./src/viewer/scene/webgl/RenderFlags.js\");\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n/* harmony import */ var _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./SceneModelTextureSet.js */ \"./src/viewer/scene/model/SceneModelTextureSet.js\");\n/* harmony import */ var _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./SceneModelTexture.js */ \"./src/viewer/scene/model/SceneModelTexture.js\");\n/* harmony import */ var _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../webgl/Texture2D.js */ \"./src/viewer/scene/webgl/Texture2D.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _utils_textureTranscoders_KTX2TextureTranscoder_KTX2TextureTranscoder_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../utils/textureTranscoders/KTX2TextureTranscoder/KTX2TextureTranscoder.js */ \"./src/viewer/scene/utils/textureTranscoders/KTX2TextureTranscoder/KTX2TextureTranscoder.js\");\n/* harmony import */ var _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../constants/constants.js */ \"./src/viewer/scene/constants/constants.js\");\n/* harmony import */ var _compression_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./compression.js */ \"./src/viewer/scene/model/compression.js\");\n/* harmony import */ var _calculateUniquePositions_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./calculateUniquePositions.js */ \"./src/viewer/scene/model/calculateUniquePositions.js\");\n/* harmony import */ var _rebucketPositions_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./rebucketPositions.js */ \"./src/viewer/scene/model/rebucketPositions.js\");\n/* harmony import */ var _SceneModelEntity_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./SceneModelEntity.js */ \"./src/viewer/scene/model/SceneModelEntity.js\");\n/* harmony import */ var _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../math/geometryCompressionUtils.js */ \"./src/viewer/scene/math/geometryCompressionUtils.js\");\n/* harmony import */ var _SceneModelTransform_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./SceneModelTransform.js */ \"./src/viewer/scene/model/SceneModelTransform.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\n\nconst tempOBB3 = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3();\n\nconst DEFAULT_SCALE = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3([1, 1, 1]);\nconst DEFAULT_POSITION = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3([0, 0, 0]);\nconst DEFAULT_ROTATION = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3([0, 0, 0]);\nconst DEFAULT_QUATERNION = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.identityQuaternion();\nconst DEFAULT_MATRIX = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.identityMat4();\n\nconst DEFAULT_COLOR_TEXTURE_ID = \"defaultColorTexture\";\nconst DEFAULT_METAL_ROUGH_TEXTURE_ID = \"defaultMetalRoughTexture\";\nconst DEFAULT_NORMALS_TEXTURE_ID = \"defaultNormalsTexture\";\nconst DEFAULT_EMISSIVE_TEXTURE_ID = \"defaultEmissiveTexture\";\nconst DEFAULT_OCCLUSION_TEXTURE_ID = \"defaultOcclusionTexture\";\nconst DEFAULT_TEXTURE_SET_ID = \"defaultTextureSet\";\n\nconst defaultCompressedColor = new Uint8Array([255, 255, 255]);\n\nconst VBO_INSTANCED = 0;\nconst VBO_BATCHED = 1;\nconst DTX = 2;\n\n/**\n * @desc A high-performance model representation for efficient rendering and low memory usage.\n *\n * # Examples\n *\n * Internally, SceneModel uses a combination of several different techniques to render and represent\n * the different parts of a typical model. Each of the live examples at these links is designed to \"unit test\" one of these\n * techniques, in isolation. If some bug occurs in SceneModel, we use these tests to debug, but they also\n * serve to demonstrate how to use the capabilities of SceneModel programmatically.\n *\n * * [Loading building models into SceneModels](/examples/buildings)\n * * [Loading city models into SceneModels](/examples/cities)\n * * [Loading LiDAR scans into SceneModels](/examples/lidar)\n * * [Loading CAD models into SceneModels](/examples/cad)\n * * [SceneModel feature tests](/examples/scenemodel)\n *\n * # Overview\n *\n * While xeokit's standard [scene graph](https://github.com/xeokit/xeokit-sdk/wiki/Scene-Graphs) is great for gizmos and medium-sized models, it doesn't scale up to millions of objects in terms of memory and rendering efficiency.\n *\n * For huge models, we have the ````SceneModel```` representation, which is optimized to pack large amounts of geometry into memory and render it efficiently using WebGL.\n *\n * ````SceneModel```` is the default model representation loaded by (at least) {@link GLTFLoaderPlugin}, {@link XKTLoaderPlugin} and {@link WebIFCLoaderPlugin}.\n *\n * In this tutorial you'll learn how to use ````SceneModel```` to create high-detail content programmatically. Ordinarily you'd be learning about ````SceneModel```` if you were writing your own model loader plugins.\n *\n * # Contents\n *\n * - [SceneModel](#DataTextureSceneModel)\n * - [GPU-Resident Geometry](#gpu-resident-geometry)\n * - [Picking](#picking)\n * - [Example 1: Geometry Instancing](#example-1--geometry-instancing)\n * - [Finalizing a SceneModel](#finalizing-a-DataTextureSceneModel)\n * - [Finding Entities](#finding-entities)\n * - [Example 2: Geometry Batching](#example-2--geometry-batching)\n * - [Classifying with Metadata](#classifying-with-metadata)\n * - [Querying Metadata](#querying-metadata)\n * - [Metadata Structure](#metadata-structure)\n * - [RTC Coordinates](#rtc-coordinates-for-double-precision)\n * - [Example 3: RTC Coordinates with Geometry Instancing](#example-2--rtc-coordinates-with-geometry-instancing)\n * - [Example 4: RTC Coordinates with Geometry Batching](#example-2--rtc-coordinates-with-geometry-batching)\n *\n * ## SceneModel\n *\n * ````SceneModel```` uses two rendering techniques internally:\n *\n * 1. ***Geometry batching*** for unique geometries, combining those into a single WebGL geometry buffer, to render in one draw call, and\n * 2. ***geometry instancing*** for geometries that are shared by multiple meshes, rendering all instances of each shared geometry in one draw call.\n *\n * <br>\n * These techniques come with certain limitations:\n *\n * * Non-realistic rendering - while scene graphs can use xeokit's full set of material workflows, ````SceneModel```` uses simple Lambertian shading without textures.\n * * Static transforms - transforms within a ````SceneModel```` are static and cannot be dynamically translated, rotated and scaled the way {@link Node}s and {@link Mesh}es in scene graphs can.\n * * Immutable model representation - while scene graph {@link Node}s and\n * {@link Mesh}es can be dynamically plugged together, ````SceneModel```` is immutable,\n * since it packs its geometries into buffers and instanced arrays.\n *\n * ````SceneModel````'s API allows us to exploit batching and instancing, while exposing its elements as\n * abstract {@link Entity} types.\n *\n * {@link Entity} is the abstract base class for\n * the various xeokit components that represent models, objects, or anonymous visible elements. An Entity has a unique ID and can be\n * individually shown, hidden, selected, highlighted, ghosted, culled, picked and clipped, and has its own World-space boundary.\n *\n * * A ````SceneModel```` is an {@link Entity} that represents a model.\n * * A ````SceneModel```` represents each of its objects with an {@link Entity}.\n * * Each {@link Entity} has one or more meshes that define its shape.\n * * Each mesh has either its own unique geometry, or shares a geometry with other meshes.\n *\n * ## GPU-Resident Geometry\n *\n * For a low memory footprint, ````SceneModel```` stores its geometries in GPU memory only, compressed (quantized) as integers. Unfortunately, GPU-resident geometry is\n * not readable by JavaScript.\n *\n *\n * ## Example 1: Geometry Instancing\n *\n * In the example below, we'll use a ````SceneModel````\n * to build a simple table model using geometry instancing.\n *\n * We'll start by adding a reusable box-shaped geometry to our ````SceneModel````.\n *\n * Then, for each object in our model we'll add an {@link Entity}\n * that has a mesh that instances our box geometry, transforming and coloring the instance.\n *\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_instancing)\n *\n * ````javascript\n * import {Viewer, SceneModel} from \"xeokit-sdk.es.js\";\n *\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\",\n * transparent: true\n * });\n *\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\n * viewer.scene.camera.look = [0, -5.75, 0];\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\n *\n * // Build a SceneModel representing a table\n * // with four legs, using geometry instancing\n *\n * const sceneModel = new SceneModel(viewer.scene, {\n * id: \"table\",\n * isModel: true, // <--- Registers SceneModel in viewer.scene.models\n * position: [0, 0, 0],\n * scale: [1, 1, 1],\n * rotation: [0, 0, 0]\n * });\n *\n * // Create a reusable geometry within the SceneModel\n * // We'll instance this geometry by five meshes\n *\n * sceneModel.createGeometry({\n *\n * id: \"myBoxGeometry\",\n *\n * // The primitive type - allowed values are \"points\", \"lines\" and \"triangles\".\n * // See the OpenGL/WebGL specification docs\n * // for how the coordinate arrays are supposed to be laid out.\n * primitive: \"triangles\",\n *\n * // The vertices - eight for our cube, each\n * // one spanning three array elements for X,Y and Z\n * positions: [\n * 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front\n * 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right\n * 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top\n * -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left\n * -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, // v7-v4-v3-v2 bottom\n * 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back\n * ],\n *\n * // Normal vectors, one for each vertex\n * normals: [\n * 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2-v3 front\n * 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right\n * 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0-v5-v6-v1 top\n * -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1-v6-v7-v2 left\n * 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, // v7-v4-v3-v2 bottom\n * 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 // v4-v7-v6-v5 back\n * ],\n *\n * // Indices - these organise the positions and and normals\n * // into geometric primitives in accordance with the \"primitive\" parameter,\n * // in this case a set of three indices for each triangle.\n * //\n * // Note that each triangle is specified in counter-clockwise winding order.\n * //\n * indices: [\n * 0, 1, 2, 0, 2, 3, // front\n * 4, 5, 6, 4, 6, 7, // right\n * 8, 9, 10, 8, 10, 11, // top\n * 12, 13, 14, 12, 14, 15, // left\n * 16, 17, 18, 16, 18, 19, // bottom\n * 20, 21, 22, 20, 22, 23\n * ]\n * });\n *\n * // Red table leg\n *\n * sceneModel.createMesh({\n * id: \"redLegMesh\",\n * geometryId: \"myBoxGeometry\",\n * position: [-4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1, 0.3, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * id: \"redLeg\",\n * meshIds: [\"redLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Green table leg\n *\n * sceneModel.createMesh({\n * id: \"greenLegMesh\",\n * geometryId: \"myBoxGeometry\",\n * position: [4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 1.0, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * id: \"greenLeg\",\n * meshIds: [\"greenLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Blue table leg\n *\n * sceneModel.createMesh({\n * id: \"blueLegMesh\",\n * geometryId: \"myBoxGeometry\",\n * position: [4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * id: \"blueLeg\",\n * meshIds: [\"blueLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Yellow table leg\n *\n * sceneModel.createMesh({\n * id: \"yellowLegMesh\",\n * geometryId: \"myBoxGeometry\",\n * position: [-4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1.0, 1.0, 0.0]\n * });\n *\n * sceneModel.createEntity({\n * id: \"yellowLeg\",\n * meshIds: [\"yellowLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Purple table top\n *\n * sceneModel.createMesh({\n * id: \"purpleTableTopMesh\",\n * geometryId: \"myBoxGeometry\",\n * position: [0, -3, 0],\n * scale: [6, 0.5, 6],\n * rotation: [0, 0, 0],\n * color: [1.0, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * id: \"purpleTableTop\",\n * meshIds: [\"purpleTableTopMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n * ````\n *\n * ## Finalizing a SceneModel\n *\n * Before we can view and interact with our ````SceneModel````, we need to **finalize** it. Internally, this causes the ````SceneModel```` to build the\n * vertex buffer objects (VBOs) that support our geometry instances. When using geometry batching (see next example),\n * this causes ````SceneModel```` to build the VBOs that combine the batched geometries. Note that you can do both instancing and\n * batching within the same ````SceneModel````.\n *\n * Once finalized, we can't add anything more to our ````SceneModel````.\n *\n * ```` javascript\n * SceneModel.finalize();\n * ````\n *\n * ## Finding Entities\n *\n * As mentioned earlier, {@link Entity} is\n * the abstract base class for components that represent models, objects, or just\n * anonymous visible elements.\n *\n * Since we created configured our ````SceneModel```` with ````isModel: true````,\n * we're able to find it as an Entity by ID in ````viewer.scene.models````. Likewise, since\n * we configured each of its Entities with ````isObject: true````, we're able to\n * find them in ````viewer.scene.objects````.\n *\n *\n * ````javascript\n * // Get the whole table model Entity\n * const table = viewer.scene.models[\"table\"];\n *\n * // Get some leg object Entities\n * const redLeg = viewer.scene.objects[\"redLeg\"];\n * const greenLeg = viewer.scene.objects[\"greenLeg\"];\n * const blueLeg = viewer.scene.objects[\"blueLeg\"];\n * ````\n *\n * ## Example 2: Geometry Batching\n *\n * Let's once more use a ````SceneModel````\n * to build the simple table model, this time exploiting geometry batching.\n *\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_batching)\n *\n * ````javascript\n * import {Viewer, SceneModel} from \"xeokit-sdk.es.js\";\n *\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\",\n * transparent: true\n * });\n *\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\n * viewer.scene.camera.look = [0, -5.75, 0];\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\n *\n * // Create a SceneModel representing a table with four legs, using geometry batching\n * const sceneModel = new SceneModel(viewer.scene, {\n * id: \"table\",\n * isModel: true, // <--- Registers SceneModel in viewer.scene.models\n * position: [0, 0, 0],\n * scale: [1, 1, 1],\n * rotation: [0, 0, 0]\n * });\n *\n * // Red table leg\n *\n * sceneModel.createMesh({\n * id: \"redLegMesh\",\n *\n * // Geometry arrays are same as for the earlier batching example\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [-4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1, 0.3, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * id: \"redLeg\",\n * meshIds: [\"redLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Green table leg\n *\n * sceneModel.createMesh({\n * id: \"greenLegMesh\",\n * primitive: \"triangles\",\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 1.0, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * id: \"greenLeg\",\n * meshIds: [\"greenLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Blue table leg\n *\n * sceneModel.createMesh({\n * id: \"blueLegMesh\",\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * id: \"blueLeg\",\n * meshIds: [\"blueLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Yellow table leg object\n *\n * sceneModel.createMesh({\n * id: \"yellowLegMesh\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [-4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1.0, 1.0, 0.0]\n * });\n *\n * sceneModel.createEntity({\n * id: \"yellowLeg\",\n * meshIds: [\"yellowLegMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Purple table top\n *\n * sceneModel.createMesh({\n * id: \"purpleTableTopMesh\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [0, -3, 0],\n * scale: [6, 0.5, 6],\n * rotation: [0, 0, 0],\n * color: [1.0, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * id: \"purpleTableTop\",\n * meshIds: [\"purpleTableTopMesh\"],\n * isObject: true // <---- Registers Entity by ID on viewer.scene.objects\n * });\n *\n * // Finalize the SceneModel.\n *\n * SceneModel.finalize();\n *\n * // Find BigModelNodes by their model and object IDs\n *\n * // Get the whole table model\n * const table = viewer.scene.models[\"table\"];\n *\n * // Get some leg objects\n * const redLeg = viewer.scene.objects[\"redLeg\"];\n * const greenLeg = viewer.scene.objects[\"greenLeg\"];\n * const blueLeg = viewer.scene.objects[\"blueLeg\"];\n * ````\n *\n * ## Classifying with Metadata\n *\n * In the previous examples, we used ````SceneModel```` to build\n * two versions of the same table model, to demonstrate geometry batching and geometry instancing.\n *\n * We'll now classify our {@link Entity}s with metadata. This metadata\n * will work the same for both our examples, since they create the exact same structure of {@link Entity}s\n * to represent their models and objects. The abstract Entity type is, after all, intended to provide an abstract interface through which differently-implemented scene content can be accessed uniformly.\n *\n * To create the metadata, we'll create a {@link MetaModel} for our model,\n * with a {@link MetaObject} for each of it's objects. The MetaModel and MetaObjects\n * get the same IDs as the {@link Entity}s that represent their model and objects within our scene.\n *\n * ```` javascript\n * const furnitureMetaModel = viewer.metaScene.createMetaModel(\"furniture\", { // Creates a MetaModel in the MetaScene\n *\n * \"projectId\": \"myTableProject\",\n * \"revisionId\": \"V1.0\",\n *\n * \"metaObjects\": [\n * { // Creates a MetaObject in the MetaModel\n * \"id\": \"table\",\n * \"name\": \"Table\", // Same ID as an object Entity\n * \"type\": \"furniture\", // Arbitrary type, could be IFC type\n * \"properties\": { // Arbitrary properties, could be IfcPropertySet\n * \"cost\": \"200\"\n * }\n * },\n * {\n * \"id\": \"redLeg\",\n * \"name\": \"Red table Leg\",\n * \"type\": \"leg\",\n * \"parent\": \"table\", // References first MetaObject as parent\n * \"properties\": {\n * \"material\": \"wood\"\n * }\n * },\n * {\n * \"id\": \"greenLeg\", // Node with corresponding id does not need to exist\n * \"name\": \"Green table leg\", // and MetaObject does not need to exist for Node with an id\n * \"type\": \"leg\",\n * \"parent\": \"table\",\n * \"properties\": {\n * \"material\": \"wood\"\n * }\n * },\n * {\n * \"id\": \"blueLeg\",\n * \"name\": \"Blue table leg\",\n * \"type\": \"leg\",\n * \"parent\": \"table\",\n * \"properties\": {\n * \"material\": \"wood\"\n * }\n * },\n * {\n * \"id\": \"yellowLeg\",\n * \"name\": \"Yellow table leg\",\n * \"type\": \"leg\",\n * \"parent\": \"table\",\n * \"properties\": {\n * \"material\": \"wood\"\n * }\n * },\n * {\n * \"id\": \"tableTop\",\n * \"name\": \"Purple table top\",\n * \"type\": \"surface\",\n * \"parent\": \"table\",\n * \"properties\": {\n * \"material\": \"formica\",\n * \"width\": \"60\",\n * \"depth\": \"60\",\n * \"thickness\": \"5\"\n * }\n * }\n * ]\n * });\n * ````\n *\n * ## Querying Metadata\n *\n * Having created and classified our model (either the instancing or batching example), we can now find the {@link MetaModel}\n * and {@link MetaObject}s using the IDs of their\n * corresponding {@link Entity}s.\n *\n * ````JavaScript\n * const furnitureMetaModel = scene.metaScene.metaModels[\"furniture\"];\n *\n * const redLegMetaObject = scene.metaScene.metaObjects[\"redLeg\"];\n * ````\n *\n * In the snippet below, we'll log metadata on each {@link Entity} we click on:\n *\n * ````JavaScript\n * viewer.scene.input.on(\"mouseclicked\", function (coords) {\n *\n * const hit = viewer.scene.pick({\n * canvasPos: coords\n * });\n *\n * if (hit) {\n * const entity = hit.entity;\n * const metaObject = viewer.metaScene.metaObjects[entity.id];\n * if (metaObject) {\n * console.log(JSON.stringify(metaObject.getJSON(), null, \"\\t\"));\n * }\n * }\n * });\n * ````\n *\n * ## Metadata Structure\n *\n * The {@link MetaModel}\n * organizes its {@link MetaObject}s in\n * a tree that describes their structural composition:\n *\n * ````JavaScript\n * // Get metadata on the root object\n * const tableMetaObject = furnitureMetaModel.rootMetaObject;\n *\n * // Get metadata on the leg objects\n * const redLegMetaObject = tableMetaObject.children[0];\n * const greenLegMetaObject = tableMetaObject.children[1];\n * const blueLegMetaObject = tableMetaObject.children[2];\n * const yellowLegMetaObject = tableMetaObject.children[3];\n * ````\n *\n * Given an {@link Entity}, we can find the object or model of which it is a part, or the objects that comprise it. We can also generate UI\n * components from the metadata, such as the tree view demonstrated in [this demo](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_glTF_OTCConferenceCenter).\n *\n * This hierarchy allows us to express the hierarchical structure of a model while representing it in\n * various ways in the 3D scene (such as with ````SceneModel````, which\n * has a non-hierarchical scene representation).\n *\n * Note also that a {@link MetaObject} does not need to have a corresponding\n * {@link Entity} and vice-versa.\n *\n * # RTC Coordinates for Double Precision\n *\n * ````SceneModel```` can emulate 64-bit precision on GPUs using relative-to-center (RTC) coordinates.\n *\n * Consider a model that contains many small objects, but with such large spatial extents that 32 bits of GPU precision (accurate to ~7 digits) will not be sufficient to render all of the the objects without jittering.\n *\n * To prevent jittering, we could spatially subdivide the objects into \"tiles\". Each tile would have a center position, and the positions of the objects within the tile would be relative to that center (\"RTC coordinates\").\n *\n * While the center positions of the tiles would be 64-bit values, the object positions only need to be 32-bit.\n *\n * Internally, when rendering an object with RTC coordinates, xeokit first temporarily translates the camera viewing matrix by the object's tile's RTC center, on the CPU, using 64-bit math.\n *\n * Then xeokit loads the viewing matrix into its WebGL shaders, where math happens at 32-bit precision. Within the shaders, the matrix is effectively down-cast to 32-bit precision, and the object's 32-bit vertex positions are transformed by the matrix.\n *\n * We see no jittering, because with RTC a detectable loss of GPU accuracy only starts happening to objects as they become very distant from the camera viewpoint, at which point they are too small to be discernible anyway.\n *\n * ## RTC Coordinates with Geometry Instancing\n *\n * To use RTC with ````SceneModel```` geometry instancing, we specify an RTC center for the geometry via its ````origin```` parameter. Then ````SceneModel```` assumes that all meshes that instance that geometry are within the same RTC coordinate system, ie. the meshes ````position```` and ````rotation```` properties are assumed to be relative to the geometry's ````origin````.\n *\n * For simplicity, our example's meshes all instance the same geometry. Therefore, our example model has only one RTC center.\n *\n * Note that the axis-aligned World-space boundary (AABB) of our model is ````[ -6, -9, -6, 1000000006, -2.5, 1000000006]````.\n *\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_batching)\n *\n * ````javascript\n * const origin = [100000000, 0, 100000000];\n *\n * sceneModel.createGeometry({\n * id: \"box\",\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg1\",\n * geometryId: \"box\",\n * position: [-4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1, 0.3, 0.3],\n * origin: origin\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg1\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg2\",\n * geometryId: \"box\",\n * position: [4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 1.0, 0.3],\n * origin: origin\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg2\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg3\",\n * geometryId: \"box\",\n * position: [4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 0.3, 1.0],\n * origin: origin\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg3\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg4\",\n * geometryId: \"box\",\n * position: [-4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1.0, 1.0, 0.0],\n * origin: origin\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg4\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"top\",\n * geometryId: \"box\",\n * position: [0, -3, 0],\n * scale: [6, 0.5, 6],\n * rotation: [0, 0, 0],\n * color: [1.0, 0.3, 1.0],\n * origin: origin\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"top\"],\n * isObject: true\n * });\n * ````\n *\n * ## RTC Coordinates with Geometry Batching\n *\n * To use RTC with ````SceneModel```` geometry batching, we specify an RTC center (````origin````) for each mesh. For performance, we try to have as many meshes share the same value for ````origin```` as possible. Each mesh's ````positions````, ````position```` and ````rotation```` properties are assumed to be relative to ````origin````.\n *\n * For simplicity, the meshes in our example all share the same RTC center.\n *\n * The axis-aligned World-space boundary (AABB) of our model is ````[ -6, -9, -6, 1000000006, -2.5, 1000000006]````.\n *\n * [](https://xeokit.github.io/xeokit-sdk/examples/#sceneRepresentation_SceneModel_batching)\n *\n * ````javascript\n * const origin = [100000000, 0, 100000000];\n *\n * sceneModel.createMesh({\n * id: \"leg1\",\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [-4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1, 0.3, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg1\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg2\",\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 1.0, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg2\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg3\",\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg3\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg4\",\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [-4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1.0, 1.0, 0.0]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg4\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"top\",\n * origin: origin, // This mesh's positions and transforms are relative to the RTC center\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * position: [0, -3, 0],\n * scale: [6, 0.5, 6],\n * rotation: [0, 0, 0],\n * color: [1.0, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"top\"],\n * isObject: true\n * });\n * ````\n *\n * ## Positioning at World-space coordinates\n *\n * To position a SceneModel at given double-precision World coordinates, we can\n * configure the ````origin```` of the SceneModel itself. The ````origin```` is a double-precision\n * 3D World-space position at which the SceneModel will be located.\n *\n * Note that ````position```` is a single-precision offset relative to ````origin````.\n *\n * ````javascript\n * const origin = [100000000, 0, 100000000];\n *\n * const sceneModel = new SceneModel(viewer.scene, {\n * id: \"table\",\n * isModel: true,\n * origin: origin, // Everything in this SceneModel is relative to this RTC center\n * position: [0, 0, 0],\n * scale: [1, 1, 1],\n * rotation: [0, 0, 0]\n * });\n *\n * sceneModel.createGeometry({\n * id: \"box\",\n * primitive: \"triangles\",\n * positions: [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1 ... ],\n * normals: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ... ],\n * indices: [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, ... ],\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg1\",\n * geometryId: \"box\",\n * position: [-4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1, 0.3, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg1\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg2\",\n * geometryId: \"box\",\n * position: [4, -6, -4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 1.0, 0.3]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg2\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg3\",\n * geometryId: \"box\",\n * position: [4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [0.3, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg3\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"leg4\",\n * geometryId: \"box\",\n * position: [-4, -6, 4],\n * scale: [1, 3, 1],\n * rotation: [0, 0, 0],\n * color: [1.0, 1.0, 0.0]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"leg4\"],\n * isObject: true\n * });\n *\n * sceneModel.createMesh({\n * id: \"top\",\n * geometryId: \"box\",\n * position: [0, -3, 0],\n * scale: [6, 0.5, 6],\n * rotation: [0, 0, 0],\n * color: [1.0, 0.3, 1.0]\n * });\n *\n * sceneModel.createEntity({\n * meshIds: [\"top\"],\n * isObject: true\n * });\n * ````\n *\n * # Textures\n *\n * ## Loading KTX2 Texture Files into a SceneModel\n *\n * A {@link SceneModel} that is configured with a {@link KTX2TextureTranscoder} will\n * allow us to load textures into it from KTX2 buffers or files.\n *\n * In the example below, we'll create a {@link Viewer}, containing a {@link SceneModel} configured with a\n * {@link KTX2TextureTranscoder}. We'll then programmatically create a simple object within the SceneModel, consisting of\n * a single mesh with a texture loaded from a KTX2 file, which our SceneModel internally transcodes, using\n * its {@link KTX2TextureTranscoder}. Note how we configure our {@link KTX2TextureTranscoder} with a path to the Basis Universal\n * transcoder WASM module.\n *\n * ````javascript\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\",\n * transparent: true\n * });\n *\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\n * viewer.scene.camera.look = [0, -5.75, 0];\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\n *\n * const textureTranscoder = new KTX2TextureTranscoder({\n * viewer,\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to BasisU transcoder module\n * });\n *\n * const sceneModel = new SceneModel(viewer.scene, {\n * id: \"myModel\",\n * textureTranscoder // <<-------------------- Configure model with our transcoder\n * });\n *\n * sceneModel.createTexture({\n * id: \"myColorTexture\",\n * src: \"../assets/textures/compressed/sample_uastc_zstd.ktx2\" // <<----- KTX2 texture asset\n * });\n *\n * sceneModel.createTexture({\n * id: \"myMetallicRoughnessTexture\",\n * src: \"../assets/textures/alpha/crosshatchAlphaMap.jpg\" // <<----- JPEG texture asset\n * });\n *\n * sceneModel.createTextureSet({\n * id: \"myTextureSet\",\n * colorTextureId: \"myColorTexture\",\n * metallicRoughnessTextureId: \"myMetallicRoughnessTexture\"\n * });\n *\n * sceneModel.createMesh({\n * id: \"myMesh\",\n * textureSetId: \"myTextureSet\",\n * primitive: \"triangles\",\n * positions: [1, 1, 1, ...],\n * normals: [0, 0, 1, 0, ...],\n * uv: [1, 0, 0, ...],\n * indices: [0, 1, 2, ...],\n * });\n *\n * sceneModel.createEntity({\n * id: \"myEntity\",\n * meshIds: [\"myMesh\"]\n * });\n *\n * sceneModel.finalize();\n * ````\n *\n * ## Loading KTX2 Textures from ArrayBuffers into a SceneModel\n *\n * A SceneModel that is configured with a {@link KTX2TextureTranscoder} will allow us to load textures into\n * it from KTX2 ArrayBuffers.\n *\n * In the example below, we'll create a {@link Viewer}, containing a {@link SceneModel} configured with a\n * {@link KTX2TextureTranscoder}. We'll then programmatically create a simple object within the SceneModel, consisting of\n * a single mesh with a texture loaded from a KTX2 ArrayBuffer, which our SceneModel internally transcodes, using\n * its {@link KTX2TextureTranscoder}.\n *\n * ````javascript\n * const viewer = new Viewer({\n * canvasId: \"myCanvas\",\n * transparent: true\n * });\n *\n * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];\n * viewer.scene.camera.look = [0, -5.75, 0];\n * viewer.scene.camera.up = [0.37, 0.91, -0.11];\n *\n * const textureTranscoder = new KTX2TextureTranscoder({\n * viewer,\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to BasisU transcoder module\n * });\n *\n * const sceneModel = new SceneModel(viewer.scene, {\n * id: \"myModel\",\n * textureTranscoder // <<-------------------- Configure model with our transcoder\n * });\n *\n * utils.loadArraybuffer(\"../assets/textures/compressed/sample_uastc_zstd.ktx2\",(arrayBuffer) => {\n *\n * sceneModel.createTexture({\n * id: \"myColorTexture\",\n * buffers: [arrayBuffer] // <<----- KTX2 texture asset\n * });\n *\n * sceneModel.createTexture({\n * id: \"myMetallicRoughnessTexture\",\n * src: \"../assets/textures/alpha/crosshatchAlphaMap.jpg\" // <<----- JPEG texture asset\n * });\n *\n * sceneModel.createTextureSet({\n * id: \"myTextureSet\",\n * colorTextureId: \"myColorTexture\",\n * metallicRoughnessTextureId: \"myMetallicRoughnessTexture\"\n * });\n *\n * sceneModel.createMesh({\n * id: \"myMesh\",\n * textureSetId: \"myTextureSet\",\n * primitive: \"triangles\",\n * positions: [1, 1, 1, ...],\n * normals: [0, 0, 1, 0, ...],\n * uv: [1, 0, 0, ...],\n * indices: [0, 1, 2, ...],\n * });\n *\n * sceneModel.createEntity({\n * id: \"myEntity\",\n * meshIds: [\"myMesh\"]\n * });\n *\n * sceneModel.finalize();\n * });\n * ````\n *\n * @implements {Entity}\n */\nclass SceneModel extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\n\n /**\n * @constructor\n * @param {Component} owner Owner component. When destroyed, the owner will destroy this component as well.\n * @param {*} [cfg] Configs\n * @param {String} [cfg.id] Optional ID, unique among all components in the parent scene, generated automatically when omitted.\n * @param {Boolean} [cfg.isModel] Specify ````true```` if this SceneModel represents a model, in which case the SceneModel will be registered by {@link SceneModel#id} in {@link Scene#models} and may also have a corresponding {@link MetaModel} with matching {@link MetaModel#id}, registered by that ID in {@link MetaScene#metaModels}.\n * @param {Number[]} [cfg.origin=[0,0,0]] World-space double-precision 3D origin.\n * @param {Number[]} [cfg.position=[0,0,0]] Local, single-precision 3D position, relative to the origin parameter.\n * @param {Number[]} [cfg.scale=[1,1,1]] Local scale.\n * @param {Number[]} [cfg.rotation=[0,0,0]] Local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] Local modelling transform matrix. Overrides the position, scale and rotation parameters.\n * @param {Boolean} [cfg.visible=true] Indicates if the SceneModel is initially visible.\n * @param {Boolean} [cfg.culled=false] Indicates if the SceneModel is initially culled from view.\n * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModel is initially pickable.\n * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModel is initially clippable.\n * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModel is initially included in boundary calculations.\n * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModel is initially xrayed.\n * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModel is initially highlighted.\n * @param {Boolean} [cfg.selected=false] Indicates if the SceneModel is initially selected.\n * @param {Boolean} [cfg.edges=false] Indicates if the SceneModel's edges are initially emphasized.\n * @param {Number[]} [cfg.colorize=[1.0,1.0,1.0]] SceneModel's initial RGB colorize color, multiplies by the rendered fragment colors.\n * @param {Number} [cfg.opacity=1.0] SceneModel's initial opacity factor, multiplies by the rendered fragment alpha.\n * @param {Number} [cfg.backfaces=false] When we set this ````true````, then we force rendering of backfaces for this SceneModel. When\n * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\n * Viewer will hide backfaces on watertight meshes, show backfaces on open meshes, and always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\n * @param {Boolean} [cfg.saoEnabled=true] Indicates if Scalable Ambient Obscurance (SAO) will apply to this SceneModel. SAO is configured by the Scene's {@link SAO} component.\n * @param {Boolean} [cfg.pbrEnabled=true] Indicates if physically-based rendering (PBR) will apply to the SceneModel when {@link Scene#pbrEnabled} is ````true````.\n * @param {Boolean} [cfg.colorTextureEnabled=true] Indicates if base color textures will be rendered for the SceneModel when {@link Scene#colorTextureEnabled} is ````true````.\n * @param {Number} [cfg.edgeThreshold=10] When xraying, highlighting, selecting or edging, this is the threshold angle between normals of adjacent triangles, below which their shared wireframe edge is not drawn.\n * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\n * to limit the size of the batched geometry arrays that SceneModel internally creates for batched geometries.\n * A lower value means less heap allocation/de-allocation while creating/loading batched geometries, but more draw calls and\n * slower rendering speed. A high value means larger heap allocation/de-allocation while creating/loading, but less draw calls\n * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\n * @param {TextureTranscoder} [cfg.textureTranscoder] Transcoder that will be used internally by {@link SceneModel#createTexture}\n * to convert transcoded texture data. Only required when we'll be providing transcoded data\n * to {@link SceneModel#createTexture}. We assume that all transcoded texture data added to a ````SceneModel````\n * will then in a format supported by this transcoder.\n * @param {Boolean} [cfg.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\n * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\n * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\n * primitives. Only works while {@link DTX#enabled} is also ````true````.\n */\n constructor(owner, cfg = {}) {\n\n super(owner, cfg);\n\n this._dtxEnabled = this.scene.dtxEnabled && (cfg.dtxEnabled !== false);\n\n this._enableVertexWelding = false; // Not needed for most objects, and very expensive, so disabled\n this._enableIndexBucketing = false; // Until fixed: https://github.com/xeokit/xeokit-sdk/issues/1204\n\n this._vboBatchingLayerScratchMemory = (0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.getScratchMemory)();\n this._textureTranscoder = cfg.textureTranscoder || (0,_utils_textureTranscoders_KTX2TextureTranscoder_KTX2TextureTranscoder_js__WEBPACK_IMPORTED_MODULE_20__.getKTX2TextureTranscoder)(this.scene.viewer);\n\n this._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\n\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n this._aabbDirty = true;\n\n this._quantizationRanges = {};\n\n this._vboInstancingLayers = {};\n this._vboBatchingLayers = {};\n this._dtxLayers = {};\n\n this.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second\n this._entityList = [];\n\n this._geometries = {};\n this._dtxBuckets = {}; // Geometries with optimizations used for data texture representation\n this._textures = {};\n this._textureSets = {};\n this._transforms = {};\n this._meshes = {};\n this._entities = {};\n\n this._scheduledMeshes = {};\n this._meshesCfgsBeforeMeshCreation = {};\n\n /** @private **/\n this.renderFlags = new _webgl_RenderFlags_js__WEBPACK_IMPORTED_MODULE_14__.RenderFlags();\n\n /**\n * @private\n */\n this.numGeometries = 0; // Number of geometries created with createGeometry()\n\n // These counts are used to avoid unnecessary render passes\n // They are incremented or decremented exclusively by BatchingLayer and InstancingLayer\n\n /**\n * @private\n */\n this.numPortions = 0;\n\n /**\n * @private\n */\n this.numVisibleLayerPortions = 0;\n\n /**\n * @private\n */\n this.numTransparentLayerPortions = 0;\n\n /**\n * @private\n */\n this.numXRayedLayerPortions = 0;\n\n /**\n * @private\n */\n this.numHighlightedLayerPortions = 0;\n\n /**\n * @private\n */\n this.numSelectedLayerPortions = 0;\n\n /**\n * @private\n */\n this.numEdgesLayerPortions = 0;\n\n /**\n * @private\n */\n this.numPickableLayerPortions = 0;\n\n /**\n * @private\n */\n this.numClippableLayerPortions = 0;\n\n /**\n * @private\n */\n this.numCulledLayerPortions = 0;\n\n this.numEntities = 0;\n this._numTriangles = 0;\n this._numLines = 0;\n this._numPoints = 0;\n\n this._edgeThreshold = cfg.edgeThreshold || 10;\n\n // Build static matrix\n\n this._origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin || [0, 0, 0]);\n this._position = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.position || [0, 0, 0]);\n this._rotation = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.rotation || [0, 0, 0]);\n this._quaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\n this._conjugateQuaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\n\n if (cfg.rotation) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\n }\n this._scale = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.scale || [1, 1, 1]);\n\n this._worldRotationMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n this._worldRotationMatrixConjugate = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n this._matrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n this._matrixDirty = true;\n\n this._rebuildMatrices();\n\n this._worldNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._matrix, this._worldNormalMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._worldNormalMatrix);\n\n if (cfg.matrix || cfg.position || cfg.rotation || cfg.scale || cfg.quaternion) {\n this._viewMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n this._viewNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n this._viewMatrixDirty = true;\n this._matrixNonIdentity = true;\n }\n\n this._opacity = 1.0;\n this._colorize = [1, 1, 1];\n\n this._saoEnabled = (cfg.saoEnabled !== false);\n this._pbrEnabled = (cfg.pbrEnabled !== false);\n this._colorTextureEnabled = (cfg.colorTextureEnabled !== false);\n\n this._isModel = cfg.isModel;\n if (this._isModel) {\n this.scene._registerModel(this);\n }\n\n this._onCameraViewMatrix = this.scene.camera.on(\"matrix\", () => {\n this._viewMatrixDirty = true;\n });\n\n this._meshesWithDirtyMatrices = [];\n this._numMeshesWithDirtyMatrices = 0;\n\n this._onTick = this.scene.on(\"tick\", () => {\n while (this._numMeshesWithDirtyMatrices > 0) {\n this._meshesWithDirtyMatrices[--this._numMeshesWithDirtyMatrices]._updateMatrix();\n }\n });\n\n this._createDefaultTextureSet();\n\n this.visible = cfg.visible;\n this.culled = cfg.culled;\n this.pickable = cfg.pickable;\n this.clippable = cfg.clippable;\n this.collidable = cfg.collidable;\n this.castsShadow = cfg.castsShadow;\n this.receivesShadow = cfg.receivesShadow;\n this.xrayed = cfg.xrayed;\n this.highlighted = cfg.highlighted;\n this.selected = cfg.selected;\n this.edges = cfg.edges;\n this.colorize = cfg.colorize;\n this.opacity = cfg.opacity;\n this.backfaces = cfg.backfaces;\n }\n\n _meshMatrixDirty(mesh) {\n this._meshesWithDirtyMatrices[this._numMeshesWithDirtyMatrices++] = mesh;\n }\n\n _createDefaultTextureSet() {\n // Every SceneModelMesh gets at least the default TextureSet,\n // which contains empty default textures filled with color\n const defaultColorTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n id: DEFAULT_COLOR_TEXTURE_ID,\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n gl: this.scene.canvas.gl,\n preloadColor: [1, 1, 1, 1] // [r, g, b, a]})\n })\n });\n const defaultMetalRoughTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n id: DEFAULT_METAL_ROUGH_TEXTURE_ID,\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n gl: this.scene.canvas.gl,\n preloadColor: [0, 1, 1, 1] // [unused, roughness, metalness, unused]\n })\n });\n const defaultNormalsTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n id: DEFAULT_NORMALS_TEXTURE_ID,\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n gl: this.scene.canvas.gl,\n preloadColor: [0, 0, 0, 0] // [x, y, z, unused] - these must be zeros\n })\n });\n const defaultEmissiveTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n id: DEFAULT_EMISSIVE_TEXTURE_ID,\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n gl: this.scene.canvas.gl,\n preloadColor: [0, 0, 0, 1] // [x, y, z, unused]\n })\n });\n const defaultOcclusionTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n id: DEFAULT_OCCLUSION_TEXTURE_ID,\n texture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n gl: this.scene.canvas.gl,\n preloadColor: [1, 1, 1, 1] // [x, y, z, unused]\n })\n });\n this._textures[DEFAULT_COLOR_TEXTURE_ID] = defaultColorTexture;\n this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID] = defaultMetalRoughTexture;\n this._textures[DEFAULT_NORMALS_TEXTURE_ID] = defaultNormalsTexture;\n this._textures[DEFAULT_EMISSIVE_TEXTURE_ID] = defaultEmissiveTexture;\n this._textures[DEFAULT_OCCLUSION_TEXTURE_ID] = defaultOcclusionTexture;\n this._textureSets[DEFAULT_TEXTURE_SET_ID] = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\n id: DEFAULT_TEXTURE_SET_ID,\n model: this,\n colorTexture: defaultColorTexture,\n metallicRoughnessTexture: defaultMetalRoughTexture,\n normalsTexture: defaultNormalsTexture,\n emissiveTexture: defaultEmissiveTexture,\n occlusionTexture: defaultOcclusionTexture\n });\n }\n\n //------------------------------------------------------------------------------------------------------------------\n // SceneModel members\n //------------------------------------------------------------------------------------------------------------------\n\n /**\n * Returns true to indicate that this Component is a SceneModel.\n * @type {Boolean}\n */\n get isPerformanceModel() {\n return true;\n }\n\n /**\n * The {@link SceneModelTransform}s in this SceneModel.\n *\n * Each {#link SceneModelTransform} is stored here against its {@link SceneModelTransform.id}.\n *\n * @returns {*|{}}\n */\n get transforms() {\n return this._transforms;\n }\n\n /**\n * The {@link SceneModelTexture}s in this SceneModel.\n *\n * * Each {@link SceneModelTexture} is created with {@link SceneModel.createTexture}.\n * * Each {@link SceneModelTexture} is stored here against its {@link SceneModelTexture.id}.\n *\n * @returns {*|{}}\n */\n get textures() {\n return this._textures;\n }\n\n /**\n * The {@link SceneModelTextureSet}s in this SceneModel.\n *\n * Each {@link SceneModelTextureSet} is stored here against its {@link SceneModelTextureSet.id}.\n *\n * @returns {*|{}}\n */\n get textureSets() {\n return this._textureSets;\n }\n\n /**\n * The {@link SceneModelMesh}es in this SceneModel.\n *\n * Each {@SceneModelMesh} is stored here against its {@link SceneModelMesh.id}.\n *\n * @returns {*|{}}\n */\n get meshes() {\n return this._meshes;\n }\n\n /**\n * The {@link SceneModelEntity}s in this SceneModel.\n *\n * Each {#link SceneModelEntity} in this SceneModel that represents an object is\n * stored here against its {@link SceneModelTransform.id}.\n *\n * @returns {*|{}}\n */\n get objects() {\n return this._entities;\n }\n\n /**\n * Gets the 3D World-space origin for this SceneModel.\n *\n * Each {@link SceneModelMesh.origin}, if supplied, is relative to this origin.\n *\n * Default value is ````[0,0,0]````.\n *\n * @type {Float64Array}\n */\n get origin() {\n return this._origin;\n }\n\n /**\n * Sets the SceneModel's local translation.\n *\n * Default value is ````[0,0,0]````.\n *\n * @type {Number[]}\n */\n set position(value) {\n this._position.set(value || [0, 0, 0]);\n this._setWorldMatrixDirty();\n this._sceneModelDirty();\n this.glRedraw();\n }\n\n /**\n * Gets the SceneModel's local translation.\n *\n * Default value is ````[0,0,0]````.\n *\n * @type {Number[]}\n */\n get position() {\n return this._position;\n }\n\n /**\n * Sets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n *\n * Default value is ````[0,0,0]````.\n *\n * @type {Number[]}\n */\n set rotation(value) {\n this._rotation.set(value || [0, 0, 0]);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\n this._setWorldMatrixDirty();\n this._sceneModelDirty();\n this.glRedraw();\n }\n\n /**\n * Gets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n *\n * Default value is ````[0,0,0]````.\n *\n * @type {Number[]}\n */\n get rotation() {\n return this._rotation;\n }\n\n /**\n * Sets the SceneModel's local rotation quaternion.\n *\n * Default value is ````[0,0,0,1]````.\n *\n * @type {Number[]}\n */\n set quaternion(value) {\n this._quaternion.set(value || [0, 0, 0, 1]);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToEuler(this._quaternion, \"XYZ\", this._rotation);\n this._setWorldMatrixDirty();\n this._sceneModelDirty();\n this.glRedraw();\n }\n\n /**\n * Gets the SceneModel's local rotation quaternion.\n *\n * Default value is ````[0,0,0,1]````.\n *\n * @type {Number[]}\n */\n get quaternion() {\n return this._quaternion;\n }\n\n /**\n * Sets the SceneModel's local scale.\n *\n * Default value is ````[1,1,1]````.\n *\n * @type {Number[]}\n * @deprecated\n */\n set scale(value) {\n // NOP - deprecated\n }\n\n /**\n * Gets the SceneModel's local scale.\n *\n * Default value is ````[1,1,1]````.\n *\n * @type {Number[]}\n * @deprecated\n */\n get scale() {\n return this._scale;\n }\n\n /**\n * Sets the SceneModel's local modeling transform matrix.\n *\n * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\n *\n * @type {Number[]}\n */\n set matrix(value) {\n this._matrix.set(value || DEFAULT_MATRIX);\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\n this._matrix.set(this._worldRotationMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\n\n this._matrixDirty = false;\n this._setWorldMatrixDirty();\n this._sceneModelDirty();\n this.glRedraw();\n }\n\n /**\n * Gets the SceneModel's local modeling transform matrix.\n *\n * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\n *\n * @type {Number[]}\n */\n get matrix() {\n if (this._matrixDirty) {\n this._rebuildMatrices();\n }\n return this._matrix;\n }\n\n /**\n * Gets the SceneModel's local modeling rotation transform matrix.\n *\n * @type {Number[]}\n */\n get rotationMatrix() {\n if (this._matrixDirty) {\n this._rebuildMatrices();\n }\n return this._worldRotationMatrix;\n }\n\n _rebuildMatrices() {\n if (this._matrixDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\n this._matrix.set(this._worldRotationMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\n this._matrixDirty = false;\n }\n }\n\n /**\n * Gets the conjugate of the SceneModel's local modeling rotation transform matrix.\n *\n * This is used for RTC view matrix management in renderers.\n *\n * @type {Number[]}\n */\n get rotationMatrixConjugate() {\n if (this._matrixDirty) {\n this._rebuildMatrices();\n }\n return this._worldRotationMatrixConjugate;\n }\n\n _setWorldMatrixDirty() {\n this._matrixDirty = true;\n this._aabbDirty = true;\n }\n\n _transformDirty() {\n this._matrixDirty = true;\n this._aabbDirty = true;\n this.scene._aabbDirty = true;\n }\n\n _sceneModelDirty() {\n this.scene._aabbDirty = true;\n this._aabbDirty = true;\n this.scene._aabbDirty = true;\n this._matrixDirty = true;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i]._sceneModelDirty(); // Entities need to retransform their World AABBs by SceneModel's worldMatrix\n }\n }\n\n /**\n * Gets the SceneModel's World matrix.\n *\n * @property worldMatrix\n * @type {Number[]}\n */\n get worldMatrix() {\n return this.matrix;\n }\n\n /**\n * Gets the SceneModel's World normal matrix.\n *\n * @type {Number[]}\n */\n get worldNormalMatrix() {\n return this._worldNormalMatrix;\n }\n\n /**\n * Called by private renderers in ./lib, returns the view matrix with which to\n * render this SceneModel. The view matrix is the concatenation of the\n * Camera view matrix with the Performance model's world (modeling) matrix.\n *\n * @private\n */\n get viewMatrix() {\n if (!this._viewMatrix) {\n return this.scene.camera.viewMatrix;\n }\n if (this._matrixDirty) {\n this._rebuildMatrices();\n this._viewMatrixDirty = true;\n }\n if (this._viewMatrixDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n this._viewMatrixDirty = false;\n }\n return this._viewMatrix;\n }\n\n /**\n * Called by private renderers in ./lib, returns the view normal matrix with which to render this SceneModel.\n *\n * @private\n */\n get viewNormalMatrix() {\n if (!this._viewNormalMatrix) {\n return this.scene.camera.viewNormalMatrix;\n }\n if (this._matrixDirty) {\n this._rebuildMatrices();\n this._viewMatrixDirty = true;\n }\n if (this._viewMatrixDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n this._viewMatrixDirty = false;\n }\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n return this._viewNormalMatrix;\n }\n\n /**\n * Sets if backfaces are rendered for this SceneModel.\n *\n * Default is ````false````.\n *\n * @type {Boolean}\n */\n get backfaces() {\n return this._backfaces;\n }\n\n /**\n * Sets if backfaces are rendered for this SceneModel.\n *\n * Default is ````false````.\n *\n * When we set this ````true````, then backfaces are always rendered for this SceneModel.\n *\n * When we set this ````false````, then we allow the Viewer to decide whether to render backfaces. In this case,\n * the Viewer will:\n *\n * * hide backfaces on watertight meshes,\n * * show backfaces on open meshes, and\n * * always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\n *\n * @type {Boolean}\n */\n set backfaces(backfaces) {\n backfaces = !!backfaces;\n this._backfaces = backfaces;\n this.glRedraw();\n }\n\n /**\n * Gets the list of {@link SceneModelEntity}s within this SceneModel.\n *\n * @returns {SceneModelEntity[]}\n */\n get entityList() {\n return this._entityList;\n }\n\n /**\n * Returns true to indicate that SceneModel is an {@link Entity}.\n * @type {Boolean}\n */\n get isEntity() {\n return true;\n }\n\n /**\n * Returns ````true```` if this SceneModel represents a model.\n *\n * When ````true```` the SceneModel will be registered by {@link SceneModel#id} in\n * {@link Scene#models} and may also have a {@link MetaObject} with matching {@link MetaObject#id}.\n *\n * @type {Boolean}\n */\n get isModel() {\n return this._isModel;\n }\n\n //------------------------------------------------------------------------------------------------------------------\n // SceneModel members\n //------------------------------------------------------------------------------------------------------------------\n\n /**\n * Returns ````false```` to indicate that SceneModel never represents an object.\n *\n * @type {Boolean}\n */\n get isObject() {\n return false;\n }\n\n /**\n * Gets the SceneModel's World-space 3D axis-aligned bounding box.\n *\n * Represented by a six-element Float64Array containing the min/max extents of the\n * axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\n *\n * @type {Number[]}\n */\n get aabb() {\n if (this._aabbDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3(this._aabb);\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3(this._aabb, this._entityList[i].aabb);\n }\n this._aabbDirty = false;\n }\n return this._aabb;\n }\n\n /**\n * The approximate number of triangle primitives in this SceneModel.\n *\n * @type {Number}\n */\n get numTriangles() {\n return this._numTriangles;\n }\n\n //------------------------------------------------------------------------------------------------------------------\n // Entity members\n //------------------------------------------------------------------------------------------------------------------\n\n /**\n * The approximate number of line primitives in this SceneModel.\n *\n * @type {Number}\n */\n get numLines() {\n return this._numLines;\n }\n\n /**\n * The approximate number of point primitives in this SceneModel.\n *\n * @type {Number}\n */\n get numPoints() {\n return this._numPoints;\n }\n\n /**\n * Gets if any {@link SceneModelEntity}s in this SceneModel are visible.\n *\n * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\n *\n * @type {Boolean}\n */\n get visible() {\n return (this.numVisibleLayerPortions > 0);\n }\n\n /**\n * Sets if this SceneModel is visible.\n *\n * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\n **\n * @type {Boolean}\n */\n set visible(visible) {\n visible = visible !== false;\n this._visible = visible;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].visible = visible;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if any {@link SceneModelEntity}s in this SceneModel are xrayed.\n *\n * @type {Boolean}\n */\n get xrayed() {\n return (this.numXRayedLayerPortions > 0);\n }\n\n /**\n * Sets if all {@link SceneModelEntity}s in this SceneModel are xrayed.\n *\n * @type {Boolean}\n */\n set xrayed(xrayed) {\n xrayed = !!xrayed;\n this._xrayed = xrayed;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].xrayed = xrayed;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if any {@link SceneModelEntity}s in this SceneModel are highlighted.\n *\n * @type {Boolean}\n */\n get highlighted() {\n return (this.numHighlightedLayerPortions > 0);\n }\n\n /**\n * Sets if all {@link SceneModelEntity}s in this SceneModel are highlighted.\n *\n * @type {Boolean}\n */\n set highlighted(highlighted) {\n highlighted = !!highlighted;\n this._highlighted = highlighted;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].highlighted = highlighted;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if any {@link SceneModelEntity}s in this SceneModel are selected.\n *\n * @type {Boolean}\n */\n get selected() {\n return (this.numSelectedLayerPortions > 0);\n }\n\n /**\n * Sets if all {@link SceneModelEntity}s in this SceneModel are selected.\n *\n * @type {Boolean}\n */\n set selected(selected) {\n selected = !!selected;\n this._selected = selected;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].selected = selected;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if any {@link SceneModelEntity}s in this SceneModel have edges emphasised.\n *\n * @type {Boolean}\n */\n get edges() {\n return (this.numEdgesLayerPortions > 0);\n }\n\n /**\n * Sets if all {@link SceneModelEntity}s in this SceneModel have edges emphasised.\n *\n * @type {Boolean}\n */\n set edges(edges) {\n edges = !!edges;\n this._edges = edges;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].edges = edges;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if this SceneModel is culled from view.\n *\n * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\n *\n * @type {Boolean}\n */\n get culled() {\n return this._culled;\n }\n\n /**\n * Sets if this SceneModel is culled from view.\n *\n * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\n *\n * @type {Boolean}\n */\n set culled(culled) {\n culled = !!culled;\n this._culled = culled;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].culled = culled;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if {@link SceneModelEntity}s in this SceneModel are clippable.\n *\n * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\n *\n * @type {Boolean}\n */\n get clippable() {\n return this._clippable;\n }\n\n /**\n * Sets if {@link SceneModelEntity}s in this SceneModel are clippable.\n *\n * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\n *\n * @type {Boolean}\n */\n set clippable(clippable) {\n clippable = clippable !== false;\n this._clippable = clippable;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].clippable = clippable;\n }\n this.glRedraw();\n }\n\n /**\n * Gets if this SceneModel is collidable.\n *\n * @type {Boolean}\n */\n get collidable() {\n return this._collidable;\n }\n\n /**\n * Sets if {@link SceneModelEntity}s in this SceneModel are collidable.\n *\n * @type {Boolean}\n */\n set collidable(collidable) {\n collidable = collidable !== false;\n this._collidable = collidable;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].collidable = collidable;\n }\n }\n\n /**\n * Gets if this SceneModel is pickable.\n *\n * Picking is done via calls to {@link Scene#pick}.\n *\n * @type {Boolean}\n */\n get pickable() {\n return (this.numPickableLayerPortions > 0);\n }\n\n /**\n * Sets if {@link SceneModelEntity}s in this SceneModel are pickable.\n *\n * Picking is done via calls to {@link Scene#pick}.\n *\n * @type {Boolean}\n */\n set pickable(pickable) {\n pickable = pickable !== false;\n this._pickable = pickable;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].pickable = pickable;\n }\n }\n\n /**\n * Gets the RGB colorize color for this SceneModel.\n *\n * Each element of the color is in range ````[0..1]````.\n *\n * @type {Number[]}\n */\n get colorize() {\n return this._colorize;\n }\n\n /**\n * Sets the RGB colorize color for this SceneModel.\n *\n * Multiplies by rendered fragment colors.\n *\n * Each element of the color is in range ````[0..1]````.\n *\n * @type {Number[]}\n */\n set colorize(colorize) {\n this._colorize = colorize;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].colorize = colorize;\n }\n }\n\n /**\n * Gets this SceneModel's opacity factor.\n *\n * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\n *\n * @type {Number}\n */\n get opacity() {\n return this._opacity;\n }\n\n /**\n * Sets the opacity factor for this SceneModel.\n *\n * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\n *\n * @type {Number}\n */\n set opacity(opacity) {\n this._opacity = opacity;\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i].opacity = opacity;\n }\n }\n\n /**\n * Gets if this SceneModel casts a shadow.\n *\n * @type {Boolean}\n */\n get castsShadow() {\n return this._castsShadow;\n }\n\n /**\n * Sets if this SceneModel casts a shadow.\n *\n * @type {Boolean}\n */\n set castsShadow(castsShadow) {\n castsShadow = (castsShadow !== false);\n if (castsShadow !== this._castsShadow) {\n this._castsShadow = castsShadow;\n this.glRedraw();\n }\n }\n\n /**\n * Sets if this SceneModel can have shadow cast upon it.\n *\n * @type {Boolean}\n */\n get receivesShadow() {\n return this._receivesShadow;\n }\n\n /**\n * Sets if this SceneModel can have shadow cast upon it.\n *\n * @type {Boolean}\n */\n set receivesShadow(receivesShadow) {\n receivesShadow = (receivesShadow !== false);\n if (receivesShadow !== this._receivesShadow) {\n this._receivesShadow = receivesShadow;\n this.glRedraw();\n }\n }\n\n /**\n * Gets if Scalable Ambient Obscurance (SAO) will apply to this SceneModel.\n *\n * SAO is configured by the Scene's {@link SAO} component.\n *\n * Only works when {@link SAO#enabled} is also true.\n *\n * @type {Boolean}\n */\n get saoEnabled() {\n return this._saoEnabled;\n }\n\n /**\n * Gets if physically-based rendering (PBR) is enabled for this SceneModel.\n *\n * Only works when {@link Scene#pbrEnabled} is also true.\n *\n * @type {Boolean}\n */\n get pbrEnabled() {\n return this._pbrEnabled;\n }\n\n /**\n * Gets if color textures are enabled for this SceneModel.\n *\n * Only works when {@link Scene#colorTextureEnabled} is also true.\n *\n * @type {Boolean}\n */\n get colorTextureEnabled() {\n return this._colorTextureEnabled;\n }\n\n /**\n * Returns true to indicate that SceneModel is implements {@link Drawable}.\n *\n * @type {Boolean}\n */\n get isDrawable() {\n return true;\n }\n\n /** @private */\n get isStateSortable() {\n return false\n }\n\n /**\n * Configures the appearance of xrayed {@link SceneModelEntity}s within this SceneModel.\n *\n * This is the {@link Scene#xrayMaterial}.\n *\n * @type {EmphasisMaterial}\n */\n get xrayMaterial() {\n return this.scene.xrayMaterial;\n }\n\n /**\n * Configures the appearance of highlighted {@link SceneModelEntity}s within this SceneModel.\n *\n * This is the {@link Scene#highlightMaterial}.\n *\n * @type {EmphasisMaterial}\n */\n get highlightMaterial() {\n return this.scene.highlightMaterial;\n }\n\n /**\n * Configures the appearance of selected {@link SceneModelEntity}s within this SceneModel.\n *\n * This is the {@link Scene#selectedMaterial}.\n *\n * @type {EmphasisMaterial}\n */\n get selectedMaterial() {\n return this.scene.selectedMaterial;\n }\n\n /**\n * Configures the appearance of edges of {@link SceneModelEntity}s within this SceneModel.\n *\n * This is the {@link Scene#edgeMaterial}.\n *\n * @type {EdgeMaterial}\n */\n get edgeMaterial() {\n return this.scene.edgeMaterial;\n }\n\n //------------------------------------------------------------------------------------------------------------------\n // Drawable members\n //------------------------------------------------------------------------------------------------------------------\n\n /**\n * Called by private renderers in ./lib, returns the picking view matrix with which to\n * ray-pick on this SceneModel.\n *\n * @private\n */\n getPickViewMatrix(pickViewMatrix) {\n if (!this._viewMatrix) {\n return pickViewMatrix;\n }\n return this._viewMatrix;\n }\n\n /**\n *\n * @param cfg\n */\n createQuantizationRange(cfg) {\n if (cfg.id === undefined || cfg.id === null) {\n this.error(\"[createQuantizationRange] Config missing: id\");\n return;\n }\n if (cfg.aabb) {\n this.error(\"[createQuantizationRange] Config missing: aabb\");\n return;\n }\n if (this._quantizationRanges[cfg.id]) {\n this.error(\"[createQuantizationRange] QuantizationRange already created: \" + cfg.id);\n return;\n }\n this._quantizationRanges[cfg.id] = {\n id: cfg.id,\n aabb: cfg.aabb,\n matrix: (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.aabb, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4())\n }\n }\n\n /**\n * Creates a reusable geometry within this SceneModel.\n *\n * We can then supply the geometry ID to {@link SceneModel#createMesh} when we want to create meshes that\n * instance the geometry.\n *\n * @param {*} cfg Geometry properties.\n * @param {String|Number} cfg.id Mandatory ID for the geometry, to refer to with {@link SceneModel#createMesh}.\n * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\n * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\n * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\n * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\n * @param {Number[]} [cfg.normals] Flat array of normal vectors. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\n * @param {Number[]} [cfg.normalsCompressed] Flat array of oct-encoded normal vectors. Overrides ````normals````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\n * @param {Number[]} [cfg.colors] Flat array of uncompressed RGBA vertex colors, as float values in range ````[0..1]````. Ignored when ````geometryId```` is given. Overridden by ````color```` and ````colorsCompressed````.\n * @param {Number[]} [cfg.colorsCompressed] Flat array of compressed RGBA vertex colors, as unsigned short integers in range ````[0..255]````. Ignored when ````geometryId```` is given. Overrides ````colors```` and is overridden by ````color````.\n * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n * @param {Number[]} [cfg.uvCompressed] Flat array of compressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Overrides ````uv````. Must be accompanied by ````uvDecodeMatrix````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\n * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\n * @param {Number[]} [cfg.edgeIndices] Array of edge line indices. Used only with 'triangles', 'solid' and 'surface' primitives. Automatically generated internally if not supplied, using the optional ````edgeThreshold```` given to the ````SceneModel```` constructor.\n */\n createGeometry(cfg) {\n if (cfg.id === undefined || cfg.id === null) {\n this.error(\"[createGeometry] Config missing: id\");\n return;\n }\n if (this._geometries[cfg.id]) {\n this.error(\"[createGeometry] Geometry already created: \" + cfg.id);\n return;\n }\n if (cfg.primitive === undefined || cfg.primitive === null) {\n cfg.primitive = \"triangles\";\n }\n if (cfg.primitive !== \"points\" && cfg.primitive !== \"lines\" && cfg.primitive !== \"triangles\" && cfg.primitive !== \"solid\" && cfg.primitive !== \"surface\") {\n this.error(`[createGeometry] Unsupported value for 'primitive': '${cfg.primitive}' - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'. Defaulting to 'triangles'.`);\n return;\n }\n if (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\n this.error(\"[createGeometry] Param expected: `positions`, `positionsCompressed' or 'buckets\");\n return null;\n }\n if (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\n this.error(\"[createGeometry] Param expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\");\n return null;\n }\n if (cfg.positionsDecodeMatrix && cfg.positionsDecodeBoundary) {\n this.error(\"[createGeometry] Only one of these params expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\");\n return null;\n }\n if (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\n this.error(\"[createGeometry] Param expected: `uvDecodeMatrix` (required for `uvCompressed')\");\n return null;\n }\n if (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\n this.error(`[createGeometry] Param expected: indices (required for '${cfg.primitive}' primitive type)`);\n return null;\n }\n if (cfg.positionsDecodeBoundary) {\n cfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n }\n if (cfg.positions) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n cfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n cfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\n cfg.aabb = aabb;\n } else if (cfg.positionsCompressed) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n cfg.positionsDecodeMatrix = new Float64Array(cfg.positionsDecodeMatrix);\n cfg.positionsCompressed = new Uint16Array(cfg.positionsCompressed);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n cfg.aabb = aabb;\n } else if (cfg.buckets) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n this._dtxBuckets[cfg.id] = cfg.buckets;\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\n const bucket = cfg.buckets[i];\n if (bucket.positions) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\n } else if (bucket.positionsCompressed) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\n }\n }\n if (cfg.positionsDecodeMatrix) {\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n }\n cfg.aabb = aabb;\n }\n if (cfg.colorsCompressed && cfg.colorsCompressed.length > 0) {\n cfg.colorsCompressed = new Uint8Array(cfg.colorsCompressed);\n } else if (cfg.colors && cfg.colors.length > 0) {\n const colors = cfg.colors;\n const colorsCompressed = new Uint8Array(colors.length);\n for (let i = 0, len = colors.length; i < len; i++) {\n colorsCompressed[i] = colors[i] * 255;\n }\n cfg.colorsCompressed = colorsCompressed;\n }\n if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")) {\n if (cfg.positions) {\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 5.0);\n } else {\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n }\n }\n if (cfg.uv) {\n const bounds = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.getUVBounds(cfg.uv);\n const result = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.compressUVs(cfg.uv, bounds.min, bounds.max);\n cfg.uvCompressed = result.quantized;\n cfg.uvDecodeMatrix = result.decodeMatrix;\n } else if (cfg.uvCompressed) {\n cfg.uvCompressed = new Uint16Array(cfg.uvCompressed);\n cfg.uvDecodeMatrix = new Float64Array(cfg.uvDecodeMatrix);\n }\n if (cfg.normals) { // HACK\n cfg.normals = null;\n }\n this._geometries [cfg.id] = cfg;\n this._numTriangles += (cfg.indices ? Math.round(cfg.indices.length / 3) : 0);\n this.numGeometries++;\n }\n\n /**\n * Creates a texture within this SceneModel.\n *\n * We can then supply the texture ID to {@link SceneModel#createTextureSet} when we want to create texture sets that use the texture.\n *\n * @param {*} cfg Texture properties.\n * @param {String|Number} cfg.id Mandatory ID for the texture, to refer to with {@link SceneModel#createTextureSet}.\n * @param {String} [cfg.src] Image file for the texture. Assumed to be transcoded if not having a recognized image file\n * extension (jpg, jpeg, png etc.). If transcoded, then assumes ````SceneModel```` is configured with a {@link TextureTranscoder}.\n * @param {ArrayBuffer[]} [cfg.buffers] Transcoded texture data. Assumes ````SceneModel```` is\n * configured with a {@link TextureTranscoder}. This parameter is given as an array of buffers so we can potentially support multi-image textures, such as cube maps.\n * @param {HTMLImageElement} [cfg.image] HTML Image object to load into this texture. Overrides ````src```` and ````buffers````. Never transcoded.\n * @param {Number} [cfg.minFilter=LinearMipmapLinearFilter] How the texture is sampled when a texel covers less than one pixel.\n * Supported values are {@link LinearMipmapLinearFilter}, {@link LinearMipMapNearestFilter}, {@link NearestMipMapNearestFilter}, {@link NearestMipMapLinearFilter} and {@link LinearMipMapLinearFilter}.\n * @param {Number} [cfg.magFilter=LinearFilter] How the texture is sampled when a texel covers more than one pixel. Supported values are {@link LinearFilter} and {@link NearestFilter}.\n * @param {Number} [cfg.wrapS=RepeatWrapping] Wrap parameter for texture coordinate *S*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\n * @param {Number} [cfg.wrapT=RepeatWrapping] Wrap parameter for texture coordinate *T*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}..\n * @param {Number} [cfg.wrapR=RepeatWrapping] Wrap parameter for texture coordinate *R*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\n * @param {Boolean} [cfg.flipY=false] Flips this Texture's source data along its vertical axis when ````true````.\n * @param {Number} [cfg.encoding=LinearEncoding] Encoding format. Supported values are {@link LinearEncoding} and {@link sRGBEncoding}.\n */\n createTexture(cfg) {\n const textureId = cfg.id;\n if (textureId === undefined || textureId === null) {\n this.error(\"[createTexture] Config missing: id\");\n return;\n }\n if (this._textures[textureId]) {\n this.error(\"[createTexture] Texture already created: \" + textureId);\n return;\n }\n if (!cfg.src && !cfg.image && !cfg.buffers) {\n this.error(\"[createTexture] Param expected: `src`, `image' or 'buffers'\");\n return null;\n }\n let minFilter = cfg.minFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\n if (minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter &&\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipMapNearestFilter &&\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter &&\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapLinearFilter &&\n minFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapNearestFilter) {\n this.error(`[createTexture] Unsupported value for 'minFilter' - \n supported values are LinearFilter, LinearMipMapNearestFilter, NearestMipMapNearestFilter, \n NearestMipMapLinearFilter and LinearMipmapLinearFilter. Defaulting to LinearMipmapLinearFilter.`);\n minFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\n }\n let magFilter = cfg.magFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\n if (magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter && magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestFilter) {\n this.error(`[createTexture] Unsupported value for 'magFilter' - supported values are LinearFilter and NearestFilter. Defaulting to LinearFilter.`);\n magFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\n }\n let wrapS = cfg.wrapS || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n if (wrapS !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.ClampToEdgeWrapping && wrapS !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.MirroredRepeatWrapping && wrapS !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping) {\n this.error(`[createTexture] Unsupported value for 'wrapS' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`);\n wrapS = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n }\n let wrapT = cfg.wrapT || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n if (wrapT !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.ClampToEdgeWrapping && wrapT !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.MirroredRepeatWrapping && wrapT !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping) {\n this.error(`[createTexture] Unsupported value for 'wrapT' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`);\n wrapT = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n }\n let wrapR = cfg.wrapR || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n if (wrapR !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.ClampToEdgeWrapping && wrapR !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.MirroredRepeatWrapping && wrapR !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping) {\n this.error(`[createTexture] Unsupported value for 'wrapR' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`);\n wrapR = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n }\n let encoding = cfg.encoding || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\n if (encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding && encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.sRGBEncoding) {\n this.error(\"[createTexture] Unsupported value for 'encoding' - supported values are LinearEncoding and sRGBEncoding. Defaulting to LinearEncoding.\");\n encoding = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\n }\n const texture = new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n gl: this.scene.canvas.gl,\n minFilter,\n magFilter,\n wrapS,\n wrapT,\n wrapR,\n // flipY: cfg.flipY,\n encoding\n });\n if (cfg.preloadColor) {\n texture.setPreloadColor(cfg.preloadColor);\n }\n if (cfg.image) { // Ignore transcoder for Images\n const image = cfg.image;\n image.crossOrigin = \"Anonymous\";\n texture.setImage(image, {minFilter, magFilter, wrapS, wrapT, wrapR, flipY: cfg.flipY, encoding});\n } else if (cfg.src) {\n const ext = cfg.src.split('.').pop();\n switch (ext) { // Don't transcode recognized image file types\n case \"jpeg\":\n case \"jpg\":\n case \"png\":\n case \"gif\":\n const image = new Image();\n image.onload = () => {\n texture.setImage(image, {\n minFilter,\n magFilter,\n wrapS,\n wrapT,\n wrapR,\n flipY: cfg.flipY,\n encoding\n });\n this.glRedraw();\n };\n image.src = cfg.src; // URL or Base64 string\n break;\n default: // Assume other file types need transcoding\n if (!this._textureTranscoder) {\n this.error(`[createTexture] Can't create texture from 'src' - SceneModel needs to be configured with a TextureTranscoder for this file type ('${ext}')`);\n } else {\n _utils_js__WEBPACK_IMPORTED_MODULE_19__.utils.loadArraybuffer(cfg.src, (arrayBuffer) => {\n if (!arrayBuffer.byteLength) {\n this.error(`[createTexture] Can't create texture from 'src': file data is zero length`);\n return;\n }\n this._textureTranscoder.transcode([arrayBuffer], texture).then(() => {\n this.glRedraw();\n });\n },\n function (errMsg) {\n this.error(`[createTexture] Can't create texture from 'src': ${errMsg}`);\n });\n }\n break;\n }\n } else if (cfg.buffers) { // Buffers implicitly require transcoding\n if (!this._textureTranscoder) {\n this.error(`[createTexture] Can't create texture from 'buffers' - SceneModel needs to be configured with a TextureTranscoder for this option`);\n } else {\n this._textureTranscoder.transcode(cfg.buffers, texture).then(() => {\n this.glRedraw();\n });\n }\n }\n this._textures[textureId] = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({id: textureId, texture});\n }\n\n /**\n * Creates a texture set within this SceneModel.\n *\n * * Stores the new {@link SceneModelTextureSet} in {@link SceneModel#textureSets}.\n *\n * A texture set is a collection of textures that can be shared among meshes. We can then supply the texture set\n * ID to {@link SceneModel#createMesh} when we want to create meshes that use the texture set.\n *\n * The textures can work as a texture atlas, where each mesh can have geometry UVs that index\n * a different part of the textures. This allows us to minimize the number of textures in our models, which\n * means faster rendering.\n *\n * @param {*} cfg Texture set properties.\n * @param {String|Number} cfg.id Mandatory ID for the texture set, to refer to with {@link SceneModel#createMesh}.\n * @param {*} [cfg.colorTextureId] ID of *RGBA* base color texture, with color in *RGB* and alpha in *A*.\n * @param {*} [cfg.metallicRoughnessTextureId] ID of *RGBA* metal-roughness texture, with the metallic factor in *R*, and roughness factor in *G*.\n * @param {*} [cfg.normalsTextureId] ID of *RGBA* normal map texture, with normal map vectors in *RGB*.\n * @param {*} [cfg.emissiveTextureId] ID of *RGBA* emissive map texture, with emissive color in *RGB*.\n * @param {*} [cfg.occlusionTextureId] ID of *RGBA* occlusion map texture, with occlusion factor in *R*.\n * @returns {SceneModelTransform} The new texture set.\n */\n createTextureSet(cfg) {\n const textureSetId = cfg.id;\n if (textureSetId === undefined || textureSetId === null) {\n this.error(\"[createTextureSet] Config missing: id\");\n return;\n }\n if (this._textureSets[textureSetId]) {\n this.error(`[createTextureSet] Texture set already created: ${textureSetId}`);\n return;\n }\n let colorTexture;\n if (cfg.colorTextureId !== undefined && cfg.colorTextureId !== null) {\n colorTexture = this._textures[cfg.colorTextureId];\n if (!colorTexture) {\n this.error(`[createTextureSet] Texture not found: ${cfg.colorTextureId} - ensure that you create it first with createTexture()`);\n return;\n }\n } else {\n colorTexture = this._textures[DEFAULT_COLOR_TEXTURE_ID];\n }\n let metallicRoughnessTexture;\n if (cfg.metallicRoughnessTextureId !== undefined && cfg.metallicRoughnessTextureId !== null) {\n metallicRoughnessTexture = this._textures[cfg.metallicRoughnessTextureId];\n if (!metallicRoughnessTexture) {\n this.error(`[createTextureSet] Texture not found: ${cfg.metallicRoughnessTextureId} - ensure that you create it first with createTexture()`);\n return;\n }\n } else {\n metallicRoughnessTexture = this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID];\n }\n let normalsTexture;\n if (cfg.normalsTextureId !== undefined && cfg.normalsTextureId !== null) {\n normalsTexture = this._textures[cfg.normalsTextureId];\n if (!normalsTexture) {\n this.error(`[createTextureSet] Texture not found: ${cfg.normalsTextureId} - ensure that you create it first with createTexture()`);\n return;\n }\n } else {\n normalsTexture = this._textures[DEFAULT_NORMALS_TEXTURE_ID];\n }\n let emissiveTexture;\n if (cfg.emissiveTextureId !== undefined && cfg.emissiveTextureId !== null) {\n emissiveTexture = this._textures[cfg.emissiveTextureId];\n if (!emissiveTexture) {\n this.error(`[createTextureSet] Texture not found: ${cfg.emissiveTextureId} - ensure that you create it first with createTexture()`);\n return;\n }\n } else {\n emissiveTexture = this._textures[DEFAULT_EMISSIVE_TEXTURE_ID];\n }\n let occlusionTexture;\n if (cfg.occlusionTextureId !== undefined && cfg.occlusionTextureId !== null) {\n occlusionTexture = this._textures[cfg.occlusionTextureId];\n if (!occlusionTexture) {\n this.error(`[createTextureSet] Texture not found: ${cfg.occlusionTextureId} - ensure that you create it first with createTexture()`);\n return;\n }\n } else {\n occlusionTexture = this._textures[DEFAULT_OCCLUSION_TEXTURE_ID];\n }\n const textureSet = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\n id: textureSetId,\n model: this,\n colorTexture,\n metallicRoughnessTexture,\n normalsTexture,\n emissiveTexture,\n occlusionTexture\n });\n this._textureSets[textureSetId] = textureSet;\n return textureSet;\n }\n\n /**\n * Creates a new {@link SceneModelTransform} within this SceneModel.\n *\n * * Stores the new {@link SceneModelTransform} in {@link SceneModel#transforms}.\n * * Can be connected into hierarchies\n * * Each {@link SceneModelTransform} can be used by unlimited {@link SceneModelMesh}es\n *\n * @param {*} cfg Transform creation parameters.\n * @param {String} cfg.id Mandatory ID for the new transform. Must not clash with any existing components within the {@link Scene}.\n * @param {String} [cfg.parentTransformId] ID of a parent transform, previously created with {@link SceneModel#createTextureSet}.\n * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\n * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the transform.\n * @param {Number[]} [cfg.rotation=[0,0,0]] Rotation of the transform as Euler angles given in degrees, for each of the X, Y and Z axis.\n * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] Modelling transform matrix. Overrides the ````position````, ````scale```` and ````rotation```` parameters.\n * @returns {SceneModelTransform} The new transform.\n */\n createTransform(cfg) {\n if (cfg.id === undefined || cfg.id === null) {\n this.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\n return;\n }\n if (this._transforms[cfg.id]) {\n this.error(`[createTransform] SceneModel already has a transform with this ID: ${cfg.id}`);\n return;\n }\n let parentTransform;\n if (this.parentTransformId) {\n parentTransform = this._transforms[cfg.parentTransformId];\n if (!parentTransform) {\n this.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\n return;\n }\n }\n const transform = new _SceneModelTransform_js__WEBPACK_IMPORTED_MODULE_27__.SceneModelTransform({\n id: cfg.id,\n model: this,\n parentTransform,\n matrix: cfg.matrix,\n position: cfg.position,\n scale: cfg.scale,\n rotation: cfg.rotation,\n quaternion: cfg.quaternion\n });\n this._transforms[transform.id] = transform;\n return transform;\n }\n\n /**\n * Creates a new {@link SceneModelMesh} within this SceneModel.\n *\n * * It prepares and saves data for a SceneModelMesh {@link SceneModel#meshes} creation. SceneModelMesh will be created only once the SceneModelEntity (which references this particular SceneModelMesh) will be created.\n * * The SceneModelMesh can either define its own geometry or share it with other SceneModelMeshes. To define own geometry, provide the\n * various geometry arrays to this method. To share a geometry, provide the ID of a geometry created earlier\n * with {@link SceneModel#createGeometry}.\n * * If you accompany the arrays with an ````origin````, then ````createMesh()```` will assume\n * that the geometry ````positions```` are in relative-to-center (RTC) coordinates, with ````origin```` being the\n * origin of their RTC coordinate system.\n *\n * @param {object} cfg Object properties.\n * @param {String} cfg.id Mandatory ID for the new mesh. Must not clash with any existing components within the {@link Scene}.\n * @param {String|Number} [cfg.textureSetId] ID of a {@link SceneModelTextureSet} previously created with {@link SceneModel#createTextureSet}.\n * @param {String|Number} [cfg.transformId] ID of a {@link SceneModelTransform} to instance, previously created with {@link SceneModel#createTransform}. Overrides all other transform parameters given to this method.\n * @param {String|Number} [cfg.geometryId] ID of a geometry to instance, previously created with {@link SceneModel#createGeometry}. Overrides all other geometry parameters given to this method.\n * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\n * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\n * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\n * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\n * @param {Number[]} [cfg.normals] Flat array of normal vectors. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\n * @param {Number[]} [cfg.normalsCompressed] Flat array of oct-encoded normal vectors. Overrides ````normals````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. When no normals are given, the geometry will be flat shaded using auto-generated face-aligned normals.\n * @param {Number[]} [cfg.colors] Flat array of uncompressed RGBA vertex colors, as float values in range ````[0..1]````. Ignored when ````geometryId```` is given. Overridden by ````color```` and ````colorsCompressed````.\n * @param {Number[]} [cfg.colorsCompressed] Flat array of compressed RGBA vertex colors, as unsigned short integers in range ````[0..255]````. Ignored when ````geometryId```` is given. Overrides ````colors```` and is overridden by ````color````.\n * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n * @param {Number[]} [cfg.uvCompressed] Flat array of compressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Overrides ````uv````. Must be accompanied by ````uvDecodeMatrix````. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\n * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\n * @param {Number[]} [cfg.edgeIndices] Array of edge line indices. Used only with 'triangles', 'solid' and 'surface' primitives. Automatically generated internally if not supplied, using the optional ````edgeThreshold```` given to the ````SceneModel```` constructor.\n * @param {Number[]} [cfg.origin] Optional geometry origin, relative to {@link SceneModel#origin}. When this is given, then ````positions```` are assumed to be relative to this.\n * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\n * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.\n * @param {Number[]} [cfg.rotation=[0,0,0]] Rotation of the mesh as Euler angles given in degrees, for each of the X, Y and Z axis. Overridden by ````transformId````.\n * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] Mesh modelling transform matrix. Overrides the ````position````, ````scale```` and ````rotation```` parameters. Also overridden by ````transformId````.\n * @param {Number[]} [cfg.color=[1,1,1]] RGB color in range ````[0..1, 0..1, 0..1]````. Overridden by texture set ````colorTexture````. Overrides ````colors```` and ````colorsCompressed````.\n * @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.\n * @param {Number} [cfg.metallic=0] Metallic factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\n * @param {Number} [cfg.roughness=1] Roughness factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\n * @returns {Boolean} True = successfully mesh was created. False = error during creation of a mesh.\n */\n createMesh(cfg) {\n\n if (cfg.id === undefined || cfg.id === null) {\n this.error(\"[createMesh] SceneModel.createMesh() config missing: id\");\n return false;\n }\n\n if (this._scheduledMeshes[cfg.id]) {\n this.error(`[createMesh] SceneModel already has a mesh with this ID: ${cfg.id}`);\n return false;\n }\n\n const instancing = (cfg.geometryId !== undefined);\n const batching = !instancing;\n\n if (batching) {\n\n // Batched geometry\n\n if (cfg.primitive === undefined || cfg.primitive === null) {\n cfg.primitive = \"triangles\";\n }\n if (cfg.primitive !== \"points\" && cfg.primitive !== \"lines\" && cfg.primitive !== \"triangles\" && cfg.primitive !== \"solid\" && cfg.primitive !== \"surface\") {\n this.error(`Unsupported value for 'primitive': '${primitive}' ('geometryId' is absent) - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'.`);\n return false;\n }\n if (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\n this.error(\"Param expected: 'positions', 'positionsCompressed' or `buckets` ('geometryId' is absent)\");\n return false;\n }\n if (cfg.positions && (cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)) {\n this.error(\"Illegal params: 'positions' not expected with 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\");\n return false;\n }\n if (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\n this.error(\"Param expected: 'positionsCompressed' should be accompanied by 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\");\n return false;\n }\n if (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\n this.error(\"Param expected: 'uvCompressed' should be accompanied by `uvDecodeMatrix` ('geometryId' is absent)\");\n return false;\n }\n if (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\n this.error(`Param expected: indices (required for '${cfg.primitive}' primitive type)`);\n return false;\n }\n if ((cfg.matrix || cfg.position || cfg.rotation || cfg.scale) && (cfg.positionsCompressed || cfg.positionsDecodeBoundary)) {\n this.error(\"Unexpected params: 'matrix', 'rotation', 'scale', 'position' not allowed with 'positionsCompressed'\");\n return false;\n }\n\n const useDTX = (!!this._dtxEnabled && (cfg.primitive === \"triangles\"\n || cfg.primitive === \"solid\"\n || cfg.primitive === \"surface\"));\n\n cfg.origin = cfg.origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(this._origin, cfg.origin, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3()) : this._origin;\n\n // MATRIX - optional for batching\n\n if (cfg.matrix) {\n cfg.meshMatrix = cfg.matrix;\n } else if (cfg.scale || cfg.rotation || cfg.position) {\n const scale = cfg.scale || DEFAULT_SCALE;\n const position = cfg.position || DEFAULT_POSITION;\n const rotation = cfg.rotation || DEFAULT_ROTATION;\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\n cfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n }\n\n if (cfg.positionsDecodeBoundary) {\n cfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n }\n\n if (useDTX) {\n\n // DTX\n\n cfg.type = DTX;\n\n // NPR\n\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\n\n // RTC\n\n if (cfg.positions) {\n const rtcCenter = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\n const rtcPositions = [];\n const rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, rtcCenter);\n if (rtcNeeded) {\n cfg.positions = rtcPositions;\n cfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, rtcCenter, rtcCenter);\n }\n }\n\n // COMPRESSION\n\n if (cfg.positions) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n cfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n cfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\n cfg.aabb = aabb;\n\n } else if (cfg.positionsCompressed) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n cfg.aabb = aabb;\n\n }\n if (cfg.buckets) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\n const bucket = cfg.buckets[i];\n if (bucket.positions) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\n } else if (bucket.positionsCompressed) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\n }\n }\n if (cfg.positionsDecodeMatrix) {\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n }\n cfg.aabb = aabb;\n }\n\n if (cfg.meshMatrix) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\n }\n\n // EDGES\n\n if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")) {\n if (cfg.positions) { // Faster\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\n } else {\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n }\n }\n\n // BUCKETING\n\n if (!cfg.buckets) {\n cfg.buckets = createDTXBuckets(cfg, this._enableVertexWelding && this._enableIndexBucketing);\n }\n\n } else {\n\n // VBO\n\n cfg.type = VBO_BATCHED;\n\n // PBR\n\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : [255, 255, 255];\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\n cfg.metallic = (cfg.metallic !== undefined && cfg.metallic !== null) ? Math.floor(cfg.metallic * 255) : 0;\n cfg.roughness = (cfg.roughness !== undefined && cfg.roughness !== null) ? Math.floor(cfg.roughness * 255) : 255;\n\n // RTC\n\n if (cfg.positions) {\n const rtcPositions = [];\n const rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, tempVec3a);\n if (rtcNeeded) {\n cfg.positions = rtcPositions;\n cfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, tempVec3a, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3());\n }\n }\n\n if (cfg.positions) {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n if (cfg.meshMatrix) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPositions3(cfg.meshMatrix, cfg.positions, cfg.positions);\n cfg.meshMatrix = null; // Positions now baked, don't need any more\n }\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n cfg.aabb = aabb;\n\n } else {\n const aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n cfg.aabb = aabb;\n }\n\n if (cfg.meshMatrix) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\n }\n\n // EDGES\n\n if (!cfg.buckets && !cfg.edgeIndices && (cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")) {\n if (cfg.positions) {\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\n } else {\n cfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n }\n }\n\n // TEXTURE\n\n // cfg.textureSetId = cfg.textureSetId || DEFAULT_TEXTURE_SET_ID;\n if (cfg.textureSetId) {\n cfg.textureSet = this._textureSets[cfg.textureSetId];\n if (!cfg.textureSet) {\n this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);\n return false;\n }\n }\n }\n\n } else {\n\n // INSTANCING\n\n if (cfg.positions || cfg.positionsCompressed || cfg.indices || cfg.edgeIndices || cfg.normals || cfg.normalsCompressed || cfg.uv || cfg.uvCompressed || cfg.positionsDecodeMatrix) {\n this.error(`Mesh geometry parameters not expected when instancing a geometry (not expected: positions, positionsCompressed, indices, edgeIndices, normals, normalsCompressed, uv, uvCompressed, positionsDecodeMatrix)`);\n return false;\n }\n\n cfg.geometry = this._geometries[cfg.geometryId];\n if (!cfg.geometry) {\n this.error(`[createMesh] Geometry not found: ${cfg.geometryId} - ensure that you create it first with createGeometry()`);\n return false;\n }\n\n cfg.origin = cfg.origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(this._origin, cfg.origin, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3()) : this._origin;\n cfg.positionsDecodeMatrix = cfg.geometry.positionsDecodeMatrix;\n\n if (cfg.transformId) {\n\n // TRANSFORM\n\n cfg.transform = this._transforms[cfg.transformId];\n\n if (!cfg.transform) {\n this.error(`[createMesh] Transform not found: ${cfg.transformId} - ensure that you create it first with createTransform()`);\n return false;\n }\n\n cfg.aabb = cfg.geometry.aabb;\n\n } else {\n\n // MATRIX\n\n if (cfg.matrix) {\n cfg.meshMatrix = cfg.matrix.slice();\n } else {\n const scale = cfg.scale || DEFAULT_SCALE;\n const position = cfg.position || DEFAULT_POSITION;\n const rotation = cfg.rotation || DEFAULT_ROTATION;\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\n cfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n }\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n cfg.aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3());\n }\n\n const useDTX = (!!this._dtxEnabled\n && (cfg.geometry.primitive === \"triangles\"\n || cfg.geometry.primitive === \"solid\"\n || cfg.geometry.primitive === \"surface\"));\n\n if (useDTX) {\n\n // DTX\n\n cfg.type = DTX;\n\n // NPR\n\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\n\n // BUCKETING - lazy generated, reused\n\n let buckets = this._dtxBuckets[cfg.geometryId];\n if (!buckets) {\n buckets = createDTXBuckets(cfg.geometry, this._enableVertexWelding, this._enableIndexBucketing);\n this._dtxBuckets[cfg.geometryId] = buckets;\n }\n cfg.buckets = buckets;\n\n } else {\n\n // VBO\n\n cfg.type = VBO_INSTANCED;\n\n // PBR\n\n cfg.color = (cfg.color) ? new Uint8Array([Math.floor(cfg.color[0] * 255), Math.floor(cfg.color[1] * 255), Math.floor(cfg.color[2] * 255)]) : defaultCompressedColor;\n cfg.opacity = (cfg.opacity !== undefined && cfg.opacity !== null) ? Math.floor(cfg.opacity * 255) : 255;\n cfg.metallic = (cfg.metallic !== undefined && cfg.metallic !== null) ? Math.floor(cfg.metallic * 255) : 0;\n cfg.roughness = (cfg.roughness !== undefined && cfg.roughness !== null) ? Math.floor(cfg.roughness * 255) : 255;\n\n // TEXTURE\n\n if (cfg.textureSetId) {\n cfg.textureSet = this._textureSets[cfg.textureSetId];\n // if (!cfg.textureSet) {\n // this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);\n // return false;\n // }\n }\n }\n }\n\n cfg.numPrimitives = this._getNumPrimitives(cfg);\n\n this._meshesCfgsBeforeMeshCreation[cfg.id] = cfg;\n\n return true;\n }\n\n _createMesh(cfg) {\n const mesh = new _SceneModelMesh_js__WEBPACK_IMPORTED_MODULE_3__.SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);\n mesh.pickId = this.scene._renderer.getPickID(mesh);\n const pickId = mesh.pickId;\n const a = pickId >> 24 & 0xFF;\n const b = pickId >> 16 & 0xFF;\n const g = pickId >> 8 & 0xFF;\n const r = pickId & 0xFF;\n cfg.pickColor = new Uint8Array([r, g, b, a]); // Quantized pick color\n cfg.solid = (cfg.primitive === \"solid\");\n mesh.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin);\n switch (cfg.type) {\n case DTX:\n mesh.layer = this._getDTXLayer(cfg);\n mesh.aabb = cfg.aabb;\n break;\n case VBO_BATCHED:\n mesh.layer = this._getVBOBatchingLayer(cfg);\n mesh.aabb = cfg.aabb;\n break;\n case VBO_INSTANCED:\n mesh.layer = this._getVBOInstancingLayer(cfg);\n mesh.aabb = cfg.aabb;\n break;\n }\n if (cfg.transform) {\n cfg.meshMatrix = cfg.transform.worldMatrix;\n }\n mesh.portionId = mesh.layer.createPortion(mesh, cfg);\n return mesh;\n }\n\n _getNumPrimitives(cfg) {\n let countIndices = 0;\n const primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\n switch (primitive) {\n case \"triangles\":\n case \"solid\":\n case \"surface\":\n switch (cfg.type) {\n case DTX:\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\n countIndices += cfg.buckets[i].indices.length;\n }\n break;\n case VBO_BATCHED:\n countIndices += cfg.indices.length;\n break;\n case VBO_INSTANCED:\n countIndices += cfg.geometry.indices.length;\n break;\n }\n return Math.round(countIndices / 3);\n case \"points\":\n switch (cfg.type) {\n case DTX:\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\n countIndices += cfg.buckets[i].positionsCompressed.length;\n }\n break;\n case VBO_BATCHED:\n countIndices += cfg.positions ? cfg.positions.length : cfg.positionsCompressed.length;\n break;\n case VBO_INSTANCED:\n const geometry = cfg.geometry;\n countIndices += geometry.positions ? geometry.positions.length : geometry.positionsCompressed.length;\n break;\n }\n return Math.round(countIndices);\n case \"lines\":\n case \"line-strip\":\n switch (cfg.type) {\n case DTX:\n for (let i = 0, len = cfg.buckets.length; i < len; i++) {\n countIndices += cfg.buckets[i].indices.length;\n }\n break;\n case VBO_BATCHED:\n countIndices += cfg.indices.length;\n break;\n case VBO_INSTANCED:\n countIndices += cfg.geometry.indices.length;\n break;\n }\n return Math.round(countIndices / 2);\n }\n return 0;\n }\n\n _getDTXLayer(cfg) {\n const origin = cfg.origin;\n const primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\n const layerId = `.${primitive}.${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}`;\n let dtxLayer = this._dtxLayers[layerId];\n if (dtxLayer) {\n if (!dtxLayer.canCreatePortion(cfg)) {\n dtxLayer.finalize();\n delete this._dtxLayers[layerId];\n dtxLayer = null;\n } else {\n return dtxLayer;\n }\n }\n switch (primitive) {\n case \"triangles\":\n case \"solid\":\n case \"surface\":\n dtxLayer = new _dtx_triangles_DTXTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_12__.DTXTrianglesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()\n break;\n case \"lines\":\n dtxLayer = new _dtx_lines_DTXLinesLayer_js__WEBPACK_IMPORTED_MODULE_11__.DTXLinesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()\n break;\n default:\n return;\n }\n this._dtxLayers[layerId] = dtxLayer;\n this.layerList.push(dtxLayer);\n return dtxLayer;\n }\n\n _getVBOBatchingLayer(cfg) {\n const model = this;\n const origin = cfg.origin;\n const positionsDecodeHash = cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary ?\n this._createHashStringFromMatrix(cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)\n : \"-\";\n const textureSetId = cfg.textureSetId || \"-\";\n const layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${cfg.primitive}.${positionsDecodeHash}.${textureSetId}`;\n let vboBatchingLayer = this._vboBatchingLayers[layerId];\n if (vboBatchingLayer) {\n return vboBatchingLayer;\n }\n let textureSet = cfg.textureSet;\n while (!vboBatchingLayer) {\n switch (cfg.primitive) {\n case \"triangles\":\n // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n vboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n model,\n textureSet,\n layerIndex: 0, // This is set in #finalize()\n scratchMemory: this._vboBatchingLayerScratchMemory,\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n origin,\n maxGeometryBatchSize: this._maxGeometryBatchSize,\n solid: (cfg.primitive === \"solid\"),\n autoNormals: true\n });\n break;\n case \"solid\":\n // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n vboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n model,\n textureSet,\n layerIndex: 0, // This is set in #finalize()\n scratchMemory: this._vboBatchingLayerScratchMemory,\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n origin,\n maxGeometryBatchSize: this._maxGeometryBatchSize,\n solid: (cfg.primitive === \"solid\"),\n autoNormals: true\n });\n break;\n case \"surface\":\n // console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n vboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n model,\n textureSet,\n layerIndex: 0, // This is set in #finalize()\n scratchMemory: this._vboBatchingLayerScratchMemory,\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n origin,\n maxGeometryBatchSize: this._maxGeometryBatchSize,\n solid: (cfg.primitive === \"solid\"),\n autoNormals: true\n });\n break;\n case \"lines\":\n // console.info(`[SceneModel ${this.id}]: creating VBOBatchingLinesLayer`);\n vboBatchingLayer = new _vbo_batching_lines_VBOBatchingLinesLayer_js__WEBPACK_IMPORTED_MODULE_7__.VBOBatchingLinesLayer({\n model,\n layerIndex: 0, // This is set in #finalize()\n scratchMemory: this._vboBatchingLayerScratchMemory,\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n origin,\n maxGeometryBatchSize: this._maxGeometryBatchSize\n });\n break;\n case \"points\":\n // console.info(`[SceneModel ${this.id}]: creating VBOBatchingPointsLayer`);\n vboBatchingLayer = new _vbo_batching_points_VBOBatchingPointsLayer_js__WEBPACK_IMPORTED_MODULE_9__.VBOBatchingPointsLayer({\n model,\n layerIndex: 0, // This is set in #finalize()\n scratchMemory: this._vboBatchingLayerScratchMemory,\n positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n origin,\n maxGeometryBatchSize: this._maxGeometryBatchSize\n });\n break;\n }\n const lenPositions = cfg.positionsCompressed ? cfg.positionsCompressed.length : cfg.positions.length;\n const canCreatePortion = (cfg.primitive === \"points\")\n ? vboBatchingLayer.canCreatePortion(lenPositions)\n : vboBatchingLayer.canCreatePortion(lenPositions, cfg.indices.length);\n if (!canCreatePortion) {\n vboBatchingLayer.finalize();\n delete this._vboBatchingLayers[layerId];\n vboBatchingLayer = null;\n }\n }\n this._vboBatchingLayers[layerId] = vboBatchingLayer;\n this.layerList.push(vboBatchingLayer);\n return vboBatchingLayer;\n }\n\n _createHashStringFromMatrix(matrix) {\n const matrixString = matrix.join('');\n let hash = 0;\n for (let i = 0; i < matrixString.length; i++) {\n const char = matrixString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash |= 0; // Convert to 32-bit integer\n }\n const hashString = (hash >>> 0).toString(16);\n return hashString;\n }\n\n _getVBOInstancingLayer(cfg) {\n const model = this;\n const origin = cfg.origin;\n const textureSetId = cfg.textureSetId || \"-\";\n const geometryId = cfg.geometryId;\n const layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${textureSetId}.${geometryId}`;\n let vboInstancingLayer = this._vboInstancingLayers[layerId];\n if (vboInstancingLayer) {\n return vboInstancingLayer;\n }\n let textureSet = cfg.textureSet;\n const geometry = cfg.geometry;\n while (!vboInstancingLayer) {\n switch (geometry.primitive) {\n case \"triangles\":\n // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n vboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n model,\n textureSet,\n geometry,\n origin,\n layerIndex: 0,\n solid: false\n });\n break;\n case \"solid\":\n // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n vboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n model,\n textureSet,\n geometry,\n origin,\n layerIndex: 0,\n solid: true\n });\n break;\n case \"surface\":\n // console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n vboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n model,\n textureSet,\n geometry,\n origin,\n layerIndex: 0,\n solid: false\n });\n break;\n case \"lines\":\n // console.info(`[SceneModel ${this.id}]: creating VBOInstancingLinesLayer`);\n vboInstancingLayer = new _vbo_instancing_lines_VBOInstancingLinesLayer_js__WEBPACK_IMPORTED_MODULE_8__.VBOInstancingLinesLayer({\n model,\n textureSet,\n geometry,\n origin,\n layerIndex: 0\n });\n break;\n case \"points\":\n // console.info(`[SceneModel ${this.id}]: creating PointsInstancingLayer`);\n vboInstancingLayer = new _vbo_instancing_points_VBOInstancingPointsLayer_js__WEBPACK_IMPORTED_MODULE_10__.VBOInstancingPointsLayer({\n model,\n textureSet,\n geometry,\n origin,\n layerIndex: 0\n });\n break;\n }\n // const lenPositions = geometry.positionsCompressed.length;\n // if (!vboInstancingLayer.canCreatePortion(lenPositions, geometry.indices.length)) { // FIXME: indices should be optional\n // vboInstancingLayer.finalize();\n // delete this._vboInstancingLayers[layerId];\n // vboInstancingLayer = null;\n // }\n }\n this._vboInstancingLayers[layerId] = vboInstancingLayer;\n this.layerList.push(vboInstancingLayer);\n return vboInstancingLayer;\n }\n\n /**\n * Creates a {@link SceneModelEntity} within this SceneModel.\n *\n * * Gives the SceneModelEntity one or more {@link SceneModelMesh}es previously created with\n * {@link SceneModel#createMesh}. A SceneModelMesh can only belong to one SceneModelEntity, so you'll get an\n * error if you try to reuse a mesh among multiple SceneModelEntitys.\n * * The SceneModelEntity can have a {@link SceneModelTextureSet}, previously created with\n * {@link SceneModel#createTextureSet}. A SceneModelTextureSet can belong to multiple SceneModelEntitys.\n * * The SceneModelEntity can have a geometry, previously created with\n * {@link SceneModel#createTextureSet}. A geometry is a \"virtual component\" and can belong to multiple SceneModelEntitys.\n *\n * @param {Object} cfg SceneModelEntity configuration.\n * @param {String} cfg.id Optional ID for the new SceneModelEntity. Must not clash with any existing components within the {@link Scene}.\n * @param {String[]} cfg.meshIds IDs of one or more meshes created previously with {@link SceneModel@createMesh}.\n * @param {Boolean} [cfg.isObject] Set ````true```` if the {@link SceneModelEntity} represents an object, in which case it will be registered by {@link SceneModelEntity#id} in {@link Scene#objects} and can also have a corresponding {@link MetaObject} with matching {@link MetaObject#id}, registered by that ID in {@link MetaScene#metaObjects}.\n * @param {Boolean} [cfg.visible=true] Indicates if the SceneModelEntity is initially visible.\n * @param {Boolean} [cfg.culled=false] Indicates if the SceneModelEntity is initially culled from view.\n * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModelEntity is initially pickable.\n * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModelEntity is initially clippable.\n * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModelEntity is initially included in boundary calculations.\n * @param {Boolean} [cfg.castsShadow=true] Indicates if the SceneModelEntity initially casts shadows.\n * @param {Boolean} [cfg.receivesShadow=true] Indicates if the SceneModelEntity initially receives shadows.\n * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModelEntity is initially xrayed. XRayed appearance is configured by {@link SceneModel#xrayMaterial}.\n * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModelEntity is initially highlighted. Highlighted appearance is configured by {@link SceneModel#highlightMaterial}.\n * @param {Boolean} [cfg.selected=false] Indicates if the SceneModelEntity is initially selected. Selected appearance is configured by {@link SceneModel#selectedMaterial}.\n * @param {Boolean} [cfg.edges=false] Indicates if the SceneModelEntity's edges are initially emphasized. Edges appearance is configured by {@link SceneModel#edgeMaterial}.\n * @returns {SceneModelEntity} The new SceneModelEntity.\n */\n createEntity(cfg) {\n if (cfg.id === undefined) {\n cfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\n } else if (this.scene.components[cfg.id]) {\n this.error(`Scene already has a Component with this ID: ${cfg.id} - will assign random ID`);\n cfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\n }\n if (cfg.meshIds === undefined) {\n this.error(\"Config missing: meshIds\");\n return;\n }\n let flags = 0;\n if (this._visible && cfg.visible !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.VISIBLE;\n }\n if (this._pickable && cfg.pickable !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.PICKABLE;\n }\n if (this._culled && cfg.culled !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CULLED;\n }\n if (this._clippable && cfg.clippable !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CLIPPABLE;\n }\n if (this._collidable && cfg.collidable !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.COLLIDABLE;\n }\n if (this._edges && cfg.edges !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.EDGES;\n }\n if (this._xrayed && cfg.xrayed !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.XRAYED;\n }\n if (this._highlighted && cfg.highlighted !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.HIGHLIGHTED;\n }\n if (this._selected && cfg.selected !== false) {\n flags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.SELECTED;\n }\n cfg.flags = flags;\n this._createEntity(cfg);\n }\n\n _createEntity(cfg) {\n let meshes = [];\n for (let i = 0, len = cfg.meshIds.length; i < len; i++) {\n const meshId = cfg.meshIds[i];\n let mesh = this._meshes[meshId]; // Trying to get already created mesh\n if (!mesh) { // Checks if there is already created mesh for this meshId\n let meshCfg = this._meshesCfgsBeforeMeshCreation[meshId]; // Trying to get already created cfg\n if (!meshCfg) { // Checks if there is already created cfg for this meshId\n this.error(`Mesh with this ID not found: \"${meshId}\" - ignoring this mesh`); // There is no such cfg\n continue;\n }\n mesh = this._createMesh(meshCfg) // There is no such mesh yet, but there is already created cfg, so it creates this mesh\n this._meshes[cfg.id] = mesh; // Now it will also add this mesh to dictionary of created meshes\n }\n if (mesh.parent) {\n this.error(`Mesh with ID \"${meshId}\" already belongs to object with ID \"${mesh.parent.id}\" - ignoring this mesh`);\n continue;\n }\n meshes.push(mesh);\n }\n const lodCullable = true;\n const entity = new _SceneModelEntity_js__WEBPACK_IMPORTED_MODULE_25__.SceneModelEntity(\n this,\n cfg.isObject,\n cfg.id,\n meshes,\n cfg.flags,\n lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel\n this._entityList.push(entity);\n this._entities[cfg.id] = entity;\n this.numEntities++;\n }\n\n /**\n * Finalizes this SceneModel.\n *\n * Once finalized, you can't add anything more to this SceneModel.\n */\n finalize() {\n if (this.destroyed) {\n return;\n }\n for (let i = 0, len = this.layerList.length; i < len; i++) {\n const layer = this.layerList[i];\n layer.finalize();\n }\n this._geometries = {};\n this._dtxBuckets = {};\n this._textures = {};\n this._textureSets = {};\n this._dtxLayers = {};\n this._vboInstancingLayers = {};\n this._vboBatchingLayers = {};\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n const entity = this._entityList[i];\n entity._finalize();\n }\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n const entity = this._entityList[i];\n entity._finalize2();\n }\n // Sort layers to reduce WebGL shader switching when rendering them\n this.layerList.sort((a, b) => {\n if (a.sortId < b.sortId) {\n return -1;\n }\n if (a.sortId > b.sortId) {\n return 1;\n }\n return 0;\n });\n for (let i = 0, len = this.layerList.length; i < len; i++) {\n const layer = this.layerList[i];\n layer.layerIndex = i;\n }\n this.glRedraw();\n this.scene._aabbDirty = true;\n this._viewMatrixDirty = true;\n this._matrixDirty = true;\n this._aabbDirty = true;\n\n this._setWorldMatrixDirty();\n this._sceneModelDirty();\n\n this.position = this._position;\n }\n\n /** @private */\n stateSortCompare(drawable1, drawable2) {\n }\n\n /** @private */\n rebuildRenderFlags() {\n this.renderFlags.reset();\n this._updateRenderFlagsVisibleLayers();\n if (this.renderFlags.numLayers > 0 && this.renderFlags.numVisibleLayers === 0) {\n this.renderFlags.culled = true;\n return;\n }\n this._updateRenderFlags();\n }\n\n /**\n * @private\n */\n _updateRenderFlagsVisibleLayers() {\n const renderFlags = this.renderFlags;\n renderFlags.numLayers = this.layerList.length;\n renderFlags.numVisibleLayers = 0;\n for (let layerIndex = 0, len = this.layerList.length; layerIndex < len; layerIndex++) {\n const layer = this.layerList[layerIndex];\n const layerVisible = this._getActiveSectionPlanesForLayer(layer);\n if (layerVisible) {\n renderFlags.visibleLayers[renderFlags.numVisibleLayers++] = layerIndex;\n }\n }\n }\n\n _getActiveSectionPlanesForLayer(layer) {\n const renderFlags = this.renderFlags;\n const sectionPlanes = this.scene._sectionPlanesState.sectionPlanes;\n const numSectionPlanes = sectionPlanes.length;\n const baseIndex = layer.layerIndex * numSectionPlanes;\n if (numSectionPlanes > 0) {\n for (let i = 0; i < numSectionPlanes; i++) {\n const sectionPlane = sectionPlanes[i];\n if (!sectionPlane.active) {\n renderFlags.sectionPlanesActivePerLayer[baseIndex + i] = false;\n } else {\n renderFlags.sectionPlanesActivePerLayer[baseIndex + i] = true;\n renderFlags.sectioned = true;\n }\n }\n }\n return true;\n }\n\n _updateRenderFlags() {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n if (this.numCulledLayerPortions === this.numPortions) {\n return;\n }\n const renderFlags = this.renderFlags;\n renderFlags.colorOpaque = (this.numTransparentLayerPortions < this.numPortions);\n if (this.numTransparentLayerPortions > 0) {\n renderFlags.colorTransparent = true;\n }\n if (this.numXRayedLayerPortions > 0) {\n const xrayMaterial = this.scene.xrayMaterial._state;\n if (xrayMaterial.fill) {\n if (xrayMaterial.fillAlpha < 1.0) {\n renderFlags.xrayedSilhouetteTransparent = true;\n } else {\n renderFlags.xrayedSilhouetteOpaque = true;\n }\n }\n if (xrayMaterial.edges) {\n if (xrayMaterial.edgeAlpha < 1.0) {\n renderFlags.xrayedEdgesTransparent = true;\n } else {\n renderFlags.xrayedEdgesOpaque = true;\n }\n }\n }\n if (this.numEdgesLayerPortions > 0) {\n const edgeMaterial = this.scene.edgeMaterial._state;\n if (edgeMaterial.edges) {\n renderFlags.edgesOpaque = (this.numTransparentLayerPortions < this.numPortions);\n if (this.numTransparentLayerPortions > 0) {\n renderFlags.edgesTransparent = true;\n }\n }\n }\n if (this.numSelectedLayerPortions > 0) {\n const selectedMaterial = this.scene.selectedMaterial._state;\n if (selectedMaterial.fill) {\n if (selectedMaterial.fillAlpha < 1.0) {\n renderFlags.selectedSilhouetteTransparent = true;\n } else {\n renderFlags.selectedSilhouetteOpaque = true;\n }\n }\n if (selectedMaterial.edges) {\n if (selectedMaterial.edgeAlpha < 1.0) {\n renderFlags.selectedEdgesTransparent = true;\n } else {\n renderFlags.selectedEdgesOpaque = true;\n }\n }\n }\n if (this.numHighlightedLayerPortions > 0) {\n const highlightMaterial = this.scene.highlightMaterial._state;\n if (highlightMaterial.fill) {\n if (highlightMaterial.fillAlpha < 1.0) {\n renderFlags.highlightedSilhouetteTransparent = true;\n } else {\n renderFlags.highlightedSilhouetteOpaque = true;\n }\n }\n if (highlightMaterial.edges) {\n if (highlightMaterial.edgeAlpha < 1.0) {\n renderFlags.highlightedEdgesTransparent = true;\n } else {\n renderFlags.highlightedEdgesOpaque = true;\n }\n }\n }\n }\n\n // -------------- RENDERING ---------------------------------------------------------------------------------------\n\n /** @private */\n drawColorOpaque(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawColorOpaque(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawColorTransparent(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawColorTransparent(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawDepth(frameCtx) { // Dedicated to SAO because it skips transparent objects\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawDepth(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawNormals(frameCtx) { // Dedicated to SAO because it skips transparent objects\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawNormals(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawSilhouetteXRayed(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawSilhouetteXRayed(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawSilhouetteHighlighted(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawSilhouetteHighlighted(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawSilhouetteSelected(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawSilhouetteSelected(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawEdgesColorOpaque(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawEdgesColorOpaque(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawEdgesColorTransparent(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawEdgesColorTransparent(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawEdgesXRayed(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawEdgesXRayed(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawEdgesHighlighted(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawEdgesHighlighted(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n drawEdgesSelected(frameCtx) {\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawEdgesSelected(renderFlags, frameCtx);\n }\n }\n\n /**\n * @private\n */\n drawOcclusion(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawOcclusion(renderFlags, frameCtx);\n }\n }\n\n /**\n * @private\n */\n drawShadow(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawShadow(renderFlags, frameCtx);\n }\n }\n\n /** @private */\n setPickMatrices(pickViewMatrix, pickProjMatrix) {\n if (this._numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n const layer = this.layerList[layerIndex];\n if (layer.setPickMatrices) {\n layer.setPickMatrices(pickViewMatrix, pickProjMatrix);\n }\n }\n }\n\n /** @private */\n drawPickMesh(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawPickMesh(renderFlags, frameCtx);\n }\n }\n\n /**\n * Called by SceneModelMesh.drawPickDepths()\n * @private\n */\n drawPickDepths(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawPickDepths(renderFlags, frameCtx);\n }\n }\n\n /**\n * Called by SceneModelMesh.drawPickNormals()\n * @private\n */\n drawPickNormals(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n this.layerList[layerIndex].drawPickNormals(renderFlags, frameCtx);\n }\n }\n\n /**\n * @private\n */\n drawSnapInit(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n const layer = this.layerList[layerIndex];\n if (layer.drawSnapInit) {\n frameCtx.snapPickOrigin = [0, 0, 0];\n frameCtx.snapPickCoordinateScale = [1, 1, 1];\n frameCtx.snapPickLayerNumber++;\n layer.drawSnapInit(renderFlags, frameCtx);\n frameCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\n origin: frameCtx.snapPickOrigin.slice(),\n coordinateScale: frameCtx.snapPickCoordinateScale.slice(),\n };\n }\n }\n }\n\n /**\n * @private\n */\n drawSnap(frameCtx) {\n if (this.numVisibleLayerPortions === 0) {\n return;\n }\n const renderFlags = this.renderFlags;\n for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n const layerIndex = renderFlags.visibleLayers[i];\n const layer = this.layerList[layerIndex];\n if (layer.drawSnap) {\n frameCtx.snapPickOrigin = [0, 0, 0];\n frameCtx.snapPickCoordinateScale = [1, 1, 1];\n frameCtx.snapPickLayerNumber++;\n layer.drawSnap(renderFlags, frameCtx);\n frameCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\n origin: frameCtx.snapPickOrigin.slice(),\n coordinateScale: frameCtx.snapPickCoordinateScale.slice(),\n };\n }\n }\n }\n\n /**\n * Destroys this SceneModel.\n */\n destroy() {\n for (let layerId in this._vboBatchingLayers) {\n if (this._vboBatchingLayers.hasOwnProperty(layerId)) {\n this._vboBatchingLayers[layerId].destroy();\n }\n }\n this._vboBatchingLayers = {};\n for (let layerId in this._vboInstancingLayers) {\n if (this._vboInstancingLayers.hasOwnProperty(layerId)) {\n this._vboInstancingLayers[layerId].destroy();\n }\n }\n this._vboInstancingLayers = {};\n this.scene.camera.off(this._onCameraViewMatrix);\n this.scene.off(this._onTick);\n for (let i = 0, len = this.layerList.length; i < len; i++) {\n this.layerList[i].destroy();\n }\n this.layerList = [];\n for (let i = 0, len = this._entityList.length; i < len; i++) {\n this._entityList[i]._destroy();\n }\n // Object.entries(this._geometries).forEach(([id, geometry]) => {\n // geometry.destroy();\n // });\n this._geometries = {};\n this._dtxBuckets = {};\n this._textures = {};\n this._textureSets = {};\n this._meshes = {};\n this._entities = {};\n this.scene._aabbDirty = true;\n if (this._isModel) {\n this.scene._deregisterModel(this);\n }\n (0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.putScratchMemory)();\n super.destroy();\n }\n}\n\n\n/**\n * This function applies two steps to the provided mesh geometry data:\n *\n * - 1st, it reduces its `.positions` to unique positions, thus removing duplicate vertices. It will adjust the `.indices` and `.edgeIndices` array accordingly to the unique `.positions`.\n *\n * - 2nd, it tries to do an optimization called `index rebucketting`\n *\n * _Rebucketting minimizes the amount of RAM usage for a given mesh geometry by trying do demote its needed index bitness._\n *\n * - _for 32 bit indices, will try to demote them to 16 bit indices_\n * - _for 16 bit indices, will try to demote them to 8 bits indices_\n * - _8 bits indices are kept as-is_\n *\n * The fact that 32/16/8 bits are needed for indices, depends on the number of maximumm indexable vertices within the mesh geometry: this is, the number of vertices in the mesh geometry.\n *\n * The function returns the same provided input `geometry`, enrichened with the additional key `.preparedBukets`.\n *\n * @param {object} geometry The mesh information containing `.positions`, `.indices`, `.edgeIndices` arrays.\n *\n * @param enableVertexWelding\n * @param enableIndexBucketing\n * @returns {object} The mesh information enrichened with `.buckets` key.\n */\nfunction createDTXBuckets(geometry, enableVertexWelding, enableIndexBucketing) {\n let uniquePositionsCompressed, uniqueIndices, uniqueEdgeIndices;\n if (enableVertexWelding || enableIndexBucketing) { // Expensive - careful!\n [\n uniquePositionsCompressed,\n uniqueIndices,\n uniqueEdgeIndices,\n ] = (0,_calculateUniquePositions_js__WEBPACK_IMPORTED_MODULE_23__.uniquifyPositions)({\n positionsCompressed: geometry.positionsCompressed,\n indices: geometry.indices,\n edgeIndices: geometry.edgeIndices\n });\n } else {\n uniquePositionsCompressed = geometry.positionsCompressed;\n uniqueIndices = geometry.indices;\n uniqueEdgeIndices = geometry.edgeIndices;\n }\n let buckets;\n if (enableIndexBucketing) {\n let numUniquePositions = uniquePositionsCompressed.length / 3;\n buckets = (0,_rebucketPositions_js__WEBPACK_IMPORTED_MODULE_24__.rebucketPositions)({\n positionsCompressed: uniquePositionsCompressed,\n indices: uniqueIndices,\n edgeIndices: uniqueEdgeIndices,\n },\n (numUniquePositions > (1 << 16)) ? 16 : 8,\n // true\n );\n } else {\n buckets = [{\n positionsCompressed: uniquePositionsCompressed,\n indices: uniqueIndices,\n edgeIndices: uniqueEdgeIndices,\n }];\n }\n return buckets;\n}\n\nfunction\n\ncreateGeometryOBB(geometry) {\n geometry.obb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3();\n if (geometry.positionsCompressed && geometry.positionsCompressed.length > 0) {\n const localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positionsCompressed);\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n } else if (geometry.positions && geometry.positions.length > 0) {\n const localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positions);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n } else if (geometry.buckets) {\n const localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n for (let i = 0, len = geometry.buckets.length; i < len; i++) {\n const bucket = geometry.buckets[i];\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, bucket.positionsCompressed);\n }\n _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n }\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/SceneModel.js?");
|
|
3528
3528
|
|
|
3529
3529
|
/***/ }),
|
|
3530
3530
|
|
|
@@ -3654,7 +3654,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3654
3654
|
\*****************************************************************/
|
|
3655
3655
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3656
3656
|
|
|
3657
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ dataTextureRamStats: () => (/* binding */ dataTextureRamStats)\n/* harmony export */ });\nconst dataTextureRamStats = {\
|
|
3657
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ dataTextureRamStats: () => (/* binding */ dataTextureRamStats)\n/* harmony export */ });\nconst dataTextureRamStats = {\n sizeDataColorsAndFlags: 0,\n sizeDataPositionDecodeMatrices: 0,\n sizeDataTextureOffsets: 0,\n sizeDataTexturePositions: 0,\n sizeDataTextureIndices: 0,\n sizeDataTexturePortionIds: 0,\n numberOfGeometries: 0,\n numberOfPortions: 0,\n numberOfLayers: 0,\n numberOfTextures: 0,\n totalLines: 0,\n totalLines8Bits: 0,\n totalLines16Bits: 0,\n totalLines32Bits: 0,\n cannotCreatePortion: {\n because10BitsObjectId: 0,\n becauseTextureSize: 0,\n },\n overheadSizeAlignementIndices: 0,\n overheadSizeAlignementEdgeIndices: 0,\n};\n\nwindow.printDataTextureRamStats = function () {\n\n console.log(JSON.stringify(dataTextureRamStats, null, 4));\n\n let totalRamSize = 0;\n\n Object.keys(dataTextureRamStats).forEach(key => {\n if (key.startsWith(\"size\")) {\n totalRamSize += dataTextureRamStats[key];\n }\n });\n\n console.log(`Total size ${totalRamSize} bytes (${(totalRamSize / 1000 / 1000).toFixed(2)} MB)`);\n console.log(`Avg bytes / triangle: ${(totalRamSize / dataTextureRamStats.totalLines).toFixed(2)}`);\n\n let percentualRamStats = {};\n\n Object.keys(dataTextureRamStats).forEach(key => {\n if (key.startsWith(\"size\")) {\n percentualRamStats[key] =\n `${(dataTextureRamStats[key] / totalRamSize * 100).toFixed(2)} % of total`;\n }\n });\n\n console.log(JSON.stringify({percentualRamUsage: percentualRamStats}, null, 4));\n};\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/dtx/lines/dataTextureRamStats.js?");
|
|
3658
3658
|
|
|
3659
3659
|
/***/ }),
|
|
3660
3660
|
|
|
@@ -3724,7 +3724,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3724
3724
|
\*************************************************************************/
|
|
3725
3725
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3726
3726
|
|
|
3727
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ dataTextureRamStats: () => (/* binding */ dataTextureRamStats)\n/* harmony export */ });\nconst dataTextureRamStats = {\
|
|
3727
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ dataTextureRamStats: () => (/* binding */ dataTextureRamStats)\n/* harmony export */ });\nconst dataTextureRamStats = {\n sizeDataColorsAndFlags: 0,\n sizeDataPositionDecodeMatrices: 0,\n sizeDataTextureOffsets: 0,\n sizeDataTexturePositions: 0,\n sizeDataTextureIndices: 0,\n sizeDataTextureEdgeIndices: 0,\n sizeDataTexturePortionIds: 0,\n numberOfGeometries: 0,\n numberOfPortions: 0,\n numberOfLayers: 0,\n numberOfTextures: 0,\n totalPolygons: 0,\n totalPolygons8Bits: 0,\n totalPolygons16Bits: 0,\n totalPolygons32Bits: 0,\n totalEdges: 0,\n totalEdges8Bits: 0,\n totalEdges16Bits: 0,\n totalEdges32Bits: 0,\n cannotCreatePortion: {\n because10BitsObjectId: 0,\n becauseTextureSize: 0,\n },\n overheadSizeAlignementIndices: 0,\n overheadSizeAlignementEdgeIndices: 0,\n};\n\nwindow.printDataTextureRamStats = function () {\n\n console.log(JSON.stringify(dataTextureRamStats, null, 4));\n\n let totalRamSize = 0;\n\n Object.keys(dataTextureRamStats).forEach(key => {\n if (key.startsWith(\"size\")) {\n totalRamSize += dataTextureRamStats[key];\n }\n });\n\n console.log(`Total size ${totalRamSize} bytes (${(totalRamSize / 1000 / 1000).toFixed(2)} MB)`);\n console.log(`Avg bytes / triangle: ${(totalRamSize / dataTextureRamStats.totalPolygons).toFixed(2)}`);\n\n let percentualRamStats = {};\n\n Object.keys(dataTextureRamStats).forEach(key => {\n if (key.startsWith(\"size\")) {\n percentualRamStats[key] =\n `${(dataTextureRamStats[key] / totalRamSize * 100).toFixed(2)} % of total`;\n }\n });\n\n console.log(JSON.stringify({percentualRamUsage: percentualRamStats}, null, 4));\n};\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/dtx/triangles/lib/dataTextureRamStats.js?");
|
|
3728
3728
|
|
|
3729
3729
|
/***/ }),
|
|
3730
3730
|
|
|
@@ -4884,7 +4884,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4884
4884
|
\***********************************/
|
|
4885
4885
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4886
4886
|
|
|
4887
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ utils: () => (/* binding */ utils)\n/* harmony export */ });\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./src/viewer/scene/core.js\");\n/**\r\n * @private\r\n */\r\n\r\n\r\nfunction xmlToJson(node, attributeRenamer) {\r\n if (node.nodeType === node.TEXT_NODE) {\r\n var v = node.nodeValue;\r\n if (v.match(/^\\s+$/) === null) {\r\n return v;\r\n }\r\n } else if (node.nodeType === node.ELEMENT_NODE ||\r\n node.nodeType === node.DOCUMENT_NODE) {\r\n var json = {type: node.nodeName, children: []};\r\n\r\n if (node.nodeType === node.ELEMENT_NODE) {\r\n for (var j = 0; j < node.attributes.length; j++) {\r\n var attribute = node.attributes[j];\r\n var nm = attributeRenamer[attribute.nodeName] || attribute.nodeName;\r\n json[nm] = attribute.nodeValue;\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.childNodes.length; i++) {\r\n var item = node.childNodes[i];\r\n var j = xmlToJson(item, attributeRenamer);\r\n if (j) json.children.push(j);\r\n }\r\n\r\n return json;\r\n }\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction clone(ob) {\r\n return JSON.parse(JSON.stringify(ob));\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nvar guidChars = [[\"0\", 10], [\"A\", 26], [\"a\", 26], [\"_\", 1], [\"$\", 1]].map(function (a) {\r\n var li = [];\r\n var st = a[0].charCodeAt(0);\r\n var en = st + a[1];\r\n for (var i = st; i < en; ++i) {\r\n li.push(i);\r\n }\r\n return String.fromCharCode.apply(null, li);\r\n}).join(\"\");\r\n\r\n/**\r\n * @private\r\n */\r\nfunction b64(v, len) {\r\n var r = (!len || len === 4) ? [0, 6, 12, 18] : [0, 6];\r\n return r.map(function (i) {\r\n return guidChars.substr(parseInt(v / (1 << i)) % 64, 1)\r\n }).reverse().join(\"\");\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction compressGuid(g) {\r\n var bs = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30].map(function (i) {\r\n return parseInt(g.substr(i, 2), 16);\r\n });\r\n return b64(bs[0], 2) + [1, 4, 7, 10, 13].map(function (i) {\r\n return b64((bs[i] << 16) + (bs[i + 1] << 8) + bs[i + 2]);\r\n }).join(\"\");\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction findNodeOfType(m, t) {\r\n var li = [];\r\n var _ = function (n) {\r\n if (n.type === t) li.push(n);\r\n (n.children || []).forEach(function (c) {\r\n _(c);\r\n });\r\n };\r\n _(m);\r\n return li;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction timeout(dt) {\r\n return new Promise(function (resolve, reject) {\r\n setTimeout(resolve, dt);\r\n });\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction httpRequest(args) {\r\n return new Promise(function (resolve, reject) {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(args.method || \"GET\", args.url, true);\r\n xhr.onload = function (e) {\r\n if (xhr.readyState === 4) {\r\n if (xhr.status === 200) {\r\n resolve(xhr.responseXML);\r\n } else {\r\n reject(xhr.statusText);\r\n }\r\n }\r\n };\r\n xhr.send(null);\r\n });\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nconst queryString = function () {\r\n // This function is anonymous, is executed immediately and\r\n // the return value is assigned to QueryString!\r\n var query_string = {};\r\n var query = window.location.search.substring(1);\r\n var vars = query.split(\"&\");\r\n for (var i = 0; i < vars.length; i++) {\r\n var pair = vars[i].split(\"=\");\r\n // If first entry with this name\r\n if (typeof query_string[pair[0]] === \"undefined\") {\r\n query_string[pair[0]] = decodeURIComponent(pair[1]);\r\n // If second entry with this name\r\n } else if (typeof query_string[pair[0]] === \"string\") {\r\n var arr = [query_string[pair[0]], decodeURIComponent(pair[1])];\r\n query_string[pair[0]] = arr;\r\n // If third or later entry with this name\r\n } else {\r\n query_string[pair[0]].push(decodeURIComponent(pair[1]));\r\n }\r\n }\r\n return query_string;\r\n}();\r\n\r\n/**\r\n * @private\r\n */\r\nfunction loadJSON(url, ok, err) {\r\n // Avoid checking ok and err on each use.\r\n var defaultCallback = (_value) => undefined;\r\n ok = ok || defaultCallback;\r\n err = err || defaultCallback;\r\n\r\n var request = new XMLHttpRequest();\r\n request.overrideMimeType(\"application/json\");\r\n request.open('GET', url, true);\r\n request.addEventListener('load', function (event) {\r\n var response = event.target.response;\r\n if (this.status === 200) {\r\n var json;\r\n try {\r\n json = JSON.parse(response);\r\n } catch (e) {\r\n err(`utils.loadJSON(): Failed to parse JSON response - ${e}`);\r\n }\r\n ok(json);\r\n } else if (this.status === 0) {\r\n // Some browsers return HTTP Status 0 when using non-http protocol\r\n // e.g. 'file://' or 'data://'. Handle as success.\r\n console.warn('loadFile: HTTP Status 0 received.');\r\n try {\r\n ok(JSON.parse(response));\r\n } catch (e) {\r\n err(`utils.loadJSON(): Failed to parse JSON response - ${e}`);\r\n }\r\n } else {\r\n err(event);\r\n }\r\n }, false);\r\n\r\n request.addEventListener('error', function (event) {\r\n err(event);\r\n }, false);\r\n request.send(null);\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction loadArraybuffer(url, ok, err) {\r\n // Check for data: URI\r\n var defaultCallback = (_value) => undefined;\r\n ok = ok || defaultCallback;\r\n err = err || defaultCallback;\r\n const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\r\n const dataUriRegexResult = url.match(dataUriRegex);\r\n if (dataUriRegexResult) { // Safari can't handle data URIs through XMLHttpRequest\r\n const isBase64 = !!dataUriRegexResult[2];\r\n var data = dataUriRegexResult[3];\r\n data = window.decodeURIComponent(data);\r\n if (isBase64) {\r\n data = window.atob(data);\r\n }\r\n try {\r\n const buffer = new ArrayBuffer(data.length);\r\n const view = new Uint8Array(buffer);\r\n for (var i = 0; i < data.length; i++) {\r\n view[i] = data.charCodeAt(i);\r\n }\r\n _core__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(() => {\r\n ok(buffer);\r\n });\r\n } catch (error) {\r\n _core__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(() => {\r\n err(error);\r\n });\r\n }\r\n } else {\r\n const request = new XMLHttpRequest();\r\n request.open('GET', url, true);\r\n request.responseType = 'arraybuffer';\r\n request.onreadystatechange = function () {\r\n if (request.readyState === 4) {\r\n if (request.status === 200) {\r\n ok(request.response);\r\n } else {\r\n err('loadArrayBuffer error : ' + request.response);\r\n }\r\n }\r\n };\r\n request.send(null);\r\n }\r\n}\r\n\r\n/**\r\n Tests if the given object is an array\r\n @private\r\n */\r\nfunction isArray(value) {\r\n return value && !(value.propertyIsEnumerable('length')) && typeof value === 'object' && typeof value.length === 'number';\r\n}\r\n\r\n/**\r\n Tests if the given value is a string\r\n @param value\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isString(value) {\r\n return (typeof value === 'string' || value instanceof String);\r\n}\r\n\r\n/**\r\n Tests if the given value is a number\r\n @param value\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isNumeric(value) {\r\n return !isNaN(parseFloat(value)) && isFinite(value);\r\n}\r\n\r\n/**\r\n Tests if the given value is an ID\r\n @param value\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isID(value) {\r\n return utils.isString(value) || utils.isNumeric(value);\r\n}\r\n\r\n/**\r\n Tests if the given components are the same, where the components can be either IDs or instances.\r\n @param c1\r\n @param c2\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isSameComponent(c1, c2) {\r\n if (!c1 || !c2) {\r\n return false;\r\n }\r\n const id1 = (utils.isNumeric(c1) || utils.isString(c1)) ? `${c1}` : c1.id;\r\n const id2 = (utils.isNumeric(c2) || utils.isString(c2)) ? `${c2}` : c2.id;\r\n return id1 === id2;\r\n}\r\n\r\n/**\r\n Tests if the given value is a function\r\n @param value\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isFunction(value) {\r\n return (typeof value === \"function\");\r\n}\r\n\r\n/**\r\n Tests if the given value is a JavaScript JSON object, eg, ````{ foo: \"bar\" }````.\r\n @param value\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isObject(value) {\r\n const objectConstructor = {}.constructor;\r\n return (!!value && value.constructor === objectConstructor);\r\n}\r\n\r\n/** Returns a shallow copy\r\n */\r\nfunction copy(o) {\r\n return utils.apply(o, {});\r\n}\r\n\r\n/** Add properties of o to o2, overwriting them on o2 if already there\r\n */\r\nfunction apply(o, o2) {\r\n for (const name in o) {\r\n if (o.hasOwnProperty(name)) {\r\n o2[name] = o[name];\r\n }\r\n }\r\n return o2;\r\n}\r\n\r\n/**\r\n Add non-null/defined properties of o to o2\r\n @private\r\n */\r\nfunction apply2(o, o2) {\r\n for (const name in o) {\r\n if (o.hasOwnProperty(name)) {\r\n if (o[name] !== undefined && o[name] !== null) {\r\n o2[name] = o[name];\r\n }\r\n }\r\n }\r\n return o2;\r\n}\r\n\r\n/**\r\n Add properties of o to o2 where undefined or null on o2\r\n @private\r\n */\r\nfunction applyIf(o, o2) {\r\n for (const name in o) {\r\n if (o.hasOwnProperty(name)) {\r\n if (o2[name] === undefined || o2[name] === null) {\r\n o2[name] = o[name];\r\n }\r\n }\r\n }\r\n return o2;\r\n}\r\n\r\n/**\r\n Returns true if the given map is empty.\r\n @param obj\r\n @returns {Boolean}\r\n @private\r\n */\r\nfunction isEmptyObject(obj) {\r\n for (const name in obj) {\r\n if (obj.hasOwnProperty(name)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n Returns the given ID as a string, in quotes if the ID was a string to begin with.\r\n\r\n This is useful for logging IDs.\r\n\r\n @param {Number| String} id The ID\r\n @returns {String}\r\n @private\r\n */\r\nfunction inQuotes(id) {\r\n return utils.isNumeric(id) ? (`${id}`) : (`'${id}'`);\r\n}\r\n\r\n/**\r\n Returns the concatenation of two typed arrays.\r\n @param a\r\n @param b\r\n @returns {*|a}\r\n @private\r\n */\r\nfunction concat(a, b) {\r\n const c = new a.constructor(a.length + b.length);\r\n c.set(a);\r\n c.set(b, a.length);\r\n return c;\r\n}\r\n\r\nfunction flattenParentChildHierarchy(root) {\r\n var list = [];\r\n\r\n function visit(node) {\r\n node.id = node.uuid;\r\n delete node.oid;\r\n list.push(node);\r\n var children = node.children;\r\n\r\n if (children) {\r\n for (var i = 0, len = children.length; i < len; i++) {\r\n const child = children[i];\r\n child.parent = node.id;\r\n visit(children[i]);\r\n }\r\n }\r\n node.children = [];\r\n }\r\n\r\n visit(root);\r\n return list;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nconst utils = {\r\n xmlToJson: xmlToJson,\r\n clone: clone,\r\n compressGuid: compressGuid,\r\n findNodeOfType: findNodeOfType,\r\n timeout: timeout,\r\n httpRequest: httpRequest,\r\n loadJSON: loadJSON,\r\n loadArraybuffer: loadArraybuffer,\r\n queryString: queryString,\r\n isArray: isArray,\r\n isString: isString,\r\n isNumeric: isNumeric,\r\n isID: isID,\r\n isSameComponent: isSameComponent,\r\n isFunction: isFunction,\r\n isObject: isObject,\r\n copy: copy,\r\n apply: apply,\r\n apply2: apply2,\r\n applyIf: applyIf,\r\n isEmptyObject: isEmptyObject,\r\n inQuotes: inQuotes,\r\n concat: concat,\r\n flattenParentChildHierarchy: flattenParentChildHierarchy\r\n};\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/utils.js?");
|
|
4887
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ utils: () => (/* binding */ utils)\n/* harmony export */ });\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./src/viewer/scene/core.js\");\n/**\n * @private\n */\n\n\nfunction xmlToJson(node, attributeRenamer) {\n if (node.nodeType === node.TEXT_NODE) {\n var v = node.nodeValue;\n if (v.match(/^\\s+$/) === null) {\n return v;\n }\n } else if (node.nodeType === node.ELEMENT_NODE ||\n node.nodeType === node.DOCUMENT_NODE) {\n var json = {type: node.nodeName, children: []};\n\n if (node.nodeType === node.ELEMENT_NODE) {\n for (var j = 0; j < node.attributes.length; j++) {\n var attribute = node.attributes[j];\n var nm = attributeRenamer[attribute.nodeName] || attribute.nodeName;\n json[nm] = attribute.nodeValue;\n }\n }\n\n for (var i = 0; i < node.childNodes.length; i++) {\n var item = node.childNodes[i];\n var j = xmlToJson(item, attributeRenamer);\n if (j) json.children.push(j);\n }\n\n return json;\n }\n}\n\n/**\n * @private\n */\nfunction clone(ob) {\n return JSON.parse(JSON.stringify(ob));\n}\n\n/**\n * @private\n */\nvar guidChars = [[\"0\", 10], [\"A\", 26], [\"a\", 26], [\"_\", 1], [\"$\", 1]].map(function (a) {\n var li = [];\n var st = a[0].charCodeAt(0);\n var en = st + a[1];\n for (var i = st; i < en; ++i) {\n li.push(i);\n }\n return String.fromCharCode.apply(null, li);\n}).join(\"\");\n\n/**\n * @private\n */\nfunction b64(v, len) {\n var r = (!len || len === 4) ? [0, 6, 12, 18] : [0, 6];\n return r.map(function (i) {\n return guidChars.substr(parseInt(v / (1 << i)) % 64, 1)\n }).reverse().join(\"\");\n}\n\n/**\n * @private\n */\nfunction compressGuid(g) {\n var bs = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30].map(function (i) {\n return parseInt(g.substr(i, 2), 16);\n });\n return b64(bs[0], 2) + [1, 4, 7, 10, 13].map(function (i) {\n return b64((bs[i] << 16) + (bs[i + 1] << 8) + bs[i + 2]);\n }).join(\"\");\n}\n\n/**\n * @private\n */\nfunction findNodeOfType(m, t) {\n var li = [];\n var _ = function (n) {\n if (n.type === t) li.push(n);\n (n.children || []).forEach(function (c) {\n _(c);\n });\n };\n _(m);\n return li;\n}\n\n/**\n * @private\n */\nfunction timeout(dt) {\n return new Promise(function (resolve, reject) {\n setTimeout(resolve, dt);\n });\n}\n\n/**\n * @private\n */\nfunction httpRequest(args) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n xhr.open(args.method || \"GET\", args.url, true);\n xhr.onload = function (e) {\n if (xhr.readyState === 4) {\n if (xhr.status === 200) {\n resolve(xhr.responseXML);\n } else {\n reject(xhr.statusText);\n }\n }\n };\n xhr.send(null);\n });\n}\n\n/**\n * @private\n */\nconst queryString = function () {\n // This function is anonymous, is executed immediately and\n // the return value is assigned to QueryString!\n var query_string = {};\n var query = window.location.search.substring(1);\n var vars = query.split(\"&\");\n for (var i = 0; i < vars.length; i++) {\n var pair = vars[i].split(\"=\");\n // If first entry with this name\n if (typeof query_string[pair[0]] === \"undefined\") {\n query_string[pair[0]] = decodeURIComponent(pair[1]);\n // If second entry with this name\n } else if (typeof query_string[pair[0]] === \"string\") {\n var arr = [query_string[pair[0]], decodeURIComponent(pair[1])];\n query_string[pair[0]] = arr;\n // If third or later entry with this name\n } else {\n query_string[pair[0]].push(decodeURIComponent(pair[1]));\n }\n }\n return query_string;\n}();\n\n/**\n * @private\n */\nfunction loadJSON(url, ok, err) {\n // Avoid checking ok and err on each use.\n var defaultCallback = (_value) => undefined;\n ok = ok || defaultCallback;\n err = err || defaultCallback;\n\n var request = new XMLHttpRequest();\n request.overrideMimeType(\"application/json\");\n request.open('GET', url, true);\n request.addEventListener('load', function (event) {\n var response = event.target.response;\n if (this.status === 200) {\n var json;\n try {\n json = JSON.parse(response);\n } catch (e) {\n err(`utils.loadJSON(): Failed to parse JSON response - ${e}`);\n }\n ok(json);\n } else if (this.status === 0) {\n // Some browsers return HTTP Status 0 when using non-http protocol\n // e.g. 'file://' or 'data://'. Handle as success.\n console.warn('loadFile: HTTP Status 0 received.');\n try {\n ok(JSON.parse(response));\n } catch (e) {\n err(`utils.loadJSON(): Failed to parse JSON response - ${e}`);\n }\n } else {\n err(event);\n }\n }, false);\n\n request.addEventListener('error', function (event) {\n err(event);\n }, false);\n request.send(null);\n}\n\n/**\n * @private\n */\nfunction loadArraybuffer(url, ok, err) {\n // Check for data: URI\n var defaultCallback = (_value) => undefined;\n ok = ok || defaultCallback;\n err = err || defaultCallback;\n const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\n const dataUriRegexResult = url.match(dataUriRegex);\n if (dataUriRegexResult) { // Safari can't handle data URIs through XMLHttpRequest\n const isBase64 = !!dataUriRegexResult[2];\n var data = dataUriRegexResult[3];\n data = window.decodeURIComponent(data);\n if (isBase64) {\n data = window.atob(data);\n }\n try {\n const buffer = new ArrayBuffer(data.length);\n const view = new Uint8Array(buffer);\n for (var i = 0; i < data.length; i++) {\n view[i] = data.charCodeAt(i);\n }\n _core__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(() => {\n ok(buffer);\n });\n } catch (error) {\n _core__WEBPACK_IMPORTED_MODULE_0__.core.scheduleTask(() => {\n err(error);\n });\n }\n } else {\n const request = new XMLHttpRequest();\n request.open('GET', url, true);\n request.responseType = 'arraybuffer';\n request.onreadystatechange = function () {\n if (request.readyState === 4) {\n if (request.status === 200) {\n ok(request.response);\n } else {\n err('loadArrayBuffer error : ' + request.response);\n }\n }\n };\n request.send(null);\n }\n}\n\n/**\n Tests if the given object is an array\n @private\n */\nfunction isArray(value) {\n return value && !(value.propertyIsEnumerable('length')) && typeof value === 'object' && typeof value.length === 'number';\n}\n\n/**\n Tests if the given value is a string\n @param value\n @returns {Boolean}\n @private\n */\nfunction isString(value) {\n return (typeof value === 'string' || value instanceof String);\n}\n\n/**\n Tests if the given value is a number\n @param value\n @returns {Boolean}\n @private\n */\nfunction isNumeric(value) {\n return !isNaN(parseFloat(value)) && isFinite(value);\n}\n\n/**\n Tests if the given value is an ID\n @param value\n @returns {Boolean}\n @private\n */\nfunction isID(value) {\n return utils.isString(value) || utils.isNumeric(value);\n}\n\n/**\n Tests if the given components are the same, where the components can be either IDs or instances.\n @param c1\n @param c2\n @returns {Boolean}\n @private\n */\nfunction isSameComponent(c1, c2) {\n if (!c1 || !c2) {\n return false;\n }\n const id1 = (utils.isNumeric(c1) || utils.isString(c1)) ? `${c1}` : c1.id;\n const id2 = (utils.isNumeric(c2) || utils.isString(c2)) ? `${c2}` : c2.id;\n return id1 === id2;\n}\n\n/**\n Tests if the given value is a function\n @param value\n @returns {Boolean}\n @private\n */\nfunction isFunction(value) {\n return (typeof value === \"function\");\n}\n\n/**\n Tests if the given value is a JavaScript JSON object, eg, ````{ foo: \"bar\" }````.\n @param value\n @returns {Boolean}\n @private\n */\nfunction isObject(value) {\n const objectConstructor = {}.constructor;\n return (!!value && value.constructor === objectConstructor);\n}\n\n/** Returns a shallow copy\n */\nfunction copy(o) {\n return utils.apply(o, {});\n}\n\n/** Add properties of o to o2, overwriting them on o2 if already there\n */\nfunction apply(o, o2) {\n for (const name in o) {\n if (o.hasOwnProperty(name)) {\n o2[name] = o[name];\n }\n }\n return o2;\n}\n\n/**\n Add non-null/defined properties of o to o2\n @private\n */\nfunction apply2(o, o2) {\n for (const name in o) {\n if (o.hasOwnProperty(name)) {\n if (o[name] !== undefined && o[name] !== null) {\n o2[name] = o[name];\n }\n }\n }\n return o2;\n}\n\n/**\n Add properties of o to o2 where undefined or null on o2\n @private\n */\nfunction applyIf(o, o2) {\n for (const name in o) {\n if (o.hasOwnProperty(name)) {\n if (o2[name] === undefined || o2[name] === null) {\n o2[name] = o[name];\n }\n }\n }\n return o2;\n}\n\n/**\n Returns true if the given map is empty.\n @param obj\n @returns {Boolean}\n @private\n */\nfunction isEmptyObject(obj) {\n for (const name in obj) {\n if (obj.hasOwnProperty(name)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n Returns the given ID as a string, in quotes if the ID was a string to begin with.\n\n This is useful for logging IDs.\n\n @param {Number| String} id The ID\n @returns {String}\n @private\n */\nfunction inQuotes(id) {\n return utils.isNumeric(id) ? (`${id}`) : (`'${id}'`);\n}\n\n/**\n Returns the concatenation of two typed arrays.\n @param a\n @param b\n @returns {*|a}\n @private\n */\nfunction concat(a, b) {\n const c = new a.constructor(a.length + b.length);\n c.set(a);\n c.set(b, a.length);\n return c;\n}\n\nfunction flattenParentChildHierarchy(root) {\n var list = [];\n\n function visit(node) {\n node.id = node.uuid;\n delete node.oid;\n list.push(node);\n var children = node.children;\n\n if (children) {\n for (var i = 0, len = children.length; i < len; i++) {\n const child = children[i];\n child.parent = node.id;\n visit(children[i]);\n }\n }\n node.children = [];\n }\n\n visit(root);\n return list;\n}\n\n/**\n * @private\n */\nconst utils = {\n xmlToJson: xmlToJson,\n clone: clone,\n compressGuid: compressGuid,\n findNodeOfType: findNodeOfType,\n timeout: timeout,\n httpRequest: httpRequest,\n loadJSON: loadJSON,\n loadArraybuffer: loadArraybuffer,\n queryString: queryString,\n isArray: isArray,\n isString: isString,\n isNumeric: isNumeric,\n isID: isID,\n isSameComponent: isSameComponent,\n isFunction: isFunction,\n isObject: isObject,\n copy: copy,\n apply: apply,\n apply2: apply2,\n applyIf: applyIf,\n isEmptyObject: isEmptyObject,\n inQuotes: inQuotes,\n concat: concat,\n flattenParentChildHierarchy: flattenParentChildHierarchy\n};\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/utils.js?");
|
|
4888
4888
|
|
|
4889
4889
|
/***/ }),
|
|
4890
4890
|
|
|
@@ -5204,7 +5204,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
5204
5204
|
\*******************************************************************/
|
|
5205
5205
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5206
5206
|
|
|
5207
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SAODepthLimitedBlurRenderer: () => (/* binding */ SAODepthLimitedBlurRenderer)\n/* harmony export */ });\n/* harmony import */ var _Program_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n\r\n\r\n\r\n\r\n\r\nconst blurStdDev = 4;\r\nconst blurDepthCutoff = 0.01;\r\nconst KERNEL_RADIUS = 100;\r\n\r\nconst sampleOffsetsVert = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [0, 1]));\r\nconst sampleOffsetsHor = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [1, 0]));\r\nconst sampleWeights = new Float32Array(createSampleWeights(KERNEL_RADIUS + 1, blurStdDev));\r\n\r\nconst tempVec2a = new Float32Array(2);\r\n\r\n/**\r\n * SAO implementation inspired from previous SAO work in THREE.js by ludobaka / ludobaka.github.io and bhouston\r\n * @private\r\n */\r\nclass SAODepthLimitedBlurRenderer {\r\n\tconstructor(scene) {\r\n\t\tthis._scene = scene;\r\n\r\n\t\t// The program\r\n\r\n\t\tthis._program = null;\r\n\t\tthis._programError = false;\r\n\r\n\t\t// Variable locations\r\n\r\n\t\tthis._aPosition = null;\r\n\t\tthis._aUV = null;\r\n\r\n\t\tthis._uDepthTexture = \"uDepthTexture\";\r\n\t\tthis._uOcclusionTexture = \"uOcclusionTexture\";\r\n\r\n\t\tthis._uViewport = null;\r\n\t\tthis._uCameraNear = null;\r\n\t\tthis._uCameraFar = null;\r\n\t\tthis._uCameraProjectionMatrix = null;\r\n\t\tthis._uCameraInverseProjectionMatrix = null;\r\n\r\n\t\t// VBOs\r\n\r\n\t\tthis._uvBuf = null;\r\n\t\tthis._positionsBuf = null;\r\n\t\tthis._indicesBuf = null;\r\n\r\n\t\tthis.init();\r\n\t}\r\n\r\n\tinit() {\r\n\t\t// Create program & VBOs, locate attributes and uniforms\r\n\r\n\t\tconst gl = this._scene.canvas.gl;\r\n\r\n\t\tthis._program = new _Program_js__WEBPACK_IMPORTED_MODULE_0__.Program(gl, {\r\n\t\t\tvertex: [\r\n\t\t\t\t`#version 300 es\r\n precision highp float;\r\n precision highp int;\r\n \r\n in vec3 aPosition;\r\n in vec2 aUV;\r\n uniform vec2 uViewport;\r\n out vec2 vUV;\r\n out vec2 vInvSize;\r\n void main () {\r\n vUV = aUV;\r\n vInvSize = 1.0 / uViewport;\r\n gl_Position = vec4(aPosition, 1.0);\r\n }`\r\n\t\t\t],\r\n\r\n\t\t\tfragment: [\r\n\t\t\t\t`#version 300 es\r\n precision highp float;\r\n precision highp int;\r\n \r\n #define PI 3.14159265359\r\n #define PI2 6.28318530718\r\n #define EPSILON 1e-6\r\n\r\n #define KERNEL_RADIUS ${KERNEL_RADIUS}\r\n\r\n in vec2 vUV;\r\n in vec2 vInvSize;\r\n \r\n uniform sampler2D uDepthTexture;\r\n uniform sampler2D uOcclusionTexture; \r\n \r\n uniform float uCameraNear;\r\n uniform float uCameraFar; \r\n uniform float uDepthCutoff;\r\n\r\n uniform vec2 uSampleOffsets[ KERNEL_RADIUS + 1 ];\r\n uniform float uSampleWeights[ KERNEL_RADIUS + 1 ];\r\n\r\n const float unpackDownscale = 255. / 256.; \r\n\r\n const vec3 packFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\r\n const vec4 unpackFactors = unpackDownscale / vec4( packFactors, 1. ); \r\n\r\n const float packUpscale = 256. / 255.;\r\n \r\n const float shiftRights = 1. / 256.;\r\n \r\n float unpackRGBAToFloat( const in vec4 v ) {\r\n return dot( floor( v * 255.0 + 0.5 ) / 255.0, unpackFactors );\r\n } \r\n\r\n vec4 packFloatToRGBA( const in float v ) {\r\n vec4 r = vec4( fract( v * packFactors ), v );\r\n r.yzw -= r.xyz * shiftRights; \r\n return r * packUpscale;\r\n }\r\n\r\n float viewZToOrthographicDepth( const in float viewZ) {\r\n return ( viewZ + uCameraNear ) / ( uCameraNear - uCameraFar );\r\n }\r\n \r\n float orthographicDepthToViewZ( const in float linearClipZ) {\r\n return linearClipZ * ( uCameraNear - uCameraFar ) - uCameraNear;\r\n }\r\n\r\n float viewZToPerspectiveDepth( const in float viewZ) {\r\n return (( uCameraNear + viewZ ) * uCameraFar ) / (( uCameraFar - uCameraNear ) * viewZ );\r\n }\r\n \r\n float perspectiveDepthToViewZ( const in float invClipZ) {\r\n return ( uCameraNear * uCameraFar ) / ( ( uCameraFar - uCameraNear ) * invClipZ - uCameraFar );\r\n }\r\n\r\n float getDepth( const in vec2 screenPosition ) {\r\n return vec4(texture(uDepthTexture, screenPosition)).r;\r\n }\r\n\r\n float getViewZ( const in float depth ) {\r\n return perspectiveDepthToViewZ( depth );\r\n }\r\n\r\n out vec4 outColor;\r\n \r\n void main() {\r\n \r\n float depth = getDepth( vUV );\r\n if( depth >= ( 1.0 - EPSILON ) ) {\r\n discard;\r\n }\r\n\r\n float centerViewZ = -getViewZ( depth );\r\n bool rBreak = false;\r\n bool lBreak = false;\r\n\r\n float weightSum = uSampleWeights[0];\r\n float occlusionSum = unpackRGBAToFloat(texture( uOcclusionTexture, vUV )) * weightSum;\r\n\r\n for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {\r\n\r\n float sampleWeight = uSampleWeights[i];\r\n vec2 sampleUVOffset = uSampleOffsets[i] * vInvSize;\r\n\r\n vec2 sampleUV = vUV + sampleUVOffset;\r\n float viewZ = -getViewZ( getDepth( sampleUV ) );\r\n\r\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\r\n rBreak = true;\r\n }\r\n\r\n if( ! rBreak ) {\r\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\r\n weightSum += sampleWeight;\r\n }\r\n\r\n sampleUV = vUV - sampleUVOffset;\r\n viewZ = -getViewZ( getDepth( sampleUV ) );\r\n\r\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\r\n lBreak = true;\r\n }\r\n\r\n if( ! lBreak ) {\r\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\r\n weightSum += sampleWeight;\r\n }\r\n }\r\n\r\n outColor = packFloatToRGBA(occlusionSum / weightSum);\r\n }`\r\n\t\t\t]\r\n\t\t});\r\n\r\n\t\tif (this._program.errors) {\r\n\t\t\tconsole.error(this._program.errors.join(\"\\n\"));\r\n\t\t\tthis._programError = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst uv = new Float32Array([1, 1, 0, 1, 0, 0, 1, 0]);\r\n\t\tconst positions = new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]);\r\n\r\n\t\t// Mitigation: if Uint8Array is used, the geometry is corrupted on OSX when using Chrome with data-textures\r\n\t\tconst indices = new Uint32Array([0, 1, 2, 0, 2, 3]);\r\n\r\n\t\tthis._positionsBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, positions, positions.length, 3, gl.STATIC_DRAW);\r\n\t\tthis._uvBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, uv, uv.length, 2, gl.STATIC_DRAW);\r\n\t\tthis._indicesBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, indices.length, 1, gl.STATIC_DRAW);\r\n\r\n\t\tthis._program.bind();\r\n\r\n\t\tthis._uViewport = this._program.getLocation(\"uViewport\");\r\n\r\n\t\tthis._uCameraNear = this._program.getLocation(\"uCameraNear\");\r\n\t\tthis._uCameraFar = this._program.getLocation(\"uCameraFar\");\r\n\r\n\t\tthis._uDepthCutoff = this._program.getLocation(\"uDepthCutoff\");\r\n\r\n\t\tthis._uSampleOffsets = gl.getUniformLocation(this._program.handle, \"uSampleOffsets\");\r\n\t\tthis._uSampleWeights = gl.getUniformLocation(this._program.handle, \"uSampleWeights\");\r\n\r\n\t\tthis._aPosition = this._program.getAttribute(\"aPosition\");\r\n\t\tthis._aUV = this._program.getAttribute(\"aUV\");\r\n\t}\r\n\r\n\trender(depthRenderBuffer, occlusionRenderBuffer, direction) {\r\n\t\tif (this._programError) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!this._getInverseProjectMat) {\r\n\t\t\t// HACK: scene.camera not defined until render time\r\n\t\t\tthis._getInverseProjectMat = (() => {\r\n\t\t\t\tlet projMatDirty = true;\r\n\t\t\t\tthis._scene.camera.on(\"projMatrix\", function () {\r\n\t\t\t\t\tprojMatDirty = true;\r\n\t\t\t\t});\r\n\t\t\t\tconst inverseProjectMat = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\r\n\t\t\t\treturn () => {\r\n\t\t\t\t\tif (projMatDirty) {\r\n\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(scene.camera.projMatrix, inverseProjectMat);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn inverseProjectMat;\r\n\t\t\t\t};\r\n\t\t\t})();\r\n\t\t}\r\n\r\n\t\tconst gl = this._scene.canvas.gl;\r\n\t\tconst program = this._program;\r\n\t\tconst scene = this._scene;\r\n\t\tconst viewportWidth = gl.drawingBufferWidth;\r\n\t\tconst viewportHeight = gl.drawingBufferHeight;\r\n\t\tconst projectState = scene.camera.project._state;\r\n\t\tconst near = projectState.near;\r\n\t\tconst far = projectState.far;\r\n\r\n\t\tgl.viewport(0, 0, viewportWidth, viewportHeight);\r\n\t\tgl.clearColor(0, 0, 0, 1);\r\n\t\tgl.enable(gl.DEPTH_TEST);\r\n\t\tgl.disable(gl.BLEND);\r\n\t\tgl.frontFace(gl.CCW);\r\n\t\tgl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\r\n\r\n\t\tprogram.bind();\r\n\r\n\t\ttempVec2a[0] = viewportWidth;\r\n\t\ttempVec2a[1] = viewportHeight;\r\n\r\n\t\tgl.uniform2fv(this._uViewport, tempVec2a);\r\n\t\tgl.uniform1f(this._uCameraNear, near);\r\n\t\tgl.uniform1f(this._uCameraFar, far);\r\n\r\n\t\tgl.uniform1f(this._uDepthCutoff, blurDepthCutoff);\r\n\r\n\t\tif (direction === 0) {\r\n\t\t\t// Horizontal\r\n\t\t\tgl.uniform2fv(this._uSampleOffsets, sampleOffsetsHor);\r\n\t\t} else {\r\n\t\t\t// Vertical\r\n\t\t\tgl.uniform2fv(this._uSampleOffsets, sampleOffsetsVert);\r\n\t\t}\r\n\r\n\t\tgl.uniform1fv(this._uSampleWeights, sampleWeights);\r\n\r\n\t\tconst depthTexture = depthRenderBuffer.getDepthTexture();\r\n\t\tconst occlusionTexture = occlusionRenderBuffer.getTexture();\r\n\r\n\t\tprogram.bindTexture(this._uDepthTexture, depthTexture, 0); // TODO: use FrameCtx.textureUnit\r\n\t\tprogram.bindTexture(this._uOcclusionTexture, occlusionTexture, 1);\r\n\r\n\t\tthis._aUV.bindArrayBuffer(this._uvBuf);\r\n\t\tthis._aPosition.bindArrayBuffer(this._positionsBuf);\r\n\t\tthis._indicesBuf.bind();\r\n\r\n\t\tgl.drawElements(gl.TRIANGLES, this._indicesBuf.numItems, this._indicesBuf.itemType, 0);\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tthis._program.destroy();\r\n\t}\r\n}\r\n\r\nfunction createSampleWeights(kernelRadius, stdDev) {\r\n\tconst weights = [];\r\n\tfor (let i = 0; i <= kernelRadius; i++) {\r\n\t\tweights.push(gaussian(i, stdDev));\r\n\t}\r\n\treturn weights; // TODO: Optimize\r\n}\r\n\r\nfunction gaussian(x, stdDev) {\r\n\treturn Math.exp(-(x * x) / (2.0 * (stdDev * stdDev))) / (Math.sqrt(2.0 * Math.PI) * stdDev);\r\n}\r\n\r\nfunction createSampleOffsets(kernelRadius, uvIncrement) {\r\n\tconst offsets = [];\r\n\tfor (let i = 0; i <= kernelRadius; i++) {\r\n\t\toffsets.push(uvIncrement[0] * i);\r\n\t\toffsets.push(uvIncrement[1] * i);\r\n\t}\r\n\treturn offsets;\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js?");
|
|
5207
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SAODepthLimitedBlurRenderer: () => (/* binding */ SAODepthLimitedBlurRenderer)\n/* harmony export */ });\n/* harmony import */ var _Program_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n\n\n\n\n\nconst blurStdDev = 4;\nconst blurDepthCutoff = 0.01;\nconst KERNEL_RADIUS = 16;\n\nconst sampleOffsetsVert = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [0, 1]));\nconst sampleOffsetsHor = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [1, 0]));\nconst sampleWeights = new Float32Array(createSampleWeights(KERNEL_RADIUS + 1, blurStdDev));\n\nconst tempVec2a = new Float32Array(2);\n\n/**\n * SAO implementation inspired from previous SAO work in THREE.js by ludobaka / ludobaka.github.io and bhouston\n * @private\n */\nclass SAODepthLimitedBlurRenderer {\n\n constructor(scene) {\n\n this._scene = scene;\n\n // The program\n\n this._program = null;\n this._programError = false;\n\n // Variable locations\n\n this._aPosition = null;\n this._aUV = null;\n\n this._uDepthTexture = \"uDepthTexture\";\n this._uOcclusionTexture = \"uOcclusionTexture\";\n\n this._uViewport = null;\n this._uCameraNear = null;\n this._uCameraFar = null;\n this._uCameraProjectionMatrix = null;\n this._uCameraInverseProjectionMatrix = null;\n\n // VBOs\n\n this._uvBuf = null;\n this._positionsBuf = null;\n this._indicesBuf = null;\n\n this.init();\n }\n\n init() {\n\n // Create program & VBOs, locate attributes and uniforms\n\n const gl = this._scene.canvas.gl;\n\n this._program = new _Program_js__WEBPACK_IMPORTED_MODULE_0__.Program(gl, {\n\n vertex: [\n `#version 300 es\n precision highp float;\n precision highp int;\n \n in vec3 aPosition;\n in vec2 aUV;\n uniform vec2 uViewport;\n out vec2 vUV;\n out vec2 vInvSize;\n void main () {\n vUV = aUV;\n vInvSize = 1.0 / uViewport;\n gl_Position = vec4(aPosition, 1.0);\n }`],\n\n fragment: [\n `#version 300 es\n precision highp float;\n precision highp int;\n \n #define PI 3.14159265359\n #define PI2 6.28318530718\n #define EPSILON 1e-6\n\n #define KERNEL_RADIUS ${KERNEL_RADIUS}\n\n in vec2 vUV;\n in vec2 vInvSize;\n \n uniform sampler2D uDepthTexture;\n uniform sampler2D uOcclusionTexture; \n \n uniform float uCameraNear;\n uniform float uCameraFar; \n uniform float uDepthCutoff;\n\n uniform vec2 uSampleOffsets[ KERNEL_RADIUS + 1 ];\n uniform float uSampleWeights[ KERNEL_RADIUS + 1 ];\n\n const float unpackDownscale = 255. / 256.; \n\n const vec3 packFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\n const vec4 unpackFactors = unpackDownscale / vec4( packFactors, 1. ); \n\n const float packUpscale = 256. / 255.;\n \n const float shiftRights = 1. / 256.;\n \n float unpackRGBAToFloat( const in vec4 v ) {\n return dot( floor( v * 255.0 + 0.5 ) / 255.0, unpackFactors );\n } \n\n vec4 packFloatToRGBA( const in float v ) {\n vec4 r = vec4( fract( v * packFactors ), v );\n r.yzw -= r.xyz * shiftRights; \n return r * packUpscale;\n }\n\n float viewZToOrthographicDepth( const in float viewZ) {\n return ( viewZ + uCameraNear ) / ( uCameraNear - uCameraFar );\n }\n \n float orthographicDepthToViewZ( const in float linearClipZ) {\n return linearClipZ * ( uCameraNear - uCameraFar ) - uCameraNear;\n }\n\n float viewZToPerspectiveDepth( const in float viewZ) {\n return (( uCameraNear + viewZ ) * uCameraFar ) / (( uCameraFar - uCameraNear ) * viewZ );\n }\n \n float perspectiveDepthToViewZ( const in float invClipZ) {\n return ( uCameraNear * uCameraFar ) / ( ( uCameraFar - uCameraNear ) * invClipZ - uCameraFar );\n }\n\n float getDepth( const in vec2 screenPosition ) {\n return vec4(texture(uDepthTexture, screenPosition)).r;\n }\n\n float getViewZ( const in float depth ) {\n return perspectiveDepthToViewZ( depth );\n }\n\n out vec4 outColor;\n \n void main() {\n \n float depth = getDepth( vUV );\n if( depth >= ( 1.0 - EPSILON ) ) {\n discard;\n }\n\n float centerViewZ = -getViewZ( depth );\n bool rBreak = false;\n bool lBreak = false;\n\n float weightSum = uSampleWeights[0];\n float occlusionSum = unpackRGBAToFloat(texture( uOcclusionTexture, vUV )) * weightSum;\n\n for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {\n\n float sampleWeight = uSampleWeights[i];\n vec2 sampleUVOffset = uSampleOffsets[i] * vInvSize;\n\n vec2 sampleUV = vUV + sampleUVOffset;\n float viewZ = -getViewZ( getDepth( sampleUV ) );\n\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\n rBreak = true;\n }\n\n if( ! rBreak ) {\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\n weightSum += sampleWeight;\n }\n\n sampleUV = vUV - sampleUVOffset;\n viewZ = -getViewZ( getDepth( sampleUV ) );\n\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\n lBreak = true;\n }\n\n if( ! lBreak ) {\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\n weightSum += sampleWeight;\n }\n }\n\n outColor = packFloatToRGBA(occlusionSum / weightSum);\n }`\n ]\n });\n\n if (this._program.errors) {\n console.error(this._program.errors.join(\"\\n\"));\n this._programError = true;\n return;\n }\n\n const uv = new Float32Array([1, 1, 0, 1, 0, 0, 1, 0]);\n const positions = new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]);\n\n // Mitigation: if Uint8Array is used, the geometry is corrupted on OSX when using Chrome with data-textures\n const indices = new Uint32Array([0, 1, 2, 0, 2, 3]);\n\n this._positionsBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, positions, positions.length, 3, gl.STATIC_DRAW);\n this._uvBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, uv, uv.length, 2, gl.STATIC_DRAW);\n this._indicesBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, indices.length, 1, gl.STATIC_DRAW);\n\n this._program.bind();\n\n this._uViewport = this._program.getLocation(\"uViewport\");\n\n this._uCameraNear = this._program.getLocation(\"uCameraNear\");\n this._uCameraFar = this._program.getLocation(\"uCameraFar\");\n\n this._uDepthCutoff = this._program.getLocation(\"uDepthCutoff\");\n\n this._uSampleOffsets = gl.getUniformLocation(this._program.handle, \"uSampleOffsets\");\n this._uSampleWeights = gl.getUniformLocation(this._program.handle, \"uSampleWeights\");\n\n this._aPosition = this._program.getAttribute(\"aPosition\");\n this._aUV = this._program.getAttribute(\"aUV\");\n }\n\n render(depthRenderBuffer, occlusionRenderBuffer, direction) {\n\n if (this._programError) {\n return;\n }\n\n if (!this._getInverseProjectMat) { // HACK: scene.camera not defined until render time\n this._getInverseProjectMat = (() => {\n let projMatDirty = true;\n this._scene.camera.on(\"projMatrix\", function () {\n projMatDirty = true;\n });\n const inverseProjectMat = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\n return () => {\n if (projMatDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(scene.camera.projMatrix, inverseProjectMat);\n }\n return inverseProjectMat;\n }\n })();\n }\n\n const gl = this._scene.canvas.gl;\n const program = this._program;\n const scene = this._scene;\n const viewportWidth = gl.drawingBufferWidth;\n const viewportHeight = gl.drawingBufferHeight;\n const projectState = scene.camera.project._state;\n const near = projectState.near;\n const far = projectState.far;\n\n gl.viewport(0, 0, viewportWidth, viewportHeight);\n gl.clearColor(0, 0, 0, 1);\n gl.enable(gl.DEPTH_TEST);\n gl.disable(gl.BLEND);\n gl.frontFace(gl.CCW);\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\n\n program.bind();\n\n tempVec2a[0] = viewportWidth;\n tempVec2a[1] = viewportHeight;\n\n gl.uniform2fv(this._uViewport, tempVec2a);\n gl.uniform1f(this._uCameraNear, near);\n gl.uniform1f(this._uCameraFar, far);\n\n gl.uniform1f(this._uDepthCutoff, blurDepthCutoff);\n\n if (direction === 0) {// Horizontal\n gl.uniform2fv(this._uSampleOffsets, sampleOffsetsHor);\n } else { // Vertical\n gl.uniform2fv(this._uSampleOffsets, sampleOffsetsVert);\n }\n\n gl.uniform1fv(this._uSampleWeights, sampleWeights);\n\n const depthTexture = depthRenderBuffer.getDepthTexture();\n const occlusionTexture = occlusionRenderBuffer.getTexture();\n\n program.bindTexture(this._uDepthTexture, depthTexture, 0); // TODO: use FrameCtx.textureUnit\n program.bindTexture(this._uOcclusionTexture, occlusionTexture, 1);\n\n this._aUV.bindArrayBuffer(this._uvBuf);\n this._aPosition.bindArrayBuffer(this._positionsBuf);\n this._indicesBuf.bind();\n\n gl.drawElements(gl.TRIANGLES, this._indicesBuf.numItems, this._indicesBuf.itemType, 0);\n }\n\n destroy() {\n this._program.destroy();\n }\n}\n\nfunction createSampleWeights(kernelRadius, stdDev) {\n const weights = [];\n for (let i = 0; i <= kernelRadius; i++) {\n weights.push(gaussian(i, stdDev));\n }\n return weights; // TODO: Optimize\n}\n\nfunction gaussian(x, stdDev) {\n return Math.exp(-(x * x) / (2.0 * (stdDev * stdDev))) / (Math.sqrt(2.0 * Math.PI) * stdDev);\n}\n\nfunction createSampleOffsets(kernelRadius, uvIncrement) {\n const offsets = [];\n for (let i = 0; i <= kernelRadius; i++) {\n offsets.push(uvIncrement[0] * i);\n offsets.push(uvIncrement[1] * i);\n }\n return offsets;\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js?");
|
|
5208
5208
|
|
|
5209
5209
|
/***/ }),
|
|
5210
5210
|
|