@xtctwins/tctwins-core 1.0.36 → 1.0.37
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.
|
@@ -2484,7 +2484,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2484
2484
|
\*********************************************************/
|
|
2485
2485
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2486
2486
|
|
|
2487
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CameraControl: () => (/* binding */ CameraControl)\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 _camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../camera/CameraFlightAnimation.js */ \"./src/viewer/scene/camera/CameraFlightAnimation.js\");\n/* harmony import */ var _lib_controllers_PanController_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/controllers/PanController.js */ \"./src/viewer/scene/CameraControl/lib/controllers/PanController.js\");\n/* harmony import */ var _lib_controllers_PivotController_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/controllers/PivotController.js */ \"./src/viewer/scene/CameraControl/lib/controllers/PivotController.js\");\n/* harmony import */ var _lib_controllers_PickController_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/controllers/PickController.js */ \"./src/viewer/scene/CameraControl/lib/controllers/PickController.js\");\n/* harmony import */ var _lib_handlers_MousePanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/handlers/MousePanRotateDollyHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/MousePanRotateDollyHandler.js\");\n/* harmony import */ var _lib_handlers_KeyboardAxisViewHandler_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/handlers/KeyboardAxisViewHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/KeyboardAxisViewHandler.js\");\n/* harmony import */ var _lib_handlers_MousePickHandler_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/handlers/MousePickHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js\");\n/* harmony import */ var _lib_handlers_KeyboardPanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/handlers/KeyboardPanRotateDollyHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/KeyboardPanRotateDollyHandler.js\");\n/* harmony import */ var _lib_CameraUpdater_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/CameraUpdater.js */ \"./src/viewer/scene/CameraControl/lib/CameraUpdater.js\");\n/* harmony import */ var _lib_handlers_MouseMiscHandler_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/handlers/MouseMiscHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/MouseMiscHandler.js\");\n/* harmony import */ var _lib_handlers_TouchPanRotateAndDollyHandler_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/handlers/TouchPanRotateAndDollyHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/TouchPanRotateAndDollyHandler.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _lib_handlers_TouchPickHandler_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/handlers/TouchPickHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/TouchPickHandler.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DEFAULT_SNAP_PICK_RADIUS = 20;\nconst DEFAULT_SNAP_VERTEX = true;\nconst DEFAULT_SNAP_EDGE = true;\n\n/**\n * @desc Controls the {@link Camera} with user input, and fires events when the user interacts with pickable {@link Entity}s.\n *\n * # Contents\n *\n * * [Overview](#overview)\n * * [Examples](#examples)\n * * [Orbit Mode](#orbit-mode)\n * + [Following the Pointer in Orbit Mode](#--following-the-pointer-in-orbit-mode--)\n * + [Showing the Pivot Position](#--showing-the-pivot-position--)\n * + [Axis-Aligned Views in Orbit Mode](#--axis-aligned-views-in-orbit-mode--)\n * + [View-Fitting Entitys in Orbit Mode](#--view-fitting-entitys-in-orbit-mode--)\n * * [First-Person Mode](#first-person-mode)\n * + [Following the Pointer in First-Person Mode](#--following-the-pointer-in-first-person-mode--)\n * + [Constraining Vertical Position in First-Person Mode](#--constraining-vertical-position-in-first-person-mode--)\n * + [Axis-Aligned Views in First-Person Mode](#--axis-aligned-views-in-first-person-mode--)\n * + [View-Fitting Entitys in First-Person Mode](#--view-fitting-entitys-in-first-person-mode--)\n * * [Plan-View Mode](#plan-view-mode)\n * + [Following the Pointer in Plan-View Mode](#--following-the-pointer-in-plan-view-mode--)\n * + [Axis-Aligned Views in Plan-View Mode](#--axis-aligned-views-in-plan-view-mode--)\n * * [CameraControl Events](#cameracontrol-events)\n * + [\"hover\"](#---hover---)\n * + [\"hoverOff\"](#---hoveroff---)\n * + [\"hoverEnter\"](#---hoverenter---)\n * + [\"hoverOut\"](#---hoverout---)\n * + [\"picked\"](#---picked---)\n * + [\"pickedSurface\"](#---pickedsurface---)\n * + [\"pickedNothing\"](#---pickednothing---)\n * + [\"doublePicked\"](#---doublepicked---)\n * + [\"doublePickedSurface\"](#---doublepickedsurface---)\n * + [\"doublePickedNothing\"](#---doublepickednothing---)\n * + [\"rightClick\"](#---rightclick---)\n * * [Custom Keyboard Mappings](#custom-keyboard-mappings)\n *\n * <br><br>\n *\n * # Overview\n *\n * * Each {@link Viewer} has a ````CameraControl````, located at {@link Viewer#cameraControl}.\n * * {@link CameraControl#navMode} selects the navigation mode:\n * * ````\"orbit\"```` rotates the {@link Camera} position about the target.\n * * ````\"firstPerson\"```` rotates the World about the Camera position.\n * * ````\"planView\"```` never rotates, but still allows to pan and dolly, typically for an axis-aligned view.\n * * {@link CameraControl#followPointer} makes the Camera follow the mouse or touch pointer.\n * * {@link CameraControl#constrainVertical} locks the Camera to its current height when in first-person mode.\n * * ````CameraControl```` fires pick events when we hover, click or tap on an {@link Entity}.\n * <br><br>\n *\n * # Examples\n *\n * * [Orbit Navigation - Duplex Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_orbit_Duplex)\n * * [Orbit Navigation - Holter Tower Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_orbit_HolterTower)\n * * [First-Person Navigation - Duplex Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_firstPerson_Duplex)\n * * [First-Person Navigation - Holter Tower Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_firstPerson_HolterTower)\n * * [Plan-view Navigation - Schependomlaan Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_planView_Schependomlaan)\n * * [Custom Keyboard Mapping](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_keyMap)\n * <br><br>\n *\n * # Orbit Mode\n *\n * In orbit mode, ````CameraControl```` orbits the {@link Camera} about the target.\n *\n * To enable orbit mode:\n *\n * ````javascript\n * const cameraControl = myViewer.cameraControl;\n * cameraControl.navMode = \"orbit\";\n * ````\n *\n * Then orbit by:\n *\n * * left-dragging the mouse,\n * * tap-dragging the touch pad, and\n * * pressing arrow keys, or ````Q```` and ````E```` on a QWERTY keyboard, or ````A```` and ````E```` on an AZERTY keyboard.\n * <br><br>\n *\n * Dolly forwards and backwards by:\n *\n * * spinning the mouse wheel,\n * * pinching on the touch pad, and\n * * pressing the ````+```` and ````-```` keys, or ````W```` and ````S```` on a QWERTY keyboard, or ````Z```` and ````S```` for AZERTY.\n * <br><br>\n *\n * Pan horizontally and vertically by:\n *\n * * right-dragging the mouse,\n * * left-dragging the mouse with the SHIFT key down,\n * * tap-dragging the touch pad with SHIFT down,\n * * pressing the ````A````, ````D````, ````Z```` and ````X```` keys on a QWERTY keyboard, and\n * * pressing the ````Q````, ````D````, ````W```` and ````X```` keys on an AZERTY keyboard,\n * <br><br>\n *\n * ## Following the Pointer in Orbit Mode\n *\n * When {@link CameraControl#followPointer} is ````true````in orbiting mode, the mouse or touch pointer will dynamically\n * indicate the target that the {@link Camera} will orbit, as well as dolly to and from.\n *\n * Lets ensure that we're in orbit mode, then enable the {@link Camera} to follow the pointer:\n *\n * ````javascript\n * cameraControl.navMode = \"orbit\";\n * cameraControl.followPointer = true;\n * ````\n *\n * ## Smart Pivoting\n *\n * TODO\n *\n * ## Showing the Pivot Position\n *\n * We can configure {@link CameraControl#pivotElement} with an HTML element to indicate the current\n * pivot position. The indicator will appear momentarily each time we move the {@link Camera} while in orbit mode with\n * {@link CameraControl#followPointer} set ````true````.\n *\n * First we'll define some CSS to style our pivot indicator as a black dot with a white border:\n *\n * ````css\n * .camera-pivot-marker {\n * color: #ffffff;\n * position: absolute;\n * width: 25px;\n * height: 25px;\n * border-radius: 15px;\n * border: 2px solid #ebebeb;\n * background: black;\n * visibility: hidden;\n * box-shadow: 5px 5px 15px 1px #000000;\n * z-index: 10000;\n * pointer-events: none;\n * }\n * ````\n *\n * Then we'll attach our pivot indicator's HTML element to the ````CameraControl````:\n *\n * ````javascript\n * const pivotElement = document.createRange().createContextualFragment(\"<div class='camera-pivot-marker'></div>\").firstChild;\n *\n * document.body.appendChild(pivotElement);\n *\n * cameraControl.pivotElement = pivotElement;\n * ````\n *\n * ## Axis-Aligned Views in Orbit Mode\n *\n * In orbit mode, we can use keys 1-6 to position the {@link Camera} to look at the center of the {@link Scene} from along each of the\n * six World-space axis. Pressing one of these keys will fly the {@link Camera} to the corresponding axis-aligned view.\n *\n * ## View-Fitting Entitys in Orbit Mode\n *\n * When {@link CameraControl#doublePickFlyTo} is ````true````, we can left-double-click or\n * double-tap (ie. \"double-pick\") an {@link Entity} to fit it to view. This will cause the {@link Camera}\n * to fly to that Entity. Our target then becomes the center of that Entity. If we are currently pivoting,\n * then our pivot position is then also set to the Entity center.\n *\n * Disable that behaviour by setting {@link CameraControl#doublePickFlyTo} ````false````.\n *\n * # First-Person Mode\n *\n * In first-person mode, ````CameraControl```` rotates the World about the {@link Camera} position.\n *\n * To enable first-person mode:\n *\n * ````javascript\n * cameraControl.navMode = \"firstPerson\";\n * ````\n *\n * Then rotate by:\n *\n * * left-dragging the mouse,\n * * tap-dragging the touch pad,\n * * pressing arrow keys, or ````Q```` and ````E```` on a QWERTY keyboard, or ````A```` and ````E```` on an AZERTY keyboard.\n * <br><br>\n *\n * Dolly forwards and backwards by:\n *\n * * spinning the mouse wheel,\n * * pinching on the touch pad, and\n * * pressing the ````+```` and ````-```` keys, or ````W```` and ````S```` on a QWERTY keyboard, or ````Z```` and ````S```` for AZERTY.\n * <br><br>\n *\n * Pan left, right, up and down by:\n *\n * * left-dragging or right-dragging the mouse, and\n * * tap-dragging the touch pad with SHIFT down.\n *\n * Pan forwards, backwards, left, right, up and down by pressing the ````WSADZX```` keys on a QWERTY keyboard,\n * or ````WSQDWX```` keys on an AZERTY keyboard.\n * <br><br>\n *\n * ## Following the Pointer in First-Person Mode\n *\n * When {@link CameraControl#followPointer} is ````true```` in first-person mode, the mouse or touch pointer will dynamically\n * indicate the target to which the {@link Camera} will dolly to and from. In first-person mode, however, the World will always rotate\n * about the {@link Camera} position.\n *\n * Lets ensure that we're in first-person mode, then enable the {@link Camera} to follow the pointer:\n *\n * ````javascript\n * cameraControl.navMode = \"firstPerson\";\n * cameraControl.followPointer = true;\n * ````\n *\n * When the pointer is over empty space, the target will remain the last object that the pointer was over.\n *\n * ## Constraining Vertical Position in First-Person Mode\n *\n * In first-person mode, we can lock the {@link Camera} to its current position on the vertical World axis, which is useful for walk-through navigation:\n *\n * ````javascript\n * cameraControl.constrainVertical = true;\n * ````\n *\n * ## Axis-Aligned Views in First-Person Mode\n *\n * In first-person mode we can use keys 1-6 to position the {@link Camera} to look at the center of\n * the {@link Scene} from along each of the six World-space axis. Pressing one of these keys will fly the {@link Camera} to the\n * corresponding axis-aligned view.\n *\n * ## View-Fitting Entitys in First-Person Mode\n *\n * As in orbit mode, when in first-person mode and {@link CameraControl#doublePickFlyTo} is ````true````, we can double-click\n * or double-tap an {@link Entity} (ie. \"double-picking\") to fit it in view. This will cause the {@link Camera} to fly to\n * that Entity. Our target then becomes the center of that Entity.\n *\n * Disable that behaviour by setting {@link CameraControl#doublePickFlyTo} ````false````.\n *\n * # Plan-View Mode\n *\n * In plan-view mode, ````CameraControl```` pans and rotates the {@link Camera}, without rotating it.\n *\n * To enable plan-view mode:\n *\n * ````javascript\n * cameraControl.navMode = \"planView\";\n * ````\n *\n * Dolly forwards and backwards by:\n *\n * * spinning the mouse wheel,\n * * pinching on the touch pad, and\n * * pressing the ````+```` and ````-```` keys.\n *\n * <br>\n * Pan left, right, up and down by:\n *\n * * left-dragging or right-dragging the mouse, and\n * * tap-dragging the touch pad with SHIFT down.\n *\n * Pan forwards, backwards, left, right, up and down by pressing the ````WSADZX```` keys on a QWERTY keyboard,\n * or ````WSQDWX```` keys on an AZERTY keyboard.\n * <br><br>\n *\n * ## Following the Pointer in Plan-View Mode\n *\n * When {@link CameraControl#followPointer} is ````true```` in plan-view mode, the mouse or touch pointer will dynamically\n * indicate the target to which the {@link Camera} will dolly to and from. In plan-view mode, however, the {@link Camera} cannot rotate.\n *\n * Lets ensure that we're in plan-view mode, then enable the {@link Camera} to follow the pointer:\n *\n * ````javascript\n * cameraControl.navMode = \"planView\";\n * cameraControl.followPointer = true; // Default\n * ````\n *\n * When the pointer is over empty space, the target will remain the last object that the pointer was over.\n *\n * ## Axis-Aligned Views in Plan-View Mode\n *\n * As in orbit and first-person modes, in plan-view mode we can use keys 1-6 to position the {@link Camera} to look at the center of\n * the {@link Scene} from along each of the six World-space axis. Pressing one of these keys will fly the {@link Camera} to the\n * corresponding axis-aligned view.\n *\n * # CameraControl Events\n *\n * ````CameraControl```` fires events as we interact with {@link Entity}s using mouse or touch input.\n *\n * The following examples demonstrate how to subscribe to those events.\n *\n * The first example shows how to save a handle to a subscription, which we can later use to unsubscribe.\n *\n * ## \"hover\"\n *\n * Event fired when the pointer moves while hovering over an Entity.\n *\n * ````javascript\n * const onHover = cameraControl.on(\"hover\", (e) => {\n * const entity = e.entity; // Entity\n * const canvasPos = e.canvasPos; // 2D canvas position\n * });\n * ````\n *\n * To unsubscribe from the event:\n *\n * ````javascript\n * cameraControl.off(onHover);\n * ````\n *\n * ## \"hoverOff\"\n *\n * Event fired when the pointer moves while hovering over empty space.\n *\n * ````javascript\n * cameraControl.on(\"hoverOff\", (e) => {\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"hoverEnter\"\n *\n * Event fired when the pointer moves onto an Entity.\n *\n * ````javascript\n * cameraControl.on(\"hoverEnter\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"hoverOut\"\n *\n * Event fired when the pointer moves off an Entity.\n *\n * ````javascript\n * cameraControl.on(\"hoverOut\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"picked\"\n *\n * Event fired when we left-click or tap on an Entity.\n *\n * ````javascript\n * cameraControl.on(\"picked\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"pickedSurface\"\n *\n * Event fired when we left-click or tap on the surface of an Entity.\n *\n * ````javascript\n * cameraControl.on(\"picked\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * const worldPos = e.worldPos; // 3D World-space position\n * const viewPos = e.viewPos; // 3D View-space position\n * const worldNormal = e.worldNormal; // 3D World-space normal vector\n * });\n * ````\n *\n * ## \"pickedNothing\"\n *\n * Event fired when we left-click or tap on empty space.\n *\n * ````javascript\n * cameraControl.on(\"pickedNothing\", (e) => {\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"doublePicked\"\n *\n * Event fired wwhen we left-double-click or double-tap on an Entity.\n *\n * ````javascript\n * cameraControl.on(\"doublePicked\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"doublePickedSurface\"\n *\n * Event fired when we left-double-click or double-tap on the surface of an Entity.\n *\n * ````javascript\n * cameraControl.on(\"doublePickedSurface\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * const worldPos = e.worldPos;\n * const viewPos = e.viewPos;\n * const worldNormal = e.worldNormal;\n * });\n * ````\n *\n * ## \"doublePickedNothing\"\n *\n * Event fired when we left-double-click or double-tap on empty space.\n *\n * ````javascript\n * cameraControl.on(\"doublePickedNothing\", (e) => {\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"rightClick\"\n *\n * Event fired when we right-click on the canvas.\n *\n * ````javascript\n * cameraControl.on(\"rightClick\", (e) => {\n * const event = e.event; // Mouse event\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## Custom Keyboard Mappings\n *\n * We can customize````CameraControl```` key bindings as shown below.\n *\n * In this example, we'll just set the default bindings for a QWERTY keyboard.\n *\n * ````javascript\n * const input = myViewer.scene.input;\n *\n * cameraControl.navMode = \"orbit\";\n * cameraControl.followPointer = true;\n *\n * const keyMap = {};\n *\n * keyMap[cameraControl.PAN_LEFT] = [input.KEY_A];\n * keyMap[cameraControl.PAN_RIGHT] = [input.KEY_D];\n * keyMap[cameraControl.PAN_UP] = [input.KEY_Z];\n * keyMap[cameraControl.PAN_DOWN] = [input.KEY_X];\n * keyMap[cameraControl.DOLLY_FORWARDS] = [input.KEY_W, input.KEY_ADD];\n * keyMap[cameraControl.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];\n * keyMap[cameraControl.ROTATE_X_POS] = [input.KEY_DOWN_ARROW];\n * keyMap[cameraControl.ROTATE_X_NEG] = [input.KEY_UP_ARROW];\n * keyMap[cameraControl.ROTATE_Y_POS] = [input.KEY_LEFT_ARROW];\n * keyMap[cameraControl.ROTATE_Y_NEG] = [input.KEY_RIGHT_ARROW];\n * keyMap[cameraControl.AXIS_VIEW_RIGHT] = [input.KEY_NUM_1];\n * keyMap[cameraControl.AXIS_VIEW_BACK] = [input.KEY_NUM_2];\n * keyMap[cameraControl.AXIS_VIEW_LEFT] = [input.KEY_NUM_3];\n * keyMap[cameraControl.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];\n * keyMap[cameraControl.AXIS_VIEW_TOP] = [input.KEY_NUM_5];\n * keyMap[cameraControl.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];\n *\n * cameraControl.keyMap = keyMap;\n * ````\n *\n * We can also just configure default bindings for a specified keyboard layout, like this:\n *\n * ````javascript\n * cameraControl.keyMap = \"qwerty\";\n * ````\n *\n * Then, ````CameraControl```` will internally set {@link CameraControl#keyMap} to the default key map for the QWERTY\n * layout (which is the same set of mappings we set in the previous example). In other words, if we subsequently\n * read {@link CameraControl#keyMap}, it will now be a key map, instead of the \"qwerty\" string value we set it to.\n *\n * Supported layouts are, so far:\n *\n * * ````\"qwerty\"````\n * * ````\"azerty\"````\n */\nclass CameraControl extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\n\t/**\n\t * @private\n\t * @constructor\n\t */\n\tconstructor(owner, cfg = {}) {\n\t\tsuper(owner, cfg);\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_LEFT = 0;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_RIGHT = 1;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_UP = 2;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_DOWN = 3;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_FORWARDS = 4;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_BACKWARDS = 5;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_X_POS = 6;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_X_NEG = 7;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_Y_POS = 8;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_Y_NEG = 9;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.DOLLY_FORWARDS = 10;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.DOLLY_BACKWARDS = 11;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_RIGHT = 12;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_BACK = 13;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_LEFT = 14;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_FRONT = 15;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_TOP = 16;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_BOTTOM = 17;\n\n\t\tthis._keyMap = {}; // Maps key codes to the above actions\n\n\t\tthis.scene.canvas.canvas.oncontextmenu = (e) => {\n\t\t\te.preventDefault();\n\t\t};\n\n\t\t// User-settable CameraControl configurations\n\n\t\tthis._configs = {\n\t\t\t// Private\n\n\t\t\tlongTapTimeout: 600, // Millisecs\n\t\t\tlongTapRadius: 5, // Pixels\n\n\t\t\t// General\n\n\t\t\tactive: true,\n\t\t\tkeyboardLayout: \"qwerty\",\n\t\t\tnavMode: \"orbit\",\n\t\t\tplanView: false,\n\t\t\tfirstPerson: false,\n\t\t\tfollowPointer: true,\n\t\t\tdoublePickFlyTo: true,\n\t\t\tpanRightClick: true,\n\t\t\tshowPivot: false,\n\t\t\tpointerEnabled: true,\n\t\t\tconstrainVertical: false,\n\t\t\tsmartPivot: false,\n\t\t\tdoubleClickTimeFrame: 250,\n\n\t\t\tsnapToVertex: DEFAULT_SNAP_VERTEX,\n\t\t\tsnapToEdge: DEFAULT_SNAP_EDGE,\n\t\t\tsnapRadius: cfg.snapRadius ? cfg.snapRadius : DEFAULT_SNAP_PICK_RADIUS,\n\n\t\t\t// Rotation\n\n\t\t\tdragRotationRate: 360.0,\n\t\t\tkeyboardRotationRate: 90.0,\n\t\t\trotationInertia: 0.0,\n\n\t\t\t// Panning\n\n\t\t\tkeyboardPanRate: 1.0,\n\t\t\ttouchPanRate: 1.0,\n\t\t\tpanInertia: 0.5,\n\n\t\t\t// Dollying\n\n\t\t\tkeyboardDollyRate: 10,\n\t\t\tmouseWheelDollyRate: 100,\n\t\t\ttouchDollyRate: 0.2,\n\t\t\tdollyInertia: 0,\n\t\t\tdollyProximityThreshold: 30.0,\n\t\t\tdollyMinSpeed: 0.04\n\t\t};\n\n\t\t// Current runtime state of the CameraControl\n\n\t\tthis._states = {\n\t\t\tpointerCanvasPos: _math_math_js__WEBPACK_IMPORTED_MODULE_13__.math.vec2(),\n\t\t\tmouseover: false,\n\t\t\tfollowPointerDirty: true,\n\t\t\tmouseDownClientX: 0,\n\t\t\tmouseDownClientY: 0,\n\t\t\tmouseDownCursorX: 0,\n\t\t\tmouseDownCursorY: 0,\n\t\t\ttouchStartTime: null,\n\t\t\tactiveTouches: [],\n\t\t\ttapStartPos: _math_math_js__WEBPACK_IMPORTED_MODULE_13__.math.vec2(),\n\t\t\ttapStartTime: -1,\n\t\t\tlastTapTime: -1,\n\t\t\tlongTouchTimeout: null\n\t\t};\n\n\t\t// Updates for CameraUpdater to process on next Scene \"tick\" event\n\n\t\tthis._updates = {\n\t\t\trotateDeltaX: 0,\n\t\t\trotateDeltaY: 0,\n\t\t\tpanDeltaX: 0,\n\t\t\tpanDeltaY: 0,\n\t\t\tpanDeltaZ: 0,\n\t\t\tdollyDelta: 0\n\t\t};\n\n\t\t// Controllers to assist input event handlers with controlling the Camera\n\n\t\tconst scene = this.scene;\n\n\t\tthis._controllers = {\n\t\t\tcameraControl: this,\n\t\t\tpickController: new _lib_controllers_PickController_js__WEBPACK_IMPORTED_MODULE_4__.PickController(this, this._configs),\n\t\t\tpivotController: new _lib_controllers_PivotController_js__WEBPACK_IMPORTED_MODULE_3__.PivotController(scene, this._configs),\n\t\t\tpanController: new _lib_controllers_PanController_js__WEBPACK_IMPORTED_MODULE_2__.PanController(scene),\n\t\t\tcameraFlight: new _camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__.CameraFlightAnimation(this, {\n\t\t\t\tduration: 0.5\n\t\t\t})\n\t\t};\n\n\t\t// Input event handlers\n\n\t\tthis._handlers = [\n\t\t\tnew _lib_handlers_MouseMiscHandler_js__WEBPACK_IMPORTED_MODULE_10__.MouseMiscHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_TouchPanRotateAndDollyHandler_js__WEBPACK_IMPORTED_MODULE_11__.TouchPanRotateAndDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_MousePanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_5__.MousePanRotateDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_KeyboardAxisViewHandler_js__WEBPACK_IMPORTED_MODULE_6__.KeyboardAxisViewHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_MousePickHandler_js__WEBPACK_IMPORTED_MODULE_7__.MousePickHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_TouchPickHandler_js__WEBPACK_IMPORTED_MODULE_14__.TouchPickHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_KeyboardPanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_8__.KeyboardPanRotateDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates)\n\t\t];\n\n\t\t// Applies scheduled updates to the Camera on each Scene \"tick\" event\n\n\t\tthis._cameraUpdater = new _lib_CameraUpdater_js__WEBPACK_IMPORTED_MODULE_9__.CameraUpdater(this.scene, this._controllers, this._configs, this._states, this._updates);\n\n\t\t// Set initial user configurations\n\n\t\tthis.navMode = cfg.navMode;\n\t\tif (cfg.planView) {\n\t\t\tthis.planView = cfg.planView;\n\t\t}\n\t\tthis.constrainVertical = cfg.constrainVertical;\n\t\tif (cfg.keyboardLayout) {\n\t\t\tthis.keyboardLayout = cfg.keyboardLayout; // Deprecated\n\t\t} else {\n\t\t\tthis.keyMap = cfg.keyMap;\n\t\t}\n\t\tthis.doublePickFlyTo = cfg.doublePickFlyTo;\n\t\tthis.panRightClick = cfg.panRightClick;\n\t\tthis.active = cfg.active;\n\t\tthis.followPointer = cfg.followPointer;\n\t\tthis.rotationInertia = cfg.rotationInertia;\n\t\tthis.keyboardPanRate = cfg.keyboardPanRate;\n\t\tthis.touchPanRate = cfg.touchPanRate;\n\t\tthis.keyboardRotationRate = cfg.keyboardRotationRate;\n\t\tthis.dragRotationRate = cfg.dragRotationRate;\n\t\tthis.touchDollyRate = cfg.touchDollyRate;\n\t\tthis.dollyInertia = cfg.dollyInertia;\n\t\tthis.dollyProximityThreshold = cfg.dollyProximityThreshold;\n\t\tthis.dollyMinSpeed = cfg.dollyMinSpeed;\n\t\tthis.panInertia = cfg.panInertia;\n\t\tthis.pointerEnabled = true;\n\t\tthis.keyboardDollyRate = cfg.keyboardDollyRate;\n\t\tthis.mouseWheelDollyRate = cfg.mouseWheelDollyRate;\n\t\tthis._moveRate = 1;\n\t\tthis.scene.on(\"tick\", () => {\n\t\t\t// if (!(this._configs.active && this._configs.pointerEnabled)) return;\n\t\t\t// if (!this._states.mouseover) return;\n\t\t\tif (!(this._goLeft || this._goRight || this._goUp || this._goDown || this._goForward || this._goBackward)) {\n\t\t\t\t// this._inputDirectionCommand = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._goRight) {\n\t\t\t\tthis._updates.panDeltaX += -0.1 * this._moveRate;\n\t\t\t} else if (this._goLeft) {\n\t\t\t\tthis._updates.panDeltaX += 0.1 * this._moveRate;\n\t\t\t}\n\n\t\t\tif (this._goUp) {\n\t\t\t\tthis._updates.panDeltaY += 0.1 * this._moveRate;\n\t\t\t} else if (this._goDown) {\n\t\t\t\tthis._updates.panDeltaY += -0.1 * this._moveRate;\n\t\t\t}\n\n\t\t\tif (this._goForward) {\n\t\t\t\tthis._updates.panDeltaZ += -0.1 * this._moveRate;\n\t\t\t} else if (this._goBackward) {\n\t\t\t\tthis._updates.panDeltaZ += +0.1 * this._moveRate;\n\t\t\t}\n\t\t\tthis._inputDirectionCommand = true;\n\t\t});\n\t}\n\t/**\n\t * 停止漫游\n\t */\n\tsetdirectionChangeCancel() {\n\t\tthis._goLeft = false;\n\t\tthis._goRight = false;\n\t\tthis._goUp = false;\n\t\tthis._goDown = false;\n\t\tthis._goForward = false;\n\t\tthis._goBackward = false;\n\t}\n\n\t/**\n\t * 设置漫游移动速率\n\t * @param {number} rate\n\t */\n\tset moveRate(rate) {\n\t\tthis._moveRate = rate;\n\t}\n\n\t/**\n\t * 漫游向右\n\t * @param {boolean} go\n\t */\n\tset goRight(go) {\n\t\tthis._goRight = go;\n\t}\n\t/**\n\t * 漫游向左\n\t * @param {boolean} go\n\t */\n\tset goLeft(go) {\n\t\tthis._goLeft = go;\n\t}\n\t/**\n\t * 漫游向上\n\t * @param {boolean} go\n\t */\n\tset goUp(go) {\n\t\tthis._goUp = go;\n\t}\n\t/**\n\t * 漫游向下\n\t * @param {boolean} go\n\t */\n\tset goDown(go) {\n\t\tthis._goDown = go;\n\t}\n\t/**\n\t * 漫游向前\n\t * @param {boolean} go\n\t */\n\tset goForward(go) {\n\t\tthis._goForward = go;\n\t}\n\t/**\n\t * 漫游向后\n\t * @param {boolean} go\n\t */\n\tset goBackward(go) {\n\t\tthis._goBackward = go;\n\t}\n\n\tupdatePivotElement() {\n\t\tthis._controllers.pivotController.updatePivotElement();\n\t}\n\n\t/**\n\t * Sets custom mappings of keys to ````CameraControl```` actions.\n\t *\n\t * See class docs for usage.\n\t *\n\t * @param {{Number:Number}|String} value Either a set of new key mappings, or a string to select a keyboard layout,\n\t * which causes ````CameraControl```` to use the default key mappings for that layout.\n\t */\n\tset keyMap(value) {\n\t\tvalue = value || \"qwerty\";\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_12__.utils.isString(value)) {\n\t\t\tconst input = this.scene.input;\n\t\t\tconst keyMap = {};\n\n\t\t\tswitch (value) {\n\t\t\t\tdefault:\n\t\t\t\t\tthis.error(\"Unsupported value for 'keyMap': \" + value + \" defaulting to 'qwerty'\");\n\t\t\t\t// Intentional fall-through to \"qwerty\"\n\t\t\t\tcase \"qwerty\":\n\t\t\t\t\tkeyMap[this.PAN_LEFT] = [input.KEY_A];\n\t\t\t\t\tkeyMap[this.PAN_RIGHT] = [input.KEY_D];\n\t\t\t\t\tkeyMap[this.PAN_UP] = [input.KEY_Z];\n\t\t\t\t\tkeyMap[this.PAN_DOWN] = [input.KEY_X];\n\t\t\t\t\tkeyMap[this.PAN_BACKWARDS] = [];\n\t\t\t\t\tkeyMap[this.PAN_FORWARDS] = [];\n\t\t\t\t\tkeyMap[this.DOLLY_FORWARDS] = [input.KEY_W, input.KEY_ADD];\n\t\t\t\t\tkeyMap[this.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];\n\t\t\t\t\tkeyMap[this.ROTATE_X_POS] = [input.KEY_DOWN_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_X_NEG] = [input.KEY_UP_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_POS] = [input.KEY_Q, input.KEY_LEFT_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_NEG] = [input.KEY_E, input.KEY_RIGHT_ARROW];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_RIGHT] = [input.KEY_NUM_1];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BACK] = [input.KEY_NUM_2];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_LEFT] = [input.KEY_NUM_3];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"azerty\":\n\t\t\t\t\tkeyMap[this.PAN_LEFT] = [input.KEY_Q];\n\t\t\t\t\tkeyMap[this.PAN_RIGHT] = [input.KEY_D];\n\t\t\t\t\tkeyMap[this.PAN_UP] = [input.KEY_W];\n\t\t\t\t\tkeyMap[this.PAN_DOWN] = [input.KEY_X];\n\t\t\t\t\tkeyMap[this.PAN_BACKWARDS] = [];\n\t\t\t\t\tkeyMap[this.PAN_FORWARDS] = [];\n\t\t\t\t\tkeyMap[this.DOLLY_FORWARDS] = [input.KEY_Z, input.KEY_ADD];\n\t\t\t\t\tkeyMap[this.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];\n\t\t\t\t\tkeyMap[this.ROTATE_X_POS] = [input.KEY_DOWN_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_X_NEG] = [input.KEY_UP_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_POS] = [input.KEY_A, input.KEY_LEFT_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_NEG] = [input.KEY_E, input.KEY_RIGHT_ARROW];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_RIGHT] = [input.KEY_NUM_1];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BACK] = [input.KEY_NUM_2];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_LEFT] = [input.KEY_NUM_3];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis._keyMap = keyMap;\n\t\t} else {\n\t\t\tconst keyMap = value;\n\t\t\tthis._keyMap = keyMap;\n\t\t}\n\t}\n\n\t/**\n\t * Gets custom mappings of keys to {@link CameraControl} actions.\n\t *\n\t * @returns {{Number:Number}} Current key mappings.\n\t */\n\tget keyMap() {\n\t\treturn this._keyMap;\n\t}\n\n\t/**\n\t * Returns true if any keys configured for the given action are down.\n\t * @param action\n\t * @param keyDownMap\n\t * @private\n\t */\n\t_isKeyDownForAction(action, keyDownMap) {\n\t\tconst keys = this._keyMap[action];\n\t\tif (!keys) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!keyDownMap) {\n\t\t\tkeyDownMap = this.scene.input.keyDown;\n\t\t}\n\t\tfor (let i = 0, len = keys.length; i < len; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tif (keyDownMap[key]) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sets the HTMl element to represent the pivot point when {@link CameraControl#followPointer} is true.\n\t *\n\t * See class comments for an example.\n\t *\n\t * @param {HTMLElement} element HTML element representing the pivot point.\n\t */\n\tset pivotElement(element) {\n\t\tthis._controllers.pivotController.setPivotElement(element);\n\t}\n\n\t/**\n\t * Sets if this ````CameraControl```` is active or not.\n\t *\n\t * When inactive, the ````CameraControl```` will not react to input.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @param {Boolean} value Set ````true```` to activate this ````CameraControl````.\n\t */\n\tset active(value) {\n\t\tvalue = value !== false;\n\t\tthis._configs.active = value;\n\t\tthis._handlers[1]._active = value;\n\t\tthis._handlers[5]._active = value;\n\t}\n\n\t/**\n\t * Gets if this ````CameraControl```` is active or not.\n\t *\n\t * When inactive, the ````CameraControl```` will not react to input.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} Returns ````true```` if this ````CameraControl```` is active.\n\t */\n\tget active() {\n\t\treturn this._configs.active;\n\t}\n\n\t/**\n\t * Sets whether the pointer snap to vertex.\n\t *\n\t * @param {boolean} snapToVertex\n\t */\n\tset snapToVertex(snapToVertex) {\n\t\tthis._configs.snapToVertex = !!snapToVertex;\n\t}\n\n\t/**\n\t * Gets whether the pointer snap to vertex.\n\t *\n\t * @returns {boolean}\n\t */\n\tget snapToVertex() {\n\t\treturn this._configs.snapToVertex;\n\t}\n\n\t/**\n\t * Sets whether the pointer snap to edge.\n\t *\n\t * @param {boolean} snapToEdge\n\t */\n\tset snapToEdge(snapToEdge) {\n\t\tthis._configs.snapToEdge = !!snapToEdge;\n\t}\n\n\t/**\n\t * Gets whether the pointer snap to edge.\n\t *\n\t * @returns {boolean}\n\t */\n\tget snapToEdge() {\n\t\treturn this._configs.snapToEdge;\n\t}\n\n\t/**\n\t * Sets the current snap radius for \"hoverSnapOrSurface\" events, to specify whether the radius\n\t * within which the pointer snaps to the nearest vertex or the nearest edge.\n\t *\n\t * Default value is 30 pixels.\n\t *\n\t * @param {Number} snapRadius The snap radius.\n\t */\n\tset snapRadius(snapRadius) {\n\t\tsnapRadius = snapRadius || DEFAULT_SNAP_PICK_RADIUS;\n\t\tthis._configs.snapRadius = snapRadius;\n\t}\n\n\t/**\n\t * Gets the current snap radius.\n\t *\n\t * @returns {Number} The snap radius.\n\t */\n\tget snapRadius() {\n\t\treturn this._configs.snapRadius;\n\t}\n\n\t/**\n\t * Sets the current navigation mode.\n\t *\n\t * Accepted values are:\n\t *\n\t * * \"orbit\" - rotation orbits about the current target or pivot point,\n\t * * \"firstPerson\" - rotation is about the current eye position,\n\t * * \"planView\" - rotation is disabled.\n\t *\n\t * See class comments for more info.\n\t *\n\t * @param {String} navMode The navigation mode: \"orbit\", \"firstPerson\" or \"planView\".\n\t */\n\tset navMode(navMode) {\n\t\tnavMode = navMode || \"orbit\";\n\t\tif (navMode !== \"firstPerson\" && navMode !== \"orbit\" && navMode !== \"planView\") {\n\t\t\tthis.error(\n\t\t\t\t\"Unsupported value for navMode: \" +\n\t\t\t\t\tnavMode +\n\t\t\t\t\t\" - supported values are 'orbit', 'firstPerson' and 'planView' - defaulting to 'orbit'\"\n\t\t\t);\n\t\t\tnavMode = \"orbit\";\n\t\t}\n\t\tthis._configs.firstPerson = navMode === \"firstPerson\";\n\t\tthis._configs.planView = navMode === \"planView\";\n\t\tif (this._configs.firstPerson || this._configs.planView) {\n\t\t\tthis._controllers.pivotController.hidePivot();\n\t\t\tthis._controllers.pivotController.endPivot();\n\t\t}\n\t\tthis._configs.navMode = navMode;\n\t}\n\n\t/**\n\t * Gets the current navigation mode.\n\t *\n\t * @returns {String} The navigation mode: \"orbit\", \"firstPerson\" or \"planView\".\n\t */\n\tget navMode() {\n\t\treturn this._configs.navMode;\n\t}\n\n\t/**\n\t * Sets whether mouse and touch input is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * Disabling mouse and touch input on ````CameraControl```` is useful when we want to temporarily use mouse or\n\t * touch input to interact with some other 3D control, without disturbing the {@link Camera}.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable mouse and touch input.\n\t */\n\tset pointerEnabled(value) {\n\t\tthis._reset();\n\t\tthis._configs.pointerEnabled = !!value;\n\t}\n\n\t_reset() {\n\t\tfor (let i = 0, len = this._handlers.length; i < len; i++) {\n\t\t\tconst handler = this._handlers[i];\n\t\t\tif (handler.reset) {\n\t\t\t\thandler.reset();\n\t\t\t}\n\t\t}\n\n\t\tthis._updates.panDeltaX = 0;\n\t\tthis._updates.panDeltaY = 0;\n\t\tthis._updates.rotateDeltaX = 0;\n\t\tthis._updates.rotateDeltaY = 0;\n\t\tthis._updates.dolyDelta = 0;\n\t}\n\n\t/**\n\t * Gets whether mouse and touch input is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * Disabling mouse and touch input on ````CameraControl```` is desirable when we want to temporarily use mouse or\n\t * touch input to interact with some other 3D control, without interfering with the {@link Camera}.\n\t *\n\t * @returns {Boolean} Returns ````true```` if mouse and touch input is enabled.\n\t */\n\tget pointerEnabled() {\n\t\treturn this._configs.pointerEnabled;\n\t}\n\n\t/**\n\t * Sets whether the {@link Camera} follows the mouse/touch pointer.\n\t *\n\t * In orbiting mode, the Camera will orbit about the pointer, and will dolly to and from the pointer.\n\t *\n\t * In fly-to mode, the Camera will dolly to and from the pointer, however the World will always rotate about the Camera position.\n\t *\n\t * In plan-view mode, the Camera will dolly to and from the pointer, however the Camera will not rotate.\n\t *\n\t * Default is ````true````.\n\t *\n\t * See class comments for more info.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable the Camera to follow the pointer.\n\t */\n\tset followPointer(value) {\n\t\tthis._configs.followPointer = value !== false;\n\t}\n\n\t/**\n\t * Sets whether the {@link Camera} follows the mouse/touch pointer.\n\t *\n\t * In orbiting mode, the Camera will orbit about the pointer, and will dolly to and from the pointer.\n\t *\n\t * In fly-to mode, the Camera will dolly to and from the pointer, however the World will always rotate about the Camera position.\n\t *\n\t * In plan-view mode, the Camera will dolly to and from the pointer, however the Camera will not rotate.\n\t *\n\t * Default is ````true````.\n\t *\n\t * See class comments for more info.\n\t *\n\t * @returns {Boolean} Returns ````true```` if the Camera follows the pointer.\n\t */\n\tget followPointer() {\n\t\treturn this._configs.followPointer;\n\t}\n\n\t/**\n\t * Sets the current World-space 3D target position.\n\t *\n\t * Only applies when {@link CameraControl#followPointer} is ````true````.\n\t *\n\t * @param {Number[]} worldPos The new World-space 3D target position.\n\t */\n\tset pivotPos(worldPos) {\n\t\tthis._controllers.pivotController.setPivotPos(worldPos);\n\t}\n\n\t/**\n\t * Gets the current World-space 3D pivot position.\n\t *\n\t * Only applies when {@link CameraControl#followPointer} is ````true````.\n\t *\n\t * @return {Number[]} worldPos The current World-space 3D pivot position.\n\t */\n\tget pivotPos() {\n\t\treturn this._controllers.pivotController.getPivotPos();\n\t}\n\n\t/**\n\t * @deprecated\n\t * @param {Boolean} value Set ````true```` to enable dolly-to-pointer behaviour.\n\t */\n\tset dollyToPointer(value) {\n\t\tthis.warn(\"dollyToPointer property is deprecated - replaced with followPointer\");\n\t\tthis.followPointer = value;\n\t}\n\n\t/**\n\t * @deprecated\n\t * @returns {Boolean} Returns ````true```` if dolly-to-pointer behaviour is enabled.\n\t */\n\tget dollyToPointer() {\n\t\tthis.warn(\"dollyToPointer property is deprecated - replaced with followPointer\");\n\t\treturn this.followPointer;\n\t}\n\n\t/**\n\t * @deprecated\n\t * @param {Boolean} value Set ````true```` to enable dolly-to-pointer behaviour.\n\t */\n\tset panToPointer(value) {\n\t\tthis.warn(\"panToPointer property is deprecated - replaced with followPointer\");\n\t}\n\n\t/**\n\t * @deprecated\n\t * @returns {Boolean} Returns ````true```` if dolly-to-pointer behaviour is enabled.\n\t */\n\tget panToPointer() {\n\t\tthis.warn(\"panToPointer property is deprecated - replaced with followPointer\");\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sets whether this ````CameraControl```` is in plan-view mode.\n\t *\n\t * When in plan-view mode, rotation is disabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable plan-view mode.\n\t * @deprecated\n\t */\n\tset planView(value) {\n\t\tthis._configs.planView = !!value;\n\t\tthis._configs.firstPerson = false;\n\t\tif (this._configs.planView) {\n\t\t\tthis._controllers.pivotController.hidePivot();\n\t\t\tthis._controllers.pivotController.endPivot();\n\t\t}\n\t\tthis.warn(\"planView property is deprecated - replaced with navMode\");\n\t}\n\n\t/**\n\t * Gets whether this ````CameraControl```` is in plan-view mode.\n\t *\n\t * When in plan-view mode, rotation is disabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @returns {Boolean} Returns ````true```` if plan-view mode is enabled.\n\t * @deprecated\n\t */\n\tget planView() {\n\t\tthis.warn(\"planView property is deprecated - replaced with navMode\");\n\t\treturn this._configs.planView;\n\t}\n\n\t/**\n\t * Sets whether this ````CameraControl```` is in first-person mode.\n\t *\n\t * In \"first person\" mode (disabled by default) the look position rotates about the eye position. Otherwise, {@link Camera#eye} rotates about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable first-person mode.\n\t * @deprecated\n\t */\n\tset firstPerson(value) {\n\t\tthis.warn(\"firstPerson property is deprecated - replaced with navMode\");\n\t\tthis._configs.firstPerson = !!value;\n\t\tthis._configs.planView = false;\n\t\tif (this._configs.firstPerson) {\n\t\t\tthis._controllers.pivotController.hidePivot();\n\t\t\tthis._controllers.pivotController.endPivot();\n\t\t}\n\t}\n\n\t/**\n\t * Gets whether this ````CameraControl```` is in first-person mode.\n\t *\n\t * In \"first person\" mode (disabled by default) the look position rotates about the eye position. Otherwise, {@link Camera#eye} rotates about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @returns {Boolean} Returns ````true```` if first-person mode is enabled.\n\t * @deprecated\n\t */\n\tget firstPerson() {\n\t\tthis.warn(\"firstPerson property is deprecated - replaced with navMode\");\n\t\treturn this._configs.firstPerson;\n\t}\n\n\t/**\n\t * Sets whether to vertically constrain the {@link Camera} position for first-person navigation.\n\t *\n\t * When set ````true````, this constrains {@link Camera#eye} to its current vertical position.\n\t *\n\t * Only applies when {@link CameraControl#navMode} is ````\"firstPerson\"````.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @param {Boolean} value Set ````true```` to vertically constrain the Camera.\n\t */\n\tset constrainVertical(value) {\n\t\tthis._configs.constrainVertical = !!value;\n\t}\n\n\t/**\n\t * Gets whether to vertically constrain the {@link Camera} position for first-person navigation.\n\t *\n\t * When set ````true````, this constrains {@link Camera#eye} to its current vertical position.\n\t *\n\t * Only applies when {@link CameraControl#navMode} is ````\"firstPerson\"````.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} ````true```` when Camera is vertically constrained.\n\t */\n\tget constrainVertical() {\n\t\treturn this._configs.constrainVertical;\n\t}\n\n\t/**\n\t * Sets whether double-picking an {@link Entity} causes the {@link Camera} to fly to its boundary.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable double-pick-fly-to mode.\n\t */\n\tset doublePickFlyTo(value) {\n\t\tthis._configs.doublePickFlyTo = value !== false;\n\t}\n\n\t/**\n\t * Gets whether double-picking an {@link Entity} causes the {@link Camera} to fly to its boundary.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} Returns ````true```` when double-pick-fly-to mode is enabled.\n\t */\n\tget doublePickFlyTo() {\n\t\treturn this._configs.doublePickFlyTo;\n\t}\n\n\t/**\n\t * Sets whether either right-clicking (true) or middle-clicking (false) pans the {@link Camera}.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @param {Boolean} value Set ````false```` to disable pan on right-click.\n\t */\n\tset panRightClick(value) {\n\t\tthis._configs.panRightClick = value !== false;\n\t}\n\n\t/**\n\t * Gets whether right-clicking pans the {@link Camera}.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} Returns ````false```` when pan on right-click is disabled.\n\t */\n\tget panRightClick() {\n\t\treturn this._configs.panRightClick;\n\t}\n\n\t/**\n\t * Sets a factor in range ````[0..1]```` indicating how much the {@link Camera} keeps moving after you finish rotating it.\n\t *\n\t * A value of ````0.0```` causes it to immediately stop, ````0.5```` causes its movement to decay 50% on each tick,\n\t * while ````1.0```` causes no decay, allowing it continue moving, by the current rate of rotation.\n\t *\n\t * You may choose an inertia of zero when you want be able to precisely rotate the Camera,\n\t * without interference from inertia. Zero inertia can also mean that less frames are rendered while\n\t * you are rotating the Camera.\n\t *\n\t * Default is ````0.0````.\n\t *\n\t * Does not apply when {@link CameraControl#navMode} is ````\"planView\"````, which disallows rotation.\n\t *\n\t * @param {Number} rotationInertia New inertial factor.\n\t */\n\tset rotationInertia(rotationInertia) {\n\t\tthis._configs.rotationInertia = rotationInertia !== undefined && rotationInertia !== null ? rotationInertia : 0.0;\n\t}\n\n\t/**\n\t * Gets the rotation inertia factor.\n\t *\n\t * Default is ````0.0````.\n\t *\n\t * Does not apply when {@link CameraControl#navMode} is ````\"planView\"````, which disallows rotation.\n\t *\n\t * @returns {Number} The inertia factor.\n\t */\n\tget rotationInertia() {\n\t\treturn this._configs.rotationInertia;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} pans each second with keyboard input.\n\t *\n\t * Default is ````5.0````, to pan the Camera ````5.0```` World-space units every second that\n\t * a panning key is depressed. See the ````CameraControl```` class documentation for which keys control\n\t * panning.\n\t *\n\t * Panning direction is aligned to our Camera's orientation. When we pan horizontally, we pan\n\t * to our left and right, when we pan vertically, we pan upwards and downwards, and when we pan forwards\n\t * and backwards, we pan along the direction the Camera is pointing.\n\t *\n\t * Unlike dollying when {@link followPointer} is ````true````, panning does not follow the pointer.\n\t *\n\t * @param {Number} keyboardPanRate The new keyboard pan rate.\n\t */\n\tset keyboardPanRate(keyboardPanRate) {\n\t\tthis._configs.keyboardPanRate = keyboardPanRate !== null && keyboardPanRate !== undefined ? keyboardPanRate : 5.0;\n\t}\n\n\t/**\n\t * Sets how fast the camera pans on touch panning\n\t *\n\t * @param {Number} touchPanRate The new touch pan rate.\n\t */\n\tset touchPanRate(touchPanRate) {\n\t\tthis._configs.touchPanRate = touchPanRate !== null && touchPanRate !== undefined ? touchPanRate : 1.0;\n\t}\n\n\t/**\n\t * Gets how fast the {@link Camera} pans on touch panning\n\t *\n\t * Default is ````1.0````.\n\t *\n\t * @returns {Number} The current touch pan rate.\n\t */\n\tget touchPanRate() {\n\t\treturn this._configs.touchPanRate;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} pans each second with keyboard input.\n\t *\n\t * Default is ````5.0````.\n\t *\n\t * @returns {Number} The current keyboard pan rate.\n\t */\n\tget keyboardPanRate() {\n\t\treturn this._configs.keyboardPanRate;\n\t}\n\n\t/**\n\t * Sets how many degrees per second the {@link Camera} rotates/orbits with keyboard input.\n\t *\n\t * Default is ````90.0````, to rotate/orbit the Camera ````90.0```` degrees every second that\n\t * a rotation key is depressed. See the ````CameraControl```` class documentation for which keys control\n\t * rotation/orbit.\n\t *\n\t * @param {Number} keyboardRotationRate The new keyboard rotation rate.\n\t */\n\tset keyboardRotationRate(keyboardRotationRate) {\n\t\tthis._configs.keyboardRotationRate =\n\t\t\tkeyboardRotationRate !== null && keyboardRotationRate !== undefined ? keyboardRotationRate : 90.0;\n\t}\n\n\t/**\n\t * Sets how many degrees per second the {@link Camera} rotates/orbits with keyboard input.\n\t *\n\t * Default is ````90.0````.\n\t *\n\t * @returns {Number} The current keyboard rotation rate.\n\t */\n\tget keyboardRotationRate() {\n\t\treturn this._configs.keyboardRotationRate;\n\t}\n\n\t/**\n\t * Sets the current drag rotation rate.\n\t *\n\t * This configures how many degrees the {@link Camera} rotates/orbits for a full sweep of the canvas by mouse or touch dragging.\n\t *\n\t * For example, a value of ````360.0```` indicates that the ````Camera```` rotates/orbits ````360.0```` degrees horizontally\n\t * when we sweep the entire width of the canvas.\n\t *\n\t * ````CameraControl```` makes vertical rotation half as sensitive as horizontal rotation, so that we don't tend to\n\t * flip upside-down. Therefore, a value of ````360.0```` rotates/orbits the ````Camera```` through ````180.0```` degrees\n\t * vertically when we sweep the entire height of the canvas.\n\t *\n\t * Default is ````360.0````.\n\t *\n\t * @param {Number} dragRotationRate The new drag rotation rate.\n\t */\n\tset dragRotationRate(dragRotationRate) {\n\t\tthis._configs.dragRotationRate =\n\t\t\tdragRotationRate !== null && dragRotationRate !== undefined ? dragRotationRate : 360.0;\n\t}\n\n\t/**\n\t * Gets the current drag rotation rate.\n\t *\n\t * Default is ````360.0````.\n\t *\n\t * @returns {Number} The current drag rotation rate.\n\t */\n\tget dragRotationRate() {\n\t\treturn this._configs.dragRotationRate;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} dollys each second with keyboard input.\n\t *\n\t * Default is ````15.0````, to dolly the {@link Camera} ````15.0```` World-space units per second while we hold down\n\t * the ````+```` and ````-```` keys.\n\t *\n\t * @param {Number} keyboardDollyRate The new keyboard dolly rate.\n\t */\n\tset keyboardDollyRate(keyboardDollyRate) {\n\t\tthis._configs.keyboardDollyRate =\n\t\t\tkeyboardDollyRate !== null && keyboardDollyRate !== undefined ? keyboardDollyRate : 15.0;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} dollys each second with keyboard input.\n\t *\n\t * Default is ````15.0````.\n\t *\n\t * @returns {Number} The current keyboard dolly rate.\n\t */\n\tget keyboardDollyRate() {\n\t\treturn this._configs.keyboardDollyRate;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} dollys with touch input.\n\t *\n\t * Default is ````0.2````\n\t *\n\t * @param {Number} touchDollyRate The new touch dolly rate.\n\t */\n\tset touchDollyRate(touchDollyRate) {\n\t\tthis._configs.touchDollyRate = touchDollyRate !== null && touchDollyRate !== undefined ? touchDollyRate : 0.2;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} dollys each second with touch input.\n\t *\n\t * Default is ````0.2````.\n\t *\n\t * @returns {Number} The current touch dolly rate.\n\t */\n\tget touchDollyRate() {\n\t\treturn this._configs.touchDollyRate;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} dollys each second while the mouse wheel is spinning.\n\t *\n\t * Default is ````100.0````, to dolly the {@link Camera} ````10.0```` World-space units per second as we spin\n\t * the mouse wheel.\n\t *\n\t * @param {Number} mouseWheelDollyRate The new mouse wheel dolly rate.\n\t */\n\tset mouseWheelDollyRate(mouseWheelDollyRate) {\n\t\tthis._configs.mouseWheelDollyRate =\n\t\t\tmouseWheelDollyRate !== null && mouseWheelDollyRate !== undefined ? mouseWheelDollyRate : 100.0;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} dollys each second while the mouse wheel is spinning.\n\t *\n\t * Default is ````100.0````.\n\t *\n\t * @returns {Number} The current mouseWheel dolly rate.\n\t */\n\tget mouseWheelDollyRate() {\n\t\treturn this._configs.mouseWheelDollyRate;\n\t}\n\n\t/**\n\t * Sets the dolly inertia factor.\n\t *\n\t * This factor configures how much the {@link Camera} keeps moving after you finish dollying it.\n\t *\n\t * This factor is a value in range ````[0..1]````. A value of ````0.0```` causes dollying to immediately stop,\n\t * ````0.5```` causes dollying to decay 50% on each animation frame, while ````1.0```` causes no decay, which allows dollying\n\t * to continue until further input stops it.\n\t *\n\t * You might set ````dollyInertia```` to zero when you want be able to precisely position or rotate the Camera,\n\t * without interference from inertia. This also means that xeokit renders less frames while dollying the Camera,\n\t * which can improve rendering performance.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @param {Number} dollyInertia New dolly inertia factor.\n\t */\n\tset dollyInertia(dollyInertia) {\n\t\tthis._configs.dollyInertia = dollyInertia !== undefined && dollyInertia !== null ? dollyInertia : 0;\n\t}\n\n\t/**\n\t * Gets the dolly inertia factor.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @returns {Number} The current dolly inertia factor.\n\t */\n\tget dollyInertia() {\n\t\treturn this._configs.dollyInertia;\n\t}\n\n\t/**\n\t * Sets the proximity to the closest object below which dolly speed decreases, and above which dolly speed increases.\n\t *\n\t * Default is ````35.0````.\n\t *\n\t * @param {Number} dollyProximityThreshold New dolly proximity threshold.\n\t */\n\tset dollyProximityThreshold(dollyProximityThreshold) {\n\t\tthis._configs.dollyProximityThreshold =\n\t\t\tdollyProximityThreshold !== undefined && dollyProximityThreshold !== null ? dollyProximityThreshold : 35.0;\n\t}\n\n\t/**\n\t * Gets the proximity to the closest object below which dolly speed decreases, and above which dolly speed increases.\n\t *\n\t * Default is ````35.0````.\n\t *\n\t * @returns {Number} The current dolly proximity threshold.\n\t */\n\tget dollyProximityThreshold() {\n\t\treturn this._configs.dollyProximityThreshold;\n\t}\n\n\t/**\n\t * Sets the minimum dolly speed.\n\t *\n\t * Default is ````0.04````.\n\t *\n\t * @param {Number} dollyMinSpeed New dolly minimum speed.\n\t */\n\tset dollyMinSpeed(dollyMinSpeed) {\n\t\tthis._configs.dollyMinSpeed = dollyMinSpeed !== undefined && dollyMinSpeed !== null ? dollyMinSpeed : 0.04;\n\t}\n\n\t/**\n\t * Gets the minimum dolly speed.\n\t *\n\t * Default is ````0.04````.\n\t *\n\t * @returns {Number} The current minimum dolly speed.\n\t */\n\tget dollyMinSpeed() {\n\t\treturn this._configs.dollyMinSpeed;\n\t}\n\n\t/**\n\t * Sets the pan inertia factor.\n\t *\n\t * This factor configures how much the {@link Camera} keeps moving after you finish panning it.\n\t *\n\t * This factor is a value in range ````[0..1]````. A value of ````0.0```` causes panning to immediately stop,\n\t * ````0.5```` causes panning to decay 50% on each animation frame, while ````1.0```` causes no decay, which allows panning\n\t * to continue until further input stops it.\n\t *\n\t * You might set ````panInertia```` to zero when you want be able to precisely position or rotate the Camera,\n\t * without interference from inertia. This also means that xeokit renders less frames while panning the Camera,\n\t * wich can improve rendering performance.\n\t *\n\t * Default is ````0.5````.\n\t *\n\t * @param {Number} panInertia New pan inertia factor.\n\t */\n\tset panInertia(panInertia) {\n\t\tthis._configs.panInertia = panInertia !== undefined && panInertia !== null ? panInertia : 0.5;\n\t}\n\n\t/**\n\t * Gets the pan inertia factor.\n\t *\n\t * Default is ````0.5````.\n\t *\n\t * @returns {Number} The current pan inertia factor.\n\t */\n\tget panInertia() {\n\t\treturn this._configs.panInertia;\n\t}\n\n\t/**\n\t * Sets the keyboard layout.\n\t *\n\t * Supported layouts are:\n\t *\n\t * * ````\"qwerty\"```` (default)\n\t * * ````\"azerty\"````\n\t *\n\t * @deprecated\n\t * @param {String} value Selects the keyboard layout.\n\t */\n\tset keyboardLayout(value) {\n\t\t// this.warn(\"keyboardLayout property is deprecated - use keyMap property instead\");\n\t\tvalue = value || \"qwerty\";\n\t\tif (value !== \"qwerty\" && value !== \"azerty\") {\n\t\t\tthis.error(\"Unsupported value for keyboardLayout - defaulting to 'qwerty'\");\n\t\t\tvalue = \"qwerty\";\n\t\t}\n\t\tthis._configs.keyboardLayout = value;\n\t\tthis.keyMap = this._configs.keyboardLayout;\n\t}\n\n\t/**\n\t * Gets the keyboard layout.\n\t *\n\t * Supported layouts are:\n\t *\n\t * * ````\"qwerty\"```` (default)\n\t * * ````\"azerty\"````\n\t *\n\t * @deprecated\n\t * @returns {String} The current keyboard layout.\n\t */\n\tget keyboardLayout() {\n\t\treturn this._configs.keyboardLayout;\n\t}\n\n\t/**\n\t * Sets a sphere as the representation of the pivot position.\n\t *\n\t * @param {Object} [cfg] Sphere configuration.\n\t * @param {String} [cfg.size=1] Optional size factor of the sphere. Defaults to 1.\n\t * @param {String} [cfg.material=PhongMaterial] Optional size factor of the sphere. Defaults to a red opaque material.\n\t */\n\tenablePivotSphere(cfg = {}) {\n\t\tthis._controllers.pivotController.enablePivotSphere(cfg);\n\t}\n\n\t/**\n\t * Remove the sphere as the representation of the pivot position.\n\t *\n\t */\n\tdisablePivotSphere() {\n\t\tthis._controllers.pivotController.disablePivotSphere();\n\t}\n\n\t/**\n\t * Sets whether smart default pivoting is enabled.\n\t *\n\t * When ````true````, we'll pivot by default about the 3D position of the mouse/touch pointer on an\n\t * imaginary sphere that's centered at {@link Camera#eye} and sized to the {@link Scene} boundary.\n\t *\n\t * When ````false````, we'll pivot by default about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @param {Boolean} enabled Set ````true```` to pivot by default about the selected point on the virtual sphere, or ````false```` to pivot by default about {@link Camera#look}.\n\t */\n\tset smartPivot(enabled) {\n\t\tthis._configs.smartPivot = enabled !== false;\n\t}\n\n\t/**\n\t * Gets whether smart default pivoting is enabled.\n\t *\n\t * When ````true````, we'll pivot by default about the 3D position of the mouse/touch pointer on an\n\t * imaginary sphere that's centered at {@link Camera#eye} and sized to the {@link Scene} boundary.\n\t *\n\t * When ````false````, we'll pivot by default about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} Returns ````true```` when pivoting by default about the selected point on the virtual sphere, or ````false```` when pivoting by default about {@link Camera#look}.\n\t */\n\tget smartPivot() {\n\t\treturn this._configs.smartPivot;\n\t}\n\n\t/**\n\t * Sets the double click time frame length in milliseconds.\n\t *\n\t * If two mouse click events occur within this time frame, it is considered a double click.\n\t *\n\t * Default is ````250````\n\t *\n\t * @param {Number} value New double click time frame.\n\t */\n\tset doubleClickTimeFrame(value) {\n\t\tthis._configs.doubleClickTimeFrame = value !== undefined && value !== null ? value : 250;\n\t}\n\n\t/**\n\t * Gets the double click time frame length in milliseconds.\n\t *\n\t * Default is ````250````\n\t *\n\t * @param {Number} value Current double click time frame.\n\t */\n\tget doubleClickTimeFrame() {\n\t\treturn this._configs.doubleClickTimeFrame;\n\t}\n\n\t/**\n\t * Destroys this ````CameraControl````.\n\t * @private\n\t */\n\tdestroy() {\n\t\tthis._destroyHandlers();\n\t\tthis._destroyControllers();\n\t\tthis._cameraUpdater.destroy();\n\t\tsuper.destroy();\n\t}\n\n\t_destroyHandlers() {\n\t\tfor (let i = 0, len = this._handlers.length; i < len; i++) {\n\t\t\tconst handler = this._handlers[i];\n\t\t\tif (handler.destroy) {\n\t\t\t\thandler.destroy();\n\t\t\t}\n\t\t}\n\t}\n\n\t_destroyControllers() {\n\t\tfor (let i = 0, len = this._controllers.length; i < len; i++) {\n\t\t\tconst controller = this._controllers[i];\n\t\t\tif (controller.destroy) {\n\t\t\t\tcontroller.destroy();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/CameraControl.js?");
|
|
2487
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CameraControl: () => (/* binding */ CameraControl)\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 _camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../camera/CameraFlightAnimation.js */ \"./src/viewer/scene/camera/CameraFlightAnimation.js\");\n/* harmony import */ var _lib_controllers_PanController_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/controllers/PanController.js */ \"./src/viewer/scene/CameraControl/lib/controllers/PanController.js\");\n/* harmony import */ var _lib_controllers_PivotController_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/controllers/PivotController.js */ \"./src/viewer/scene/CameraControl/lib/controllers/PivotController.js\");\n/* harmony import */ var _lib_controllers_PickController_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/controllers/PickController.js */ \"./src/viewer/scene/CameraControl/lib/controllers/PickController.js\");\n/* harmony import */ var _lib_handlers_MousePanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/handlers/MousePanRotateDollyHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/MousePanRotateDollyHandler.js\");\n/* harmony import */ var _lib_handlers_KeyboardAxisViewHandler_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/handlers/KeyboardAxisViewHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/KeyboardAxisViewHandler.js\");\n/* harmony import */ var _lib_handlers_MousePickHandler_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/handlers/MousePickHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js\");\n/* harmony import */ var _lib_handlers_KeyboardPanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/handlers/KeyboardPanRotateDollyHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/KeyboardPanRotateDollyHandler.js\");\n/* harmony import */ var _lib_CameraUpdater_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/CameraUpdater.js */ \"./src/viewer/scene/CameraControl/lib/CameraUpdater.js\");\n/* harmony import */ var _lib_handlers_MouseMiscHandler_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/handlers/MouseMiscHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/MouseMiscHandler.js\");\n/* harmony import */ var _lib_handlers_TouchPanRotateAndDollyHandler_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/handlers/TouchPanRotateAndDollyHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/TouchPanRotateAndDollyHandler.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _lib_handlers_TouchPickHandler_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/handlers/TouchPickHandler.js */ \"./src/viewer/scene/CameraControl/lib/handlers/TouchPickHandler.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DEFAULT_SNAP_PICK_RADIUS = 20;\nconst DEFAULT_SNAP_VERTEX = true;\nconst DEFAULT_SNAP_EDGE = true;\n\n/**\n * @desc Controls the {@link Camera} with user input, and fires events when the user interacts with pickable {@link Entity}s.\n *\n * # Contents\n *\n * * [Overview](#overview)\n * * [Examples](#examples)\n * * [Orbit Mode](#orbit-mode)\n * + [Following the Pointer in Orbit Mode](#--following-the-pointer-in-orbit-mode--)\n * + [Showing the Pivot Position](#--showing-the-pivot-position--)\n * + [Axis-Aligned Views in Orbit Mode](#--axis-aligned-views-in-orbit-mode--)\n * + [View-Fitting Entitys in Orbit Mode](#--view-fitting-entitys-in-orbit-mode--)\n * * [First-Person Mode](#first-person-mode)\n * + [Following the Pointer in First-Person Mode](#--following-the-pointer-in-first-person-mode--)\n * + [Constraining Vertical Position in First-Person Mode](#--constraining-vertical-position-in-first-person-mode--)\n * + [Axis-Aligned Views in First-Person Mode](#--axis-aligned-views-in-first-person-mode--)\n * + [View-Fitting Entitys in First-Person Mode](#--view-fitting-entitys-in-first-person-mode--)\n * * [Plan-View Mode](#plan-view-mode)\n * + [Following the Pointer in Plan-View Mode](#--following-the-pointer-in-plan-view-mode--)\n * + [Axis-Aligned Views in Plan-View Mode](#--axis-aligned-views-in-plan-view-mode--)\n * * [CameraControl Events](#cameracontrol-events)\n * + [\"hover\"](#---hover---)\n * + [\"hoverOff\"](#---hoveroff---)\n * + [\"hoverEnter\"](#---hoverenter---)\n * + [\"hoverOut\"](#---hoverout---)\n * + [\"picked\"](#---picked---)\n * + [\"pickedSurface\"](#---pickedsurface---)\n * + [\"pickedNothing\"](#---pickednothing---)\n * + [\"doublePicked\"](#---doublepicked---)\n * + [\"doublePickedSurface\"](#---doublepickedsurface---)\n * + [\"doublePickedNothing\"](#---doublepickednothing---)\n * + [\"rightClick\"](#---rightclick---)\n * * [Custom Keyboard Mappings](#custom-keyboard-mappings)\n *\n * <br><br>\n *\n * # Overview\n *\n * * Each {@link Viewer} has a ````CameraControl````, located at {@link Viewer#cameraControl}.\n * * {@link CameraControl#navMode} selects the navigation mode:\n * * ````\"orbit\"```` rotates the {@link Camera} position about the target.\n * * ````\"firstPerson\"```` rotates the World about the Camera position.\n * * ````\"planView\"```` never rotates, but still allows to pan and dolly, typically for an axis-aligned view.\n * * {@link CameraControl#followPointer} makes the Camera follow the mouse or touch pointer.\n * * {@link CameraControl#constrainVertical} locks the Camera to its current height when in first-person mode.\n * * ````CameraControl```` fires pick events when we hover, click or tap on an {@link Entity}.\n * <br><br>\n *\n * # Examples\n *\n * * [Orbit Navigation - Duplex Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_orbit_Duplex)\n * * [Orbit Navigation - Holter Tower Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_orbit_HolterTower)\n * * [First-Person Navigation - Duplex Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_firstPerson_Duplex)\n * * [First-Person Navigation - Holter Tower Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_firstPerson_HolterTower)\n * * [Plan-view Navigation - Schependomlaan Model](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_planView_Schependomlaan)\n * * [Custom Keyboard Mapping](https://xeokit.github.io/xeokit-sdk/examples/#CameraControl_keyMap)\n * <br><br>\n *\n * # Orbit Mode\n *\n * In orbit mode, ````CameraControl```` orbits the {@link Camera} about the target.\n *\n * To enable orbit mode:\n *\n * ````javascript\n * const cameraControl = myViewer.cameraControl;\n * cameraControl.navMode = \"orbit\";\n * ````\n *\n * Then orbit by:\n *\n * * left-dragging the mouse,\n * * tap-dragging the touch pad, and\n * * pressing arrow keys, or ````Q```` and ````E```` on a QWERTY keyboard, or ````A```` and ````E```` on an AZERTY keyboard.\n * <br><br>\n *\n * Dolly forwards and backwards by:\n *\n * * spinning the mouse wheel,\n * * pinching on the touch pad, and\n * * pressing the ````+```` and ````-```` keys, or ````W```` and ````S```` on a QWERTY keyboard, or ````Z```` and ````S```` for AZERTY.\n * <br><br>\n *\n * Pan horizontally and vertically by:\n *\n * * right-dragging the mouse,\n * * left-dragging the mouse with the SHIFT key down,\n * * tap-dragging the touch pad with SHIFT down,\n * * pressing the ````A````, ````D````, ````Z```` and ````X```` keys on a QWERTY keyboard, and\n * * pressing the ````Q````, ````D````, ````W```` and ````X```` keys on an AZERTY keyboard,\n * <br><br>\n *\n * ## Following the Pointer in Orbit Mode\n *\n * When {@link CameraControl#followPointer} is ````true````in orbiting mode, the mouse or touch pointer will dynamically\n * indicate the target that the {@link Camera} will orbit, as well as dolly to and from.\n *\n * Lets ensure that we're in orbit mode, then enable the {@link Camera} to follow the pointer:\n *\n * ````javascript\n * cameraControl.navMode = \"orbit\";\n * cameraControl.followPointer = true;\n * ````\n *\n * ## Smart Pivoting\n *\n * TODO\n *\n * ## Showing the Pivot Position\n *\n * We can configure {@link CameraControl#pivotElement} with an HTML element to indicate the current\n * pivot position. The indicator will appear momentarily each time we move the {@link Camera} while in orbit mode with\n * {@link CameraControl#followPointer} set ````true````.\n *\n * First we'll define some CSS to style our pivot indicator as a black dot with a white border:\n *\n * ````css\n * .camera-pivot-marker {\n * color: #ffffff;\n * position: absolute;\n * width: 25px;\n * height: 25px;\n * border-radius: 15px;\n * border: 2px solid #ebebeb;\n * background: black;\n * visibility: hidden;\n * box-shadow: 5px 5px 15px 1px #000000;\n * z-index: 10000;\n * pointer-events: none;\n * }\n * ````\n *\n * Then we'll attach our pivot indicator's HTML element to the ````CameraControl````:\n *\n * ````javascript\n * const pivotElement = document.createRange().createContextualFragment(\"<div class='camera-pivot-marker'></div>\").firstChild;\n *\n * document.body.appendChild(pivotElement);\n *\n * cameraControl.pivotElement = pivotElement;\n * ````\n *\n * ## Axis-Aligned Views in Orbit Mode\n *\n * In orbit mode, we can use keys 1-6 to position the {@link Camera} to look at the center of the {@link Scene} from along each of the\n * six World-space axis. Pressing one of these keys will fly the {@link Camera} to the corresponding axis-aligned view.\n *\n * ## View-Fitting Entitys in Orbit Mode\n *\n * When {@link CameraControl#doublePickFlyTo} is ````true````, we can left-double-click or\n * double-tap (ie. \"double-pick\") an {@link Entity} to fit it to view. This will cause the {@link Camera}\n * to fly to that Entity. Our target then becomes the center of that Entity. If we are currently pivoting,\n * then our pivot position is then also set to the Entity center.\n *\n * Disable that behaviour by setting {@link CameraControl#doublePickFlyTo} ````false````.\n *\n * # First-Person Mode\n *\n * In first-person mode, ````CameraControl```` rotates the World about the {@link Camera} position.\n *\n * To enable first-person mode:\n *\n * ````javascript\n * cameraControl.navMode = \"firstPerson\";\n * ````\n *\n * Then rotate by:\n *\n * * left-dragging the mouse,\n * * tap-dragging the touch pad,\n * * pressing arrow keys, or ````Q```` and ````E```` on a QWERTY keyboard, or ````A```` and ````E```` on an AZERTY keyboard.\n * <br><br>\n *\n * Dolly forwards and backwards by:\n *\n * * spinning the mouse wheel,\n * * pinching on the touch pad, and\n * * pressing the ````+```` and ````-```` keys, or ````W```` and ````S```` on a QWERTY keyboard, or ````Z```` and ````S```` for AZERTY.\n * <br><br>\n *\n * Pan left, right, up and down by:\n *\n * * left-dragging or right-dragging the mouse, and\n * * tap-dragging the touch pad with SHIFT down.\n *\n * Pan forwards, backwards, left, right, up and down by pressing the ````WSADZX```` keys on a QWERTY keyboard,\n * or ````WSQDWX```` keys on an AZERTY keyboard.\n * <br><br>\n *\n * ## Following the Pointer in First-Person Mode\n *\n * When {@link CameraControl#followPointer} is ````true```` in first-person mode, the mouse or touch pointer will dynamically\n * indicate the target to which the {@link Camera} will dolly to and from. In first-person mode, however, the World will always rotate\n * about the {@link Camera} position.\n *\n * Lets ensure that we're in first-person mode, then enable the {@link Camera} to follow the pointer:\n *\n * ````javascript\n * cameraControl.navMode = \"firstPerson\";\n * cameraControl.followPointer = true;\n * ````\n *\n * When the pointer is over empty space, the target will remain the last object that the pointer was over.\n *\n * ## Constraining Vertical Position in First-Person Mode\n *\n * In first-person mode, we can lock the {@link Camera} to its current position on the vertical World axis, which is useful for walk-through navigation:\n *\n * ````javascript\n * cameraControl.constrainVertical = true;\n * ````\n *\n * ## Axis-Aligned Views in First-Person Mode\n *\n * In first-person mode we can use keys 1-6 to position the {@link Camera} to look at the center of\n * the {@link Scene} from along each of the six World-space axis. Pressing one of these keys will fly the {@link Camera} to the\n * corresponding axis-aligned view.\n *\n * ## View-Fitting Entitys in First-Person Mode\n *\n * As in orbit mode, when in first-person mode and {@link CameraControl#doublePickFlyTo} is ````true````, we can double-click\n * or double-tap an {@link Entity} (ie. \"double-picking\") to fit it in view. This will cause the {@link Camera} to fly to\n * that Entity. Our target then becomes the center of that Entity.\n *\n * Disable that behaviour by setting {@link CameraControl#doublePickFlyTo} ````false````.\n *\n * # Plan-View Mode\n *\n * In plan-view mode, ````CameraControl```` pans and rotates the {@link Camera}, without rotating it.\n *\n * To enable plan-view mode:\n *\n * ````javascript\n * cameraControl.navMode = \"planView\";\n * ````\n *\n * Dolly forwards and backwards by:\n *\n * * spinning the mouse wheel,\n * * pinching on the touch pad, and\n * * pressing the ````+```` and ````-```` keys.\n *\n * <br>\n * Pan left, right, up and down by:\n *\n * * left-dragging or right-dragging the mouse, and\n * * tap-dragging the touch pad with SHIFT down.\n *\n * Pan forwards, backwards, left, right, up and down by pressing the ````WSADZX```` keys on a QWERTY keyboard,\n * or ````WSQDWX```` keys on an AZERTY keyboard.\n * <br><br>\n *\n * ## Following the Pointer in Plan-View Mode\n *\n * When {@link CameraControl#followPointer} is ````true```` in plan-view mode, the mouse or touch pointer will dynamically\n * indicate the target to which the {@link Camera} will dolly to and from. In plan-view mode, however, the {@link Camera} cannot rotate.\n *\n * Lets ensure that we're in plan-view mode, then enable the {@link Camera} to follow the pointer:\n *\n * ````javascript\n * cameraControl.navMode = \"planView\";\n * cameraControl.followPointer = true; // Default\n * ````\n *\n * When the pointer is over empty space, the target will remain the last object that the pointer was over.\n *\n * ## Axis-Aligned Views in Plan-View Mode\n *\n * As in orbit and first-person modes, in plan-view mode we can use keys 1-6 to position the {@link Camera} to look at the center of\n * the {@link Scene} from along each of the six World-space axis. Pressing one of these keys will fly the {@link Camera} to the\n * corresponding axis-aligned view.\n *\n * # CameraControl Events\n *\n * ````CameraControl```` fires events as we interact with {@link Entity}s using mouse or touch input.\n *\n * The following examples demonstrate how to subscribe to those events.\n *\n * The first example shows how to save a handle to a subscription, which we can later use to unsubscribe.\n *\n * ## \"hover\"\n *\n * Event fired when the pointer moves while hovering over an Entity.\n *\n * ````javascript\n * const onHover = cameraControl.on(\"hover\", (e) => {\n * const entity = e.entity; // Entity\n * const canvasPos = e.canvasPos; // 2D canvas position\n * });\n * ````\n *\n * To unsubscribe from the event:\n *\n * ````javascript\n * cameraControl.off(onHover);\n * ````\n *\n * ## \"hoverOff\"\n *\n * Event fired when the pointer moves while hovering over empty space.\n *\n * ````javascript\n * cameraControl.on(\"hoverOff\", (e) => {\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"hoverEnter\"\n *\n * Event fired when the pointer moves onto an Entity.\n *\n * ````javascript\n * cameraControl.on(\"hoverEnter\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"hoverOut\"\n *\n * Event fired when the pointer moves off an Entity.\n *\n * ````javascript\n * cameraControl.on(\"hoverOut\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"picked\"\n *\n * Event fired when we left-click or tap on an Entity.\n *\n * ````javascript\n * cameraControl.on(\"picked\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"pickedSurface\"\n *\n * Event fired when we left-click or tap on the surface of an Entity.\n *\n * ````javascript\n * cameraControl.on(\"picked\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * const worldPos = e.worldPos; // 3D World-space position\n * const viewPos = e.viewPos; // 3D View-space position\n * const worldNormal = e.worldNormal; // 3D World-space normal vector\n * });\n * ````\n *\n * ## \"pickedNothing\"\n *\n * Event fired when we left-click or tap on empty space.\n *\n * ````javascript\n * cameraControl.on(\"pickedNothing\", (e) => {\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"doublePicked\"\n *\n * Event fired wwhen we left-double-click or double-tap on an Entity.\n *\n * ````javascript\n * cameraControl.on(\"doublePicked\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"doublePickedSurface\"\n *\n * Event fired when we left-double-click or double-tap on the surface of an Entity.\n *\n * ````javascript\n * cameraControl.on(\"doublePickedSurface\", (e) => {\n * const entity = e.entity;\n * const canvasPos = e.canvasPos;\n * const worldPos = e.worldPos;\n * const viewPos = e.viewPos;\n * const worldNormal = e.worldNormal;\n * });\n * ````\n *\n * ## \"doublePickedNothing\"\n *\n * Event fired when we left-double-click or double-tap on empty space.\n *\n * ````javascript\n * cameraControl.on(\"doublePickedNothing\", (e) => {\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## \"rightClick\"\n *\n * Event fired when we right-click on the canvas.\n *\n * ````javascript\n * cameraControl.on(\"rightClick\", (e) => {\n * const event = e.event; // Mouse event\n * const canvasPos = e.canvasPos;\n * });\n * ````\n *\n * ## Custom Keyboard Mappings\n *\n * We can customize````CameraControl```` key bindings as shown below.\n *\n * In this example, we'll just set the default bindings for a QWERTY keyboard.\n *\n * ````javascript\n * const input = myViewer.scene.input;\n *\n * cameraControl.navMode = \"orbit\";\n * cameraControl.followPointer = true;\n *\n * const keyMap = {};\n *\n * keyMap[cameraControl.PAN_LEFT] = [input.KEY_A];\n * keyMap[cameraControl.PAN_RIGHT] = [input.KEY_D];\n * keyMap[cameraControl.PAN_UP] = [input.KEY_Z];\n * keyMap[cameraControl.PAN_DOWN] = [input.KEY_X];\n * keyMap[cameraControl.DOLLY_FORWARDS] = [input.KEY_W, input.KEY_ADD];\n * keyMap[cameraControl.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];\n * keyMap[cameraControl.ROTATE_X_POS] = [input.KEY_DOWN_ARROW];\n * keyMap[cameraControl.ROTATE_X_NEG] = [input.KEY_UP_ARROW];\n * keyMap[cameraControl.ROTATE_Y_POS] = [input.KEY_LEFT_ARROW];\n * keyMap[cameraControl.ROTATE_Y_NEG] = [input.KEY_RIGHT_ARROW];\n * keyMap[cameraControl.AXIS_VIEW_RIGHT] = [input.KEY_NUM_1];\n * keyMap[cameraControl.AXIS_VIEW_BACK] = [input.KEY_NUM_2];\n * keyMap[cameraControl.AXIS_VIEW_LEFT] = [input.KEY_NUM_3];\n * keyMap[cameraControl.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];\n * keyMap[cameraControl.AXIS_VIEW_TOP] = [input.KEY_NUM_5];\n * keyMap[cameraControl.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];\n *\n * cameraControl.keyMap = keyMap;\n * ````\n *\n * We can also just configure default bindings for a specified keyboard layout, like this:\n *\n * ````javascript\n * cameraControl.keyMap = \"qwerty\";\n * ````\n *\n * Then, ````CameraControl```` will internally set {@link CameraControl#keyMap} to the default key map for the QWERTY\n * layout (which is the same set of mappings we set in the previous example). In other words, if we subsequently\n * read {@link CameraControl#keyMap}, it will now be a key map, instead of the \"qwerty\" string value we set it to.\n *\n * Supported layouts are, so far:\n *\n * * ````\"qwerty\"````\n * * ````\"azerty\"````\n */\nclass CameraControl extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\n\t/**\n\t * @private\n\t * @constructor\n\t */\n\tconstructor(owner, cfg = {}) {\n\t\tsuper(owner, cfg);\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_LEFT = 0;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_RIGHT = 1;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_UP = 2;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_DOWN = 3;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_FORWARDS = 4;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.PAN_BACKWARDS = 5;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_X_POS = 6;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_X_NEG = 7;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_Y_POS = 8;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.ROTATE_Y_NEG = 9;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.DOLLY_FORWARDS = 10;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.DOLLY_BACKWARDS = 11;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_RIGHT = 12;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_BACK = 13;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_LEFT = 14;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_FRONT = 15;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_TOP = 16;\n\n\t\t/**\n\t\t * Identifies the XX action.\n\t\t * @final\n\t\t * @type {Number}\n\t\t */\n\t\tthis.AXIS_VIEW_BOTTOM = 17;\n\n\t\tthis._keyMap = {}; // Maps key codes to the above actions\n\n\t\tthis.scene.canvas.canvas.oncontextmenu = (e) => {\n\t\t\te.preventDefault();\n\t\t};\n\n\t\t// User-settable CameraControl configurations\n\n\t\tthis._configs = {\n\t\t\t// Private\n\n\t\t\tlongTapTimeout: 600, // Millisecs\n\t\t\tlongTapRadius: 5, // Pixels\n\n\t\t\t// General\n\n\t\t\tactive: true,\n\t\t\tkeyboardLayout: \"qwerty\",\n\t\t\tnavMode: \"orbit\",\n\t\t\tplanView: false,\n\t\t\tfirstPerson: false,\n\t\t\tfollowPointer: true,\n\t\t\tdoublePickFlyTo: true,\n\t\t\tpanRightClick: true,\n\t\t\tshowPivot: false,\n\t\t\tpointerEnabled: true,\n\t\t\tconstrainVertical: false,\n\t\t\tsmartPivot: false,\n\t\t\tdoubleClickTimeFrame: 250,\n\n\t\t\tsnapToVertex: DEFAULT_SNAP_VERTEX,\n\t\t\tsnapToEdge: DEFAULT_SNAP_EDGE,\n\t\t\tsnapRadius: cfg.snapRadius ? cfg.snapRadius : DEFAULT_SNAP_PICK_RADIUS,\n\n\t\t\t// Rotation\n\n\t\t\tdragRotationRate: 360.0,\n\t\t\tkeyboardRotationRate: 90.0,\n\t\t\trotationInertia: 0.0,\n\n\t\t\t// Panning\n\n\t\t\tkeyboardPanRate: 1.0,\n\t\t\ttouchPanRate: 1.0,\n\t\t\tpanInertia: 0.5,\n\n\t\t\t// Dollying\n\n\t\t\tkeyboardDollyRate: 10,\n\t\t\tmouseWheelDollyRate: 100,\n\t\t\ttouchDollyRate: 0.2,\n\t\t\tdollyInertia: 0,\n\t\t\tdollyProximityThreshold: 30.0,\n\t\t\tdollyMinSpeed: 0.04\n\t\t};\n\n\t\t// Current runtime state of the CameraControl\n\n\t\tthis._states = {\n\t\t\tpointerCanvasPos: _math_math_js__WEBPACK_IMPORTED_MODULE_13__.math.vec2(),\n\t\t\tmouseover: false,\n\t\t\tfollowPointerDirty: true,\n\t\t\tmouseDownClientX: 0,\n\t\t\tmouseDownClientY: 0,\n\t\t\tmouseDownCursorX: 0,\n\t\t\tmouseDownCursorY: 0,\n\t\t\ttouchStartTime: null,\n\t\t\tactiveTouches: [],\n\t\t\ttapStartPos: _math_math_js__WEBPACK_IMPORTED_MODULE_13__.math.vec2(),\n\t\t\ttapStartTime: -1,\n\t\t\tlastTapTime: -1,\n\t\t\tlongTouchTimeout: null\n\t\t};\n\n\t\t// Updates for CameraUpdater to process on next Scene \"tick\" event\n\n\t\tthis._updates = {\n\t\t\trotateDeltaX: 0,\n\t\t\trotateDeltaY: 0,\n\t\t\tpanDeltaX: 0,\n\t\t\tpanDeltaY: 0,\n\t\t\tpanDeltaZ: 0,\n\t\t\tdollyDelta: 0\n\t\t};\n\n\t\t// Controllers to assist input event handlers with controlling the Camera\n\n\t\tconst scene = this.scene;\n\n\t\tthis._controllers = {\n\t\t\tcameraControl: this,\n\t\t\tpickController: new _lib_controllers_PickController_js__WEBPACK_IMPORTED_MODULE_4__.PickController(this, this._configs),\n\t\t\tpivotController: new _lib_controllers_PivotController_js__WEBPACK_IMPORTED_MODULE_3__.PivotController(scene, this._configs),\n\t\t\tpanController: new _lib_controllers_PanController_js__WEBPACK_IMPORTED_MODULE_2__.PanController(scene),\n\t\t\tcameraFlight: new _camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__.CameraFlightAnimation(this, {\n\t\t\t\tduration: 0.5\n\t\t\t})\n\t\t};\n\n\t\t// Input event handlers\n\n\t\tthis._handlers = [\n\t\t\tnew _lib_handlers_MouseMiscHandler_js__WEBPACK_IMPORTED_MODULE_10__.MouseMiscHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_TouchPanRotateAndDollyHandler_js__WEBPACK_IMPORTED_MODULE_11__.TouchPanRotateAndDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_MousePanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_5__.MousePanRotateDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_KeyboardAxisViewHandler_js__WEBPACK_IMPORTED_MODULE_6__.KeyboardAxisViewHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_MousePickHandler_js__WEBPACK_IMPORTED_MODULE_7__.MousePickHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_TouchPickHandler_js__WEBPACK_IMPORTED_MODULE_14__.TouchPickHandler(this.scene, this._controllers, this._configs, this._states, this._updates),\n\t\t\tnew _lib_handlers_KeyboardPanRotateDollyHandler_js__WEBPACK_IMPORTED_MODULE_8__.KeyboardPanRotateDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates)\n\t\t];\n\n\t\t// Applies scheduled updates to the Camera on each Scene \"tick\" event\n\n\t\tthis._cameraUpdater = new _lib_CameraUpdater_js__WEBPACK_IMPORTED_MODULE_9__.CameraUpdater(this.scene, this._controllers, this._configs, this._states, this._updates);\n\n\t\t// Set initial user configurations\n\n\t\tthis.navMode = cfg.navMode;\n\t\tif (cfg.planView) {\n\t\t\tthis.planView = cfg.planView;\n\t\t}\n\t\tthis.constrainVertical = cfg.constrainVertical;\n\t\tif (cfg.keyboardLayout) {\n\t\t\tthis.keyboardLayout = cfg.keyboardLayout; // Deprecated\n\t\t} else {\n\t\t\tthis.keyMap = cfg.keyMap;\n\t\t}\n\t\tthis.doublePickFlyTo = cfg.doublePickFlyTo;\n\t\tthis.panRightClick = cfg.panRightClick;\n\t\tthis.active = cfg.active;\n\t\tthis.followPointer = cfg.followPointer;\n\t\tthis.rotationInertia = cfg.rotationInertia;\n\t\tthis.keyboardPanRate = cfg.keyboardPanRate;\n\t\tthis.touchPanRate = cfg.touchPanRate;\n\t\tthis.keyboardRotationRate = cfg.keyboardRotationRate;\n\t\tthis.dragRotationRate = cfg.dragRotationRate;\n\t\tthis.touchDollyRate = cfg.touchDollyRate;\n\t\tthis.dollyInertia = cfg.dollyInertia;\n\t\tthis.dollyProximityThreshold = cfg.dollyProximityThreshold;\n\t\tthis.dollyMinSpeed = cfg.dollyMinSpeed;\n\t\tthis.panInertia = cfg.panInertia;\n\t\tthis.pointerEnabled = true;\n\t\tthis.keyboardDollyRate = cfg.keyboardDollyRate;\n\t\tthis.mouseWheelDollyRate = cfg.mouseWheelDollyRate;\n\t\tthis._moveRate = 1;\n\t\tthis.scene.on(\"tick\", () => {\n\t\t\t// if (!(this._configs.active && this._configs.pointerEnabled)) return;\n\t\t\t// if (!this._states.mouseover) return;\n\t\t\tif (!(this._goLeft || this._goRight || this._goUp || this._goDown || this._goForward || this._goBackward)) {\n\t\t\t\t// this._inputDirectionCommand = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._goRight) {\n\t\t\t\tthis._updates.panDeltaX += -0.1 * this._moveRate;\n\t\t\t} else if (this._goLeft) {\n\t\t\t\tthis._updates.panDeltaX += 0.1 * this._moveRate;\n\t\t\t}\n\n\t\t\tif (this._goUp) {\n\t\t\t\tthis._updates.panDeltaY += 0.1 * this._moveRate;\n\t\t\t} else if (this._goDown) {\n\t\t\t\tthis._updates.panDeltaY += -0.1 * this._moveRate;\n\t\t\t}\n\n\t\t\tif (this._goForward) {\n\t\t\t\tthis._updates.panDeltaZ += -0.1 * this._moveRate;\n\t\t\t} else if (this._goBackward) {\n\t\t\t\tthis._updates.panDeltaZ += +0.1 * this._moveRate;\n\t\t\t}\n\t\t\tthis._inputDirectionCommand = true;\n\t\t});\n\t}\n\t/**\n\t * 停止漫游\n\t */\n\tsetdirectionChangeCancel() {\n\t\tthis._goLeft = false;\n\t\tthis._goRight = false;\n\t\tthis._goUp = false;\n\t\tthis._goDown = false;\n\t\tthis._goForward = false;\n\t\tthis._goBackward = false;\n\t}\n\n\t/**\n\t * 设置漫游移动速率\n\t * @param {number} rate\n\t */\n\tset moveRate(rate) {\n\t\tthis._moveRate = rate;\n\t}\n\n\t/**\n\t * 漫游向右\n\t * @param {boolean} go\n\t */\n\tset goRight(go) {\n\t\tthis._goRight = go;\n\t}\n\t/**\n\t * 漫游向左\n\t * @param {boolean} go\n\t */\n\tset goLeft(go) {\n\t\tthis._goLeft = go;\n\t}\n\t/**\n\t * 漫游向上\n\t * @param {boolean} go\n\t */\n\tset goUp(go) {\n\t\tthis._goUp = go;\n\t}\n\t/**\n\t * 漫游向下\n\t * @param {boolean} go\n\t */\n\tset goDown(go) {\n\t\tthis._goDown = go;\n\t}\n\t/**\n\t * 漫游向前\n\t * @param {boolean} go\n\t */\n\tset goForward(go) {\n\t\tthis._goForward = go;\n\t}\n\t/**\n\t * 漫游向后\n\t * @param {boolean} go\n\t */\n\tset goBackward(go) {\n\t\tthis._goBackward = go;\n\t}\n\n\tupdatePivotElement() {\n\t\tthis._controllers.pivotController.updatePivotElement();\n\t}\n\n\t/**\n\t * Sets custom mappings of keys to ````CameraControl```` actions.\n\t *\n\t * See class docs for usage.\n\t *\n\t * @param {{Number:Number}|String} value Either a set of new key mappings, or a string to select a keyboard layout,\n\t * which causes ````CameraControl```` to use the default key mappings for that layout.\n\t */\n\tset keyMap(value) {\n\t\tvalue = value || \"qwerty\";\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_12__.utils.isString(value)) {\n\t\t\tconst input = this.scene.input;\n\t\t\tconst keyMap = {};\n\n\t\t\tswitch (value) {\n\t\t\t\tdefault:\n\t\t\t\t\tthis.error(\"Unsupported value for 'keyMap': \" + value + \" defaulting to 'qwerty'\");\n\t\t\t\t// Intentional fall-through to \"qwerty\"\n\t\t\t\tcase \"qwerty\":\n\t\t\t\t\tkeyMap[this.PAN_LEFT] = [input.KEY_A];\n\t\t\t\t\tkeyMap[this.PAN_RIGHT] = [input.KEY_D];\n\t\t\t\t\tkeyMap[this.PAN_UP] = [input.KEY_Z];\n\t\t\t\t\tkeyMap[this.PAN_DOWN] = [input.KEY_X];\n\t\t\t\t\tkeyMap[this.PAN_BACKWARDS] = [];\n\t\t\t\t\tkeyMap[this.PAN_FORWARDS] = [];\n\t\t\t\t\tkeyMap[this.DOLLY_FORWARDS] = [input.KEY_W, input.KEY_ADD];\n\t\t\t\t\tkeyMap[this.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];\n\t\t\t\t\tkeyMap[this.ROTATE_X_POS] = [input.KEY_DOWN_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_X_NEG] = [input.KEY_UP_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_POS] = [input.KEY_Q, input.KEY_LEFT_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_NEG] = [input.KEY_E, input.KEY_RIGHT_ARROW];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_RIGHT] = [input.KEY_NUM_1];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BACK] = [input.KEY_NUM_2];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_LEFT] = [input.KEY_NUM_3];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"azerty\":\n\t\t\t\t\tkeyMap[this.PAN_LEFT] = [input.KEY_Q];\n\t\t\t\t\tkeyMap[this.PAN_RIGHT] = [input.KEY_D];\n\t\t\t\t\tkeyMap[this.PAN_UP] = [input.KEY_W];\n\t\t\t\t\tkeyMap[this.PAN_DOWN] = [input.KEY_X];\n\t\t\t\t\tkeyMap[this.PAN_BACKWARDS] = [];\n\t\t\t\t\tkeyMap[this.PAN_FORWARDS] = [];\n\t\t\t\t\tkeyMap[this.DOLLY_FORWARDS] = [input.KEY_Z, input.KEY_ADD];\n\t\t\t\t\tkeyMap[this.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];\n\t\t\t\t\tkeyMap[this.ROTATE_X_POS] = [input.KEY_DOWN_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_X_NEG] = [input.KEY_UP_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_POS] = [input.KEY_A, input.KEY_LEFT_ARROW];\n\t\t\t\t\tkeyMap[this.ROTATE_Y_NEG] = [input.KEY_E, input.KEY_RIGHT_ARROW];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_RIGHT] = [input.KEY_NUM_1];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BACK] = [input.KEY_NUM_2];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_LEFT] = [input.KEY_NUM_3];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];\n\t\t\t\t\tkeyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis._keyMap = keyMap;\n\t\t} else {\n\t\t\tconst keyMap = value;\n\t\t\tthis._keyMap = keyMap;\n\t\t}\n\t}\n\n\t/**\n\t * Gets custom mappings of keys to {@link CameraControl} actions.\n\t *\n\t * @returns {{Number:Number}} Current key mappings.\n\t */\n\tget keyMap() {\n\t\treturn this._keyMap;\n\t}\n\n\t/**\n\t * Returns true if any keys configured for the given action are down.\n\t * @param action\n\t * @param keyDownMap\n\t * @private\n\t */\n\t_isKeyDownForAction(action, keyDownMap) {\n\t\tconst keys = this._keyMap[action];\n\t\tif (!keys) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!keyDownMap) {\n\t\t\tkeyDownMap = this.scene.input.keyDown;\n\t\t}\n\t\tfor (let i = 0, len = keys.length; i < len; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tif (keyDownMap[key]) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sets the HTMl element to represent the pivot point when {@link CameraControl#followPointer} is true.\n\t *\n\t * See class comments for an example.\n\t *\n\t * @param {HTMLElement} element HTML element representing the pivot point.\n\t */\n\tset pivotElement(element) {\n\t\tthis._controllers.pivotController.setPivotElement(element);\n\t}\n\n\t/**\n\t * Sets if this ````CameraControl```` is active or not.\n\t *\n\t * When inactive, the ````CameraControl```` will not react to input.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @param {Boolean} value Set ````true```` to activate this ````CameraControl````.\n\t */\n\tset active(value) {\n\t\tvalue = value !== false;\n\t\tthis._configs.active = value;\n\t\tthis._handlers[1]._active = value;\n\t\tthis._handlers[5]._active = value;\n\t}\n\n\t/**\n\t * Gets if this ````CameraControl```` is active or not.\n\t *\n\t * When inactive, the ````CameraControl```` will not react to input.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} Returns ````true```` if this ````CameraControl```` is active.\n\t */\n\tget active() {\n\t\treturn this._configs.active;\n\t}\n\n\t/**\n\t * Sets whether the pointer snap to vertex.\n\t *\n\t * @param {boolean} snapToVertex\n\t */\n\tset snapToVertex(snapToVertex) {\n\t\tthis._configs.snapToVertex = !!snapToVertex;\n\t}\n\n\t/**\n\t * Gets whether the pointer snap to vertex.\n\t *\n\t * @returns {boolean}\n\t */\n\tget snapToVertex() {\n\t\treturn this._configs.snapToVertex;\n\t}\n\n\t/**\n\t * Sets whether the pointer snap to edge.\n\t *\n\t * @param {boolean} snapToEdge\n\t */\n\tset snapToEdge(snapToEdge) {\n\t\tthis._configs.snapToEdge = !!snapToEdge;\n\t}\n\n\t/**\n\t * Gets whether the pointer snap to edge.\n\t *\n\t * @returns {boolean}\n\t */\n\tget snapToEdge() {\n\t\treturn this._configs.snapToEdge;\n\t}\n\n\t/**\n\t * Sets the current snap radius for \"hoverSnapOrSurface\" events, to specify whether the radius\n\t * within which the pointer snaps to the nearest vertex or the nearest edge.\n\t *\n\t * Default value is 30 pixels.\n\t *\n\t * @param {Number} snapRadius The snap radius.\n\t */\n\tset snapRadius(snapRadius) {\n\t\tsnapRadius = snapRadius || DEFAULT_SNAP_PICK_RADIUS;\n\t\tthis._configs.snapRadius = snapRadius;\n\t}\n\n\t/**\n\t * Gets the current snap radius.\n\t *\n\t * @returns {Number} The snap radius.\n\t */\n\tget snapRadius() {\n\t\treturn this._configs.snapRadius;\n\t}\n\n\t/**\n\t * Sets the current navigation mode.\n\t *\n\t * Accepted values are:\n\t *\n\t * * \"orbit\" - rotation orbits about the current target or pivot point,\n\t * * \"firstPerson\" - rotation is about the current eye position,\n\t * * \"planView\" - rotation is disabled.\n\t *\n\t * See class comments for more info.\n\t *\n\t * @param {String} navMode The navigation mode: \"orbit\", \"firstPerson\" or \"planView\".\n\t */\n\tset navMode(navMode) {\n\t\tnavMode = navMode || \"orbit\";\n\t\tif (navMode !== \"firstPerson\" && navMode !== \"orbit\" && navMode !== \"planView\") {\n\t\t\tthis.error(\n\t\t\t\t\"Unsupported value for navMode: \" +\n\t\t\t\t\tnavMode +\n\t\t\t\t\t\" - supported values are 'orbit', 'firstPerson' and 'planView' - defaulting to 'orbit'\"\n\t\t\t);\n\t\t\tnavMode = \"orbit\";\n\t\t}\n\t\tthis._configs.firstPerson = navMode === \"firstPerson\";\n\t\tthis._configs.planView = navMode === \"planView\";\n\t\tif (this._configs.firstPerson || this._configs.planView) {\n\t\t\tthis._controllers.pivotController.hidePivot();\n\t\t\tthis._controllers.pivotController.endPivot();\n\t\t}\n\t\tthis._configs.navMode = navMode;\n\t}\n\n\t/**\n\t * Gets the current navigation mode.\n\t *\n\t * @returns {String} The navigation mode: \"orbit\", \"firstPerson\" or \"planView\".\n\t */\n\tget navMode() {\n\t\treturn this._configs.navMode;\n\t}\n\n\t/**\n\t * Sets whether mouse and touch input is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * Disabling mouse and touch input on ````CameraControl```` is useful when we want to temporarily use mouse or\n\t * touch input to interact with some other 3D control, without disturbing the {@link Camera}.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable mouse and touch input.\n\t */\n\tset pointerEnabled(value) {\n\t\tthis._reset();\n\t\tthis._configs.pointerEnabled = !!value;\n\t}\n\n\t_reset() {\n\t\tfor (let i = 0, len = this._handlers.length; i < len; i++) {\n\t\t\tconst handler = this._handlers[i];\n\t\t\tif (handler.reset) {\n\t\t\t\thandler.reset();\n\t\t\t}\n\t\t}\n\n\t\tthis._updates.panDeltaX = 0;\n\t\tthis._updates.panDeltaY = 0;\n\t\tthis._updates.rotateDeltaX = 0;\n\t\tthis._updates.rotateDeltaY = 0;\n\t\tthis._updates.dolyDelta = 0;\n\t}\n\n\t/**\n\t * Gets whether mouse and touch input is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * Disabling mouse and touch input on ````CameraControl```` is desirable when we want to temporarily use mouse or\n\t * touch input to interact with some other 3D control, without interfering with the {@link Camera}.\n\t *\n\t * @returns {Boolean} Returns ````true```` if mouse and touch input is enabled.\n\t */\n\tget pointerEnabled() {\n\t\treturn this._configs.pointerEnabled;\n\t}\n\n\t/**\n\t * Sets whether the {@link Camera} follows the mouse/touch pointer.\n\t *\n\t * In orbiting mode, the Camera will orbit about the pointer, and will dolly to and from the pointer.\n\t *\n\t * In fly-to mode, the Camera will dolly to and from the pointer, however the World will always rotate about the Camera position.\n\t *\n\t * In plan-view mode, the Camera will dolly to and from the pointer, however the Camera will not rotate.\n\t *\n\t * Default is ````true````.\n\t *\n\t * See class comments for more info.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable the Camera to follow the pointer.\n\t */\n\tset followPointer(value) {\n\t\tthis._configs.followPointer = value !== false;\n\t}\n\n\t/**\n\t * Sets whether the {@link Camera} follows the mouse/touch pointer.\n\t *\n\t * In orbiting mode, the Camera will orbit about the pointer, and will dolly to and from the pointer.\n\t *\n\t * In fly-to mode, the Camera will dolly to and from the pointer, however the World will always rotate about the Camera position.\n\t *\n\t * In plan-view mode, the Camera will dolly to and from the pointer, however the Camera will not rotate.\n\t *\n\t * Default is ````true````.\n\t *\n\t * See class comments for more info.\n\t *\n\t * @returns {Boolean} Returns ````true```` if the Camera follows the pointer.\n\t */\n\tget followPointer() {\n\t\treturn this._configs.followPointer;\n\t}\n\n\t/**\n\t * Sets the current World-space 3D target position.\n\t *\n\t * Only applies when {@link CameraControl#followPointer} is ````true````.\n\t *\n\t * @param {Number[]} worldPos The new World-space 3D target position.\n\t */\n\tset pivotPos(worldPos) {\n\t\tthis._controllers.pivotController.setPivotPos(worldPos);\n\t}\n\n\t/**\n\t * Gets the current World-space 3D pivot position.\n\t *\n\t * Only applies when {@link CameraControl#followPointer} is ````true````.\n\t *\n\t * @return {Number[]} worldPos The current World-space 3D pivot position.\n\t */\n\tget pivotPos() {\n\t\treturn this._controllers.pivotController.getPivotPos();\n\t}\n\n\t/**\n\t * @deprecated\n\t * @param {Boolean} value Set ````true```` to enable dolly-to-pointer behaviour.\n\t */\n\tset dollyToPointer(value) {\n\t\tthis.warn(\"dollyToPointer property is deprecated - replaced with followPointer\");\n\t\tthis.followPointer = value;\n\t}\n\n\t/**\n\t * @deprecated\n\t * @returns {Boolean} Returns ````true```` if dolly-to-pointer behaviour is enabled.\n\t */\n\tget dollyToPointer() {\n\t\tthis.warn(\"dollyToPointer property is deprecated - replaced with followPointer\");\n\t\treturn this.followPointer;\n\t}\n\n\t/**\n\t * @deprecated\n\t * @param {Boolean} value Set ````true```` to enable dolly-to-pointer behaviour.\n\t */\n\tset panToPointer(value) {\n\t\tthis.warn(\"panToPointer property is deprecated - replaced with followPointer\");\n\t}\n\n\t/**\n\t * @deprecated\n\t * @returns {Boolean} Returns ````true```` if dolly-to-pointer behaviour is enabled.\n\t */\n\tget panToPointer() {\n\t\tthis.warn(\"panToPointer property is deprecated - replaced with followPointer\");\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sets whether this ````CameraControl```` is in plan-view mode.\n\t *\n\t * When in plan-view mode, rotation is disabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable plan-view mode.\n\t * @deprecated\n\t */\n\tset planView(value) {\n\t\tthis._configs.planView = !!value;\n\t\tthis._configs.firstPerson = false;\n\t\tif (this._configs.planView) {\n\t\t\tthis._controllers.pivotController.hidePivot();\n\t\t\tthis._controllers.pivotController.endPivot();\n\t\t}\n\t\tthis.warn(\"planView property is deprecated - replaced with navMode\");\n\t}\n\n\t/**\n\t * Gets whether this ````CameraControl```` is in plan-view mode.\n\t *\n\t * When in plan-view mode, rotation is disabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @returns {Boolean} Returns ````true```` if plan-view mode is enabled.\n\t * @deprecated\n\t */\n\tget planView() {\n\t\t// this.warn(\"planView property is deprecated - replaced with navMode\");\n\t\treturn this._configs.planView;\n\t}\n\n\t/**\n\t * Sets whether this ````CameraControl```` is in first-person mode.\n\t *\n\t * In \"first person\" mode (disabled by default) the look position rotates about the eye position. Otherwise, {@link Camera#eye} rotates about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable first-person mode.\n\t * @deprecated\n\t */\n\tset firstPerson(value) {\n\t\tthis.warn(\"firstPerson property is deprecated - replaced with navMode\");\n\t\tthis._configs.firstPerson = !!value;\n\t\tthis._configs.planView = false;\n\t\tif (this._configs.firstPerson) {\n\t\t\tthis._controllers.pivotController.hidePivot();\n\t\t\tthis._controllers.pivotController.endPivot();\n\t\t}\n\t}\n\n\t/**\n\t * Gets whether this ````CameraControl```` is in first-person mode.\n\t *\n\t * In \"first person\" mode (disabled by default) the look position rotates about the eye position. Otherwise, {@link Camera#eye} rotates about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * Deprecated - use {@link CameraControl#navMode} instead.\n\t *\n\t * @returns {Boolean} Returns ````true```` if first-person mode is enabled.\n\t * @deprecated\n\t */\n\tget firstPerson() {\n\t\tthis.warn(\"firstPerson property is deprecated - replaced with navMode\");\n\t\treturn this._configs.firstPerson;\n\t}\n\n\t/**\n\t * Sets whether to vertically constrain the {@link Camera} position for first-person navigation.\n\t *\n\t * When set ````true````, this constrains {@link Camera#eye} to its current vertical position.\n\t *\n\t * Only applies when {@link CameraControl#navMode} is ````\"firstPerson\"````.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @param {Boolean} value Set ````true```` to vertically constrain the Camera.\n\t */\n\tset constrainVertical(value) {\n\t\tthis._configs.constrainVertical = !!value;\n\t}\n\n\t/**\n\t * Gets whether to vertically constrain the {@link Camera} position for first-person navigation.\n\t *\n\t * When set ````true````, this constrains {@link Camera#eye} to its current vertical position.\n\t *\n\t * Only applies when {@link CameraControl#navMode} is ````\"firstPerson\"````.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} ````true```` when Camera is vertically constrained.\n\t */\n\tget constrainVertical() {\n\t\treturn this._configs.constrainVertical;\n\t}\n\n\t/**\n\t * Sets whether double-picking an {@link Entity} causes the {@link Camera} to fly to its boundary.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @param {Boolean} value Set ````true```` to enable double-pick-fly-to mode.\n\t */\n\tset doublePickFlyTo(value) {\n\t\tthis._configs.doublePickFlyTo = value !== false;\n\t}\n\n\t/**\n\t * Gets whether double-picking an {@link Entity} causes the {@link Camera} to fly to its boundary.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} Returns ````true```` when double-pick-fly-to mode is enabled.\n\t */\n\tget doublePickFlyTo() {\n\t\treturn this._configs.doublePickFlyTo;\n\t}\n\n\t/**\n\t * Sets whether either right-clicking (true) or middle-clicking (false) pans the {@link Camera}.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @param {Boolean} value Set ````false```` to disable pan on right-click.\n\t */\n\tset panRightClick(value) {\n\t\tthis._configs.panRightClick = value !== false;\n\t}\n\n\t/**\n\t * Gets whether right-clicking pans the {@link Camera}.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} Returns ````false```` when pan on right-click is disabled.\n\t */\n\tget panRightClick() {\n\t\treturn this._configs.panRightClick;\n\t}\n\n\t/**\n\t * Sets a factor in range ````[0..1]```` indicating how much the {@link Camera} keeps moving after you finish rotating it.\n\t *\n\t * A value of ````0.0```` causes it to immediately stop, ````0.5```` causes its movement to decay 50% on each tick,\n\t * while ````1.0```` causes no decay, allowing it continue moving, by the current rate of rotation.\n\t *\n\t * You may choose an inertia of zero when you want be able to precisely rotate the Camera,\n\t * without interference from inertia. Zero inertia can also mean that less frames are rendered while\n\t * you are rotating the Camera.\n\t *\n\t * Default is ````0.0````.\n\t *\n\t * Does not apply when {@link CameraControl#navMode} is ````\"planView\"````, which disallows rotation.\n\t *\n\t * @param {Number} rotationInertia New inertial factor.\n\t */\n\tset rotationInertia(rotationInertia) {\n\t\tthis._configs.rotationInertia = rotationInertia !== undefined && rotationInertia !== null ? rotationInertia : 0.0;\n\t}\n\n\t/**\n\t * Gets the rotation inertia factor.\n\t *\n\t * Default is ````0.0````.\n\t *\n\t * Does not apply when {@link CameraControl#navMode} is ````\"planView\"````, which disallows rotation.\n\t *\n\t * @returns {Number} The inertia factor.\n\t */\n\tget rotationInertia() {\n\t\treturn this._configs.rotationInertia;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} pans each second with keyboard input.\n\t *\n\t * Default is ````5.0````, to pan the Camera ````5.0```` World-space units every second that\n\t * a panning key is depressed. See the ````CameraControl```` class documentation for which keys control\n\t * panning.\n\t *\n\t * Panning direction is aligned to our Camera's orientation. When we pan horizontally, we pan\n\t * to our left and right, when we pan vertically, we pan upwards and downwards, and when we pan forwards\n\t * and backwards, we pan along the direction the Camera is pointing.\n\t *\n\t * Unlike dollying when {@link followPointer} is ````true````, panning does not follow the pointer.\n\t *\n\t * @param {Number} keyboardPanRate The new keyboard pan rate.\n\t */\n\tset keyboardPanRate(keyboardPanRate) {\n\t\tthis._configs.keyboardPanRate = keyboardPanRate !== null && keyboardPanRate !== undefined ? keyboardPanRate : 5.0;\n\t}\n\n\t/**\n\t * Sets how fast the camera pans on touch panning\n\t *\n\t * @param {Number} touchPanRate The new touch pan rate.\n\t */\n\tset touchPanRate(touchPanRate) {\n\t\tthis._configs.touchPanRate = touchPanRate !== null && touchPanRate !== undefined ? touchPanRate : 1.0;\n\t}\n\n\t/**\n\t * Gets how fast the {@link Camera} pans on touch panning\n\t *\n\t * Default is ````1.0````.\n\t *\n\t * @returns {Number} The current touch pan rate.\n\t */\n\tget touchPanRate() {\n\t\treturn this._configs.touchPanRate;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} pans each second with keyboard input.\n\t *\n\t * Default is ````5.0````.\n\t *\n\t * @returns {Number} The current keyboard pan rate.\n\t */\n\tget keyboardPanRate() {\n\t\treturn this._configs.keyboardPanRate;\n\t}\n\n\t/**\n\t * Sets how many degrees per second the {@link Camera} rotates/orbits with keyboard input.\n\t *\n\t * Default is ````90.0````, to rotate/orbit the Camera ````90.0```` degrees every second that\n\t * a rotation key is depressed. See the ````CameraControl```` class documentation for which keys control\n\t * rotation/orbit.\n\t *\n\t * @param {Number} keyboardRotationRate The new keyboard rotation rate.\n\t */\n\tset keyboardRotationRate(keyboardRotationRate) {\n\t\tthis._configs.keyboardRotationRate =\n\t\t\tkeyboardRotationRate !== null && keyboardRotationRate !== undefined ? keyboardRotationRate : 90.0;\n\t}\n\n\t/**\n\t * Sets how many degrees per second the {@link Camera} rotates/orbits with keyboard input.\n\t *\n\t * Default is ````90.0````.\n\t *\n\t * @returns {Number} The current keyboard rotation rate.\n\t */\n\tget keyboardRotationRate() {\n\t\treturn this._configs.keyboardRotationRate;\n\t}\n\n\t/**\n\t * Sets the current drag rotation rate.\n\t *\n\t * This configures how many degrees the {@link Camera} rotates/orbits for a full sweep of the canvas by mouse or touch dragging.\n\t *\n\t * For example, a value of ````360.0```` indicates that the ````Camera```` rotates/orbits ````360.0```` degrees horizontally\n\t * when we sweep the entire width of the canvas.\n\t *\n\t * ````CameraControl```` makes vertical rotation half as sensitive as horizontal rotation, so that we don't tend to\n\t * flip upside-down. Therefore, a value of ````360.0```` rotates/orbits the ````Camera```` through ````180.0```` degrees\n\t * vertically when we sweep the entire height of the canvas.\n\t *\n\t * Default is ````360.0````.\n\t *\n\t * @param {Number} dragRotationRate The new drag rotation rate.\n\t */\n\tset dragRotationRate(dragRotationRate) {\n\t\tthis._configs.dragRotationRate =\n\t\t\tdragRotationRate !== null && dragRotationRate !== undefined ? dragRotationRate : 360.0;\n\t}\n\n\t/**\n\t * Gets the current drag rotation rate.\n\t *\n\t * Default is ````360.0````.\n\t *\n\t * @returns {Number} The current drag rotation rate.\n\t */\n\tget dragRotationRate() {\n\t\treturn this._configs.dragRotationRate;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} dollys each second with keyboard input.\n\t *\n\t * Default is ````15.0````, to dolly the {@link Camera} ````15.0```` World-space units per second while we hold down\n\t * the ````+```` and ````-```` keys.\n\t *\n\t * @param {Number} keyboardDollyRate The new keyboard dolly rate.\n\t */\n\tset keyboardDollyRate(keyboardDollyRate) {\n\t\tthis._configs.keyboardDollyRate =\n\t\t\tkeyboardDollyRate !== null && keyboardDollyRate !== undefined ? keyboardDollyRate : 15.0;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} dollys each second with keyboard input.\n\t *\n\t * Default is ````15.0````.\n\t *\n\t * @returns {Number} The current keyboard dolly rate.\n\t */\n\tget keyboardDollyRate() {\n\t\treturn this._configs.keyboardDollyRate;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} dollys with touch input.\n\t *\n\t * Default is ````0.2````\n\t *\n\t * @param {Number} touchDollyRate The new touch dolly rate.\n\t */\n\tset touchDollyRate(touchDollyRate) {\n\t\tthis._configs.touchDollyRate = touchDollyRate !== null && touchDollyRate !== undefined ? touchDollyRate : 0.2;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} dollys each second with touch input.\n\t *\n\t * Default is ````0.2````.\n\t *\n\t * @returns {Number} The current touch dolly rate.\n\t */\n\tget touchDollyRate() {\n\t\treturn this._configs.touchDollyRate;\n\t}\n\n\t/**\n\t * Sets how much the {@link Camera} dollys each second while the mouse wheel is spinning.\n\t *\n\t * Default is ````100.0````, to dolly the {@link Camera} ````10.0```` World-space units per second as we spin\n\t * the mouse wheel.\n\t *\n\t * @param {Number} mouseWheelDollyRate The new mouse wheel dolly rate.\n\t */\n\tset mouseWheelDollyRate(mouseWheelDollyRate) {\n\t\tthis._configs.mouseWheelDollyRate =\n\t\t\tmouseWheelDollyRate !== null && mouseWheelDollyRate !== undefined ? mouseWheelDollyRate : 100.0;\n\t}\n\n\t/**\n\t * Gets how much the {@link Camera} dollys each second while the mouse wheel is spinning.\n\t *\n\t * Default is ````100.0````.\n\t *\n\t * @returns {Number} The current mouseWheel dolly rate.\n\t */\n\tget mouseWheelDollyRate() {\n\t\treturn this._configs.mouseWheelDollyRate;\n\t}\n\n\t/**\n\t * Sets the dolly inertia factor.\n\t *\n\t * This factor configures how much the {@link Camera} keeps moving after you finish dollying it.\n\t *\n\t * This factor is a value in range ````[0..1]````. A value of ````0.0```` causes dollying to immediately stop,\n\t * ````0.5```` causes dollying to decay 50% on each animation frame, while ````1.0```` causes no decay, which allows dollying\n\t * to continue until further input stops it.\n\t *\n\t * You might set ````dollyInertia```` to zero when you want be able to precisely position or rotate the Camera,\n\t * without interference from inertia. This also means that xeokit renders less frames while dollying the Camera,\n\t * which can improve rendering performance.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @param {Number} dollyInertia New dolly inertia factor.\n\t */\n\tset dollyInertia(dollyInertia) {\n\t\tthis._configs.dollyInertia = dollyInertia !== undefined && dollyInertia !== null ? dollyInertia : 0;\n\t}\n\n\t/**\n\t * Gets the dolly inertia factor.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @returns {Number} The current dolly inertia factor.\n\t */\n\tget dollyInertia() {\n\t\treturn this._configs.dollyInertia;\n\t}\n\n\t/**\n\t * Sets the proximity to the closest object below which dolly speed decreases, and above which dolly speed increases.\n\t *\n\t * Default is ````35.0````.\n\t *\n\t * @param {Number} dollyProximityThreshold New dolly proximity threshold.\n\t */\n\tset dollyProximityThreshold(dollyProximityThreshold) {\n\t\tthis._configs.dollyProximityThreshold =\n\t\t\tdollyProximityThreshold !== undefined && dollyProximityThreshold !== null ? dollyProximityThreshold : 35.0;\n\t}\n\n\t/**\n\t * Gets the proximity to the closest object below which dolly speed decreases, and above which dolly speed increases.\n\t *\n\t * Default is ````35.0````.\n\t *\n\t * @returns {Number} The current dolly proximity threshold.\n\t */\n\tget dollyProximityThreshold() {\n\t\treturn this._configs.dollyProximityThreshold;\n\t}\n\n\t/**\n\t * Sets the minimum dolly speed.\n\t *\n\t * Default is ````0.04````.\n\t *\n\t * @param {Number} dollyMinSpeed New dolly minimum speed.\n\t */\n\tset dollyMinSpeed(dollyMinSpeed) {\n\t\tthis._configs.dollyMinSpeed = dollyMinSpeed !== undefined && dollyMinSpeed !== null ? dollyMinSpeed : 0.04;\n\t}\n\n\t/**\n\t * Gets the minimum dolly speed.\n\t *\n\t * Default is ````0.04````.\n\t *\n\t * @returns {Number} The current minimum dolly speed.\n\t */\n\tget dollyMinSpeed() {\n\t\treturn this._configs.dollyMinSpeed;\n\t}\n\n\t/**\n\t * Sets the pan inertia factor.\n\t *\n\t * This factor configures how much the {@link Camera} keeps moving after you finish panning it.\n\t *\n\t * This factor is a value in range ````[0..1]````. A value of ````0.0```` causes panning to immediately stop,\n\t * ````0.5```` causes panning to decay 50% on each animation frame, while ````1.0```` causes no decay, which allows panning\n\t * to continue until further input stops it.\n\t *\n\t * You might set ````panInertia```` to zero when you want be able to precisely position or rotate the Camera,\n\t * without interference from inertia. This also means that xeokit renders less frames while panning the Camera,\n\t * wich can improve rendering performance.\n\t *\n\t * Default is ````0.5````.\n\t *\n\t * @param {Number} panInertia New pan inertia factor.\n\t */\n\tset panInertia(panInertia) {\n\t\tthis._configs.panInertia = panInertia !== undefined && panInertia !== null ? panInertia : 0.5;\n\t}\n\n\t/**\n\t * Gets the pan inertia factor.\n\t *\n\t * Default is ````0.5````.\n\t *\n\t * @returns {Number} The current pan inertia factor.\n\t */\n\tget panInertia() {\n\t\treturn this._configs.panInertia;\n\t}\n\n\t/**\n\t * Sets the keyboard layout.\n\t *\n\t * Supported layouts are:\n\t *\n\t * * ````\"qwerty\"```` (default)\n\t * * ````\"azerty\"````\n\t *\n\t * @deprecated\n\t * @param {String} value Selects the keyboard layout.\n\t */\n\tset keyboardLayout(value) {\n\t\t// this.warn(\"keyboardLayout property is deprecated - use keyMap property instead\");\n\t\tvalue = value || \"qwerty\";\n\t\tif (value !== \"qwerty\" && value !== \"azerty\") {\n\t\t\tthis.error(\"Unsupported value for keyboardLayout - defaulting to 'qwerty'\");\n\t\t\tvalue = \"qwerty\";\n\t\t}\n\t\tthis._configs.keyboardLayout = value;\n\t\tthis.keyMap = this._configs.keyboardLayout;\n\t}\n\n\t/**\n\t * Gets the keyboard layout.\n\t *\n\t * Supported layouts are:\n\t *\n\t * * ````\"qwerty\"```` (default)\n\t * * ````\"azerty\"````\n\t *\n\t * @deprecated\n\t * @returns {String} The current keyboard layout.\n\t */\n\tget keyboardLayout() {\n\t\treturn this._configs.keyboardLayout;\n\t}\n\n\t/**\n\t * Sets a sphere as the representation of the pivot position.\n\t *\n\t * @param {Object} [cfg] Sphere configuration.\n\t * @param {String} [cfg.size=1] Optional size factor of the sphere. Defaults to 1.\n\t * @param {String} [cfg.material=PhongMaterial] Optional size factor of the sphere. Defaults to a red opaque material.\n\t */\n\tenablePivotSphere(cfg = {}) {\n\t\tthis._controllers.pivotController.enablePivotSphere(cfg);\n\t}\n\n\t/**\n\t * Remove the sphere as the representation of the pivot position.\n\t *\n\t */\n\tdisablePivotSphere() {\n\t\tthis._controllers.pivotController.disablePivotSphere();\n\t}\n\n\t/**\n\t * Sets whether smart default pivoting is enabled.\n\t *\n\t * When ````true````, we'll pivot by default about the 3D position of the mouse/touch pointer on an\n\t * imaginary sphere that's centered at {@link Camera#eye} and sized to the {@link Scene} boundary.\n\t *\n\t * When ````false````, we'll pivot by default about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @param {Boolean} enabled Set ````true```` to pivot by default about the selected point on the virtual sphere, or ````false```` to pivot by default about {@link Camera#look}.\n\t */\n\tset smartPivot(enabled) {\n\t\tthis._configs.smartPivot = enabled !== false;\n\t}\n\n\t/**\n\t * Gets whether smart default pivoting is enabled.\n\t *\n\t * When ````true````, we'll pivot by default about the 3D position of the mouse/touch pointer on an\n\t * imaginary sphere that's centered at {@link Camera#eye} and sized to the {@link Scene} boundary.\n\t *\n\t * When ````false````, we'll pivot by default about {@link Camera#look}.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} Returns ````true```` when pivoting by default about the selected point on the virtual sphere, or ````false```` when pivoting by default about {@link Camera#look}.\n\t */\n\tget smartPivot() {\n\t\treturn this._configs.smartPivot;\n\t}\n\n\t/**\n\t * Sets the double click time frame length in milliseconds.\n\t *\n\t * If two mouse click events occur within this time frame, it is considered a double click.\n\t *\n\t * Default is ````250````\n\t *\n\t * @param {Number} value New double click time frame.\n\t */\n\tset doubleClickTimeFrame(value) {\n\t\tthis._configs.doubleClickTimeFrame = value !== undefined && value !== null ? value : 250;\n\t}\n\n\t/**\n\t * Gets the double click time frame length in milliseconds.\n\t *\n\t * Default is ````250````\n\t *\n\t * @param {Number} value Current double click time frame.\n\t */\n\tget doubleClickTimeFrame() {\n\t\treturn this._configs.doubleClickTimeFrame;\n\t}\n\n\t/**\n\t * Destroys this ````CameraControl````.\n\t * @private\n\t */\n\tdestroy() {\n\t\tthis._destroyHandlers();\n\t\tthis._destroyControllers();\n\t\tthis._cameraUpdater.destroy();\n\t\tsuper.destroy();\n\t}\n\n\t_destroyHandlers() {\n\t\tfor (let i = 0, len = this._handlers.length; i < len; i++) {\n\t\t\tconst handler = this._handlers[i];\n\t\t\tif (handler.destroy) {\n\t\t\t\thandler.destroy();\n\t\t\t}\n\t\t}\n\t}\n\n\t_destroyControllers() {\n\t\tfor (let i = 0, len = this._controllers.length; i < len; i++) {\n\t\t\tconst controller = this._controllers[i];\n\t\t\tif (controller.destroy) {\n\t\t\t\tcontroller.destroy();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/CameraControl.js?");
|
|
2488
2488
|
|
|
2489
2489
|
/***/ }),
|
|
2490
2490
|
|
|
@@ -3354,7 +3354,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3354
3354
|
\****************************************************/
|
|
3355
3355
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3356
3356
|
|
|
3357
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DrawRenderer: () => (/* binding */ DrawRenderer)\n/* harmony export */ });\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n/* harmony import */ var _DrawShaderSource_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./DrawShaderSource.js */ \"./src/viewer/scene/mesh/draw/DrawShaderSource.js\");\n/* harmony import */ var _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../webgl/Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _stats_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../stats.js */ \"./src/viewer/scene/stats.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n/**\r\n * @author xeolabs / https://github.com/xeolabs\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_5__.math.vec3();\r\n\r\nconst ids = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__.Map({});\r\n\r\n/**\r\n * @private\r\n */\r\nconst DrawRenderer = function (hash, mesh) {\r\n this.id = ids.addItem({});\r\n this._hash = hash;\r\n this._scene = mesh.scene;\r\n this._useCount = 0;\r\n this._shaderSource = new _DrawShaderSource_js__WEBPACK_IMPORTED_MODULE_1__.DrawShaderSource(mesh);\r\n this._allocate(mesh);\r\n};\r\n\r\nconst drawRenderers = {};\r\n\r\nDrawRenderer.get = function (mesh) {\r\n const scene = mesh.scene;\r\n const hash = [\r\n scene.canvas.canvas.id,\r\n (scene.gammaInput ? \"gi;\" : \";\") + (scene.gammaOutput ? \"go\" : \"\"),\r\n scene._lightsState.getHash(),\r\n scene._sectionPlanesState.getHash(),\r\n mesh._geometry._state.hash,\r\n mesh._material._state.hash,\r\n mesh._state.drawHash\r\n ].join(\";\");\r\n let renderer = drawRenderers[hash];\r\n if (!renderer) {\r\n renderer = new DrawRenderer(hash, mesh);\r\n if (renderer.errors) {\r\n console.log(renderer.errors.join(\"\\n\"));\r\n return null;\r\n }\r\n drawRenderers[hash] = renderer;\r\n _stats_js__WEBPACK_IMPORTED_MODULE_3__.stats.memory.programs++;\r\n }\r\n renderer._useCount++;\r\n return renderer;\r\n};\r\n\r\nDrawRenderer.prototype.put = function () {\r\n if (--this._useCount === 0) {\r\n ids.removeItem(this.id);\r\n if (this._program) {\r\n this._program.destroy();\r\n }\r\n delete drawRenderers[this._hash];\r\n _stats_js__WEBPACK_IMPORTED_MODULE_3__.stats.memory.programs--;\r\n }\r\n};\r\n\r\nDrawRenderer.prototype.webglContextRestored = function () {\r\n this._program = null;\r\n};\r\n\r\nDrawRenderer.prototype.drawMesh = function (frameCtx, mesh) {\r\n\r\n if (!this._program) {\r\n this._allocate(mesh);\r\n }\r\n\r\n const maxTextureUnits = _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__.WEBGL_INFO.MAX_TEXTURE_UNITS;\r\n const scene = mesh.scene;\r\n const material = mesh._material;\r\n const gl = scene.canvas.gl;\r\n const program = this._program;\r\n const meshState = mesh._state;\r\n const materialState = mesh._material._state;\r\n const geometryState = mesh._geometry._state;\r\n const camera = scene.camera;\r\n const origin = mesh.origin;\r\n const background = meshState.background;\r\n\r\n if (frameCtx.lastProgramId !== this._program.id) {\r\n frameCtx.lastProgramId = this._program.id;\r\n if (background) {\r\n gl.depthFunc(gl.LEQUAL);\r\n }\r\n this._bindProgram(frameCtx);\r\n }\r\n\r\n gl.uniformMatrix4fv(this._uViewMatrix, false, origin ? frameCtx.getRTCViewMatrix(meshState.originHash, origin) : camera.viewMatrix);\r\n gl.uniformMatrix4fv(this._uViewNormalMatrix, false, camera.viewNormalMatrix);\r\n\r\n if (meshState.clippable) {\r\n const numAllocatedSectionPlanes = scene._sectionPlanesState.getNumAllocatedSectionPlanes();\r\n const numSectionPlanes = scene._sectionPlanesState.sectionPlanes.length;\r\n if (numAllocatedSectionPlanes > 0) {\r\n const sectionPlanes = scene._sectionPlanesState.sectionPlanes;\r\n const renderFlags = mesh.renderFlags;\r\n for (let sectionPlaneIndex = 0; sectionPlaneIndex < numAllocatedSectionPlanes; sectionPlaneIndex++) {\r\n const sectionPlaneUniforms = this._uSectionPlanes[sectionPlaneIndex];\r\n if (sectionPlaneUniforms) {\r\n if (sectionPlaneIndex < numSectionPlanes) {\r\n const active = renderFlags.sectionPlanesActivePerLayer[sectionPlaneIndex];\r\n gl.uniform1i(sectionPlaneUniforms.active, active ? 1 : 0);\r\n if (active) {\r\n const sectionPlane = sectionPlanes[sectionPlaneIndex];\r\n if (origin) {\r\n const rtcSectionPlanePos = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_6__.getPlaneRTCPos)(sectionPlane.dist, sectionPlane.dir, origin, tempVec3a);\r\n gl.uniform3fv(sectionPlaneUniforms.pos, rtcSectionPlanePos);\r\n } else {\r\n gl.uniform3fv(sectionPlaneUniforms.pos, sectionPlane.pos);\r\n }\r\n gl.uniform3fv(sectionPlaneUniforms.dir, sectionPlane.dir);\r\n }\r\n } else {\r\n gl.uniform1i(sectionPlaneUniforms.active, 0);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (materialState.id !== this._lastMaterialId) {\r\n\r\n frameCtx.textureUnit = this._baseTextureUnit;\r\n\r\n const backfaces = materialState.backfaces;\r\n if (frameCtx.backfaces !== backfaces) {\r\n if (backfaces) {\r\n gl.disable(gl.CULL_FACE);\r\n } else {\r\n gl.enable(gl.CULL_FACE);\r\n }\r\n frameCtx.backfaces = backfaces;\r\n }\r\n\r\n const frontface = materialState.frontface;\r\n if (frameCtx.frontface !== frontface) {\r\n if (frontface) {\r\n gl.frontFace(gl.CCW);\r\n } else {\r\n gl.frontFace(gl.CW);\r\n }\r\n frameCtx.frontface = frontface;\r\n }\r\n\r\n if (frameCtx.lineWidth !== materialState.lineWidth) {\r\n gl.lineWidth(materialState.lineWidth);\r\n frameCtx.lineWidth = materialState.lineWidth;\r\n }\r\n\r\n if (this._uPointSize) {\r\n gl.uniform1f(this._uPointSize, materialState.pointSize);\r\n }\r\n\r\n switch (materialState.type) {\r\n case \"LambertMaterial\":\r\n if (this._uMaterialAmbient) {\r\n gl.uniform3fv(this._uMaterialAmbient, materialState.ambient);\r\n }\r\n if (this._uMaterialColor) {\r\n gl.uniform4f(this._uMaterialColor, materialState.color[0], materialState.color[1], materialState.color[2], materialState.alpha);\r\n }\r\n if (this._uMaterialEmissive) {\r\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\r\n }\r\n break;\r\n\r\n case \"PhongMaterial\":\r\n if (this._uMaterialShininess) {\r\n gl.uniform1f(this._uMaterialShininess, materialState.shininess);\r\n }\r\n if (this._uMaterialAmbient) {\r\n gl.uniform3fv(this._uMaterialAmbient, materialState.ambient);\r\n }\r\n if (this._uMaterialDiffuse) {\r\n gl.uniform3fv(this._uMaterialDiffuse, materialState.diffuse);\r\n }\r\n if (this._uMaterialSpecular) {\r\n gl.uniform3fv(this._uMaterialSpecular, materialState.specular);\r\n }\r\n if (this._uMaterialEmissive) {\r\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\r\n }\r\n if (this._uAlphaModeCutoff) {\r\n gl.uniform4f(\r\n this._uAlphaModeCutoff,\r\n 1.0 * materialState.alpha,\r\n materialState.alphaMode === 1 ? 1.0 : 0.0,\r\n materialState.alphaCutoff,\r\n 0);\r\n }\r\n if (material._ambientMap && material._ambientMap._state.texture && this._uMaterialAmbientMap) {\r\n program.bindTexture(this._uMaterialAmbientMap, material._ambientMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uMaterialAmbientMapMatrix) {\r\n gl.uniformMatrix4fv(this._uMaterialAmbientMapMatrix, false, material._ambientMap._state.matrix);\r\n }\r\n }\r\n if (material._diffuseMap && material._diffuseMap._state.texture && this._uDiffuseMap) {\r\n program.bindTexture(this._uDiffuseMap, material._diffuseMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uDiffuseMapMatrix) {\r\n gl.uniformMatrix4fv(this._uDiffuseMapMatrix, false, material._diffuseMap._state.matrix);\r\n }\r\n }\r\n if (material._specularMap && material._specularMap._state.texture && this._uSpecularMap) {\r\n program.bindTexture(this._uSpecularMap, material._specularMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uSpecularMapMatrix) {\r\n gl.uniformMatrix4fv(this._uSpecularMapMatrix, false, material._specularMap._state.matrix);\r\n }\r\n }\r\n if (material._emissiveMap && material._emissiveMap._state.texture && this._uEmissiveMap) {\r\n program.bindTexture(this._uEmissiveMap, material._emissiveMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uEmissiveMapMatrix) {\r\n gl.uniformMatrix4fv(this._uEmissiveMapMatrix, false, material._emissiveMap._state.matrix);\r\n }\r\n }\r\n if (material._alphaMap && material._alphaMap._state.texture && this._uAlphaMap) {\r\n program.bindTexture(this._uAlphaMap, material._alphaMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uAlphaMapMatrix) {\r\n gl.uniformMatrix4fv(this._uAlphaMapMatrix, false, material._alphaMap._state.matrix);\r\n }\r\n }\r\n if (material._reflectivityMap && material._reflectivityMap._state.texture && this._uReflectivityMap) {\r\n program.bindTexture(this._uReflectivityMap, material._reflectivityMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n if (this._uReflectivityMapMatrix) {\r\n gl.uniformMatrix4fv(this._uReflectivityMapMatrix, false, material._reflectivityMap._state.matrix);\r\n }\r\n }\r\n if (material._normalMap && material._normalMap._state.texture && this._uNormalMap) {\r\n program.bindTexture(this._uNormalMap, material._normalMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uNormalMapMatrix) {\r\n gl.uniformMatrix4fv(this._uNormalMapMatrix, false, material._normalMap._state.matrix);\r\n }\r\n }\r\n if (material._occlusionMap && material._occlusionMap._state.texture && this._uOcclusionMap) {\r\n program.bindTexture(this._uOcclusionMap, material._occlusionMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uOcclusionMapMatrix) {\r\n gl.uniformMatrix4fv(this._uOcclusionMapMatrix, false, material._occlusionMap._state.matrix);\r\n }\r\n }\r\n if (material._diffuseFresnel) {\r\n if (this._uDiffuseFresnelEdgeBias) {\r\n gl.uniform1f(this._uDiffuseFresnelEdgeBias, material._diffuseFresnel.edgeBias);\r\n }\r\n if (this._uDiffuseFresnelCenterBias) {\r\n gl.uniform1f(this._uDiffuseFresnelCenterBias, material._diffuseFresnel.centerBias);\r\n }\r\n if (this._uDiffuseFresnelEdgeColor) {\r\n gl.uniform3fv(this._uDiffuseFresnelEdgeColor, material._diffuseFresnel.edgeColor);\r\n }\r\n if (this._uDiffuseFresnelCenterColor) {\r\n gl.uniform3fv(this._uDiffuseFresnelCenterColor, material._diffuseFresnel.centerColor);\r\n }\r\n if (this._uDiffuseFresnelPower) {\r\n gl.uniform1f(this._uDiffuseFresnelPower, material._diffuseFresnel.power);\r\n }\r\n }\r\n if (material._specularFresnel) {\r\n if (this._uSpecularFresnelEdgeBias) {\r\n gl.uniform1f(this._uSpecularFresnelEdgeBias, material._specularFresnel.edgeBias);\r\n }\r\n if (this._uSpecularFresnelCenterBias) {\r\n gl.uniform1f(this._uSpecularFresnelCenterBias, material._specularFresnel.centerBias);\r\n }\r\n if (this._uSpecularFresnelEdgeColor) {\r\n gl.uniform3fv(this._uSpecularFresnelEdgeColor, material._specularFresnel.edgeColor);\r\n }\r\n if (this._uSpecularFresnelCenterColor) {\r\n gl.uniform3fv(this._uSpecularFresnelCenterColor, material._specularFresnel.centerColor);\r\n }\r\n if (this._uSpecularFresnelPower) {\r\n gl.uniform1f(this._uSpecularFresnelPower, material._specularFresnel.power);\r\n }\r\n }\r\n if (material._alphaFresnel) {\r\n if (this._uAlphaFresnelEdgeBias) {\r\n gl.uniform1f(this._uAlphaFresnelEdgeBias, material._alphaFresnel.edgeBias);\r\n }\r\n if (this._uAlphaFresnelCenterBias) {\r\n gl.uniform1f(this._uAlphaFresnelCenterBias, material._alphaFresnel.centerBias);\r\n }\r\n if (this._uAlphaFresnelEdgeColor) {\r\n gl.uniform3fv(this._uAlphaFresnelEdgeColor, material._alphaFresnel.edgeColor);\r\n }\r\n if (this._uAlphaFresnelCenterColor) {\r\n gl.uniform3fv(this._uAlphaFresnelCenterColor, material._alphaFresnel.centerColor);\r\n }\r\n if (this._uAlphaFresnelPower) {\r\n gl.uniform1f(this._uAlphaFresnelPower, material._alphaFresnel.power);\r\n }\r\n }\r\n if (material._reflectivityFresnel) {\r\n if (this._uReflectivityFresnelEdgeBias) {\r\n gl.uniform1f(this._uReflectivityFresnelEdgeBias, material._reflectivityFresnel.edgeBias);\r\n }\r\n if (this._uReflectivityFresnelCenterBias) {\r\n gl.uniform1f(this._uReflectivityFresnelCenterBias, material._reflectivityFresnel.centerBias);\r\n }\r\n if (this._uReflectivityFresnelEdgeColor) {\r\n gl.uniform3fv(this._uReflectivityFresnelEdgeColor, material._reflectivityFresnel.edgeColor);\r\n }\r\n if (this._uReflectivityFresnelCenterColor) {\r\n gl.uniform3fv(this._uReflectivityFresnelCenterColor, material._reflectivityFresnel.centerColor);\r\n }\r\n if (this._uReflectivityFresnelPower) {\r\n gl.uniform1f(this._uReflectivityFresnelPower, material._reflectivityFresnel.power);\r\n }\r\n }\r\n if (material._emissiveFresnel) {\r\n if (this._uEmissiveFresnelEdgeBias) {\r\n gl.uniform1f(this._uEmissiveFresnelEdgeBias, material._emissiveFresnel.edgeBias);\r\n }\r\n if (this._uEmissiveFresnelCenterBias) {\r\n gl.uniform1f(this._uEmissiveFresnelCenterBias, material._emissiveFresnel.centerBias);\r\n }\r\n if (this._uEmissiveFresnelEdgeColor) {\r\n gl.uniform3fv(this._uEmissiveFresnelEdgeColor, material._emissiveFresnel.edgeColor);\r\n }\r\n if (this._uEmissiveFresnelCenterColor) {\r\n gl.uniform3fv(this._uEmissiveFresnelCenterColor, material._emissiveFresnel.centerColor);\r\n }\r\n if (this._uEmissiveFresnelPower) {\r\n gl.uniform1f(this._uEmissiveFresnelPower, material._emissiveFresnel.power);\r\n }\r\n }\r\n break;\r\n\r\n case \"MetallicMaterial\":\r\n if (this._uBaseColor) {\r\n gl.uniform3fv(this._uBaseColor, materialState.baseColor);\r\n }\r\n if (this._uMaterialMetallic) {\r\n gl.uniform1f(this._uMaterialMetallic, materialState.metallic);\r\n }\r\n if (this._uMaterialRoughness) {\r\n gl.uniform1f(this._uMaterialRoughness, materialState.roughness);\r\n }\r\n if (this._uMaterialSpecularF0) {\r\n gl.uniform1f(this._uMaterialSpecularF0, materialState.specularF0);\r\n }\r\n if (this._uMaterialEmissive) {\r\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\r\n }\r\n if (this._uAlphaModeCutoff) {\r\n gl.uniform4f(\r\n this._uAlphaModeCutoff,\r\n 1.0 * materialState.alpha,\r\n materialState.alphaMode === 1 ? 1.0 : 0.0,\r\n materialState.alphaCutoff,\r\n 0.0);\r\n }\r\n const baseColorMap = material._baseColorMap;\r\n if (baseColorMap && baseColorMap._state.texture && this._uBaseColorMap) {\r\n program.bindTexture(this._uBaseColorMap, baseColorMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uBaseColorMapMatrix) {\r\n gl.uniformMatrix4fv(this._uBaseColorMapMatrix, false, baseColorMap._state.matrix);\r\n }\r\n }\r\n const metallicMap = material._metallicMap;\r\n if (metallicMap && metallicMap._state.texture && this._uMetallicMap) {\r\n program.bindTexture(this._uMetallicMap, metallicMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uMetallicMapMatrix) {\r\n gl.uniformMatrix4fv(this._uMetallicMapMatrix, false, metallicMap._state.matrix);\r\n }\r\n }\r\n const roughnessMap = material._roughnessMap;\r\n if (roughnessMap && roughnessMap._state.texture && this._uRoughnessMap) {\r\n program.bindTexture(this._uRoughnessMap, roughnessMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uRoughnessMapMatrix) {\r\n gl.uniformMatrix4fv(this._uRoughnessMapMatrix, false, roughnessMap._state.matrix);\r\n }\r\n }\r\n const metallicRoughnessMap = material._metallicRoughnessMap;\r\n if (metallicRoughnessMap && metallicRoughnessMap._state.texture && this._uMetallicRoughnessMap) {\r\n program.bindTexture(this._uMetallicRoughnessMap, metallicRoughnessMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uMetallicRoughnessMapMatrix) {\r\n gl.uniformMatrix4fv(this._uMetallicRoughnessMapMatrix, false, metallicRoughnessMap._state.matrix);\r\n }\r\n }\r\n var emissiveMap = material._emissiveMap;\r\n if (emissiveMap && emissiveMap._state.texture && this._uEmissiveMap) {\r\n program.bindTexture(this._uEmissiveMap, emissiveMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uEmissiveMapMatrix) {\r\n gl.uniformMatrix4fv(this._uEmissiveMapMatrix, false, emissiveMap._state.matrix);\r\n }\r\n }\r\n var occlusionMap = material._occlusionMap;\r\n if (occlusionMap && material._occlusionMap._state.texture && this._uOcclusionMap) {\r\n program.bindTexture(this._uOcclusionMap, occlusionMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uOcclusionMapMatrix) {\r\n gl.uniformMatrix4fv(this._uOcclusionMapMatrix, false, occlusionMap._state.matrix);\r\n }\r\n }\r\n var alphaMap = material._alphaMap;\r\n if (alphaMap && alphaMap._state.texture && this._uAlphaMap) {\r\n program.bindTexture(this._uAlphaMap, alphaMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uAlphaMapMatrix) {\r\n gl.uniformMatrix4fv(this._uAlphaMapMatrix, false, alphaMap._state.matrix);\r\n }\r\n }\r\n var normalMap = material._normalMap;\r\n if (normalMap && normalMap._state.texture && this._uNormalMap) {\r\n program.bindTexture(this._uNormalMap, normalMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uNormalMapMatrix) {\r\n gl.uniformMatrix4fv(this._uNormalMapMatrix, false, normalMap._state.matrix);\r\n }\r\n }\r\n break;\r\n\r\n case \"SpecularMaterial\":\r\n if (this._uMaterialDiffuse) {\r\n gl.uniform3fv(this._uMaterialDiffuse, materialState.diffuse);\r\n }\r\n if (this._uMaterialSpecular) {\r\n gl.uniform3fv(this._uMaterialSpecular, materialState.specular);\r\n }\r\n if (this._uMaterialGlossiness) {\r\n gl.uniform1f(this._uMaterialGlossiness, materialState.glossiness);\r\n }\r\n if (this._uMaterialReflectivity) {\r\n gl.uniform1f(this._uMaterialReflectivity, materialState.reflectivity);\r\n }\r\n if (this._uMaterialEmissive) {\r\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\r\n }\r\n if (this._uAlphaModeCutoff) {\r\n gl.uniform4f(\r\n this._uAlphaModeCutoff,\r\n 1.0 * materialState.alpha,\r\n materialState.alphaMode === 1 ? 1.0 : 0.0,\r\n materialState.alphaCutoff,\r\n 0.0);\r\n }\r\n const diffuseMap = material._diffuseMap;\r\n if (diffuseMap && diffuseMap._state.texture && this._uDiffuseMap) {\r\n program.bindTexture(this._uDiffuseMap, diffuseMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uDiffuseMapMatrix) {\r\n gl.uniformMatrix4fv(this._uDiffuseMapMatrix, false, diffuseMap._state.matrix);\r\n }\r\n }\r\n const specularMap = material._specularMap;\r\n if (specularMap && specularMap._state.texture && this._uSpecularMap) {\r\n program.bindTexture(this._uSpecularMap, specularMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uSpecularMapMatrix) {\r\n gl.uniformMatrix4fv(this._uSpecularMapMatrix, false, specularMap._state.matrix);\r\n }\r\n }\r\n const glossinessMap = material._glossinessMap;\r\n if (glossinessMap && glossinessMap._state.texture && this._uGlossinessMap) {\r\n program.bindTexture(this._uGlossinessMap, glossinessMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uGlossinessMapMatrix) {\r\n gl.uniformMatrix4fv(this._uGlossinessMapMatrix, false, glossinessMap._state.matrix);\r\n }\r\n }\r\n const specularGlossinessMap = material._specularGlossinessMap;\r\n if (specularGlossinessMap && specularGlossinessMap._state.texture && this._uSpecularGlossinessMap) {\r\n program.bindTexture(this._uSpecularGlossinessMap, specularGlossinessMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uSpecularGlossinessMapMatrix) {\r\n gl.uniformMatrix4fv(this._uSpecularGlossinessMapMatrix, false, specularGlossinessMap._state.matrix);\r\n }\r\n }\r\n var emissiveMap = material._emissiveMap;\r\n if (emissiveMap && emissiveMap._state.texture && this._uEmissiveMap) {\r\n program.bindTexture(this._uEmissiveMap, emissiveMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uEmissiveMapMatrix) {\r\n gl.uniformMatrix4fv(this._uEmissiveMapMatrix, false, emissiveMap._state.matrix);\r\n }\r\n }\r\n var occlusionMap = material._occlusionMap;\r\n if (occlusionMap && occlusionMap._state.texture && this._uOcclusionMap) {\r\n program.bindTexture(this._uOcclusionMap, occlusionMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uOcclusionMapMatrix) {\r\n gl.uniformMatrix4fv(this._uOcclusionMapMatrix, false, occlusionMap._state.matrix);\r\n }\r\n }\r\n var alphaMap = material._alphaMap;\r\n if (alphaMap && alphaMap._state.texture && this._uAlphaMap) {\r\n program.bindTexture(this._uAlphaMap, alphaMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uAlphaMapMatrix) {\r\n gl.uniformMatrix4fv(this._uAlphaMapMatrix, false, alphaMap._state.matrix);\r\n }\r\n }\r\n var normalMap = material._normalMap;\r\n if (normalMap && normalMap._state.texture && this._uNormalMap) {\r\n program.bindTexture(this._uNormalMap, normalMap._state.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n if (this._uNormalMapMatrix) {\r\n gl.uniformMatrix4fv(this._uNormalMapMatrix, false, normalMap._state.matrix);\r\n }\r\n }\r\n break;\r\n }\r\n this._lastMaterialId = materialState.id;\r\n }\r\n\r\n gl.uniformMatrix4fv(this._uModelMatrix, gl.FALSE, mesh.worldMatrix);\r\n if (this._uModelNormalMatrix) {\r\n gl.uniformMatrix4fv(this._uModelNormalMatrix, gl.FALSE, mesh.worldNormalMatrix);\r\n }\r\n\r\n if (this._uClippable) {\r\n gl.uniform1i(this._uClippable, meshState.clippable);\r\n }\r\n\r\n if (this._uColorize) {\r\n const colorize = meshState.colorize;\r\n const lastColorize = this._lastColorize;\r\n if (lastColorize[0] !== colorize[0] ||\r\n lastColorize[1] !== colorize[1] ||\r\n lastColorize[2] !== colorize[2] ||\r\n lastColorize[3] !== colorize[3]) {\r\n gl.uniform4fv(this._uColorize, colorize);\r\n lastColorize[0] = colorize[0];\r\n lastColorize[1] = colorize[1];\r\n lastColorize[2] = colorize[2];\r\n lastColorize[3] = colorize[3];\r\n }\r\n }\r\n\r\n gl.uniform3fv(this._uOffset, meshState.offset);\r\n\r\n // Bind VBOs\r\n\r\n if (geometryState.id !== this._lastGeometryId) {\r\n if (this._uPositionsDecodeMatrix) {\r\n gl.uniformMatrix4fv(this._uPositionsDecodeMatrix, false, geometryState.positionsDecodeMatrix);\r\n }\r\n if (this._uUVDecodeMatrix) {\r\n gl.uniformMatrix3fv(this._uUVDecodeMatrix, false, geometryState.uvDecodeMatrix);\r\n }\r\n if (this._aPosition) {\r\n this._aPosition.bindArrayBuffer(geometryState.positionsBuf);\r\n frameCtx.bindArray++;\r\n }\r\n if (this._aNormal) {\r\n this._aNormal.bindArrayBuffer(geometryState.normalsBuf);\r\n frameCtx.bindArray++;\r\n }\r\n if (this._aUV) {\r\n this._aUV.bindArrayBuffer(geometryState.uvBuf);\r\n frameCtx.bindArray++;\r\n }\r\n if (this._aColor) {\r\n this._aColor.bindArrayBuffer(geometryState.colorsBuf);\r\n frameCtx.bindArray++;\r\n }\r\n if (this._aFlags) {\r\n this._aFlags.bindArrayBuffer(geometryState.flagsBuf);\r\n frameCtx.bindArray++;\r\n }\r\n if (geometryState.indicesBuf) {\r\n geometryState.indicesBuf.bind();\r\n frameCtx.bindArray++;\r\n }\r\n this._lastGeometryId = geometryState.id;\r\n }\r\n\r\n // Draw (indices bound in prev step)\r\n\r\n if (geometryState.indicesBuf) {\r\n gl.drawElements(geometryState.primitive, geometryState.indicesBuf.numItems, geometryState.indicesBuf.itemType, 0);\r\n frameCtx.drawElements++;\r\n } else if (geometryState.positions) {\r\n gl.drawArrays(gl.TRIANGLES, 0, geometryState.positions.numItems);\r\n frameCtx.drawArrays++;\r\n }\r\n\r\n if (background) {\r\n gl.depthFunc(gl.LESS);\r\n }\r\n};\r\n\r\nDrawRenderer.prototype._allocate = function (mesh) {\r\n const scene = mesh.scene;\r\n const gl = scene.canvas.gl;\r\n const material = mesh._material;\r\n const lightsState = scene._lightsState;\r\n const sectionPlanesState = scene._sectionPlanesState;\r\n const materialState = mesh._material._state;\r\n\r\n this._program = new _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__.Program(gl, this._shaderSource);\r\n if (this._program.errors) {\r\n this.errors = this._program.errors;\r\n return;\r\n }\r\n const program = this._program;\r\n this._uPositionsDecodeMatrix = program.getLocation(\"positionsDecodeMatrix\");\r\n this._uUVDecodeMatrix = program.getLocation(\"uvDecodeMatrix\");\r\n this._uModelMatrix = program.getLocation(\"modelMatrix\");\r\n this._uModelNormalMatrix = program.getLocation(\"modelNormalMatrix\");\r\n this._uViewMatrix = program.getLocation(\"viewMatrix\");\r\n this._uViewNormalMatrix = program.getLocation(\"viewNormalMatrix\");\r\n this._uProjMatrix = program.getLocation(\"projMatrix\");\r\n this._uGammaFactor = program.getLocation(\"gammaFactor\");\r\n this._uLightAmbient = [];\r\n this._uLightColor = [];\r\n this._uLightDir = [];\r\n this._uLightPos = [];\r\n this._uLightAttenuation = [];\r\n this._uShadowViewMatrix = [];\r\n this._uShadowProjMatrix = [];\r\n\r\n if (scene.logarithmicDepthBufferEnabled) {\r\n this._uLogDepthBufFC = program.getLocation(\"logDepthBufFC\");\r\n }\r\n\r\n const lights = lightsState.lights;\r\n let light;\r\n\r\n for (var i = 0, len = lights.length; i < len; i++) {\r\n light = lights[i];\r\n switch (light.type) {\r\n\r\n case \"ambient\":\r\n this._uLightAmbient[i] = program.getLocation(\"lightAmbient\");\r\n break;\r\n\r\n case \"dir\":\r\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\r\n this._uLightPos[i] = null;\r\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\r\n break;\r\n\r\n case \"point\":\r\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\r\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\r\n this._uLightDir[i] = null;\r\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\r\n break;\r\n\r\n case \"spot\":\r\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\r\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\r\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\r\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\r\n break;\r\n }\r\n\r\n if (light.castsShadow) {\r\n this._uShadowViewMatrix[i] = program.getLocation(\"shadowViewMatrix\" + i);\r\n this._uShadowProjMatrix[i] = program.getLocation(\"shadowProjMatrix\" + i);\r\n }\r\n }\r\n\r\n if (lightsState.lightMaps.length > 0) {\r\n this._uLightMap = \"lightMap\";\r\n }\r\n\r\n if (lightsState.reflectionMaps.length > 0) {\r\n this._uReflectionMap = \"reflectionMap\";\r\n }\r\n\r\n this._uSectionPlanes = [];\r\n const sectionPlanes = sectionPlanesState.sectionPlanes;\r\n for (var i = 0, len = sectionPlanes.length; i < len; i++) {\r\n this._uSectionPlanes.push({\r\n active: program.getLocation(\"sectionPlaneActive\" + i),\r\n pos: program.getLocation(\"sectionPlanePos\" + i),\r\n dir: program.getLocation(\"sectionPlaneDir\" + i)\r\n });\r\n }\r\n\r\n this._uPointSize = program.getLocation(\"pointSize\");\r\n\r\n switch (materialState.type) {\r\n case \"LambertMaterial\":\r\n this._uMaterialColor = program.getLocation(\"materialColor\");\r\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\r\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\r\n break;\r\n\r\n case \"PhongMaterial\":\r\n this._uMaterialAmbient = program.getLocation(\"materialAmbient\");\r\n this._uMaterialDiffuse = program.getLocation(\"materialDiffuse\");\r\n this._uMaterialSpecular = program.getLocation(\"materialSpecular\");\r\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\r\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\r\n this._uMaterialShininess = program.getLocation(\"materialShininess\");\r\n if (material._ambientMap) {\r\n this._uMaterialAmbientMap = \"ambientMap\";\r\n this._uMaterialAmbientMapMatrix = program.getLocation(\"ambientMapMatrix\");\r\n }\r\n if (material._diffuseMap) {\r\n this._uDiffuseMap = \"diffuseMap\";\r\n this._uDiffuseMapMatrix = program.getLocation(\"diffuseMapMatrix\");\r\n }\r\n if (material._specularMap) {\r\n this._uSpecularMap = \"specularMap\";\r\n this._uSpecularMapMatrix = program.getLocation(\"specularMapMatrix\");\r\n }\r\n if (material._emissiveMap) {\r\n this._uEmissiveMap = \"emissiveMap\";\r\n this._uEmissiveMapMatrix = program.getLocation(\"emissiveMapMatrix\");\r\n }\r\n if (material._alphaMap) {\r\n this._uAlphaMap = \"alphaMap\";\r\n this._uAlphaMapMatrix = program.getLocation(\"alphaMapMatrix\");\r\n }\r\n if (material._reflectivityMap) {\r\n this._uReflectivityMap = \"reflectivityMap\";\r\n this._uReflectivityMapMatrix = program.getLocation(\"reflectivityMapMatrix\");\r\n }\r\n if (material._normalMap) {\r\n this._uNormalMap = \"normalMap\";\r\n this._uNormalMapMatrix = program.getLocation(\"normalMapMatrix\");\r\n }\r\n if (material._occlusionMap) {\r\n this._uOcclusionMap = \"occlusionMap\";\r\n this._uOcclusionMapMatrix = program.getLocation(\"occlusionMapMatrix\");\r\n }\r\n if (material._diffuseFresnel) {\r\n this._uDiffuseFresnelEdgeBias = program.getLocation(\"diffuseFresnelEdgeBias\");\r\n this._uDiffuseFresnelCenterBias = program.getLocation(\"diffuseFresnelCenterBias\");\r\n this._uDiffuseFresnelEdgeColor = program.getLocation(\"diffuseFresnelEdgeColor\");\r\n this._uDiffuseFresnelCenterColor = program.getLocation(\"diffuseFresnelCenterColor\");\r\n this._uDiffuseFresnelPower = program.getLocation(\"diffuseFresnelPower\");\r\n }\r\n if (material._specularFresnel) {\r\n this._uSpecularFresnelEdgeBias = program.getLocation(\"specularFresnelEdgeBias\");\r\n this._uSpecularFresnelCenterBias = program.getLocation(\"specularFresnelCenterBias\");\r\n this._uSpecularFresnelEdgeColor = program.getLocation(\"specularFresnelEdgeColor\");\r\n this._uSpecularFresnelCenterColor = program.getLocation(\"specularFresnelCenterColor\");\r\n this._uSpecularFresnelPower = program.getLocation(\"specularFresnelPower\");\r\n }\r\n if (material._alphaFresnel) {\r\n this._uAlphaFresnelEdgeBias = program.getLocation(\"alphaFresnelEdgeBias\");\r\n this._uAlphaFresnelCenterBias = program.getLocation(\"alphaFresnelCenterBias\");\r\n this._uAlphaFresnelEdgeColor = program.getLocation(\"alphaFresnelEdgeColor\");\r\n this._uAlphaFresnelCenterColor = program.getLocation(\"alphaFresnelCenterColor\");\r\n this._uAlphaFresnelPower = program.getLocation(\"alphaFresnelPower\");\r\n }\r\n if (material._reflectivityFresnel) {\r\n this._uReflectivityFresnelEdgeBias = program.getLocation(\"reflectivityFresnelEdgeBias\");\r\n this._uReflectivityFresnelCenterBias = program.getLocation(\"reflectivityFresnelCenterBias\");\r\n this._uReflectivityFresnelEdgeColor = program.getLocation(\"reflectivityFresnelEdgeColor\");\r\n this._uReflectivityFresnelCenterColor = program.getLocation(\"reflectivityFresnelCenterColor\");\r\n this._uReflectivityFresnelPower = program.getLocation(\"reflectivityFresnelPower\");\r\n }\r\n if (material._emissiveFresnel) {\r\n this._uEmissiveFresnelEdgeBias = program.getLocation(\"emissiveFresnelEdgeBias\");\r\n this._uEmissiveFresnelCenterBias = program.getLocation(\"emissiveFresnelCenterBias\");\r\n this._uEmissiveFresnelEdgeColor = program.getLocation(\"emissiveFresnelEdgeColor\");\r\n this._uEmissiveFresnelCenterColor = program.getLocation(\"emissiveFresnelCenterColor\");\r\n this._uEmissiveFresnelPower = program.getLocation(\"emissiveFresnelPower\");\r\n }\r\n break;\r\n\r\n case \"MetallicMaterial\":\r\n this._uBaseColor = program.getLocation(\"materialBaseColor\");\r\n this._uMaterialMetallic = program.getLocation(\"materialMetallic\");\r\n this._uMaterialRoughness = program.getLocation(\"materialRoughness\");\r\n this._uMaterialSpecularF0 = program.getLocation(\"materialSpecularF0\");\r\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\r\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\r\n if (material._baseColorMap) {\r\n this._uBaseColorMap = \"baseColorMap\";\r\n this._uBaseColorMapMatrix = program.getLocation(\"baseColorMapMatrix\");\r\n }\r\n if (material._metallicMap) {\r\n this._uMetallicMap = \"metallicMap\";\r\n this._uMetallicMapMatrix = program.getLocation(\"metallicMapMatrix\");\r\n }\r\n if (material._roughnessMap) {\r\n this._uRoughnessMap = \"roughnessMap\";\r\n this._uRoughnessMapMatrix = program.getLocation(\"roughnessMapMatrix\");\r\n }\r\n if (material._metallicRoughnessMap) {\r\n this._uMetallicRoughnessMap = \"metallicRoughnessMap\";\r\n this._uMetallicRoughnessMapMatrix = program.getLocation(\"metallicRoughnessMapMatrix\");\r\n }\r\n if (material._emissiveMap) {\r\n this._uEmissiveMap = \"emissiveMap\";\r\n this._uEmissiveMapMatrix = program.getLocation(\"emissiveMapMatrix\");\r\n }\r\n if (material._occlusionMap) {\r\n this._uOcclusionMap = \"occlusionMap\";\r\n this._uOcclusionMapMatrix = program.getLocation(\"occlusionMapMatrix\");\r\n }\r\n if (material._alphaMap) {\r\n this._uAlphaMap = \"alphaMap\";\r\n this._uAlphaMapMatrix = program.getLocation(\"alphaMapMatrix\");\r\n }\r\n if (material._normalMap) {\r\n this._uNormalMap = \"normalMap\";\r\n this._uNormalMapMatrix = program.getLocation(\"normalMapMatrix\");\r\n }\r\n break;\r\n\r\n case \"SpecularMaterial\":\r\n this._uMaterialDiffuse = program.getLocation(\"materialDiffuse\");\r\n this._uMaterialSpecular = program.getLocation(\"materialSpecular\");\r\n this._uMaterialGlossiness = program.getLocation(\"materialGlossiness\");\r\n this._uMaterialReflectivity = program.getLocation(\"reflectivityFresnel\");\r\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\r\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\r\n if (material._diffuseMap) {\r\n this._uDiffuseMap = \"diffuseMap\";\r\n this._uDiffuseMapMatrix = program.getLocation(\"diffuseMapMatrix\");\r\n }\r\n if (material._specularMap) {\r\n this._uSpecularMap = \"specularMap\";\r\n this._uSpecularMapMatrix = program.getLocation(\"specularMapMatrix\");\r\n }\r\n if (material._glossinessMap) {\r\n this._uGlossinessMap = \"glossinessMap\";\r\n this._uGlossinessMapMatrix = program.getLocation(\"glossinessMapMatrix\");\r\n }\r\n if (material._specularGlossinessMap) {\r\n this._uSpecularGlossinessMap = \"materialSpecularGlossinessMap\";\r\n this._uSpecularGlossinessMapMatrix = program.getLocation(\"materialSpecularGlossinessMapMatrix\");\r\n }\r\n if (material._emissiveMap) {\r\n this._uEmissiveMap = \"emissiveMap\";\r\n this._uEmissiveMapMatrix = program.getLocation(\"emissiveMapMatrix\");\r\n }\r\n if (material._occlusionMap) {\r\n this._uOcclusionMap = \"occlusionMap\";\r\n this._uOcclusionMapMatrix = program.getLocation(\"occlusionMapMatrix\");\r\n }\r\n if (material._alphaMap) {\r\n this._uAlphaMap = \"alphaMap\";\r\n this._uAlphaMapMatrix = program.getLocation(\"alphaMapMatrix\");\r\n }\r\n if (material._normalMap) {\r\n this._uNormalMap = \"normalMap\";\r\n this._uNormalMapMatrix = program.getLocation(\"normalMapMatrix\");\r\n }\r\n break;\r\n }\r\n\r\n this._aPosition = program.getAttribute(\"position\");\r\n this._aNormal = program.getAttribute(\"normal\");\r\n this._aUV = program.getAttribute(\"uv\");\r\n this._aColor = program.getAttribute(\"color\");\r\n this._aFlags = program.getAttribute(\"flags\");\r\n\r\n this._uClippable = program.getLocation(\"clippable\");\r\n this._uColorize = program.getLocation(\"colorize\");\r\n this._uOffset = program.getLocation(\"offset\");\r\n\r\n this._lastMaterialId = null;\r\n this._lastVertexBufsId = null;\r\n this._lastGeometryId = null;\r\n\r\n this._lastColorize = new Float32Array(4);\r\n\r\n this._baseTextureUnit = 0;\r\n\r\n};\r\n\r\nDrawRenderer.prototype._bindProgram = function (frameCtx) {\r\n\r\n const maxTextureUnits = _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__.WEBGL_INFO.MAX_TEXTURE_UNITS;\r\n const scene = this._scene;\r\n const gl = scene.canvas.gl;\r\n const lightsState = scene._lightsState;\r\n const project = scene.camera.project;\r\n let light;\r\n\r\n const program = this._program;\r\n\r\n program.bind();\r\n\r\n frameCtx.useProgram++;\r\n frameCtx.textureUnit = 0;\r\n\r\n this._lastMaterialId = null;\r\n this._lastVertexBufsId = null;\r\n this._lastGeometryId = null;\r\n\r\n this._lastColorize[0] = -1;\r\n this._lastColorize[1] = -1;\r\n this._lastColorize[2] = -1;\r\n this._lastColorize[3] = -1;\r\n\r\n gl.uniformMatrix4fv(this._uProjMatrix, false, project.matrix);\r\n\r\n if (scene.logarithmicDepthBufferEnabled) {\r\n const logDepthBufFC = 2.0 / (Math.log(project.far + 1.0) / Math.LN2);\r\n gl.uniform1f(this._uLogDepthBufFC, logDepthBufFC);\r\n }\r\n\r\n for (var i = 0, len = lightsState.lights.length; i < len; i++) {\r\n\r\n light = lightsState.lights[i];\r\n\r\n if (this._uLightAmbient[i]) {\r\n gl.uniform4f(this._uLightAmbient[i], light.color[0], light.color[1], light.color[2], light.intensity);\r\n\r\n } else {\r\n\r\n if (this._uLightColor[i]) {\r\n gl.uniform4f(this._uLightColor[i], light.color[0], light.color[1], light.color[2], light.intensity);\r\n }\r\n\r\n if (this._uLightPos[i]) {\r\n gl.uniform3fv(this._uLightPos[i], light.pos);\r\n if (this._uLightAttenuation[i]) {\r\n gl.uniform1f(this._uLightAttenuation[i], light.attenuation);\r\n }\r\n }\r\n\r\n if (this._uLightDir[i]) {\r\n gl.uniform3fv(this._uLightDir[i], light.dir);\r\n }\r\n\r\n if (light.castsShadow) {\r\n if (this._uShadowViewMatrix[i]) {\r\n gl.uniformMatrix4fv(this._uShadowViewMatrix[i], false, light.getShadowViewMatrix());\r\n }\r\n if (this._uShadowProjMatrix[i]) {\r\n gl.uniformMatrix4fv(this._uShadowProjMatrix[i], false, light.getShadowProjMatrix());\r\n }\r\n const shadowRenderBuf = light.getShadowRenderBuf();\r\n if (shadowRenderBuf) {\r\n program.bindTexture(\"shadowMap\" + i, shadowRenderBuf.getTexture(), frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (lightsState.lightMaps.length > 0 && lightsState.lightMaps[0].texture && this._uLightMap) {\r\n program.bindTexture(this._uLightMap, lightsState.lightMaps[0].texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n }\r\n\r\n if (lightsState.reflectionMaps.length > 0 && lightsState.reflectionMaps[0].texture && this._uReflectionMap) {\r\n program.bindTexture(this._uReflectionMap, lightsState.reflectionMaps[0].texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n }\r\n\r\n if (this._uGammaFactor) {\r\n gl.uniform1f(this._uGammaFactor, scene.gammaFactor);\r\n }\r\n\r\n this._baseTextureUnit = frameCtx.textureUnit;\r\n};\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/mesh/draw/DrawRenderer.js?");
|
|
3357
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DrawRenderer: () => (/* binding */ DrawRenderer)\n/* harmony export */ });\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n/* harmony import */ var _DrawShaderSource_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./DrawShaderSource.js */ \"./src/viewer/scene/mesh/draw/DrawShaderSource.js\");\n/* harmony import */ var _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../webgl/Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _stats_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../stats.js */ \"./src/viewer/scene/stats.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n/**\n * @author xeolabs / https://github.com/xeolabs\n */\n\n\n\n\n\n\n\n\n\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_5__.math.vec3();\n\nconst ids = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__.Map({});\n\n/**\n * @private\n */\nconst DrawRenderer = function (hash, mesh) {\n this.id = ids.addItem({});\n this._hash = hash;\n this._scene = mesh.scene;\n this._useCount = 0;\n this._shaderSource = new _DrawShaderSource_js__WEBPACK_IMPORTED_MODULE_1__.DrawShaderSource(mesh);\n this._allocate(mesh);\n};\n\nconst drawRenderers = {};\n\nDrawRenderer.get = function (mesh) {\n const scene = mesh.scene;\n const hash = [\n scene.canvas.canvas.id,\n (scene.gammaInput ? \"gi;\" : \";\") + (scene.gammaOutput ? \"go\" : \"\"),\n scene._lightsState.getHash(),\n scene._sectionPlanesState.getHash(),\n mesh._geometry._state.hash,\n mesh._material._state.hash,\n mesh._state.drawHash\n ].join(\";\");\n let renderer = drawRenderers[hash];\n if (!renderer) {\n renderer = new DrawRenderer(hash, mesh);\n if (renderer.errors) {\n console.log(renderer.errors.join(\"\\n\"));\n return null;\n }\n drawRenderers[hash] = renderer;\n _stats_js__WEBPACK_IMPORTED_MODULE_3__.stats.memory.programs++;\n }\n renderer._useCount++;\n return renderer;\n};\n\nDrawRenderer.prototype.put = function () {\n if (--this._useCount === 0) {\n ids.removeItem(this.id);\n if (this._program) {\n this._program.destroy();\n }\n delete drawRenderers[this._hash];\n _stats_js__WEBPACK_IMPORTED_MODULE_3__.stats.memory.programs--;\n }\n};\n\nDrawRenderer.prototype.webglContextRestored = function () {\n this._program = null;\n};\n\nDrawRenderer.prototype.drawMesh = function (frameCtx, mesh) {\n\n if (!this._program) {\n this._allocate(mesh);\n }\n\n const maxTextureUnits = _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__.WEBGL_INFO.MAX_TEXTURE_UNITS;\n const scene = mesh.scene;\n const material = mesh._material;\n const gl = scene.canvas.gl;\n const program = this._program;\n const meshState = mesh._state;\n const materialState = mesh._material._state;\n const geometryState = mesh._geometry._state;\n const camera = scene.camera;\n const origin = mesh.origin;\n const background = meshState.background;\n\n if (frameCtx.lastProgramId !== this._program.id) {\n frameCtx.lastProgramId = this._program.id;\n if (background) {\n gl.depthFunc(gl.LEQUAL);\n }\n this._bindProgram(frameCtx);\n }\n\n gl.uniformMatrix4fv(this._uViewMatrix, false, origin ? frameCtx.getRTCViewMatrix(meshState.originHash, origin) : camera.viewMatrix);\n gl.uniformMatrix4fv(this._uViewNormalMatrix, false, camera.viewNormalMatrix);\n\n if (meshState.clippable) {\n const numAllocatedSectionPlanes = scene._sectionPlanesState.getNumAllocatedSectionPlanes();\n const numSectionPlanes = scene._sectionPlanesState.sectionPlanes.length;\n if (numAllocatedSectionPlanes > 0) {\n const sectionPlanes = scene._sectionPlanesState.sectionPlanes;\n const renderFlags = mesh.renderFlags;\n for (let sectionPlaneIndex = 0; sectionPlaneIndex < numAllocatedSectionPlanes; sectionPlaneIndex++) {\n const sectionPlaneUniforms = this._uSectionPlanes[sectionPlaneIndex];\n if (sectionPlaneUniforms) {\n if (sectionPlaneIndex < numSectionPlanes) {\n const active = renderFlags.sectionPlanesActivePerLayer[sectionPlaneIndex];\n gl.uniform1i(sectionPlaneUniforms.active, active ? 1 : 0);\n if (active) {\n const sectionPlane = sectionPlanes[sectionPlaneIndex];\n if (origin) {\n const rtcSectionPlanePos = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_6__.getPlaneRTCPos)(sectionPlane.dist, sectionPlane.dir, origin, tempVec3a);\n gl.uniform3fv(sectionPlaneUniforms.pos, rtcSectionPlanePos);\n } else {\n gl.uniform3fv(sectionPlaneUniforms.pos, sectionPlane.pos);\n }\n gl.uniform3fv(sectionPlaneUniforms.dir, sectionPlane.dir);\n }\n } else {\n gl.uniform1i(sectionPlaneUniforms.active, 0);\n }\n }\n }\n }\n }\n\n if (materialState.id !== this._lastMaterialId) {\n\n frameCtx.textureUnit = this._baseTextureUnit;\n\n const backfaces = materialState.backfaces;\n if (frameCtx.backfaces !== backfaces) {\n if (backfaces) {\n gl.disable(gl.CULL_FACE);\n } else {\n gl.enable(gl.CULL_FACE);\n }\n frameCtx.backfaces = backfaces;\n }\n\n const frontface = materialState.frontface;\n if (frameCtx.frontface !== frontface) {\n if (frontface) {\n gl.frontFace(gl.CCW);\n } else {\n gl.frontFace(gl.CW);\n }\n frameCtx.frontface = frontface;\n }\n\n if (frameCtx.lineWidth !== materialState.lineWidth) {\n gl.lineWidth(materialState.lineWidth);\n frameCtx.lineWidth = materialState.lineWidth;\n }\n\n if (this._uPointSize) {\n gl.uniform1f(this._uPointSize, materialState.pointSize);\n }\n\n switch (materialState.type) {\n case \"LambertMaterial\":\n if (this._uMaterialAmbient) {\n gl.uniform3fv(this._uMaterialAmbient, materialState.ambient);\n }\n if (this._uMaterialColor) {\n gl.uniform4f(this._uMaterialColor, materialState.color[0], materialState.color[1], materialState.color[2], materialState.alpha);\n }\n if (this._uMaterialEmissive) {\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\n }\n break;\n\n case \"PhongMaterial\":\n if (this._uMaterialShininess) {\n gl.uniform1f(this._uMaterialShininess, materialState.shininess);\n }\n if (this._uMaterialAmbient) {\n gl.uniform3fv(this._uMaterialAmbient, materialState.ambient);\n }\n if (this._uMaterialDiffuse) {\n gl.uniform3fv(this._uMaterialDiffuse, materialState.diffuse);\n }\n if (this._uMaterialSpecular) {\n gl.uniform3fv(this._uMaterialSpecular, materialState.specular);\n }\n if (this._uMaterialEmissive) {\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\n }\n if (this._uAlphaModeCutoff) {\n gl.uniform4f(\n this._uAlphaModeCutoff,\n 1.0 * materialState.alpha,\n materialState.alphaMode === 1 ? 1.0 : 0.0,\n materialState.alphaCutoff,\n 0);\n }\n if (material._ambientMap && material._ambientMap._state.texture && this._uMaterialAmbientMap) {\n program.bindTexture(this._uMaterialAmbientMap, material._ambientMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uMaterialAmbientMapMatrix) {\n gl.uniformMatrix4fv(this._uMaterialAmbientMapMatrix, false, material._ambientMap._state.matrix);\n }\n }\n if (material._diffuseMap && material._diffuseMap._state.texture && this._uDiffuseMap) {\n program.bindTexture(this._uDiffuseMap, material._diffuseMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uDiffuseMapMatrix) {\n gl.uniformMatrix4fv(this._uDiffuseMapMatrix, false, material._diffuseMap._state.matrix);\n }\n }\n if (material._specularMap && material._specularMap._state.texture && this._uSpecularMap) {\n program.bindTexture(this._uSpecularMap, material._specularMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uSpecularMapMatrix) {\n gl.uniformMatrix4fv(this._uSpecularMapMatrix, false, material._specularMap._state.matrix);\n }\n }\n if (material._emissiveMap && material._emissiveMap._state.texture && this._uEmissiveMap) {\n program.bindTexture(this._uEmissiveMap, material._emissiveMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uEmissiveMapMatrix) {\n gl.uniformMatrix4fv(this._uEmissiveMapMatrix, false, material._emissiveMap._state.matrix);\n }\n }\n if (material._alphaMap && material._alphaMap._state.texture && this._uAlphaMap) {\n program.bindTexture(this._uAlphaMap, material._alphaMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uAlphaMapMatrix) {\n gl.uniformMatrix4fv(this._uAlphaMapMatrix, false, material._alphaMap._state.matrix);\n }\n }\n if (material._reflectivityMap && material._reflectivityMap._state.texture && this._uReflectivityMap) {\n program.bindTexture(this._uReflectivityMap, material._reflectivityMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n if (this._uReflectivityMapMatrix) {\n gl.uniformMatrix4fv(this._uReflectivityMapMatrix, false, material._reflectivityMap._state.matrix);\n }\n }\n if (material._normalMap && material._normalMap._state.texture && this._uNormalMap) {\n program.bindTexture(this._uNormalMap, material._normalMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uNormalMapMatrix) {\n gl.uniformMatrix4fv(this._uNormalMapMatrix, false, material._normalMap._state.matrix);\n }\n }\n if (material._occlusionMap && material._occlusionMap._state.texture && this._uOcclusionMap) {\n program.bindTexture(this._uOcclusionMap, material._occlusionMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uOcclusionMapMatrix) {\n gl.uniformMatrix4fv(this._uOcclusionMapMatrix, false, material._occlusionMap._state.matrix);\n }\n }\n if (material._diffuseFresnel) {\n if (this._uDiffuseFresnelEdgeBias) {\n gl.uniform1f(this._uDiffuseFresnelEdgeBias, material._diffuseFresnel.edgeBias);\n }\n if (this._uDiffuseFresnelCenterBias) {\n gl.uniform1f(this._uDiffuseFresnelCenterBias, material._diffuseFresnel.centerBias);\n }\n if (this._uDiffuseFresnelEdgeColor) {\n gl.uniform3fv(this._uDiffuseFresnelEdgeColor, material._diffuseFresnel.edgeColor);\n }\n if (this._uDiffuseFresnelCenterColor) {\n gl.uniform3fv(this._uDiffuseFresnelCenterColor, material._diffuseFresnel.centerColor);\n }\n if (this._uDiffuseFresnelPower) {\n gl.uniform1f(this._uDiffuseFresnelPower, material._diffuseFresnel.power);\n }\n }\n if (material._specularFresnel) {\n if (this._uSpecularFresnelEdgeBias) {\n gl.uniform1f(this._uSpecularFresnelEdgeBias, material._specularFresnel.edgeBias);\n }\n if (this._uSpecularFresnelCenterBias) {\n gl.uniform1f(this._uSpecularFresnelCenterBias, material._specularFresnel.centerBias);\n }\n if (this._uSpecularFresnelEdgeColor) {\n gl.uniform3fv(this._uSpecularFresnelEdgeColor, material._specularFresnel.edgeColor);\n }\n if (this._uSpecularFresnelCenterColor) {\n gl.uniform3fv(this._uSpecularFresnelCenterColor, material._specularFresnel.centerColor);\n }\n if (this._uSpecularFresnelPower) {\n gl.uniform1f(this._uSpecularFresnelPower, material._specularFresnel.power);\n }\n }\n if (material._alphaFresnel) {\n if (this._uAlphaFresnelEdgeBias) {\n gl.uniform1f(this._uAlphaFresnelEdgeBias, material._alphaFresnel.edgeBias);\n }\n if (this._uAlphaFresnelCenterBias) {\n gl.uniform1f(this._uAlphaFresnelCenterBias, material._alphaFresnel.centerBias);\n }\n if (this._uAlphaFresnelEdgeColor) {\n gl.uniform3fv(this._uAlphaFresnelEdgeColor, material._alphaFresnel.edgeColor);\n }\n if (this._uAlphaFresnelCenterColor) {\n gl.uniform3fv(this._uAlphaFresnelCenterColor, material._alphaFresnel.centerColor);\n }\n if (this._uAlphaFresnelPower) {\n gl.uniform1f(this._uAlphaFresnelPower, material._alphaFresnel.power);\n }\n }\n if (material._reflectivityFresnel) {\n if (this._uReflectivityFresnelEdgeBias) {\n gl.uniform1f(this._uReflectivityFresnelEdgeBias, material._reflectivityFresnel.edgeBias);\n }\n if (this._uReflectivityFresnelCenterBias) {\n gl.uniform1f(this._uReflectivityFresnelCenterBias, material._reflectivityFresnel.centerBias);\n }\n if (this._uReflectivityFresnelEdgeColor) {\n gl.uniform3fv(this._uReflectivityFresnelEdgeColor, material._reflectivityFresnel.edgeColor);\n }\n if (this._uReflectivityFresnelCenterColor) {\n gl.uniform3fv(this._uReflectivityFresnelCenterColor, material._reflectivityFresnel.centerColor);\n }\n if (this._uReflectivityFresnelPower) {\n gl.uniform1f(this._uReflectivityFresnelPower, material._reflectivityFresnel.power);\n }\n }\n if (material._emissiveFresnel) {\n if (this._uEmissiveFresnelEdgeBias) {\n gl.uniform1f(this._uEmissiveFresnelEdgeBias, material._emissiveFresnel.edgeBias);\n }\n if (this._uEmissiveFresnelCenterBias) {\n gl.uniform1f(this._uEmissiveFresnelCenterBias, material._emissiveFresnel.centerBias);\n }\n if (this._uEmissiveFresnelEdgeColor) {\n gl.uniform3fv(this._uEmissiveFresnelEdgeColor, material._emissiveFresnel.edgeColor);\n }\n if (this._uEmissiveFresnelCenterColor) {\n gl.uniform3fv(this._uEmissiveFresnelCenterColor, material._emissiveFresnel.centerColor);\n }\n if (this._uEmissiveFresnelPower) {\n gl.uniform1f(this._uEmissiveFresnelPower, material._emissiveFresnel.power);\n }\n }\n break;\n\n case \"MetallicMaterial\":\n if (this._uBaseColor) {\n gl.uniform3fv(this._uBaseColor, materialState.baseColor);\n }\n if (this._uMaterialMetallic) {\n gl.uniform1f(this._uMaterialMetallic, materialState.metallic);\n }\n if (this._uMaterialRoughness) {\n gl.uniform1f(this._uMaterialRoughness, materialState.roughness);\n }\n if (this._uMaterialSpecularF0) {\n gl.uniform1f(this._uMaterialSpecularF0, materialState.specularF0);\n }\n if (this._uMaterialEmissive) {\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\n }\n if (this._uAlphaModeCutoff) {\n gl.uniform4f(\n this._uAlphaModeCutoff,\n 1.0 * materialState.alpha,\n materialState.alphaMode === 1 ? 1.0 : 0.0,\n materialState.alphaCutoff,\n 0.0);\n }\n const baseColorMap = material._baseColorMap;\n if (baseColorMap && baseColorMap._state.texture && this._uBaseColorMap) {\n program.bindTexture(this._uBaseColorMap, baseColorMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uBaseColorMapMatrix) {\n gl.uniformMatrix4fv(this._uBaseColorMapMatrix, false, baseColorMap._state.matrix);\n }\n }\n const metallicMap = material._metallicMap;\n if (metallicMap && metallicMap._state.texture && this._uMetallicMap) {\n program.bindTexture(this._uMetallicMap, metallicMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uMetallicMapMatrix) {\n gl.uniformMatrix4fv(this._uMetallicMapMatrix, false, metallicMap._state.matrix);\n }\n }\n const roughnessMap = material._roughnessMap;\n if (roughnessMap && roughnessMap._state.texture && this._uRoughnessMap) {\n program.bindTexture(this._uRoughnessMap, roughnessMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uRoughnessMapMatrix) {\n gl.uniformMatrix4fv(this._uRoughnessMapMatrix, false, roughnessMap._state.matrix);\n }\n }\n const metallicRoughnessMap = material._metallicRoughnessMap;\n if (metallicRoughnessMap && metallicRoughnessMap._state.texture && this._uMetallicRoughnessMap) {\n program.bindTexture(this._uMetallicRoughnessMap, metallicRoughnessMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uMetallicRoughnessMapMatrix) {\n gl.uniformMatrix4fv(this._uMetallicRoughnessMapMatrix, false, metallicRoughnessMap._state.matrix);\n }\n }\n var emissiveMap = material._emissiveMap;\n if (emissiveMap && emissiveMap._state.texture && this._uEmissiveMap) {\n program.bindTexture(this._uEmissiveMap, emissiveMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uEmissiveMapMatrix) {\n gl.uniformMatrix4fv(this._uEmissiveMapMatrix, false, emissiveMap._state.matrix);\n }\n }\n var occlusionMap = material._occlusionMap;\n if (occlusionMap && material._occlusionMap._state.texture && this._uOcclusionMap) {\n program.bindTexture(this._uOcclusionMap, occlusionMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uOcclusionMapMatrix) {\n gl.uniformMatrix4fv(this._uOcclusionMapMatrix, false, occlusionMap._state.matrix);\n }\n }\n var alphaMap = material._alphaMap;\n if (alphaMap && alphaMap._state.texture && this._uAlphaMap) {\n program.bindTexture(this._uAlphaMap, alphaMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uAlphaMapMatrix) {\n gl.uniformMatrix4fv(this._uAlphaMapMatrix, false, alphaMap._state.matrix);\n }\n }\n var normalMap = material._normalMap;\n if (normalMap && normalMap._state.texture && this._uNormalMap) {\n program.bindTexture(this._uNormalMap, normalMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uNormalMapMatrix) {\n gl.uniformMatrix4fv(this._uNormalMapMatrix, false, normalMap._state.matrix);\n }\n }\n break;\n\n case \"SpecularMaterial\":\n if (this._uMaterialDiffuse) {\n gl.uniform3fv(this._uMaterialDiffuse, materialState.diffuse);\n }\n if (this._uMaterialSpecular) {\n gl.uniform3fv(this._uMaterialSpecular, materialState.specular);\n }\n if (this._uMaterialGlossiness) {\n gl.uniform1f(this._uMaterialGlossiness, materialState.glossiness);\n }\n if (this._uMaterialReflectivity) {\n gl.uniform1f(this._uMaterialReflectivity, materialState.reflectivity);\n }\n if (this._uMaterialEmissive) {\n gl.uniform3fv(this._uMaterialEmissive, materialState.emissive);\n }\n if (this._uAlphaModeCutoff) {\n gl.uniform4f(\n this._uAlphaModeCutoff,\n 1.0 * materialState.alpha,\n materialState.alphaMode === 1 ? 1.0 : 0.0,\n materialState.alphaCutoff,\n 0.0);\n }\n const diffuseMap = material._diffuseMap;\n if (diffuseMap && diffuseMap._state.texture && this._uDiffuseMap) {\n program.bindTexture(this._uDiffuseMap, diffuseMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uDiffuseMapMatrix) {\n gl.uniformMatrix4fv(this._uDiffuseMapMatrix, false, diffuseMap._state.matrix);\n }\n }\n const specularMap = material._specularMap;\n if (specularMap && specularMap._state.texture && this._uSpecularMap) {\n program.bindTexture(this._uSpecularMap, specularMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uSpecularMapMatrix) {\n gl.uniformMatrix4fv(this._uSpecularMapMatrix, false, specularMap._state.matrix);\n }\n }\n const glossinessMap = material._glossinessMap;\n if (glossinessMap && glossinessMap._state.texture && this._uGlossinessMap) {\n program.bindTexture(this._uGlossinessMap, glossinessMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uGlossinessMapMatrix) {\n gl.uniformMatrix4fv(this._uGlossinessMapMatrix, false, glossinessMap._state.matrix);\n }\n }\n const specularGlossinessMap = material._specularGlossinessMap;\n if (specularGlossinessMap && specularGlossinessMap._state.texture && this._uSpecularGlossinessMap) {\n program.bindTexture(this._uSpecularGlossinessMap, specularGlossinessMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uSpecularGlossinessMapMatrix) {\n gl.uniformMatrix4fv(this._uSpecularGlossinessMapMatrix, false, specularGlossinessMap._state.matrix);\n }\n }\n var emissiveMap = material._emissiveMap;\n if (emissiveMap && emissiveMap._state.texture && this._uEmissiveMap) {\n program.bindTexture(this._uEmissiveMap, emissiveMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uEmissiveMapMatrix) {\n gl.uniformMatrix4fv(this._uEmissiveMapMatrix, false, emissiveMap._state.matrix);\n }\n }\n var occlusionMap = material._occlusionMap;\n if (occlusionMap && occlusionMap._state.texture && this._uOcclusionMap) {\n program.bindTexture(this._uOcclusionMap, occlusionMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uOcclusionMapMatrix) {\n gl.uniformMatrix4fv(this._uOcclusionMapMatrix, false, occlusionMap._state.matrix);\n }\n }\n var alphaMap = material._alphaMap;\n if (alphaMap && alphaMap._state.texture && this._uAlphaMap) {\n program.bindTexture(this._uAlphaMap, alphaMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uAlphaMapMatrix) {\n gl.uniformMatrix4fv(this._uAlphaMapMatrix, false, alphaMap._state.matrix);\n }\n }\n var normalMap = material._normalMap;\n if (normalMap && normalMap._state.texture && this._uNormalMap) {\n program.bindTexture(this._uNormalMap, normalMap._state.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n if (this._uNormalMapMatrix) {\n gl.uniformMatrix4fv(this._uNormalMapMatrix, false, normalMap._state.matrix);\n }\n }\n break;\n }\n this._lastMaterialId = materialState.id;\n }\n\n gl.uniformMatrix4fv(this._uModelMatrix, gl.FALSE, mesh.worldMatrix);\n if (this._uModelNormalMatrix) {\n gl.uniformMatrix4fv(this._uModelNormalMatrix, gl.FALSE, mesh.worldNormalMatrix);\n }\n\n if (this._uClippable) {\n gl.uniform1i(this._uClippable, meshState.clippable);\n }\n\n if (this._uColorize) {\n const colorize = meshState.colorize;\n const lastColorize = this._lastColorize;\n if (lastColorize[0] !== colorize[0] ||\n lastColorize[1] !== colorize[1] ||\n lastColorize[2] !== colorize[2] ||\n lastColorize[3] !== colorize[3]) {\n gl.uniform4fv(this._uColorize, colorize);\n lastColorize[0] = colorize[0];\n lastColorize[1] = colorize[1];\n lastColorize[2] = colorize[2];\n lastColorize[3] = colorize[3];\n }\n }\n\n gl.uniform3fv(this._uOffset, meshState.offset);\n\n // Bind VBOs\n\n if (geometryState.id !== this._lastGeometryId) {\n if (this._uPositionsDecodeMatrix) {\n gl.uniformMatrix4fv(this._uPositionsDecodeMatrix, false, geometryState.positionsDecodeMatrix);\n }\n if (this._uUVDecodeMatrix) {\n gl.uniformMatrix3fv(this._uUVDecodeMatrix, false, geometryState.uvDecodeMatrix);\n }\n if (this._aPosition) {\n this._aPosition.bindArrayBuffer(geometryState.positionsBuf);\n frameCtx.bindArray++;\n }\n if (this._aNormal) {\n this._aNormal.bindArrayBuffer(geometryState.normalsBuf);\n frameCtx.bindArray++;\n }\n if (this._aUV) {\n this._aUV.bindArrayBuffer(geometryState.uvBuf);\n frameCtx.bindArray++;\n }\n if (this._aColor) {\n this._aColor.bindArrayBuffer(geometryState.colorsBuf);\n frameCtx.bindArray++;\n }\n if (this._aFlags) {\n this._aFlags.bindArrayBuffer(geometryState.flagsBuf);\n frameCtx.bindArray++;\n }\n if (geometryState.indicesBuf) {\n geometryState.indicesBuf.bind();\n frameCtx.bindArray++;\n }\n this._lastGeometryId = geometryState.id;\n }\n\n // Draw (indices bound in prev step)\n\n if (geometryState.indicesBuf) {\n gl.drawElements(geometryState.primitive, geometryState.indicesBuf.numItems, geometryState.indicesBuf.itemType, 0);\n frameCtx.drawElements++;\n } else if (geometryState.positions) {\n gl.drawArrays(gl.TRIANGLES, 0, geometryState.positions.numItems);\n frameCtx.drawArrays++;\n }\n\n if (background) {\n gl.depthFunc(gl.LESS);\n }\n};\n\nDrawRenderer.prototype._allocate = function (mesh) {\n const scene = mesh.scene;\n const gl = scene.canvas.gl;\n const material = mesh._material;\n const lightsState = scene._lightsState;\n const sectionPlanesState = scene._sectionPlanesState;\n const materialState = mesh._material._state;\n\n this._program = new _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__.Program(gl, this._shaderSource);\n if (this._program.errors) {\n this.errors = this._program.errors;\n return;\n }\n const program = this._program;\n this._uPositionsDecodeMatrix = program.getLocation(\"positionsDecodeMatrix\");\n this._uUVDecodeMatrix = program.getLocation(\"uvDecodeMatrix\");\n this._uModelMatrix = program.getLocation(\"modelMatrix\");\n this._uModelNormalMatrix = program.getLocation(\"modelNormalMatrix\");\n this._uViewMatrix = program.getLocation(\"viewMatrix\");\n this._uViewNormalMatrix = program.getLocation(\"viewNormalMatrix\");\n this._uProjMatrix = program.getLocation(\"projMatrix\");\n this._uGammaFactor = program.getLocation(\"gammaFactor\");\n this._uLightAmbient = [];\n this._uLightColor = [];\n this._uLightDir = [];\n this._uLightPos = [];\n this._uLightAttenuation = [];\n this._uShadowViewMatrix = [];\n this._uShadowProjMatrix = [];\n\n if (scene.logarithmicDepthBufferEnabled) {\n this._uLogDepthBufFC = program.getLocation(\"logDepthBufFC\");\n }\n\n const lights = lightsState.lights;\n let light;\n\n for (var i = 0, len = lights.length; i < len; i++) {\n light = lights[i];\n switch (light.type) {\n\n case \"ambient\":\n this._uLightAmbient[i] = program.getLocation(\"lightAmbient\");\n break;\n\n case \"dir\":\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\n this._uLightPos[i] = null;\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\n break;\n\n case \"point\":\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\n this._uLightDir[i] = null;\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\n break;\n\n case \"spot\":\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\n break;\n }\n\n if (light.castsShadow) {\n this._uShadowViewMatrix[i] = program.getLocation(\"shadowViewMatrix\" + i);\n this._uShadowProjMatrix[i] = program.getLocation(\"shadowProjMatrix\" + i);\n }\n }\n\n if (lightsState.lightMaps.length > 0) {\n this._uLightMap = \"lightMap\";\n }\n\n if (lightsState.reflectionMaps.length > 0) {\n this._uReflectionMap = \"reflectionMap\";\n }\n\n this._uSectionPlanes = [];\n const sectionPlanes = sectionPlanesState.sectionPlanes;\n for (var i = 0, len = sectionPlanes.length; i < len; i++) {\n this._uSectionPlanes.push({\n active: program.getLocation(\"sectionPlaneActive\" + i),\n pos: program.getLocation(\"sectionPlanePos\" + i),\n dir: program.getLocation(\"sectionPlaneDir\" + i)\n });\n }\n\n this._uPointSize = program.getLocation(\"pointSize\");\n\n switch (materialState.type) {\n case \"LambertMaterial\":\n this._uMaterialColor = program.getLocation(\"materialColor\");\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\n break;\n\n case \"PhongMaterial\":\n this._uMaterialAmbient = program.getLocation(\"materialAmbient\");\n this._uMaterialDiffuse = program.getLocation(\"materialDiffuse\");\n this._uMaterialSpecular = program.getLocation(\"materialSpecular\");\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\n this._uMaterialShininess = program.getLocation(\"materialShininess\");\n if (material._ambientMap) {\n this._uMaterialAmbientMap = \"ambientMap\";\n this._uMaterialAmbientMapMatrix = program.getLocation(\"ambientMapMatrix\");\n }\n if (material._diffuseMap) {\n this._uDiffuseMap = \"diffuseMap\";\n this._uDiffuseMapMatrix = program.getLocation(\"diffuseMapMatrix\");\n }\n if (material._specularMap) {\n this._uSpecularMap = \"specularMap\";\n this._uSpecularMapMatrix = program.getLocation(\"specularMapMatrix\");\n }\n if (material._emissiveMap) {\n this._uEmissiveMap = \"emissiveMap\";\n this._uEmissiveMapMatrix = program.getLocation(\"emissiveMapMatrix\");\n }\n if (material._alphaMap) {\n this._uAlphaMap = \"alphaMap\";\n this._uAlphaMapMatrix = program.getLocation(\"alphaMapMatrix\");\n }\n if (material._reflectivityMap) {\n this._uReflectivityMap = \"reflectivityMap\";\n this._uReflectivityMapMatrix = program.getLocation(\"reflectivityMapMatrix\");\n }\n if (material._normalMap) {\n this._uNormalMap = \"normalMap\";\n this._uNormalMapMatrix = program.getLocation(\"normalMapMatrix\");\n }\n if (material._occlusionMap) {\n this._uOcclusionMap = \"occlusionMap\";\n this._uOcclusionMapMatrix = program.getLocation(\"occlusionMapMatrix\");\n }\n if (material._diffuseFresnel) {\n this._uDiffuseFresnelEdgeBias = program.getLocation(\"diffuseFresnelEdgeBias\");\n this._uDiffuseFresnelCenterBias = program.getLocation(\"diffuseFresnelCenterBias\");\n this._uDiffuseFresnelEdgeColor = program.getLocation(\"diffuseFresnelEdgeColor\");\n this._uDiffuseFresnelCenterColor = program.getLocation(\"diffuseFresnelCenterColor\");\n this._uDiffuseFresnelPower = program.getLocation(\"diffuseFresnelPower\");\n }\n if (material._specularFresnel) {\n this._uSpecularFresnelEdgeBias = program.getLocation(\"specularFresnelEdgeBias\");\n this._uSpecularFresnelCenterBias = program.getLocation(\"specularFresnelCenterBias\");\n this._uSpecularFresnelEdgeColor = program.getLocation(\"specularFresnelEdgeColor\");\n this._uSpecularFresnelCenterColor = program.getLocation(\"specularFresnelCenterColor\");\n this._uSpecularFresnelPower = program.getLocation(\"specularFresnelPower\");\n }\n if (material._alphaFresnel) {\n this._uAlphaFresnelEdgeBias = program.getLocation(\"alphaFresnelEdgeBias\");\n this._uAlphaFresnelCenterBias = program.getLocation(\"alphaFresnelCenterBias\");\n this._uAlphaFresnelEdgeColor = program.getLocation(\"alphaFresnelEdgeColor\");\n this._uAlphaFresnelCenterColor = program.getLocation(\"alphaFresnelCenterColor\");\n this._uAlphaFresnelPower = program.getLocation(\"alphaFresnelPower\");\n }\n if (material._reflectivityFresnel) {\n this._uReflectivityFresnelEdgeBias = program.getLocation(\"reflectivityFresnelEdgeBias\");\n this._uReflectivityFresnelCenterBias = program.getLocation(\"reflectivityFresnelCenterBias\");\n this._uReflectivityFresnelEdgeColor = program.getLocation(\"reflectivityFresnelEdgeColor\");\n this._uReflectivityFresnelCenterColor = program.getLocation(\"reflectivityFresnelCenterColor\");\n this._uReflectivityFresnelPower = program.getLocation(\"reflectivityFresnelPower\");\n }\n if (material._emissiveFresnel) {\n this._uEmissiveFresnelEdgeBias = program.getLocation(\"emissiveFresnelEdgeBias\");\n this._uEmissiveFresnelCenterBias = program.getLocation(\"emissiveFresnelCenterBias\");\n this._uEmissiveFresnelEdgeColor = program.getLocation(\"emissiveFresnelEdgeColor\");\n this._uEmissiveFresnelCenterColor = program.getLocation(\"emissiveFresnelCenterColor\");\n this._uEmissiveFresnelPower = program.getLocation(\"emissiveFresnelPower\");\n }\n break;\n\n case \"MetallicMaterial\":\n this._uBaseColor = program.getLocation(\"materialBaseColor\");\n this._uMaterialMetallic = program.getLocation(\"materialMetallic\");\n this._uMaterialRoughness = program.getLocation(\"materialRoughness\");\n this._uMaterialSpecularF0 = program.getLocation(\"materialSpecularF0\");\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\n if (material._baseColorMap) {\n this._uBaseColorMap = \"baseColorMap\";\n this._uBaseColorMapMatrix = program.getLocation(\"baseColorMapMatrix\");\n }\n if (material._metallicMap) {\n this._uMetallicMap = \"metallicMap\";\n this._uMetallicMapMatrix = program.getLocation(\"metallicMapMatrix\");\n }\n if (material._roughnessMap) {\n this._uRoughnessMap = \"roughnessMap\";\n this._uRoughnessMapMatrix = program.getLocation(\"roughnessMapMatrix\");\n }\n if (material._metallicRoughnessMap) {\n this._uMetallicRoughnessMap = \"metallicRoughnessMap\";\n this._uMetallicRoughnessMapMatrix = program.getLocation(\"metallicRoughnessMapMatrix\");\n }\n if (material._emissiveMap) {\n this._uEmissiveMap = \"emissiveMap\";\n this._uEmissiveMapMatrix = program.getLocation(\"emissiveMapMatrix\");\n }\n if (material._occlusionMap) {\n this._uOcclusionMap = \"occlusionMap\";\n this._uOcclusionMapMatrix = program.getLocation(\"occlusionMapMatrix\");\n }\n if (material._alphaMap) {\n this._uAlphaMap = \"alphaMap\";\n this._uAlphaMapMatrix = program.getLocation(\"alphaMapMatrix\");\n }\n if (material._normalMap) {\n this._uNormalMap = \"normalMap\";\n this._uNormalMapMatrix = program.getLocation(\"normalMapMatrix\");\n }\n break;\n\n case \"SpecularMaterial\":\n this._uMaterialDiffuse = program.getLocation(\"materialDiffuse\");\n this._uMaterialSpecular = program.getLocation(\"materialSpecular\");\n this._uMaterialGlossiness = program.getLocation(\"materialGlossiness\");\n this._uMaterialReflectivity = program.getLocation(\"reflectivityFresnel\");\n this._uMaterialEmissive = program.getLocation(\"materialEmissive\");\n this._uAlphaModeCutoff = program.getLocation(\"materialAlphaModeCutoff\");\n if (material._diffuseMap) {\n this._uDiffuseMap = \"diffuseMap\";\n this._uDiffuseMapMatrix = program.getLocation(\"diffuseMapMatrix\");\n }\n if (material._specularMap) {\n this._uSpecularMap = \"specularMap\";\n this._uSpecularMapMatrix = program.getLocation(\"specularMapMatrix\");\n }\n if (material._glossinessMap) {\n this._uGlossinessMap = \"glossinessMap\";\n this._uGlossinessMapMatrix = program.getLocation(\"glossinessMapMatrix\");\n }\n if (material._specularGlossinessMap) {\n this._uSpecularGlossinessMap = \"materialSpecularGlossinessMap\";\n this._uSpecularGlossinessMapMatrix = program.getLocation(\"materialSpecularGlossinessMapMatrix\");\n }\n if (material._emissiveMap) {\n this._uEmissiveMap = \"emissiveMap\";\n this._uEmissiveMapMatrix = program.getLocation(\"emissiveMapMatrix\");\n }\n if (material._occlusionMap) {\n this._uOcclusionMap = \"occlusionMap\";\n this._uOcclusionMapMatrix = program.getLocation(\"occlusionMapMatrix\");\n }\n if (material._alphaMap) {\n this._uAlphaMap = \"alphaMap\";\n this._uAlphaMapMatrix = program.getLocation(\"alphaMapMatrix\");\n }\n if (material._normalMap) {\n this._uNormalMap = \"normalMap\";\n this._uNormalMapMatrix = program.getLocation(\"normalMapMatrix\");\n }\n break;\n }\n\n this._aPosition = program.getAttribute(\"position\");\n this._aNormal = program.getAttribute(\"normal\");\n this._aUV = program.getAttribute(\"uv\");\n this._aColor = program.getAttribute(\"color\");\n this._aFlags = program.getAttribute(\"flags\");\n\n this._uClippable = program.getLocation(\"clippable\");\n this._uColorize = program.getLocation(\"colorize\");\n this._uOffset = program.getLocation(\"offset\");\n\n this._lastMaterialId = null;\n this._lastVertexBufsId = null;\n this._lastGeometryId = null;\n\n this._lastColorize = new Float32Array(4);\n\n this._baseTextureUnit = 0;\n\n};\n\nDrawRenderer.prototype._bindProgram = function (frameCtx) {\n\n const maxTextureUnits = _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__.WEBGL_INFO.MAX_TEXTURE_UNITS;\n const scene = this._scene;\n const gl = scene.canvas.gl;\n const lightsState = scene._lightsState;\n const project = scene.camera.project;\n let light;\n\n const program = this._program;\n\n program.bind();\n\n frameCtx.useProgram++;\n frameCtx.textureUnit = 0;\n\n this._lastMaterialId = null;\n this._lastVertexBufsId = null;\n this._lastGeometryId = null;\n\n this._lastColorize[0] = -1;\n this._lastColorize[1] = -1;\n this._lastColorize[2] = -1;\n this._lastColorize[3] = -1;\n\n gl.uniformMatrix4fv(this._uProjMatrix, false, project.matrix);\n\n if (scene.logarithmicDepthBufferEnabled) {\n const logDepthBufFC = 2.0 / (Math.log(project.far + 1.0) / Math.LN2);\n gl.uniform1f(this._uLogDepthBufFC, logDepthBufFC);\n }\n\n for (var i = 0, len = lightsState.lights.length; i < len; i++) {\n\n light = lightsState.lights[i];\n\n if (this._uLightAmbient[i]) {\n gl.uniform4f(this._uLightAmbient[i], light.color[0], light.color[1], light.color[2], light.intensity);\n\n } else {\n\n if (this._uLightColor[i]) {\n gl.uniform4f(this._uLightColor[i], light.color[0], light.color[1], light.color[2], light.intensity);\n }\n\n if (this._uLightPos[i]) {\n gl.uniform3fv(this._uLightPos[i], light.pos);\n if (this._uLightAttenuation[i]) {\n gl.uniform1f(this._uLightAttenuation[i], light.attenuation);\n }\n }\n\n if (this._uLightDir[i]) {\n gl.uniform3fv(this._uLightDir[i], light.dir);\n }\n\n if (light.castsShadow) {\n if (this._uShadowViewMatrix[i]) {\n gl.uniformMatrix4fv(this._uShadowViewMatrix[i], false, light.getShadowViewMatrix());\n }\n if (this._uShadowProjMatrix[i]) {\n gl.uniformMatrix4fv(this._uShadowProjMatrix[i], false, light.getShadowProjMatrix());\n }\n const shadowRenderBuf = light.getShadowRenderBuf();\n if (shadowRenderBuf) {\n program.bindTexture(\"shadowMap\" + i, shadowRenderBuf.getTexture(), frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n }\n }\n }\n }\n\n if (lightsState.lightMaps.length > 0 && lightsState.lightMaps[0].texture && this._uLightMap) {\n program.bindTexture(this._uLightMap, lightsState.lightMaps[0].texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n }\n\n if (lightsState.reflectionMaps.length > 0 && lightsState.reflectionMaps[0].texture && this._uReflectionMap) {\n program.bindTexture(this._uReflectionMap, lightsState.reflectionMaps[0].texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n }\n\n if (this._uGammaFactor) {\n gl.uniform1f(this._uGammaFactor, scene.gammaFactor);\n }\n\n this._baseTextureUnit = frameCtx.textureUnit;\n};\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/mesh/draw/DrawRenderer.js?");
|
|
3358
3358
|
|
|
3359
3359
|
/***/ }),
|
|
3360
3360
|
|
|
@@ -3544,7 +3544,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3544
3544
|
\**********************************************/
|
|
3545
3545
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3546
3546
|
|
|
3547
|
-
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\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\t/**\n\t * @constructor\n\t * @param {Component} owner Owner component. When destroyed, the owner will destroy this component as well.\n\t * @param {*} [cfg] Configs\n\t * @param {String} [cfg.id] Optional ID, unique among all components in the parent scene, generated automatically when omitted.\n\t * @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\t * @param {Number[]} [cfg.origin=[0,0,0]] World-space double-precision 3D origin.\n\t * @param {Number[]} [cfg.position=[0,0,0]] Local, single-precision 3D position, relative to the origin parameter.\n\t * @param {Number[]} [cfg.scale=[1,1,1]] Local scale.\n\t * @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\t * @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\t * @param {Boolean} [cfg.visible=true] Indicates if the SceneModel is initially visible.\n\t * @param {Boolean} [cfg.culled=false] Indicates if the SceneModel is initially culled from view.\n\t * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModel is initially pickable.\n\t * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModel is initially clippable.\n\t * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModel is initially included in boundary calculations.\n\t * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModel is initially xrayed.\n\t * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModel is initially highlighted.\n\t * @param {Boolean} [cfg.selected=false] Indicates if the SceneModel is initially selected.\n\t * @param {Boolean} [cfg.edges=false] Indicates if the SceneModel's edges are initially emphasized.\n\t * @param {Number[]} [cfg.colorize=[1.0,1.0,1.0]] SceneModel's initial RGB colorize color, multiplies by the rendered fragment colors.\n\t * @param {Number} [cfg.opacity=1.0] SceneModel's initial opacity factor, multiplies by the rendered fragment alpha.\n\t * @param {Number} [cfg.backfaces=false] When we set this ````true````, then we force rendering of backfaces for this SceneModel. When\n\t * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\n\t * 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\t * @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\t * @param {Boolean} [cfg.pbrEnabled=true] Indicates if physically-based rendering (PBR) will apply to the SceneModel when {@link Scene#pbrEnabled} is ````true````.\n\t * @param {Boolean} [cfg.colorTextureEnabled=true] Indicates if base color textures will be rendered for the SceneModel when {@link Scene#colorTextureEnabled} is ````true````.\n\t * @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\t * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\n\t * to limit the size of the batched geometry arrays that SceneModel internally creates for batched geometries.\n\t * A lower value means less heap allocation/de-allocation while creating/loading batched geometries, but more draw calls and\n\t * slower rendering speed. A high value means larger heap allocation/de-allocation while creating/loading, but less draw calls\n\t * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\n\t * @param {TextureTranscoder} [cfg.textureTranscoder] Transcoder that will be used internally by {@link SceneModel#createTexture}\n\t * to convert transcoded texture data. Only required when we'll be providing transcoded data\n\t * to {@link SceneModel#createTexture}. We assume that all transcoded texture data added to a ````SceneModel````\n\t * will then in a format supported by this transcoder.\n\t * @param {Boolean} [cfg.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\n\t * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\n\t * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\n\t * primitives. Only works while {@link DTX#enabled} is also ````true````.\n\t */\n\tconstructor(owner, cfg = {}) {\n\t\tsuper(owner, cfg);\n\n\t\tthis._dtxEnabled = this.scene.dtxEnabled && cfg.dtxEnabled !== false;\n\n\t\tthis._enableVertexWelding = false; // Not needed for most objects, and very expensive, so disabled\n\t\tthis._enableIndexBucketing = false; // Until fixed: https://github.com/xeokit/xeokit-sdk/issues/1204\n\n\t\tthis._vboBatchingLayerScratchMemory = (0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.getScratchMemory)();\n\t\tthis._textureTranscoder = cfg.textureTranscoder || (0,_utils_textureTranscoders_KTX2TextureTranscoder_KTX2TextureTranscoder_js__WEBPACK_IMPORTED_MODULE_20__.getKTX2TextureTranscoder)(this.scene.viewer);\n\n\t\tthis._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\n\n\t\tthis._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\t\tthis._exceptionIds = [];\n\n\t\tthis._quantizationRanges = {};\n\n\t\tthis._vboInstancingLayers = {};\n\t\tthis._vboBatchingLayers = {};\n\t\tthis._dtxLayers = {};\n\n\t\tthis.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second\n\t\tthis._entityList = [];\n\n\t\tthis._geometries = {};\n\t\tthis._dtxBuckets = {}; // Geometries with optimizations used for data texture representation\n\t\tthis._textures = {};\n\t\tthis._textureSets = {};\n\t\tthis._transforms = {};\n\t\tthis._meshes = {};\n\t\tthis._entities = {};\n\n\t\tthis._scheduledMeshes = {};\n\t\tthis._meshesCfgsBeforeMeshCreation = {};\n\n\t\t/** @private **/\n\t\tthis.renderFlags = new _webgl_RenderFlags_js__WEBPACK_IMPORTED_MODULE_14__.RenderFlags();\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numGeometries = 0; // Number of geometries created with createGeometry()\n\n\t\t// These counts are used to avoid unnecessary render passes\n\t\t// They are incremented or decremented exclusively by BatchingLayer and InstancingLayer\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numVisibleLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numTransparentLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numXRayedLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numHighlightedLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numSelectedLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numEdgesLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numPickableLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numClippableLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numCulledLayerPortions = 0;\n\n\t\tthis.numEntities = 0;\n\t\tthis._numTriangles = 0;\n\t\tthis._numLines = 0;\n\t\tthis._numPoints = 0;\n\n\t\tthis._edgeThreshold = cfg.edgeThreshold || 10;\n\n\t\t// Build static matrix\n\n\t\tthis._origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin || [0, 0, 0]);\n\t\tthis._position = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.position || [0, 0, 0]);\n\t\tthis._rotation = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.rotation || [0, 0, 0]);\n\t\tthis._quaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\n\t\tthis._conjugateQuaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\n\n\t\tif (cfg.rotation) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\n\t\t}\n\t\tthis._scale = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.scale || [1, 1, 1]);\n\n\t\tthis._worldRotationMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\tthis._worldRotationMatrixConjugate = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\tthis._matrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\tthis._matrixDirty = true;\n\n\t\tthis._rebuildMatrices();\n\n\t\tthis._worldNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._matrix, this._worldNormalMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._worldNormalMatrix);\n\n\t\tif (cfg.matrix || cfg.position || cfg.rotation || cfg.scale || cfg.quaternion) {\n\t\t\tthis._viewMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\tthis._viewNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\tthis._viewMatrixDirty = true;\n\t\t\tthis._matrixNonIdentity = true;\n\t\t}\n\n\t\tthis._opacity = 1.0;\n\t\tthis._colorize = [1, 1, 1];\n\n\t\tthis._saoEnabled = cfg.saoEnabled !== false;\n\t\tthis._pbrEnabled = cfg.pbrEnabled !== false;\n\t\tthis._colorTextureEnabled = cfg.colorTextureEnabled !== false;\n\n\t\tthis._isModel = cfg.isModel;\n\t\tif (this._isModel) {\n\t\t\tthis.scene._registerModel(this);\n\t\t}\n\n\t\tthis._onCameraViewMatrix = this.scene.camera.on(\"matrix\", () => {\n\t\t\tthis._viewMatrixDirty = true;\n\t\t});\n\n\t\tthis._meshesWithDirtyMatrices = [];\n\t\tthis._numMeshesWithDirtyMatrices = 0;\n\n\t\tthis._onTick = this.scene.on(\"tick\", () => {\n\t\t\twhile (this._numMeshesWithDirtyMatrices > 0) {\n\t\t\t\tthis._meshesWithDirtyMatrices[--this._numMeshesWithDirtyMatrices]._updateMatrix();\n\t\t\t}\n\t\t});\n\n\t\tthis._createDefaultTextureSet();\n\n\t\tthis.visible = cfg.visible;\n\t\tthis.culled = cfg.culled;\n\t\tthis.pickable = cfg.pickable;\n\t\tthis.clippable = cfg.clippable;\n\t\tthis.collidable = cfg.collidable;\n\t\tthis.castsShadow = cfg.castsShadow;\n\t\tthis.receivesShadow = cfg.receivesShadow;\n\t\tthis.xrayed = cfg.xrayed;\n\t\tthis.highlighted = cfg.highlighted;\n\t\tthis.selected = cfg.selected;\n\t\tthis.edges = cfg.edges;\n\t\tthis.colorize = cfg.colorize;\n\t\tthis.opacity = cfg.opacity;\n\t\tthis.backfaces = cfg.backfaces;\n\t}\n\n\t_meshMatrixDirty(mesh) {\n\t\tthis._meshesWithDirtyMatrices[this._numMeshesWithDirtyMatrices++] = mesh;\n\t}\n\n\t_createDefaultTextureSet() {\n\t\t// Every SceneModelMesh gets at least the default TextureSet,\n\t\t// which contains empty default textures filled with color\n\t\tconst defaultColorTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_COLOR_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [1, 1, 1, 1] // [r, g, b, a]})\n\t\t\t})\n\t\t});\n\t\tconst defaultMetalRoughTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_METAL_ROUGH_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [0, 1, 1, 1] // [unused, roughness, metalness, unused]\n\t\t\t})\n\t\t});\n\t\tconst defaultNormalsTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_NORMALS_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [0, 0, 0, 0] // [x, y, z, unused] - these must be zeros\n\t\t\t})\n\t\t});\n\t\tconst defaultEmissiveTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_EMISSIVE_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [0, 0, 0, 1] // [x, y, z, unused]\n\t\t\t})\n\t\t});\n\t\tconst defaultOcclusionTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_OCCLUSION_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [1, 1, 1, 1] // [x, y, z, unused]\n\t\t\t})\n\t\t});\n\t\tthis._textures[DEFAULT_COLOR_TEXTURE_ID] = defaultColorTexture;\n\t\tthis._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID] = defaultMetalRoughTexture;\n\t\tthis._textures[DEFAULT_NORMALS_TEXTURE_ID] = defaultNormalsTexture;\n\t\tthis._textures[DEFAULT_EMISSIVE_TEXTURE_ID] = defaultEmissiveTexture;\n\t\tthis._textures[DEFAULT_OCCLUSION_TEXTURE_ID] = defaultOcclusionTexture;\n\t\tthis._textureSets[DEFAULT_TEXTURE_SET_ID] = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\n\t\t\tid: DEFAULT_TEXTURE_SET_ID,\n\t\t\tmodel: this,\n\t\t\tcolorTexture: defaultColorTexture,\n\t\t\tmetallicRoughnessTexture: defaultMetalRoughTexture,\n\t\t\tnormalsTexture: defaultNormalsTexture,\n\t\t\temissiveTexture: defaultEmissiveTexture,\n\t\t\tocclusionTexture: defaultOcclusionTexture\n\t\t});\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// SceneModel members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * Returns true to indicate that this Component is a SceneModel.\n\t * @type {Boolean}\n\t */\n\tget isPerformanceModel() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * The {@link SceneModelTransform}s in this SceneModel.\n\t *\n\t * Each {#link SceneModelTransform} is stored here against its {@link SceneModelTransform.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget transforms() {\n\t\treturn this._transforms;\n\t}\n\n\t/**\n\t * The {@link SceneModelTexture}s in this SceneModel.\n\t *\n\t * * Each {@link SceneModelTexture} is created with {@link SceneModel.createTexture}.\n\t * * Each {@link SceneModelTexture} is stored here against its {@link SceneModelTexture.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget textures() {\n\t\treturn this._textures;\n\t}\n\n\t/**\n\t * The {@link SceneModelTextureSet}s in this SceneModel.\n\t *\n\t * Each {@link SceneModelTextureSet} is stored here against its {@link SceneModelTextureSet.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget textureSets() {\n\t\treturn this._textureSets;\n\t}\n\n\t/**\n\t * The {@link SceneModelMesh}es in this SceneModel.\n\t *\n\t * Each {@SceneModelMesh} is stored here against its {@link SceneModelMesh.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget meshes() {\n\t\treturn this._meshes;\n\t}\n\n\t/**\n\t * The {@link SceneModelEntity}s in this SceneModel.\n\t *\n\t * Each {#link SceneModelEntity} in this SceneModel that represents an object is\n\t * stored here against its {@link SceneModelTransform.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget objects() {\n\t\treturn this._entities;\n\t}\n\n\t/**\n\t * Gets the 3D World-space origin for this SceneModel.\n\t *\n\t * Each {@link SceneModelMesh.origin}, if supplied, is relative to this origin.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Float64Array}\n\t */\n\tget origin() {\n\t\treturn this._origin;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local translation.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset position(value) {\n\t\tthis._position.set(value || [0, 0, 0]);\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local translation.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget position() {\n\t\treturn this._position;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset rotation(value) {\n\t\tthis._rotation.set(value || [0, 0, 0]);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget rotation() {\n\t\treturn this._rotation;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local rotation quaternion.\n\t *\n\t * Default value is ````[0,0,0,1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset quaternion(value) {\n\t\tthis._quaternion.set(value || [0, 0, 0, 1]);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToEuler(this._quaternion, \"XYZ\", this._rotation);\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local rotation quaternion.\n\t *\n\t * Default value is ````[0,0,0,1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget quaternion() {\n\t\treturn this._quaternion;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local scale.\n\t *\n\t * Default value is ````[1,1,1]````.\n\t *\n\t * @type {Number[]}\n\t * @deprecated\n\t */\n\tset scale(value) {\n\t\t// NOP - deprecated\n\t}\n\n\t/**\n\t * Gets the SceneModel's local scale.\n\t *\n\t * Default value is ````[1,1,1]````.\n\t *\n\t * @type {Number[]}\n\t * @deprecated\n\t */\n\tget scale() {\n\t\treturn this._scale;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local modeling transform matrix.\n\t *\n\t * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset matrix(value) {\n\t\tthis._matrix.set(value || DEFAULT_MATRIX);\n\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\n\t\tthis._matrix.set(this._worldRotationMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\n\n\t\tthis._matrixDirty = false;\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local modeling transform matrix.\n\t *\n\t * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget matrix() {\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t}\n\t\treturn this._matrix;\n\t}\n\n\t/**\n\t * Gets the SceneModel's local modeling rotation transform matrix.\n\t *\n\t * @type {Number[]}\n\t */\n\tget rotationMatrix() {\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t}\n\t\treturn this._worldRotationMatrix;\n\t}\n\n\t_rebuildMatrices() {\n\t\tif (this._matrixDirty) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\n\t\t\tthis._matrix.set(this._worldRotationMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\n\t\t\tthis._matrixDirty = false;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the conjugate of the SceneModel's local modeling rotation transform matrix.\n\t *\n\t * This is used for RTC view matrix management in renderers.\n\t *\n\t * @type {Number[]}\n\t */\n\tget rotationMatrixConjugate() {\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t}\n\t\treturn this._worldRotationMatrixConjugate;\n\t}\n\n\t_setWorldMatrixDirty() {\n\t\tthis._matrixDirty = true;\n\t\tthis._aabbDirty = true;\n\t}\n\n\t_transformDirty() {\n\t\tthis._matrixDirty = true;\n\t\tthis._aabbDirty = true;\n\t\tthis.scene._aabbDirty = true;\n\t}\n\n\t_sceneModelDirty() {\n\t\tthis.scene._aabbDirty = true;\n\t\tthis._aabbDirty = true;\n\t\tthis.scene._aabbDirty = true;\n\t\tthis._matrixDirty = true;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i]._sceneModelDirty(); // Entities need to retransform their World AABBs by SceneModel's worldMatrix\n\t\t}\n\t}\n\n\t/**\n\t * Gets the SceneModel's World matrix.\n\t *\n\t * @property worldMatrix\n\t * @type {Number[]}\n\t */\n\tget worldMatrix() {\n\t\treturn this.matrix;\n\t}\n\n\t/**\n\t * Gets the SceneModel's World normal matrix.\n\t *\n\t * @type {Number[]}\n\t */\n\tget worldNormalMatrix() {\n\t\treturn this._worldNormalMatrix;\n\t}\n\n\t/**\n\t * Called by private renderers in ./lib, returns the view matrix with which to\n\t * render this SceneModel. The view matrix is the concatenation of the\n\t * Camera view matrix with the Performance model's world (modeling) matrix.\n\t *\n\t * @private\n\t */\n\tget viewMatrix() {\n\t\tif (!this._viewMatrix) {\n\t\t\treturn this.scene.camera.viewMatrix;\n\t\t}\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t\tthis._viewMatrixDirty = true;\n\t\t}\n\t\tif (this._viewMatrixDirty) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n\t\t\tthis._viewMatrixDirty = false;\n\t\t}\n\t\treturn this._viewMatrix;\n\t}\n\n\t/**\n\t * Called by private renderers in ./lib, returns the view normal matrix with which to render this SceneModel.\n\t *\n\t * @private\n\t */\n\tget viewNormalMatrix() {\n\t\tif (!this._viewNormalMatrix) {\n\t\t\treturn this.scene.camera.viewNormalMatrix;\n\t\t}\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t\tthis._viewMatrixDirty = true;\n\t\t}\n\t\tif (this._viewMatrixDirty) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n\t\t\tthis._viewMatrixDirty = false;\n\t\t}\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n\t\treturn this._viewNormalMatrix;\n\t}\n\n\t/**\n\t * Sets if backfaces are rendered for this SceneModel.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget backfaces() {\n\t\treturn this._backfaces;\n\t}\n\n\t/**\n\t * Sets if backfaces are rendered for this SceneModel.\n\t *\n\t * Default is ````false````.\n\t *\n\t * When we set this ````true````, then backfaces are always rendered for this SceneModel.\n\t *\n\t * When we set this ````false````, then we allow the Viewer to decide whether to render backfaces. In this case,\n\t * the Viewer will:\n\t *\n\t * * hide backfaces on watertight meshes,\n\t * * show backfaces on open meshes, and\n\t * * always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\n\t *\n\t * @type {Boolean}\n\t */\n\tset backfaces(backfaces) {\n\t\tbackfaces = !!backfaces;\n\t\tthis._backfaces = backfaces;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the list of {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * @returns {SceneModelEntity[]}\n\t */\n\tget entityList() {\n\t\treturn this._entityList;\n\t}\n\n\t/**\n\t * Returns true to indicate that SceneModel is an {@link Entity}.\n\t * @type {Boolean}\n\t */\n\tget isEntity() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns ````true```` if this SceneModel represents a model.\n\t *\n\t * When ````true```` the SceneModel will be registered by {@link SceneModel#id} in\n\t * {@link Scene#models} and may also have a {@link MetaObject} with matching {@link MetaObject#id}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isModel() {\n\t\treturn this._isModel;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// SceneModel members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * Returns ````false```` to indicate that SceneModel never represents an object.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isObject() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Gets the SceneModel's World-space 3D axis-aligned bounding box.\n\t *\n\t * Represented by a six-element Float64Array containing the min/max extents of the\n\t * axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget aabb() {\n\t\tif (this._aabbDirty) {\n\t\t\tif (this._aabbUpdate) {\n\t\t\t\treturn this._aabb;\n\t\t\t}\n\t\t\tif (this._exceptionIds.length > 0) this.updateAABBCullException(this._exceptionIds);\n\t\t\telse {\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3(this._aabb);\n\t\t\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3(this._aabb, this._entityList[i].aabb);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._aabbDirty = false;\n\t\t}\n\t\treturn this._aabb;\n\t}\n\n\tupdateAABBCullException(exceptionIds, callback) {\n\t\tfunction noExceptionId(id) {\n\t\t\tlet noExceptionId = true;\n\t\t\texceptionIds.forEach((exceptionId) => {\n\t\t\t\tif (exceptionId === id) {\n\t\t\t\t\tnoExceptionId = false;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn noExceptionId;\n\t\t}\n\t\tconst newAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tif (noExceptionId(this._entityList[i].id)) {\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3(newAABB, this._entityList[i].aabb);\n\t\t\t}\n\t\t}\n\n\t\tfor (let a = 0; a < newAABB.length; a++) {\n\t\t\tthis._aabb[a] = newAABB[a];\n\t\t}\n\t\tthis._aabbDirty = false;\n\t\tthis._aabbUpdate = true;\n\t\tthis.scene._setAABBDirty();\n\t\tthis.scene._aabbUpdate = true;\n\t\tif (typeof callback === \"function\") callback();\n\t}\n\n\tcancelCullException(callback) {\n\t\tthis._exceptionIds = [];\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\t\tthis.aabb;\n\t\tthis.scene._aabbUpdate = false;\n\t\tthis.scene._setAABBDirty();\n\t\tif (typeof callback === \"function\") callback();\n\t}\n\n\t/**\n\t * 获取所有实体的aabb\n\t */\n\tget aabbs() {\n\t\tlet aabbArray = [];\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\taabbArray.push(this._entityList[i].aabb);\n\t\t}\n\t\treturn aabbArray;\n\t}\n\n\t/**\n\t * The approximate number of triangle primitives in this SceneModel.\n\t *\n\t * @type {Number}\n\t */\n\tget numTriangles() {\n\t\treturn this._numTriangles;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// Entity members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * The approximate number of line primitives in this SceneModel.\n\t *\n\t * @type {Number}\n\t */\n\tget numLines() {\n\t\treturn this._numLines;\n\t}\n\n\t/**\n\t * The approximate number of point primitives in this SceneModel.\n\t *\n\t * @type {Number}\n\t */\n\tget numPoints() {\n\t\treturn this._numPoints;\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are visible.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget visible() {\n\t\treturn this.numVisibleLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if this SceneModel is visible.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\n\t **\n\t * @type {Boolean}\n\t */\n\tset visible(visible) {\n\t\tvisible = visible !== false;\n\t\tthis._visible = visible;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].visible = visible;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are xrayed.\n\t *\n\t * @type {Boolean}\n\t */\n\tget xrayed() {\n\t\treturn this.numXRayedLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel are xrayed.\n\t *\n\t * @type {Boolean}\n\t */\n\tset xrayed(xrayed) {\n\t\txrayed = !!xrayed;\n\t\tthis._xrayed = xrayed;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].xrayed = xrayed;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are highlighted.\n\t *\n\t * @type {Boolean}\n\t */\n\tget highlighted() {\n\t\treturn this.numHighlightedLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel are highlighted.\n\t *\n\t * @type {Boolean}\n\t */\n\tset highlighted(highlighted) {\n\t\thighlighted = !!highlighted;\n\t\tthis._highlighted = highlighted;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].highlighted = highlighted;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are selected.\n\t *\n\t * @type {Boolean}\n\t */\n\tget selected() {\n\t\treturn this.numSelectedLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel are selected.\n\t *\n\t * @type {Boolean}\n\t */\n\tset selected(selected) {\n\t\tselected = !!selected;\n\t\tthis._selected = selected;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].selected = selected;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel have edges emphasised.\n\t *\n\t * @type {Boolean}\n\t */\n\tget edges() {\n\t\treturn this.numEdgesLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel have edges emphasised.\n\t *\n\t * @type {Boolean}\n\t */\n\tset edges(edges) {\n\t\tedges = !!edges;\n\t\tthis._edges = edges;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].edges = edges;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if this SceneModel is culled from view.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\n\t *\n\t * @type {Boolean}\n\t */\n\tget culled() {\n\t\treturn this._culled;\n\t}\n\n\t/**\n\t * Sets if this SceneModel is culled from view.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\n\t *\n\t * @type {Boolean}\n\t */\n\tset culled(culled) {\n\t\tculled = !!culled;\n\t\tthis._culled = culled;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].culled = culled;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if {@link SceneModelEntity}s in this SceneModel are clippable.\n\t *\n\t * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget clippable() {\n\t\treturn this._clippable;\n\t}\n\n\t/**\n\t * Sets if {@link SceneModelEntity}s in this SceneModel are clippable.\n\t *\n\t * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\n\t *\n\t * @type {Boolean}\n\t */\n\tset clippable(clippable) {\n\t\tclippable = clippable !== false;\n\t\tthis._clippable = clippable;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].clippable = clippable;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if this SceneModel is collidable.\n\t *\n\t * @type {Boolean}\n\t */\n\tget collidable() {\n\t\treturn this._collidable;\n\t}\n\n\t/**\n\t * Sets if {@link SceneModelEntity}s in this SceneModel are collidable.\n\t *\n\t * @type {Boolean}\n\t */\n\tset collidable(collidable) {\n\t\tcollidable = collidable !== false;\n\t\tthis._collidable = collidable;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].collidable = collidable;\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this SceneModel is pickable.\n\t *\n\t * Picking is done via calls to {@link Scene#pick}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget pickable() {\n\t\treturn this.numPickableLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if {@link SceneModelEntity}s in this SceneModel are pickable.\n\t *\n\t * Picking is done via calls to {@link Scene#pick}.\n\t *\n\t * @type {Boolean}\n\t */\n\tset pickable(pickable) {\n\t\tpickable = pickable !== false;\n\t\tthis._pickable = pickable;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].pickable = pickable;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the RGB colorize color for this SceneModel.\n\t *\n\t * Each element of the color is in range ````[0..1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget colorize() {\n\t\treturn this._colorize;\n\t}\n\n\t/**\n\t * Sets the RGB colorize color for this SceneModel.\n\t *\n\t * Multiplies by rendered fragment colors.\n\t *\n\t * Each element of the color is in range ````[0..1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset colorize(colorize) {\n\t\tthis._colorize = colorize;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].colorize = colorize;\n\t\t}\n\t}\n\n\t/**\n\t * Gets this SceneModel's opacity factor.\n\t *\n\t * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\n\t *\n\t * @type {Number}\n\t */\n\tget opacity() {\n\t\treturn this._opacity;\n\t}\n\n\t/**\n\t * Sets the opacity factor for this SceneModel.\n\t *\n\t * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\n\t *\n\t * @type {Number}\n\t */\n\tset opacity(opacity) {\n\t\tthis._opacity = opacity;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].opacity = opacity;\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this SceneModel casts a shadow.\n\t *\n\t * @type {Boolean}\n\t */\n\tget castsShadow() {\n\t\treturn this._castsShadow;\n\t}\n\n\t/**\n\t * Sets if this SceneModel casts a shadow.\n\t *\n\t * @type {Boolean}\n\t */\n\tset castsShadow(castsShadow) {\n\t\tcastsShadow = castsShadow !== false;\n\t\tif (castsShadow !== this._castsShadow) {\n\t\t\tthis._castsShadow = castsShadow;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Sets if this SceneModel can have shadow cast upon it.\n\t *\n\t * @type {Boolean}\n\t */\n\tget receivesShadow() {\n\t\treturn this._receivesShadow;\n\t}\n\n\t/**\n\t * Sets if this SceneModel can have shadow cast upon it.\n\t *\n\t * @type {Boolean}\n\t */\n\tset receivesShadow(receivesShadow) {\n\t\treceivesShadow = receivesShadow !== false;\n\t\tif (receivesShadow !== this._receivesShadow) {\n\t\t\tthis._receivesShadow = receivesShadow;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Gets if Scalable Ambient Obscurance (SAO) will apply to this SceneModel.\n\t *\n\t * SAO is configured by the Scene's {@link SAO} component.\n\t *\n\t * Only works when {@link SAO#enabled} is also true.\n\t *\n\t * @type {Boolean}\n\t */\n\tget saoEnabled() {\n\t\treturn this._saoEnabled;\n\t}\n\n\t/**\n\t * Gets if physically-based rendering (PBR) is enabled for this SceneModel.\n\t *\n\t * Only works when {@link Scene#pbrEnabled} is also true.\n\t *\n\t * @type {Boolean}\n\t */\n\tget pbrEnabled() {\n\t\treturn this._pbrEnabled;\n\t}\n\n\t/**\n\t * Gets if color textures are enabled for this SceneModel.\n\t *\n\t * Only works when {@link Scene#colorTextureEnabled} is also true.\n\t *\n\t * @type {Boolean}\n\t */\n\tget colorTextureEnabled() {\n\t\treturn this._colorTextureEnabled;\n\t}\n\n\t/**\n\t * Returns true to indicate that SceneModel is implements {@link Drawable}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isDrawable() {\n\t\treturn true;\n\t}\n\n\t/** @private */\n\tget isStateSortable() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Configures the appearance of xrayed {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#xrayMaterial}.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget xrayMaterial() {\n\t\treturn this.scene.xrayMaterial;\n\t}\n\n\t/**\n\t * Configures the appearance of highlighted {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#highlightMaterial}.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget highlightMaterial() {\n\t\treturn this.scene.highlightMaterial;\n\t}\n\n\t/**\n\t * Configures the appearance of selected {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#selectedMaterial}.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget selectedMaterial() {\n\t\treturn this.scene.selectedMaterial;\n\t}\n\n\t/**\n\t * Configures the appearance of edges of {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#edgeMaterial}.\n\t *\n\t * @type {EdgeMaterial}\n\t */\n\tget edgeMaterial() {\n\t\treturn this.scene.edgeMaterial;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// Drawable members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * Called by private renderers in ./lib, returns the picking view matrix with which to\n\t * ray-pick on this SceneModel.\n\t *\n\t * @private\n\t */\n\tgetPickViewMatrix(pickViewMatrix) {\n\t\tif (!this._viewMatrix) {\n\t\t\treturn pickViewMatrix;\n\t\t}\n\t\treturn this._viewMatrix;\n\t}\n\n\t/**\n\t *\n\t * @param cfg\n\t */\n\tcreateQuantizationRange(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createQuantizationRange] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (cfg.aabb) {\n\t\t\tthis.error(\"[createQuantizationRange] Config missing: aabb\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._quantizationRanges[cfg.id]) {\n\t\t\tthis.error(\"[createQuantizationRange] QuantizationRange already created: \" + cfg.id);\n\t\t\treturn;\n\t\t}\n\t\tthis._quantizationRanges[cfg.id] = {\n\t\t\tid: cfg.id,\n\t\t\taabb: cfg.aabb,\n\t\t\tmatrix: (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.aabb, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4())\n\t\t};\n\t}\n\n\t/**\n\t * Creates a reusable geometry within this SceneModel.\n\t *\n\t * We can then supply the geometry ID to {@link SceneModel#createMesh} when we want to create meshes that\n\t * instance the geometry.\n\t *\n\t * @param {*} cfg Geometry properties.\n\t * @param {String|Number} cfg.id Mandatory ID for the geometry, to refer to with {@link SceneModel#createMesh}.\n\t * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\n\t * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\n\t * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\n\t * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\n\t * @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\t * @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\t * @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\t * @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\t * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n\t * @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\t * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\n\t * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\n\t * @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\t */\n\tcreateGeometry(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createGeometry] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._geometries[cfg.id]) {\n\t\t\tthis.error(\"[createGeometry] Geometry already created: \" + cfg.id);\n\t\t\treturn;\n\t\t}\n\t\tif (cfg.primitive === undefined || cfg.primitive === null) {\n\t\t\tcfg.primitive = \"triangles\";\n\t\t}\n\t\tif (\n\t\t\tcfg.primitive !== \"points\" &&\n\t\t\tcfg.primitive !== \"lines\" &&\n\t\t\tcfg.primitive !== \"triangles\" &&\n\t\t\tcfg.primitive !== \"solid\" &&\n\t\t\tcfg.primitive !== \"surface\"\n\t\t) {\n\t\t\tthis.error(\n\t\t\t\t`[createGeometry] Unsupported value for 'primitive': '${cfg.primitive}' - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'. Defaulting to 'triangles'.`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\n\t\t\tthis.error(\"[createGeometry] Param expected: `positions`, `positionsCompressed' or 'buckets\");\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\n\t\t\tthis.error(\n\t\t\t\t\"[createGeometry] Param expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\"\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.positionsDecodeMatrix && cfg.positionsDecodeBoundary) {\n\t\t\tthis.error(\n\t\t\t\t\"[createGeometry] Only one of these params expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\"\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\n\t\t\tthis.error(\"[createGeometry] Param expected: `uvDecodeMatrix` (required for `uvCompressed')\");\n\t\t\treturn null;\n\t\t}\n\t\tif (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\n\t\t\tthis.error(`[createGeometry] Param expected: indices (required for '${cfg.primitive}' primitive type)`);\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.positionsDecodeBoundary) {\n\t\t\tcfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t}\n\t\tif (cfg.positions) {\n\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\tcfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n\t\t\tcfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\n\t\t\tcfg.aabb = aabb;\n\t\t} else if (cfg.positionsCompressed) {\n\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\tcfg.positionsDecodeMatrix = new Float64Array(cfg.positionsDecodeMatrix);\n\t\t\tcfg.positionsCompressed = new Uint16Array(cfg.positionsCompressed);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\tcfg.aabb = aabb;\n\t\t} else if (cfg.buckets) {\n\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\tthis._dtxBuckets[cfg.id] = cfg.buckets;\n\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\tconst bucket = cfg.buckets[i];\n\t\t\t\tif (bucket.positions) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\n\t\t\t\t} else if (bucket.positionsCompressed) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (cfg.positionsDecodeMatrix) {\n\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t}\n\t\t\tcfg.aabb = aabb;\n\t\t}\n\t\tif (cfg.colorsCompressed && cfg.colorsCompressed.length > 0) {\n\t\t\tcfg.colorsCompressed = new Uint8Array(cfg.colorsCompressed);\n\t\t} else if (cfg.colors && cfg.colors.length > 0) {\n\t\t\tconst colors = cfg.colors;\n\t\t\tconst colorsCompressed = new Uint8Array(colors.length);\n\t\t\tfor (let i = 0, len = colors.length; i < len; i++) {\n\t\t\t\tcolorsCompressed[i] = colors[i] * 255;\n\t\t\t}\n\t\t\tcfg.colorsCompressed = colorsCompressed;\n\t\t}\n\t\tif (\n\t\t\t!cfg.buckets &&\n\t\t\t!cfg.edgeIndices &&\n\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")\n\t\t) {\n\t\t\tif (cfg.positions) {\n\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 5.0);\n\t\t\t} else {\n\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n\t\t\t}\n\t\t}\n\t\tif (cfg.uv) {\n\t\t\tconst bounds = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.getUVBounds(cfg.uv);\n\t\t\tconst result = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.compressUVs(cfg.uv, bounds.min, bounds.max);\n\t\t\tcfg.uvCompressed = result.quantized;\n\t\t\tcfg.uvDecodeMatrix = result.decodeMatrix;\n\t\t} else if (cfg.uvCompressed) {\n\t\t\tcfg.uvCompressed = new Uint16Array(cfg.uvCompressed);\n\t\t\tcfg.uvDecodeMatrix = new Float64Array(cfg.uvDecodeMatrix);\n\t\t}\n\t\tif (cfg.normals) {\n\t\t\t// HACK\n\t\t\tcfg.normals = null;\n\t\t}\n\t\tthis._geometries[cfg.id] = cfg;\n\t\tthis._numTriangles += cfg.indices ? Math.round(cfg.indices.length / 3) : 0;\n\t\tthis.numGeometries++;\n\t}\n\n\t/**\n\t * Creates a texture within this SceneModel.\n\t *\n\t * We can then supply the texture ID to {@link SceneModel#createTextureSet} when we want to create texture sets that use the texture.\n\t *\n\t * @param {*} cfg Texture properties.\n\t * @param {String|Number} cfg.id Mandatory ID for the texture, to refer to with {@link SceneModel#createTextureSet}.\n\t * @param {String} [cfg.src] Image file for the texture. Assumed to be transcoded if not having a recognized image file\n\t * extension (jpg, jpeg, png etc.). If transcoded, then assumes ````SceneModel```` is configured with a {@link TextureTranscoder}.\n\t * @param {ArrayBuffer[]} [cfg.buffers] Transcoded texture data. Assumes ````SceneModel```` is\n\t * 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\t * @param {HTMLImageElement} [cfg.image] HTML Image object to load into this texture. Overrides ````src```` and ````buffers````. Never transcoded.\n\t * @param {Number} [cfg.minFilter=LinearMipmapLinearFilter] How the texture is sampled when a texel covers less than one pixel.\n\t * Supported values are {@link LinearMipmapLinearFilter}, {@link LinearMipMapNearestFilter}, {@link NearestMipMapNearestFilter}, {@link NearestMipMapLinearFilter} and {@link LinearMipMapLinearFilter}.\n\t * @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\t * @param {Number} [cfg.wrapS=RepeatWrapping] Wrap parameter for texture coordinate *S*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\n\t * @param {Number} [cfg.wrapT=RepeatWrapping] Wrap parameter for texture coordinate *T*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}..\n\t * @param {Number} [cfg.wrapR=RepeatWrapping] Wrap parameter for texture coordinate *R*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\n\t * @param {Boolean} [cfg.flipY=false] Flips this Texture's source data along its vertical axis when ````true````.\n\t * @param {Number} [cfg.encoding=LinearEncoding] Encoding format. Supported values are {@link LinearEncoding} and {@link sRGBEncoding}.\n\t */\n\tcreateTexture(cfg) {\n\t\tconst textureId = cfg.id;\n\t\tif (textureId === undefined || textureId === null) {\n\t\t\tthis.error(\"[createTexture] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._textures[textureId]) {\n\t\t\tthis.error(\"[createTexture] Texture already created: \" + textureId);\n\t\t\treturn;\n\t\t}\n\t\tif (!cfg.src && !cfg.image && !cfg.buffers) {\n\t\t\tthis.error(\"[createTexture] Param expected: `src`, `image' or 'buffers'\");\n\t\t\treturn null;\n\t\t}\n\t\tlet minFilter = cfg.minFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\n\t\tif (\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipMapNearestFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapLinearFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapNearestFilter\n\t\t) {\n\t\t\tthis.error(`[createTexture] Unsupported value for 'minFilter' - \n supported values are LinearFilter, LinearMipMapNearestFilter, NearestMipMapNearestFilter, \n NearestMipMapLinearFilter and LinearMipmapLinearFilter. Defaulting to LinearMipmapLinearFilter.`);\n\t\t\tminFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\n\t\t}\n\t\tlet magFilter = cfg.magFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\n\t\tif (magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter && magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestFilter) {\n\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'magFilter' - supported values are LinearFilter and NearestFilter. Defaulting to LinearFilter.`\n\t\t\t);\n\t\t\tmagFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\n\t\t}\n\t\tlet wrapS = cfg.wrapS || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\tif (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\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'wrapS' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`\n\t\t\t);\n\t\t\twrapS = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\t}\n\t\tlet wrapT = cfg.wrapT || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\tif (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\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'wrapT' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`\n\t\t\t);\n\t\t\twrapT = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\t}\n\t\tlet wrapR = cfg.wrapR || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\tif (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\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'wrapR' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`\n\t\t\t);\n\t\t\twrapR = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\t}\n\t\tlet encoding = cfg.encoding || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\n\t\tif (encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding && encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.sRGBEncoding) {\n\t\t\tthis.error(\n\t\t\t\t\"[createTexture] Unsupported value for 'encoding' - supported values are LinearEncoding and sRGBEncoding. Defaulting to LinearEncoding.\"\n\t\t\t);\n\t\t\tencoding = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\n\t\t}\n\t\tconst texture = new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\tgl: this.scene.canvas.gl,\n\t\t\tminFilter,\n\t\t\tmagFilter,\n\t\t\twrapS,\n\t\t\twrapT,\n\t\t\twrapR,\n\t\t\t// flipY: cfg.flipY,\n\t\t\tencoding\n\t\t});\n\t\tif (cfg.preloadColor) {\n\t\t\ttexture.setPreloadColor(cfg.preloadColor);\n\t\t}\n\t\tif (cfg.image) {\n\t\t\t// Ignore transcoder for Images\n\t\t\tconst image = cfg.image;\n\t\t\timage.crossOrigin = \"Anonymous\";\n\t\t\ttexture.setImage(image, { minFilter, magFilter, wrapS, wrapT, wrapR, flipY: cfg.flipY, encoding });\n\t\t} else if (cfg.src) {\n\t\t\tconst ext = cfg.src.split(\".\").pop();\n\t\t\tswitch (\n\t\t\t\text // Don't transcode recognized image file types\n\t\t\t) {\n\t\t\t\tcase \"jpeg\":\n\t\t\t\tcase \"jpg\":\n\t\t\t\tcase \"png\":\n\t\t\t\tcase \"gif\":\n\t\t\t\t\tconst image = new Image();\n\t\t\t\t\timage.onload = () => {\n\t\t\t\t\t\ttexture.setImage(image, {\n\t\t\t\t\t\t\tminFilter,\n\t\t\t\t\t\t\tmagFilter,\n\t\t\t\t\t\t\twrapS,\n\t\t\t\t\t\t\twrapT,\n\t\t\t\t\t\t\twrapR,\n\t\t\t\t\t\t\tflipY: cfg.flipY,\n\t\t\t\t\t\t\tencoding\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.glRedraw();\n\t\t\t\t\t};\n\t\t\t\t\timage.src = cfg.src; // URL or Base64 string\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: // Assume other file types need transcoding\n\t\t\t\t\tif (!this._textureTranscoder) {\n\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t`[createTexture] Can't create texture from 'src' - SceneModel needs to be configured with a TextureTranscoder for this file type ('${ext}')`\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_utils_js__WEBPACK_IMPORTED_MODULE_19__.utils.loadArraybuffer(\n\t\t\t\t\t\t\tcfg.src,\n\t\t\t\t\t\t\t(arrayBuffer) => {\n\t\t\t\t\t\t\t\tif (!arrayBuffer.byteLength) {\n\t\t\t\t\t\t\t\t\tthis.error(`[createTexture] Can't create texture from 'src': file data is zero length`);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis._textureTranscoder.transcode([arrayBuffer], texture).then(() => {\n\t\t\t\t\t\t\t\t\tthis.glRedraw();\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfunction (errMsg) {\n\t\t\t\t\t\t\t\tthis.error(`[createTexture] Can't create texture from 'src': ${errMsg}`);\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\tbreak;\n\t\t\t}\n\t\t} else if (cfg.buffers) {\n\t\t\t// Buffers implicitly require transcoding\n\t\t\tif (!this._textureTranscoder) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTexture] Can't create texture from 'buffers' - SceneModel needs to be configured with a TextureTranscoder for this option`\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis._textureTranscoder.transcode(cfg.buffers, texture).then(() => {\n\t\t\t\t\tthis.glRedraw();\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis._textures[textureId] = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({ id: textureId, texture });\n\t}\n\n\t/**\n\t * Creates a texture set within this SceneModel.\n\t *\n\t * * Stores the new {@link SceneModelTextureSet} in {@link SceneModel#textureSets}.\n\t *\n\t * A texture set is a collection of textures that can be shared among meshes. We can then supply the texture set\n\t * ID to {@link SceneModel#createMesh} when we want to create meshes that use the texture set.\n\t *\n\t * The textures can work as a texture atlas, where each mesh can have geometry UVs that index\n\t * a different part of the textures. This allows us to minimize the number of textures in our models, which\n\t * means faster rendering.\n\t *\n\t * @param {*} cfg Texture set properties.\n\t * @param {String|Number} cfg.id Mandatory ID for the texture set, to refer to with {@link SceneModel#createMesh}.\n\t * @param {*} [cfg.colorTextureId] ID of *RGBA* base color texture, with color in *RGB* and alpha in *A*.\n\t * @param {*} [cfg.metallicRoughnessTextureId] ID of *RGBA* metal-roughness texture, with the metallic factor in *R*, and roughness factor in *G*.\n\t * @param {*} [cfg.normalsTextureId] ID of *RGBA* normal map texture, with normal map vectors in *RGB*.\n\t * @param {*} [cfg.emissiveTextureId] ID of *RGBA* emissive map texture, with emissive color in *RGB*.\n\t * @param {*} [cfg.occlusionTextureId] ID of *RGBA* occlusion map texture, with occlusion factor in *R*.\n\t * @returns {SceneModelTransform} The new texture set.\n\t */\n\tcreateTextureSet(cfg) {\n\t\tconst textureSetId = cfg.id;\n\t\tif (textureSetId === undefined || textureSetId === null) {\n\t\t\tthis.error(\"[createTextureSet] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._textureSets[textureSetId]) {\n\t\t\tthis.error(`[createTextureSet] Texture set already created: ${textureSetId}`);\n\t\t\treturn;\n\t\t}\n\t\tlet colorTexture;\n\t\tif (cfg.colorTextureId !== undefined && cfg.colorTextureId !== null) {\n\t\t\tcolorTexture = this._textures[cfg.colorTextureId];\n\t\t\tif (!colorTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.colorTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tcolorTexture = this._textures[DEFAULT_COLOR_TEXTURE_ID];\n\t\t}\n\t\tlet metallicRoughnessTexture;\n\t\tif (cfg.metallicRoughnessTextureId !== undefined && cfg.metallicRoughnessTextureId !== null) {\n\t\t\tmetallicRoughnessTexture = this._textures[cfg.metallicRoughnessTextureId];\n\t\t\tif (!metallicRoughnessTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.metallicRoughnessTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tmetallicRoughnessTexture = this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID];\n\t\t}\n\t\tlet normalsTexture;\n\t\tif (cfg.normalsTextureId !== undefined && cfg.normalsTextureId !== null) {\n\t\t\tnormalsTexture = this._textures[cfg.normalsTextureId];\n\t\t\tif (!normalsTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.normalsTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tnormalsTexture = this._textures[DEFAULT_NORMALS_TEXTURE_ID];\n\t\t}\n\t\tlet emissiveTexture;\n\t\tif (cfg.emissiveTextureId !== undefined && cfg.emissiveTextureId !== null) {\n\t\t\temissiveTexture = this._textures[cfg.emissiveTextureId];\n\t\t\tif (!emissiveTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.emissiveTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\temissiveTexture = this._textures[DEFAULT_EMISSIVE_TEXTURE_ID];\n\t\t}\n\t\tlet occlusionTexture;\n\t\tif (cfg.occlusionTextureId !== undefined && cfg.occlusionTextureId !== null) {\n\t\t\tocclusionTexture = this._textures[cfg.occlusionTextureId];\n\t\t\tif (!occlusionTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.occlusionTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tocclusionTexture = this._textures[DEFAULT_OCCLUSION_TEXTURE_ID];\n\t\t}\n\t\tconst textureSet = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\n\t\t\tid: textureSetId,\n\t\t\tmodel: this,\n\t\t\tcolorTexture,\n\t\t\tmetallicRoughnessTexture,\n\t\t\tnormalsTexture,\n\t\t\temissiveTexture,\n\t\t\tocclusionTexture\n\t\t});\n\t\tthis._textureSets[textureSetId] = textureSet;\n\t\treturn textureSet;\n\t}\n\n\t/**\n\t * Creates a new {@link SceneModelTransform} within this SceneModel.\n\t *\n\t * * Stores the new {@link SceneModelTransform} in {@link SceneModel#transforms}.\n\t * * Can be connected into hierarchies\n\t * * Each {@link SceneModelTransform} can be used by unlimited {@link SceneModelMesh}es\n\t *\n\t * @param {*} cfg Transform creation parameters.\n\t * @param {String} cfg.id Mandatory ID for the new transform. Must not clash with any existing components within the {@link Scene}.\n\t * @param {String} [cfg.parentTransformId] ID of a parent transform, previously created with {@link SceneModel#createTextureSet}.\n\t * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\n\t * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the transform.\n\t * @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\t * @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\t * @returns {SceneModelTransform} The new transform.\n\t */\n\tcreateTransform(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._transforms[cfg.id]) {\n\t\t\tthis.error(`[createTransform] SceneModel already has a transform with this ID: ${cfg.id}`);\n\t\t\treturn;\n\t\t}\n\t\tlet parentTransform;\n\t\tif (this.parentTransformId) {\n\t\t\tparentTransform = this._transforms[cfg.parentTransformId];\n\t\t\tif (!parentTransform) {\n\t\t\t\tthis.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tconst transform = new _SceneModelTransform_js__WEBPACK_IMPORTED_MODULE_27__.SceneModelTransform({\n\t\t\tid: cfg.id,\n\t\t\tmodel: this,\n\t\t\tparentTransform,\n\t\t\tmatrix: cfg.matrix,\n\t\t\tposition: cfg.position,\n\t\t\tscale: cfg.scale,\n\t\t\trotation: cfg.rotation,\n\t\t\tquaternion: cfg.quaternion\n\t\t});\n\t\tthis._transforms[transform.id] = transform;\n\t\treturn transform;\n\t}\n\n\t/**\n\t * Creates a new {@link SceneModelMesh} within this SceneModel.\n\t *\n\t * * 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\t * * The SceneModelMesh can either define its own geometry or share it with other SceneModelMeshes. To define own geometry, provide the\n\t * various geometry arrays to this method. To share a geometry, provide the ID of a geometry created earlier\n\t * with {@link SceneModel#createGeometry}.\n\t * * If you accompany the arrays with an ````origin````, then ````createMesh()```` will assume\n\t * that the geometry ````positions```` are in relative-to-center (RTC) coordinates, with ````origin```` being the\n\t * origin of their RTC coordinate system.\n\t *\n\t * @param {object} cfg Object properties.\n\t * @param {String} cfg.id Mandatory ID for the new mesh. Must not clash with any existing components within the {@link Scene}.\n\t * @param {String|Number} [cfg.textureSetId] ID of a {@link SceneModelTextureSet} previously created with {@link SceneModel#createTextureSet}.\n\t * @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\t * @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\t * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\n\t * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\n\t * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\n\t * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\n\t * @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\t * @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\t * @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\t * @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\t * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n\t * @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\t * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\n\t * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\n\t * @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\t * @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\t * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\n\t * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.\n\t * @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\t * @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\t * @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\t * @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.\n\t * @param {Number} [cfg.metallic=0] Metallic factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\n\t * @param {Number} [cfg.roughness=1] Roughness factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\n\t * @returns {Boolean} True = successfully mesh was created. False = error during creation of a mesh.\n\t */\n\tcreateMesh(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createMesh] SceneModel.createMesh() config missing: id\");\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this._scheduledMeshes[cfg.id]) {\n\t\t\tthis.error(`[createMesh] SceneModel already has a mesh with this ID: ${cfg.id}`);\n\t\t\treturn false;\n\t\t}\n\n\t\tconst instancing = cfg.geometryId !== undefined;\n\t\tconst batching = !instancing;\n\n\t\tif (batching) {\n\t\t\t// Batched geometry\n\n\t\t\tif (cfg.primitive === undefined || cfg.primitive === null) {\n\t\t\t\tcfg.primitive = \"triangles\";\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcfg.primitive !== \"points\" &&\n\t\t\t\tcfg.primitive !== \"lines\" &&\n\t\t\t\tcfg.primitive !== \"triangles\" &&\n\t\t\t\tcfg.primitive !== \"solid\" &&\n\t\t\t\tcfg.primitive !== \"surface\"\n\t\t\t) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`Unsupported value for 'primitive': '${primitive}' ('geometryId' is absent) - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'.`\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\n\t\t\t\tthis.error(\"Param expected: 'positions', 'positionsCompressed' or `buckets` ('geometryId' is absent)\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cfg.positions && (cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Illegal params: 'positions' not expected with 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\"\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Param expected: 'positionsCompressed' should be accompanied by 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\"\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\n\t\t\t\tthis.error(\"Param expected: 'uvCompressed' should be accompanied by `uvDecodeMatrix` ('geometryId' is absent)\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\n\t\t\t\tthis.error(`Param expected: indices (required for '${cfg.primitive}' primitive type)`);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t(cfg.matrix || cfg.position || cfg.rotation || cfg.scale) &&\n\t\t\t\t(cfg.positionsCompressed || cfg.positionsDecodeBoundary)\n\t\t\t) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Unexpected params: 'matrix', 'rotation', 'scale', 'position' not allowed with 'positionsCompressed'\"\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst useDTX =\n\t\t\t\t!!this._dtxEnabled &&\n\t\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\");\n\n\t\t\tcfg.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\t\t\t// MATRIX - optional for batching\n\n\t\t\tif (cfg.matrix) {\n\t\t\t\tcfg.meshMatrix = cfg.matrix;\n\t\t\t} else if (cfg.scale || cfg.rotation || cfg.position) {\n\t\t\t\tconst scale = cfg.scale || DEFAULT_SCALE;\n\t\t\t\tconst position = cfg.position || DEFAULT_POSITION;\n\t\t\t\tconst rotation = cfg.rotation || DEFAULT_ROTATION;\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\n\t\t\t\tcfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t\t}\n\n\t\t\tif (cfg.positionsDecodeBoundary) {\n\t\t\t\tcfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t\t}\n\n\t\t\tif (useDTX) {\n\t\t\t\t// DTX\n\n\t\t\t\tcfg.type = DTX;\n\n\t\t\t\t// NPR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: defaultCompressedColor;\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\n\t\t\t\t// RTC\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst rtcCenter = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\n\t\t\t\t\tconst rtcPositions = [];\n\t\t\t\t\tconst rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, rtcCenter);\n\t\t\t\t\tif (rtcNeeded) {\n\t\t\t\t\t\tcfg.positions = rtcPositions;\n\t\t\t\t\t\tcfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, rtcCenter, rtcCenter);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// COMPRESSION\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\tcfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n\t\t\t\t\tcfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t} else if (cfg.positionsCompressed) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n\t\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t}\n\t\t\t\tif (cfg.buckets) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\tconst bucket = cfg.buckets[i];\n\t\t\t\t\t\tif (bucket.positions) {\n\t\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\n\t\t\t\t\t\t} else if (bucket.positionsCompressed) {\n\t\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (cfg.positionsDecodeMatrix) {\n\t\t\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\t}\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t}\n\n\t\t\t\tif (cfg.meshMatrix) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\n\t\t\t\t}\n\n\t\t\t\t// EDGES\n\n\t\t\t\tif (\n\t\t\t\t\t!cfg.buckets &&\n\t\t\t\t\t!cfg.edgeIndices &&\n\t\t\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")\n\t\t\t\t) {\n\t\t\t\t\tif (cfg.positions) {\n\t\t\t\t\t\t// Faster\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// BUCKETING\n\n\t\t\t\tif (!cfg.buckets) {\n\t\t\t\t\tcfg.buckets = createDTXBuckets(cfg, this._enableVertexWelding && this._enableIndexBucketing);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// VBO\n\n\t\t\t\tcfg.type = VBO_BATCHED;\n\n\t\t\t\t// PBR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: [255, 255, 255];\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\t\t\t\tcfg.metallic = cfg.metallic !== undefined && cfg.metallic !== null ? Math.floor(cfg.metallic * 255) : 0;\n\t\t\t\tcfg.roughness = cfg.roughness !== undefined && cfg.roughness !== null ? Math.floor(cfg.roughness * 255) : 255;\n\n\t\t\t\t// RTC\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst rtcPositions = [];\n\t\t\t\t\tconst rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, tempVec3a);\n\t\t\t\t\tif (rtcNeeded) {\n\t\t\t\t\t\tcfg.positions = rtcPositions;\n\t\t\t\t\t\tcfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, tempVec3a, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\tif (cfg.meshMatrix) {\n\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPositions3(cfg.meshMatrix, cfg.positions, cfg.positions);\n\t\t\t\t\t\tcfg.meshMatrix = null; // Positions now baked, don't need any more\n\t\t\t\t\t}\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t} else {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n\t\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t}\n\n\t\t\t\tif (cfg.meshMatrix) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\n\t\t\t\t}\n\n\t\t\t\t// EDGES\n\n\t\t\t\tif (\n\t\t\t\t\t!cfg.buckets &&\n\t\t\t\t\t!cfg.edgeIndices &&\n\t\t\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")\n\t\t\t\t) {\n\t\t\t\t\tif (cfg.positions) {\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// TEXTURE\n\n\t\t\t\t// cfg.textureSetId = cfg.textureSetId || DEFAULT_TEXTURE_SET_ID;\n\t\t\t\tif (cfg.textureSetId) {\n\t\t\t\t\tcfg.textureSet = this._textureSets[cfg.textureSetId];\n\t\t\t\t\tif (!cfg.textureSet) {\n\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// INSTANCING\n\n\t\t\tif (\n\t\t\t\tcfg.positions ||\n\t\t\t\tcfg.positionsCompressed ||\n\t\t\t\tcfg.indices ||\n\t\t\t\tcfg.edgeIndices ||\n\t\t\t\tcfg.normals ||\n\t\t\t\tcfg.normalsCompressed ||\n\t\t\t\tcfg.uv ||\n\t\t\t\tcfg.uvCompressed ||\n\t\t\t\tcfg.positionsDecodeMatrix\n\t\t\t) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`Mesh geometry parameters not expected when instancing a geometry (not expected: positions, positionsCompressed, indices, edgeIndices, normals, normalsCompressed, uv, uvCompressed, positionsDecodeMatrix)`\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tcfg.geometry = this._geometries[cfg.geometryId];\n\t\t\tif (!cfg.geometry) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createMesh] Geometry not found: ${cfg.geometryId} - ensure that you create it first with createGeometry()`\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tcfg.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\t\t\tcfg.positionsDecodeMatrix = cfg.geometry.positionsDecodeMatrix;\n\n\t\t\tif (cfg.transformId) {\n\t\t\t\t// TRANSFORM\n\n\t\t\t\tcfg.transform = this._transforms[cfg.transformId];\n\n\t\t\t\tif (!cfg.transform) {\n\t\t\t\t\tthis.error(\n\t\t\t\t\t\t`[createMesh] Transform not found: ${cfg.transformId} - ensure that you create it first with createTransform()`\n\t\t\t\t\t);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcfg.aabb = cfg.geometry.aabb;\n\t\t\t} else {\n\t\t\t\t// MATRIX\n\n\t\t\t\tif (cfg.matrix) {\n\t\t\t\t\tcfg.meshMatrix = cfg.matrix.slice();\n\t\t\t\t} else {\n\t\t\t\t\tconst scale = cfg.scale || DEFAULT_SCALE;\n\t\t\t\t\tconst position = cfg.position || DEFAULT_POSITION;\n\t\t\t\t\tconst rotation = cfg.rotation || DEFAULT_ROTATION;\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\n\t\t\t\t\tcfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t\t\t}\n\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n\t\t\t\tcfg.aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3());\n\t\t\t}\n\n\t\t\tconst useDTX =\n\t\t\t\t!!this._dtxEnabled &&\n\t\t\t\t(cfg.geometry.primitive === \"triangles\" ||\n\t\t\t\t\tcfg.geometry.primitive === \"solid\" ||\n\t\t\t\t\tcfg.geometry.primitive === \"surface\");\n\n\t\t\tif (useDTX) {\n\t\t\t\t// DTX\n\n\t\t\t\tcfg.type = DTX;\n\n\t\t\t\t// NPR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: defaultCompressedColor;\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\n\t\t\t\t// BUCKETING - lazy generated, reused\n\n\t\t\t\tlet buckets = this._dtxBuckets[cfg.geometryId];\n\t\t\t\tif (!buckets) {\n\t\t\t\t\tbuckets = createDTXBuckets(cfg.geometry, this._enableVertexWelding, this._enableIndexBucketing);\n\t\t\t\t\tthis._dtxBuckets[cfg.geometryId] = buckets;\n\t\t\t\t}\n\t\t\t\tcfg.buckets = buckets;\n\t\t\t} else {\n\t\t\t\t// VBO\n\n\t\t\t\tcfg.type = VBO_INSTANCED;\n\n\t\t\t\t// PBR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: defaultCompressedColor;\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\t\t\t\tcfg.metallic = cfg.metallic !== undefined && cfg.metallic !== null ? Math.floor(cfg.metallic * 255) : 0;\n\t\t\t\tcfg.roughness = cfg.roughness !== undefined && cfg.roughness !== null ? Math.floor(cfg.roughness * 255) : 255;\n\n\t\t\t\t// TEXTURE\n\n\t\t\t\tif (cfg.textureSetId) {\n\t\t\t\t\tcfg.textureSet = this._textureSets[cfg.textureSetId];\n\t\t\t\t\t// if (!cfg.textureSet) {\n\t\t\t\t\t// this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);\n\t\t\t\t\t// return false;\n\t\t\t\t\t// }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tcfg.numPrimitives = this._getNumPrimitives(cfg);\n\n\t\tthis._meshesCfgsBeforeMeshCreation[cfg.id] = cfg;\n\n\t\treturn true;\n\t}\n\n\t_createMesh(cfg) {\n\t\tconst mesh = new _SceneModelMesh_js__WEBPACK_IMPORTED_MODULE_3__.SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);\n\t\tmesh.pickId = this.scene._renderer.getPickID(mesh);\n\t\tconst pickId = mesh.pickId;\n\t\tconst a = (pickId >> 24) & 0xff;\n\t\tconst b = (pickId >> 16) & 0xff;\n\t\tconst g = (pickId >> 8) & 0xff;\n\t\tconst r = pickId & 0xff;\n\t\tcfg.pickColor = new Uint8Array([r, g, b, a]); // Quantized pick color\n\t\tcfg.solid = cfg.primitive === \"solid\";\n\t\tmesh.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin);\n\t\tswitch (cfg.type) {\n\t\t\tcase DTX:\n\t\t\t\tmesh.layer = this._getDTXLayer(cfg);\n\t\t\t\tmesh.aabb = cfg.aabb;\n\t\t\t\tbreak;\n\t\t\tcase VBO_BATCHED:\n\t\t\t\tmesh.layer = this._getVBOBatchingLayer(cfg);\n\t\t\t\tmesh.aabb = cfg.aabb;\n\t\t\t\tbreak;\n\t\t\tcase VBO_INSTANCED:\n\t\t\t\tmesh.layer = this._getVBOInstancingLayer(cfg);\n\t\t\t\tmesh.aabb = cfg.aabb;\n\t\t\t\tbreak;\n\t\t}\n\t\tif (cfg.transform) {\n\t\t\tcfg.meshMatrix = cfg.transform.worldMatrix;\n\t\t}\n\t\tmesh.portionId = mesh.layer.createPortion(mesh, cfg);\n\t\treturn mesh;\n\t}\n\n\t_getNumPrimitives(cfg) {\n\t\tlet countIndices = 0;\n\t\tconst primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\n\t\tswitch (primitive) {\n\t\t\tcase \"triangles\":\n\t\t\tcase \"solid\":\n\t\t\tcase \"surface\":\n\t\t\t\tswitch (cfg.type) {\n\t\t\t\t\tcase DTX:\n\t\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\t\tcountIndices += cfg.buckets[i].indices.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_BATCHED:\n\t\t\t\t\t\tcountIndices += cfg.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_INSTANCED:\n\t\t\t\t\t\tcountIndices += cfg.geometry.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn Math.round(countIndices / 3);\n\t\t\tcase \"points\":\n\t\t\t\tswitch (cfg.type) {\n\t\t\t\t\tcase DTX:\n\t\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\t\tcountIndices += cfg.buckets[i].positionsCompressed.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_BATCHED:\n\t\t\t\t\t\tcountIndices += cfg.positions ? cfg.positions.length : cfg.positionsCompressed.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_INSTANCED:\n\t\t\t\t\t\tconst geometry = cfg.geometry;\n\t\t\t\t\t\tcountIndices += geometry.positions ? geometry.positions.length : geometry.positionsCompressed.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn Math.round(countIndices);\n\t\t\tcase \"lines\":\n\t\t\tcase \"line-strip\":\n\t\t\t\tswitch (cfg.type) {\n\t\t\t\t\tcase DTX:\n\t\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\t\tcountIndices += cfg.buckets[i].indices.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_BATCHED:\n\t\t\t\t\t\tcountIndices += cfg.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_INSTANCED:\n\t\t\t\t\t\tcountIndices += cfg.geometry.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn Math.round(countIndices / 2);\n\t\t}\n\t\treturn 0;\n\t}\n\n\t_getDTXLayer(cfg) {\n\t\tconst origin = cfg.origin;\n\t\tconst primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\n\t\tconst layerId = `.${primitive}.${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}`;\n\t\tlet dtxLayer = this._dtxLayers[layerId];\n\t\tif (dtxLayer) {\n\t\t\tif (!dtxLayer.canCreatePortion(cfg)) {\n\t\t\t\tdtxLayer.finalize();\n\t\t\t\tdelete this._dtxLayers[layerId];\n\t\t\t\tdtxLayer = null;\n\t\t\t} else {\n\t\t\t\treturn dtxLayer;\n\t\t\t}\n\t\t}\n\t\tswitch (primitive) {\n\t\t\tcase \"triangles\":\n\t\t\tcase \"solid\":\n\t\t\tcase \"surface\":\n\t\t\t\tdtxLayer = new _dtx_triangles_DTXTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_12__.DTXTrianglesLayer(this, { layerIndex: 0, origin }); // layerIndex is set in #finalize()\n\t\t\t\tbreak;\n\t\t\tcase \"lines\":\n\t\t\t\tdtxLayer = new _dtx_lines_DTXLinesLayer_js__WEBPACK_IMPORTED_MODULE_11__.DTXLinesLayer(this, { layerIndex: 0, origin }); // layerIndex is set in #finalize()\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t\tthis._dtxLayers[layerId] = dtxLayer;\n\t\tthis.layerList.push(dtxLayer);\n\t\treturn dtxLayer;\n\t}\n\n\t_getVBOBatchingLayer(cfg) {\n\t\tconst model = this;\n\t\tconst origin = cfg.origin;\n\t\tconst positionsDecodeHash =\n\t\t\tcfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary\n\t\t\t\t? this._createHashStringFromMatrix(cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)\n\t\t\t\t: \"-\";\n\t\tconst textureSetId = cfg.textureSetId || \"-\";\n\t\tconst layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${\n\t\t\tcfg.primitive\n\t\t}.${positionsDecodeHash}.${textureSetId}`;\n\t\tlet vboBatchingLayer = this._vboBatchingLayers[layerId];\n\t\tif (vboBatchingLayer) {\n\t\t\treturn vboBatchingLayer;\n\t\t}\n\t\tlet textureSet = cfg.textureSet;\n\t\twhile (!vboBatchingLayer) {\n\t\t\tswitch (cfg.primitive) {\n\t\t\t\tcase \"triangles\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\n\t\t\t\t\t\tsolid: cfg.primitive === \"solid\",\n\t\t\t\t\t\tautoNormals: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"solid\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\n\t\t\t\t\t\tsolid: cfg.primitive === \"solid\",\n\t\t\t\t\t\tautoNormals: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"surface\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\n\t\t\t\t\t\tsolid: cfg.primitive === \"solid\",\n\t\t\t\t\t\tautoNormals: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lines\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating VBOBatchingLinesLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_lines_VBOBatchingLinesLayer_js__WEBPACK_IMPORTED_MODULE_7__.VBOBatchingLinesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"points\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating VBOBatchingPointsLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_points_VBOBatchingPointsLayer_js__WEBPACK_IMPORTED_MODULE_9__.VBOBatchingPointsLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst lenPositions = cfg.positionsCompressed ? cfg.positionsCompressed.length : cfg.positions.length;\n\t\t\tconst canCreatePortion =\n\t\t\t\tcfg.primitive === \"points\"\n\t\t\t\t\t? vboBatchingLayer.canCreatePortion(lenPositions)\n\t\t\t\t\t: vboBatchingLayer.canCreatePortion(lenPositions, cfg.indices.length);\n\t\t\tif (!canCreatePortion) {\n\t\t\t\tvboBatchingLayer.finalize();\n\t\t\t\tdelete this._vboBatchingLayers[layerId];\n\t\t\t\tvboBatchingLayer = null;\n\t\t\t}\n\t\t}\n\t\tthis._vboBatchingLayers[layerId] = vboBatchingLayer;\n\t\tthis.layerList.push(vboBatchingLayer);\n\t\treturn vboBatchingLayer;\n\t}\n\n\t_createHashStringFromMatrix(matrix) {\n\t\tconst matrixString = matrix.join(\"\");\n\t\tlet hash = 0;\n\t\tfor (let i = 0; i < matrixString.length; i++) {\n\t\t\tconst char = matrixString.charCodeAt(i);\n\t\t\thash = (hash << 5) - hash + char;\n\t\t\thash |= 0; // Convert to 32-bit integer\n\t\t}\n\t\tconst hashString = (hash >>> 0).toString(16);\n\t\treturn hashString;\n\t}\n\n\t_getVBOInstancingLayer(cfg) {\n\t\tconst model = this;\n\t\tconst origin = cfg.origin;\n\t\tconst textureSetId = cfg.textureSetId || \"-\";\n\t\tconst geometryId = cfg.geometryId;\n\t\tconst layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(\n\t\t\torigin[2]\n\t\t)}.${textureSetId}.${geometryId}`;\n\t\tlet vboInstancingLayer = this._vboInstancingLayers[layerId];\n\t\tif (vboInstancingLayer) {\n\t\t\treturn vboInstancingLayer;\n\t\t}\n\t\tlet textureSet = cfg.textureSet;\n\t\tconst geometry = cfg.geometry;\n\t\twhile (!vboInstancingLayer) {\n\t\t\tswitch (geometry.primitive) {\n\t\t\t\tcase \"triangles\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0,\n\t\t\t\t\t\tsolid: false\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"solid\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0,\n\t\t\t\t\t\tsolid: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"surface\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0,\n\t\t\t\t\t\tsolid: false\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lines\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating VBOInstancingLinesLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_lines_VBOInstancingLinesLayer_js__WEBPACK_IMPORTED_MODULE_8__.VBOInstancingLinesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"points\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating PointsInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_points_VBOInstancingPointsLayer_js__WEBPACK_IMPORTED_MODULE_10__.VBOInstancingPointsLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// const lenPositions = geometry.positionsCompressed.length;\n\t\t\t// if (!vboInstancingLayer.canCreatePortion(lenPositions, geometry.indices.length)) { // FIXME: indices should be optional\n\t\t\t// vboInstancingLayer.finalize();\n\t\t\t// delete this._vboInstancingLayers[layerId];\n\t\t\t// vboInstancingLayer = null;\n\t\t\t// }\n\t\t}\n\t\tthis._vboInstancingLayers[layerId] = vboInstancingLayer;\n\t\tthis.layerList.push(vboInstancingLayer);\n\t\treturn vboInstancingLayer;\n\t}\n\n\t/**\n\t * Creates a {@link SceneModelEntity} within this SceneModel.\n\t *\n\t * * Gives the SceneModelEntity one or more {@link SceneModelMesh}es previously created with\n\t * {@link SceneModel#createMesh}. A SceneModelMesh can only belong to one SceneModelEntity, so you'll get an\n\t * error if you try to reuse a mesh among multiple SceneModelEntitys.\n\t * * The SceneModelEntity can have a {@link SceneModelTextureSet}, previously created with\n\t * {@link SceneModel#createTextureSet}. A SceneModelTextureSet can belong to multiple SceneModelEntitys.\n\t * * The SceneModelEntity can have a geometry, previously created with\n\t * {@link SceneModel#createTextureSet}. A geometry is a \"virtual component\" and can belong to multiple SceneModelEntitys.\n\t *\n\t * @param {Object} cfg SceneModelEntity configuration.\n\t * @param {String} cfg.id Optional ID for the new SceneModelEntity. Must not clash with any existing components within the {@link Scene}.\n\t * @param {String[]} cfg.meshIds IDs of one or more meshes created previously with {@link SceneModel@createMesh}.\n\t * @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\t * @param {Boolean} [cfg.visible=true] Indicates if the SceneModelEntity is initially visible.\n\t * @param {Boolean} [cfg.culled=false] Indicates if the SceneModelEntity is initially culled from view.\n\t * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModelEntity is initially pickable.\n\t * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModelEntity is initially clippable.\n\t * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModelEntity is initially included in boundary calculations.\n\t * @param {Boolean} [cfg.castsShadow=true] Indicates if the SceneModelEntity initially casts shadows.\n\t * @param {Boolean} [cfg.receivesShadow=true] Indicates if the SceneModelEntity initially receives shadows.\n\t * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModelEntity is initially xrayed. XRayed appearance is configured by {@link SceneModel#xrayMaterial}.\n\t * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModelEntity is initially highlighted. Highlighted appearance is configured by {@link SceneModel#highlightMaterial}.\n\t * @param {Boolean} [cfg.selected=false] Indicates if the SceneModelEntity is initially selected. Selected appearance is configured by {@link SceneModel#selectedMaterial}.\n\t * @param {Boolean} [cfg.edges=false] Indicates if the SceneModelEntity's edges are initially emphasized. Edges appearance is configured by {@link SceneModel#edgeMaterial}.\n\t * @returns {SceneModelEntity} The new SceneModelEntity.\n\t */\n\tcreateEntity(cfg) {\n\t\tif (cfg.id === undefined) {\n\t\t\tcfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\n\t\t} else if (this.scene.components[cfg.id]) {\n\t\t\tthis.error(`Scene already has a Component with this ID: ${cfg.id} - will assign random ID`);\n\t\t\tcfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\n\t\t}\n\t\tif (cfg.meshIds === undefined) {\n\t\t\tthis.error(\"Config missing: meshIds\");\n\t\t\treturn;\n\t\t}\n\t\tlet flags = 0;\n\t\tif (this._visible && cfg.visible !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.VISIBLE;\n\t\t}\n\t\tif (this._pickable && cfg.pickable !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.PICKABLE;\n\t\t}\n\t\tif (this._culled && cfg.culled !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CULLED;\n\t\t}\n\t\tif (this._clippable && cfg.clippable !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CLIPPABLE;\n\t\t}\n\t\tif (this._collidable && cfg.collidable !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.COLLIDABLE;\n\t\t}\n\t\tif (this._edges && cfg.edges !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.EDGES;\n\t\t}\n\t\tif (this._xrayed && cfg.xrayed !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.XRAYED;\n\t\t}\n\t\tif (this._highlighted && cfg.highlighted !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.HIGHLIGHTED;\n\t\t}\n\t\tif (this._selected && cfg.selected !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.SELECTED;\n\t\t}\n\t\tcfg.flags = flags;\n\t\tthis._createEntity(cfg);\n\t}\n\n\t_createEntity(cfg) {\n\t\tlet meshes = [];\n\t\tfor (let i = 0, len = cfg.meshIds.length; i < len; i++) {\n\t\t\tconst meshId = cfg.meshIds[i];\n\t\t\tlet mesh = this._meshes[meshId]; // Trying to get already created mesh\n\t\t\tif (!mesh) {\n\t\t\t\t// Checks if there is already created mesh for this meshId\n\t\t\t\tlet meshCfg = this._meshesCfgsBeforeMeshCreation[meshId]; // Trying to get already created cfg\n\t\t\t\tif (!meshCfg) {\n\t\t\t\t\t// Checks if there is already created cfg for this meshId\n\t\t\t\t\tthis.error(`Mesh with this ID not found: \"${meshId}\" - ignoring this mesh`); // There is no such cfg\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tmesh = this._createMesh(meshCfg); // There is no such mesh yet, but there is already created cfg, so it creates this mesh\n\t\t\t\tthis._meshes[cfg.id] = mesh; // Now it will also add this mesh to dictionary of created meshes\n\t\t\t}\n\t\t\tif (mesh.parent) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`Mesh with ID \"${meshId}\" already belongs to object with ID \"${mesh.parent.id}\" - ignoring this mesh`\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmeshes.push(mesh);\n\t\t}\n\t\tconst lodCullable = true;\n\t\tconst entity = new _SceneModelEntity_js__WEBPACK_IMPORTED_MODULE_25__.SceneModelEntity(this, cfg.isObject, cfg.id, meshes, cfg.flags, lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel\n\t\tthis._entityList.push(entity);\n\t\tthis._entities[cfg.id] = entity;\n\t\tthis.numEntities++;\n\t}\n\n\t/**\n\t * Finalizes this SceneModel.\n\t *\n\t * Once finalized, you can't add anything more to this SceneModel.\n\t */\n\tfinalize() {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\n\t\t\tconst layer = this.layerList[i];\n\t\t\tlayer.finalize();\n\t\t}\n\t\tthis._geometries = {};\n\t\tthis._dtxBuckets = {};\n\t\tthis._textures = {};\n\t\tthis._textureSets = {};\n\t\tthis._dtxLayers = {};\n\t\tthis._vboInstancingLayers = {};\n\t\tthis._vboBatchingLayers = {};\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tconst entity = this._entityList[i];\n\t\t\tentity._finalize();\n\t\t}\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tconst entity = this._entityList[i];\n\t\t\tentity._finalize2();\n\t\t}\n\t\t// Sort layers to reduce WebGL shader switching when rendering them\n\t\tthis.layerList.sort((a, b) => {\n\t\t\tif (a.sortId < b.sortId) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (a.sortId > b.sortId) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\treturn 0;\n\t\t});\n\t\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\n\t\t\tconst layer = this.layerList[i];\n\t\t\tlayer.layerIndex = i;\n\t\t}\n\t\tthis.glRedraw();\n\t\tthis.scene._aabbDirty = true;\n\t\tthis._viewMatrixDirty = true;\n\t\tthis._matrixDirty = true;\n\t\tthis._aabbDirty = true;\n\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\n\t\tthis.position = this._position;\n\t}\n\n\t/** @private */\n\tstateSortCompare(drawable1, drawable2) {}\n\n\t/** @private */\n\trebuildRenderFlags() {\n\t\tthis.renderFlags.reset();\n\t\tthis._updateRenderFlagsVisibleLayers();\n\t\tif (this.renderFlags.numLayers > 0 && this.renderFlags.numVisibleLayers === 0) {\n\t\t\tthis.renderFlags.culled = true;\n\t\t\treturn;\n\t\t}\n\t\tthis._updateRenderFlags();\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_updateRenderFlagsVisibleLayers() {\n\t\tconst renderFlags = this.renderFlags;\n\t\trenderFlags.numLayers = this.layerList.length;\n\t\trenderFlags.numVisibleLayers = 0;\n\t\tfor (let layerIndex = 0, len = this.layerList.length; layerIndex < len; layerIndex++) {\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tconst layerVisible = this._getActiveSectionPlanesForLayer(layer);\n\t\t\tif (layerVisible) {\n\t\t\t\trenderFlags.visibleLayers[renderFlags.numVisibleLayers++] = layerIndex;\n\t\t\t}\n\t\t}\n\t}\n\n\t_getActiveSectionPlanesForLayer(layer) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tconst sectionPlanes = this.scene._sectionPlanesState.sectionPlanes;\n\t\tconst numSectionPlanes = sectionPlanes.length;\n\t\tconst baseIndex = layer.layerIndex * numSectionPlanes;\n\t\tif (numSectionPlanes > 0) {\n\t\t\tfor (let i = 0; i < numSectionPlanes; i++) {\n\t\t\t\tconst sectionPlane = sectionPlanes[i];\n\t\t\t\tif (!sectionPlane.active) {\n\t\t\t\t\trenderFlags.sectionPlanesActivePerLayer[baseIndex + i] = false;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.sectionPlanesActivePerLayer[baseIndex + i] = true;\n\t\t\t\t\trenderFlags.sectioned = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t_updateRenderFlags() {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.numCulledLayerPortions === this.numPortions) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\trenderFlags.colorOpaque = this.numTransparentLayerPortions < this.numPortions;\n\t\tif (this.numTransparentLayerPortions > 0) {\n\t\t\trenderFlags.colorTransparent = true;\n\t\t}\n\t\tif (this.numXRayedLayerPortions > 0) {\n\t\t\tconst xrayMaterial = this.scene.xrayMaterial._state;\n\t\t\tif (xrayMaterial.fill) {\n\t\t\t\tif (xrayMaterial.fillAlpha < 1.0) {\n\t\t\t\t\trenderFlags.xrayedSilhouetteTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.xrayedSilhouetteOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (xrayMaterial.edges) {\n\t\t\t\tif (xrayMaterial.edgeAlpha < 1.0) {\n\t\t\t\t\trenderFlags.xrayedEdgesTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.xrayedEdgesOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.numEdgesLayerPortions > 0) {\n\t\t\tconst edgeMaterial = this.scene.edgeMaterial._state;\n\t\t\tif (edgeMaterial.edges) {\n\t\t\t\trenderFlags.edgesOpaque = this.numTransparentLayerPortions < this.numPortions;\n\t\t\t\tif (this.numTransparentLayerPortions > 0) {\n\t\t\t\t\trenderFlags.edgesTransparent = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.numSelectedLayerPortions > 0) {\n\t\t\tconst selectedMaterial = this.scene.selectedMaterial._state;\n\t\t\tif (selectedMaterial.fill) {\n\t\t\t\tif (selectedMaterial.fillAlpha < 1.0) {\n\t\t\t\t\trenderFlags.selectedSilhouetteTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.selectedSilhouetteOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (selectedMaterial.edges) {\n\t\t\t\tif (selectedMaterial.edgeAlpha < 1.0) {\n\t\t\t\t\trenderFlags.selectedEdgesTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.selectedEdgesOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.numHighlightedLayerPortions > 0) {\n\t\t\tconst highlightMaterial = this.scene.highlightMaterial._state;\n\t\t\tif (highlightMaterial.fill) {\n\t\t\t\tif (highlightMaterial.fillAlpha < 1.0) {\n\t\t\t\t\trenderFlags.highlightedSilhouetteTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.highlightedSilhouetteOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (highlightMaterial.edges) {\n\t\t\t\tif (highlightMaterial.edgeAlpha < 1.0) {\n\t\t\t\t\trenderFlags.highlightedEdgesTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.highlightedEdgesOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// -------------- RENDERING ---------------------------------------------------------------------------------------\n\n\t/** @private */\n\tdrawColorOpaque(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawColorOpaque(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawColorTransparent(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawColorTransparent(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawDepth(frameCtx) {\n\t\t// Dedicated to SAO because it skips transparent objects\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawDepth(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawNormals(frameCtx) {\n\t\t// Dedicated to SAO because it skips transparent objects\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawNormals(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawSilhouetteXRayed(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawSilhouetteXRayed(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawSilhouetteHighlighted(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawSilhouetteHighlighted(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawSilhouetteSelected(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawSilhouetteSelected(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesColorOpaque(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesColorOpaque(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesColorTransparent(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesColorTransparent(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesXRayed(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesXRayed(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesHighlighted(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesHighlighted(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesSelected(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesSelected(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawOcclusion(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawOcclusion(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawShadow(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawShadow(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tsetPickMatrices(pickViewMatrix, pickProjMatrix) {\n\t\tif (this._numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tif (layer.setPickMatrices) {\n\t\t\t\tlayer.setPickMatrices(pickViewMatrix, pickProjMatrix);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawPickMesh(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawPickMesh(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * Called by SceneModelMesh.drawPickDepths()\n\t * @private\n\t */\n\tdrawPickDepths(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawPickDepths(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * Called by SceneModelMesh.drawPickNormals()\n\t * @private\n\t */\n\tdrawPickNormals(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawPickNormals(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawSnapInit(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tif (layer.drawSnapInit) {\n\t\t\t\tframeCtx.snapPickOrigin = [0, 0, 0];\n\t\t\t\tframeCtx.snapPickCoordinateScale = [1, 1, 1];\n\t\t\t\tframeCtx.snapPickLayerNumber++;\n\t\t\t\tlayer.drawSnapInit(renderFlags, frameCtx);\n\t\t\t\tframeCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\n\t\t\t\t\torigin: frameCtx.snapPickOrigin.slice(),\n\t\t\t\t\tcoordinateScale: frameCtx.snapPickCoordinateScale.slice()\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawSnap(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tif (layer.drawSnap) {\n\t\t\t\tframeCtx.snapPickOrigin = [0, 0, 0];\n\t\t\t\tframeCtx.snapPickCoordinateScale = [1, 1, 1];\n\t\t\t\tframeCtx.snapPickLayerNumber++;\n\t\t\t\tlayer.drawSnap(renderFlags, frameCtx);\n\t\t\t\tframeCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\n\t\t\t\t\torigin: frameCtx.snapPickOrigin.slice(),\n\t\t\t\t\tcoordinateScale: frameCtx.snapPickCoordinateScale.slice()\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys this SceneModel.\n\t */\n\tdestroy() {\n\t\tfor (let layerId in this._vboBatchingLayers) {\n\t\t\tif (this._vboBatchingLayers.hasOwnProperty(layerId)) {\n\t\t\t\tthis._vboBatchingLayers[layerId].destroy();\n\t\t\t}\n\t\t}\n\t\tthis._vboBatchingLayers = {};\n\t\tfor (let layerId in this._vboInstancingLayers) {\n\t\t\tif (this._vboInstancingLayers.hasOwnProperty(layerId)) {\n\t\t\t\tthis._vboInstancingLayers[layerId].destroy();\n\t\t\t}\n\t\t}\n\t\tthis._vboInstancingLayers = {};\n\t\tthis.scene.camera.off(this._onCameraViewMatrix);\n\t\tthis.scene.off(this._onTick);\n\t\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\n\t\t\tthis.layerList[i].destroy();\n\t\t}\n\t\tthis.layerList = [];\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i]._destroy();\n\t\t}\n\t\t// Object.entries(this._geometries).forEach(([id, geometry]) => {\n\t\t// geometry.destroy();\n\t\t// });\n\t\tthis._geometries = {};\n\t\tthis._dtxBuckets = {};\n\t\tthis._textures = {};\n\t\tthis._textureSets = {};\n\t\tthis._meshes = {};\n\t\tthis._entities = {};\n\t\tthis.scene._aabbDirty = true;\n\t\tif (this._isModel) {\n\t\t\tthis.scene._deregisterModel(this);\n\t\t}\n\t\t(0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.putScratchMemory)();\n\t\tsuper.destroy();\n\t}\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\tlet uniquePositionsCompressed, uniqueIndices, uniqueEdgeIndices;\n\tif (enableVertexWelding || enableIndexBucketing) {\n\t\t// Expensive - careful!\n\t\t[uniquePositionsCompressed, uniqueIndices, uniqueEdgeIndices] = (0,_calculateUniquePositions_js__WEBPACK_IMPORTED_MODULE_23__.uniquifyPositions)({\n\t\t\tpositionsCompressed: geometry.positionsCompressed,\n\t\t\tindices: geometry.indices,\n\t\t\tedgeIndices: geometry.edgeIndices\n\t\t});\n\t} else {\n\t\tuniquePositionsCompressed = geometry.positionsCompressed;\n\t\tuniqueIndices = geometry.indices;\n\t\tuniqueEdgeIndices = geometry.edgeIndices;\n\t}\n\tlet buckets;\n\tif (enableIndexBucketing) {\n\t\tlet numUniquePositions = uniquePositionsCompressed.length / 3;\n\t\tbuckets = (0,_rebucketPositions_js__WEBPACK_IMPORTED_MODULE_24__.rebucketPositions)(\n\t\t\t{\n\t\t\t\tpositionsCompressed: uniquePositionsCompressed,\n\t\t\t\tindices: uniqueIndices,\n\t\t\t\tedgeIndices: uniqueEdgeIndices\n\t\t\t},\n\t\t\tnumUniquePositions > 1 << 16 ? 16 : 8\n\t\t\t// true\n\t\t);\n\t} else {\n\t\tbuckets = [\n\t\t\t{\n\t\t\t\tpositionsCompressed: uniquePositionsCompressed,\n\t\t\t\tindices: uniqueIndices,\n\t\t\t\tedgeIndices: uniqueEdgeIndices\n\t\t\t}\n\t\t];\n\t}\n\treturn buckets;\n}\n\nfunction createGeometryOBB(geometry) {\n\tgeometry.obb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3();\n\tif (geometry.positionsCompressed && geometry.positionsCompressed.length > 0) {\n\t\tconst localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positionsCompressed);\n\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n\t} else if (geometry.positions && geometry.positions.length > 0) {\n\t\tconst localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positions);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n\t} else if (geometry.buckets) {\n\t\tconst localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\tfor (let i = 0, len = geometry.buckets.length; i < len; i++) {\n\t\t\tconst bucket = geometry.buckets[i];\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, bucket.positionsCompressed);\n\t\t}\n\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n\t}\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/SceneModel.js?");
|
|
3547
|
+
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\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\t/**\n\t * @constructor\n\t * @param {Component} owner Owner component. When destroyed, the owner will destroy this component as well.\n\t * @param {*} [cfg] Configs\n\t * @param {String} [cfg.id] Optional ID, unique among all components in the parent scene, generated automatically when omitted.\n\t * @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\t * @param {Number[]} [cfg.origin=[0,0,0]] World-space double-precision 3D origin.\n\t * @param {Number[]} [cfg.position=[0,0,0]] Local, single-precision 3D position, relative to the origin parameter.\n\t * @param {Number[]} [cfg.scale=[1,1,1]] Local scale.\n\t * @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\t * @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\t * @param {Boolean} [cfg.visible=true] Indicates if the SceneModel is initially visible.\n\t * @param {Boolean} [cfg.culled=false] Indicates if the SceneModel is initially culled from view.\n\t * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModel is initially pickable.\n\t * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModel is initially clippable.\n\t * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModel is initially included in boundary calculations.\n\t * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModel is initially xrayed.\n\t * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModel is initially highlighted.\n\t * @param {Boolean} [cfg.selected=false] Indicates if the SceneModel is initially selected.\n\t * @param {Boolean} [cfg.edges=false] Indicates if the SceneModel's edges are initially emphasized.\n\t * @param {Number[]} [cfg.colorize=[1.0,1.0,1.0]] SceneModel's initial RGB colorize color, multiplies by the rendered fragment colors.\n\t * @param {Number} [cfg.opacity=1.0] SceneModel's initial opacity factor, multiplies by the rendered fragment alpha.\n\t * @param {Number} [cfg.backfaces=false] When we set this ````true````, then we force rendering of backfaces for this SceneModel. When\n\t * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\n\t * 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\t * @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\t * @param {Boolean} [cfg.pbrEnabled=true] Indicates if physically-based rendering (PBR) will apply to the SceneModel when {@link Scene#pbrEnabled} is ````true````.\n\t * @param {Boolean} [cfg.colorTextureEnabled=true] Indicates if base color textures will be rendered for the SceneModel when {@link Scene#colorTextureEnabled} is ````true````.\n\t * @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\t * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\n\t * to limit the size of the batched geometry arrays that SceneModel internally creates for batched geometries.\n\t * A lower value means less heap allocation/de-allocation while creating/loading batched geometries, but more draw calls and\n\t * slower rendering speed. A high value means larger heap allocation/de-allocation while creating/loading, but less draw calls\n\t * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\n\t * @param {TextureTranscoder} [cfg.textureTranscoder] Transcoder that will be used internally by {@link SceneModel#createTexture}\n\t * to convert transcoded texture data. Only required when we'll be providing transcoded data\n\t * to {@link SceneModel#createTexture}. We assume that all transcoded texture data added to a ````SceneModel````\n\t * will then in a format supported by this transcoder.\n\t * @param {Boolean} [cfg.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\n\t * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\n\t * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\n\t * primitives. Only works while {@link DTX#enabled} is also ````true````.\n\t */\n\tconstructor(owner, cfg = {}) {\n\t\tsuper(owner, cfg);\n\n\t\tthis._dtxEnabled = this.scene.dtxEnabled && cfg.dtxEnabled !== false;\n\n\t\tthis._enableVertexWelding = false; // Not needed for most objects, and very expensive, so disabled\n\t\tthis._enableIndexBucketing = false; // Until fixed: https://github.com/xeokit/xeokit-sdk/issues/1204\n\n\t\tthis._vboBatchingLayerScratchMemory = (0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.getScratchMemory)();\n\t\tthis._textureTranscoder = cfg.textureTranscoder || (0,_utils_textureTranscoders_KTX2TextureTranscoder_KTX2TextureTranscoder_js__WEBPACK_IMPORTED_MODULE_20__.getKTX2TextureTranscoder)(this.scene.viewer);\n\n\t\tthis._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\n\n\t\tthis._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\t\tthis._exceptionIds = [];\n\n\t\tthis._quantizationRanges = {};\n\n\t\tthis._vboInstancingLayers = {};\n\t\tthis._vboBatchingLayers = {};\n\t\tthis._dtxLayers = {};\n\n\t\tthis.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second\n\t\tthis._entityList = [];\n\n\t\tthis._geometries = {};\n\t\tthis._dtxBuckets = {}; // Geometries with optimizations used for data texture representation\n\t\tthis._textures = {};\n\t\tthis._textureSets = {};\n\t\tthis._transforms = {};\n\t\tthis._meshes = {};\n\t\tthis._entities = {};\n\n\t\tthis._scheduledMeshes = {};\n\t\tthis._meshesCfgsBeforeMeshCreation = {};\n\n\t\t/** @private **/\n\t\tthis.renderFlags = new _webgl_RenderFlags_js__WEBPACK_IMPORTED_MODULE_14__.RenderFlags();\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numGeometries = 0; // Number of geometries created with createGeometry()\n\n\t\t// These counts are used to avoid unnecessary render passes\n\t\t// They are incremented or decremented exclusively by BatchingLayer and InstancingLayer\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numVisibleLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numTransparentLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numXRayedLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numHighlightedLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numSelectedLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numEdgesLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numPickableLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numClippableLayerPortions = 0;\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis.numCulledLayerPortions = 0;\n\n\t\tthis.numEntities = 0;\n\t\tthis._numTriangles = 0;\n\t\tthis._numLines = 0;\n\t\tthis._numPoints = 0;\n\n\t\tthis._edgeThreshold = cfg.edgeThreshold || 10;\n\n\t\t// Build static matrix\n\n\t\tthis._origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin || [0, 0, 0]);\n\t\tthis._position = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.position || [0, 0, 0]);\n\t\tthis._rotation = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.rotation || [0, 0, 0]);\n\t\tthis._quaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\n\t\tthis._conjugateQuaternion = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4(cfg.quaternion || [0, 0, 0, 1]);\n\n\t\tif (cfg.rotation) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\n\t\t}\n\t\tthis._scale = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.scale || [1, 1, 1]);\n\n\t\tthis._worldRotationMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\tthis._worldRotationMatrixConjugate = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\tthis._matrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\tthis._matrixDirty = true;\n\n\t\tthis._rebuildMatrices();\n\n\t\tthis._worldNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._matrix, this._worldNormalMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._worldNormalMatrix);\n\n\t\tif (cfg.matrix || cfg.position || cfg.rotation || cfg.scale || cfg.quaternion) {\n\t\t\tthis._viewMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\tthis._viewNormalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\tthis._viewMatrixDirty = true;\n\t\t\tthis._matrixNonIdentity = true;\n\t\t}\n\n\t\tthis._opacity = 1.0;\n\t\tthis._colorize = [1, 1, 1];\n\n\t\tthis._saoEnabled = cfg.saoEnabled !== false;\n\t\tthis._pbrEnabled = cfg.pbrEnabled !== false;\n\t\tthis._colorTextureEnabled = cfg.colorTextureEnabled !== false;\n\n\t\tthis._isModel = cfg.isModel;\n\t\tif (this._isModel) {\n\t\t\tthis.scene._registerModel(this);\n\t\t}\n\n\t\tthis._onCameraViewMatrix = this.scene.camera.on(\"matrix\", () => {\n\t\t\tthis._viewMatrixDirty = true;\n\t\t});\n\n\t\tthis._meshesWithDirtyMatrices = [];\n\t\tthis._numMeshesWithDirtyMatrices = 0;\n\n\t\tthis._onTick = this.scene.on(\"tick\", () => {\n\t\t\twhile (this._numMeshesWithDirtyMatrices > 0) {\n\t\t\t\tthis._meshesWithDirtyMatrices[--this._numMeshesWithDirtyMatrices]._updateMatrix();\n\t\t\t}\n\t\t});\n\n\t\tthis._createDefaultTextureSet();\n\n\t\tthis.visible = cfg.visible;\n\t\tthis.culled = cfg.culled;\n\t\tthis.pickable = cfg.pickable;\n\t\tthis.clippable = cfg.clippable;\n\t\tthis.collidable = cfg.collidable;\n\t\tthis.castsShadow = cfg.castsShadow;\n\t\tthis.receivesShadow = cfg.receivesShadow;\n\t\tthis.xrayed = cfg.xrayed;\n\t\tthis.highlighted = cfg.highlighted;\n\t\tthis.selected = cfg.selected;\n\t\tthis.edges = cfg.edges;\n\t\tthis.colorize = cfg.colorize;\n\t\tthis.opacity = cfg.opacity;\n\t\tthis.backfaces = cfg.backfaces;\n\t}\n\n\t_meshMatrixDirty(mesh) {\n\t\tthis._meshesWithDirtyMatrices[this._numMeshesWithDirtyMatrices++] = mesh;\n\t}\n\n\t_createDefaultTextureSet() {\n\t\t// Every SceneModelMesh gets at least the default TextureSet,\n\t\t// which contains empty default textures filled with color\n\t\tconst defaultColorTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_COLOR_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [1, 1, 1, 1] // [r, g, b, a]})\n\t\t\t})\n\t\t});\n\t\tconst defaultMetalRoughTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_METAL_ROUGH_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [0, 1, 1, 1] // [unused, roughness, metalness, unused]\n\t\t\t})\n\t\t});\n\t\tconst defaultNormalsTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_NORMALS_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [0, 0, 0, 0] // [x, y, z, unused] - these must be zeros\n\t\t\t})\n\t\t});\n\t\tconst defaultEmissiveTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_EMISSIVE_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [0, 0, 0, 1] // [x, y, z, unused]\n\t\t\t})\n\t\t});\n\t\tconst defaultOcclusionTexture = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({\n\t\t\tid: DEFAULT_OCCLUSION_TEXTURE_ID,\n\t\t\ttexture: new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\t\tgl: this.scene.canvas.gl,\n\t\t\t\tpreloadColor: [1, 1, 1, 1] // [x, y, z, unused]\n\t\t\t})\n\t\t});\n\t\tthis._textures[DEFAULT_COLOR_TEXTURE_ID] = defaultColorTexture;\n\t\tthis._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID] = defaultMetalRoughTexture;\n\t\tthis._textures[DEFAULT_NORMALS_TEXTURE_ID] = defaultNormalsTexture;\n\t\tthis._textures[DEFAULT_EMISSIVE_TEXTURE_ID] = defaultEmissiveTexture;\n\t\tthis._textures[DEFAULT_OCCLUSION_TEXTURE_ID] = defaultOcclusionTexture;\n\t\tthis._textureSets[DEFAULT_TEXTURE_SET_ID] = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\n\t\t\tid: DEFAULT_TEXTURE_SET_ID,\n\t\t\tmodel: this,\n\t\t\tcolorTexture: defaultColorTexture,\n\t\t\tmetallicRoughnessTexture: defaultMetalRoughTexture,\n\t\t\tnormalsTexture: defaultNormalsTexture,\n\t\t\temissiveTexture: defaultEmissiveTexture,\n\t\t\tocclusionTexture: defaultOcclusionTexture\n\t\t});\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// SceneModel members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * Returns true to indicate that this Component is a SceneModel.\n\t * @type {Boolean}\n\t */\n\tget isPerformanceModel() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * The {@link SceneModelTransform}s in this SceneModel.\n\t *\n\t * Each {#link SceneModelTransform} is stored here against its {@link SceneModelTransform.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget transforms() {\n\t\treturn this._transforms;\n\t}\n\n\t/**\n\t * The {@link SceneModelTexture}s in this SceneModel.\n\t *\n\t * * Each {@link SceneModelTexture} is created with {@link SceneModel.createTexture}.\n\t * * Each {@link SceneModelTexture} is stored here against its {@link SceneModelTexture.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget textures() {\n\t\treturn this._textures;\n\t}\n\n\t/**\n\t * The {@link SceneModelTextureSet}s in this SceneModel.\n\t *\n\t * Each {@link SceneModelTextureSet} is stored here against its {@link SceneModelTextureSet.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget textureSets() {\n\t\treturn this._textureSets;\n\t}\n\n\t/**\n\t * The {@link SceneModelMesh}es in this SceneModel.\n\t *\n\t * Each {@SceneModelMesh} is stored here against its {@link SceneModelMesh.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget meshes() {\n\t\treturn this._meshes;\n\t}\n\n\t/**\n\t * The {@link SceneModelEntity}s in this SceneModel.\n\t *\n\t * Each {#link SceneModelEntity} in this SceneModel that represents an object is\n\t * stored here against its {@link SceneModelTransform.id}.\n\t *\n\t * @returns {*|{}}\n\t */\n\tget objects() {\n\t\treturn this._entities;\n\t}\n\n\t/**\n\t * Gets the 3D World-space origin for this SceneModel.\n\t *\n\t * Each {@link SceneModelMesh.origin}, if supplied, is relative to this origin.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Float64Array}\n\t */\n\tget origin() {\n\t\treturn this._origin;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local translation.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset position(value) {\n\t\tthis._position.set(value || [0, 0, 0]);\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local translation.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget position() {\n\t\treturn this._position;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset rotation(value) {\n\t\tthis._rotation.set(value || [0, 0, 0]);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(this._rotation, \"XYZ\", this._quaternion);\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local rotation, as Euler angles given in degrees, for each of the X, Y and Z axis.\n\t *\n\t * Default value is ````[0,0,0]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget rotation() {\n\t\treturn this._rotation;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local rotation quaternion.\n\t *\n\t * Default value is ````[0,0,0,1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset quaternion(value) {\n\t\tthis._quaternion.set(value || [0, 0, 0, 1]);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToEuler(this._quaternion, \"XYZ\", this._rotation);\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local rotation quaternion.\n\t *\n\t * Default value is ````[0,0,0,1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget quaternion() {\n\t\treturn this._quaternion;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local scale.\n\t *\n\t * Default value is ````[1,1,1]````.\n\t *\n\t * @type {Number[]}\n\t * @deprecated\n\t */\n\tset scale(value) {\n\t\t// NOP - deprecated\n\t}\n\n\t/**\n\t * Gets the SceneModel's local scale.\n\t *\n\t * Default value is ````[1,1,1]````.\n\t *\n\t * @type {Number[]}\n\t * @deprecated\n\t */\n\tget scale() {\n\t\treturn this._scale;\n\t}\n\n\t/**\n\t * Sets the SceneModel's local modeling transform matrix.\n\t *\n\t * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset matrix(value) {\n\t\tthis._matrix.set(value || DEFAULT_MATRIX);\n\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\n\t\tthis._matrix.set(this._worldRotationMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\n\n\t\tthis._matrixDirty = false;\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the SceneModel's local modeling transform matrix.\n\t *\n\t * Default value is ````[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget matrix() {\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t}\n\t\treturn this._matrix;\n\t}\n\n\t/**\n\t * Gets the SceneModel's local modeling rotation transform matrix.\n\t *\n\t * @type {Number[]}\n\t */\n\tget rotationMatrix() {\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t}\n\t\treturn this._worldRotationMatrix;\n\t}\n\n\t_rebuildMatrices() {\n\t\tif (this._matrixDirty) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.conjugateQuaternion(this._quaternion, this._conjugateQuaternion);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.quaternionToRotationMat4(this._quaternion, this._worldRotationMatrixConjugate);\n\t\t\tthis._matrix.set(this._worldRotationMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.translateMat4v(this._position, this._matrix);\n\t\t\tthis._matrixDirty = false;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the conjugate of the SceneModel's local modeling rotation transform matrix.\n\t *\n\t * This is used for RTC view matrix management in renderers.\n\t *\n\t * @type {Number[]}\n\t */\n\tget rotationMatrixConjugate() {\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t}\n\t\treturn this._worldRotationMatrixConjugate;\n\t}\n\n\t_setWorldMatrixDirty() {\n\t\tthis._matrixDirty = true;\n\t\tthis._aabbDirty = true;\n\t}\n\n\t_transformDirty() {\n\t\tthis._matrixDirty = true;\n\t\tthis._aabbDirty = true;\n\t\tthis.scene._aabbDirty = true;\n\t}\n\n\t_sceneModelDirty() {\n\t\tthis.scene._aabbDirty = true;\n\t\tthis._aabbDirty = true;\n\t\tthis.scene._aabbDirty = true;\n\t\tthis._matrixDirty = true;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i]._sceneModelDirty(); // Entities need to retransform their World AABBs by SceneModel's worldMatrix\n\t\t}\n\t}\n\n\t/**\n\t * Gets the SceneModel's World matrix.\n\t *\n\t * @property worldMatrix\n\t * @type {Number[]}\n\t */\n\tget worldMatrix() {\n\t\treturn this.matrix;\n\t}\n\n\t/**\n\t * Gets the SceneModel's World normal matrix.\n\t *\n\t * @type {Number[]}\n\t */\n\tget worldNormalMatrix() {\n\t\treturn this._worldNormalMatrix;\n\t}\n\n\t/**\n\t * Called by private renderers in ./lib, returns the view matrix with which to\n\t * render this SceneModel. The view matrix is the concatenation of the\n\t * Camera view matrix with the Performance model's world (modeling) matrix.\n\t *\n\t * @private\n\t */\n\tget viewMatrix() {\n\t\tif (!this._viewMatrix) {\n\t\t\treturn this.scene.camera.viewMatrix;\n\t\t}\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t\tthis._viewMatrixDirty = true;\n\t\t}\n\t\tif (this._viewMatrixDirty) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n\t\t\tthis._viewMatrixDirty = false;\n\t\t}\n\t\treturn this._viewMatrix;\n\t}\n\n\t/**\n\t * Called by private renderers in ./lib, returns the view normal matrix with which to render this SceneModel.\n\t *\n\t * @private\n\t */\n\tget viewNormalMatrix() {\n\t\tif (!this._viewNormalMatrix) {\n\t\t\treturn this.scene.camera.viewNormalMatrix;\n\t\t}\n\t\tif (this._matrixDirty) {\n\t\t\tthis._rebuildMatrices();\n\t\t\tthis._viewMatrixDirty = true;\n\t\t}\n\t\tif (this._viewMatrixDirty) {\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulMat4(this.scene.camera.viewMatrix, this._matrix, this._viewMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n\t\t\tthis._viewMatrixDirty = false;\n\t\t}\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.inverseMat4(this._viewMatrix, this._viewNormalMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transposeMat4(this._viewNormalMatrix);\n\t\treturn this._viewNormalMatrix;\n\t}\n\n\t/**\n\t * Sets if backfaces are rendered for this SceneModel.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget backfaces() {\n\t\treturn this._backfaces;\n\t}\n\n\t/**\n\t * Sets if backfaces are rendered for this SceneModel.\n\t *\n\t * Default is ````false````.\n\t *\n\t * When we set this ````true````, then backfaces are always rendered for this SceneModel.\n\t *\n\t * When we set this ````false````, then we allow the Viewer to decide whether to render backfaces. In this case,\n\t * the Viewer will:\n\t *\n\t * * hide backfaces on watertight meshes,\n\t * * show backfaces on open meshes, and\n\t * * always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\n\t *\n\t * @type {Boolean}\n\t */\n\tset backfaces(backfaces) {\n\t\tbackfaces = !!backfaces;\n\t\tthis._backfaces = backfaces;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the list of {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * @returns {SceneModelEntity[]}\n\t */\n\tget entityList() {\n\t\treturn this._entityList;\n\t}\n\n\t/**\n\t * Returns true to indicate that SceneModel is an {@link Entity}.\n\t * @type {Boolean}\n\t */\n\tget isEntity() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns ````true```` if this SceneModel represents a model.\n\t *\n\t * When ````true```` the SceneModel will be registered by {@link SceneModel#id} in\n\t * {@link Scene#models} and may also have a {@link MetaObject} with matching {@link MetaObject#id}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isModel() {\n\t\treturn this._isModel;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// SceneModel members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * Returns ````false```` to indicate that SceneModel never represents an object.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isObject() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Gets the SceneModel's World-space 3D axis-aligned bounding box.\n\t *\n\t * Represented by a six-element Float64Array containing the min/max extents of the\n\t * axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget aabb() {\n\t\tif (this._aabbDirty) {\n\t\t\tif (this._aabbUpdate) {\n\t\t\t\treturn this._aabb;\n\t\t\t}\n\t\t\tif (this._exceptionIds.length > 0) this.updateAABBCullException(this._exceptionIds);\n\t\t\telse {\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3(this._aabb);\n\t\t\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3(this._aabb, this._entityList[i].aabb);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._aabbDirty = false;\n\t\t}\n\t\treturn this._aabb;\n\t}\n\n\t/**\n\t * 获取aabb排除在外的对象id\n\t * @type {string[]}\n\t */\n\tget exceptionIds() {\n\t\treturn this._exceptionIds;\n\t}\n\n\t/**\n\t * 设置aabb排除在外的对象id(自动更新新的aabb)\n\t * @param {string[]} exceptionIds\n\t */\n\tset exceptionIds(exceptionIds) {\n\t\tthis._exceptionIds = exceptionIds;\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\t\tthis.scene._setAABBDirty();\n\t}\n\n\tupdateAABBCullException(exceptionIds, callback) {\n\t\tfunction noExceptionId(id) {\n\t\t\tlet noExceptionId = true;\n\t\t\texceptionIds.forEach((exceptionId) => {\n\t\t\t\tif (exceptionId === id) {\n\t\t\t\t\tnoExceptionId = false;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn noExceptionId;\n\t\t}\n\t\tconst newAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tif (noExceptionId(this._entityList[i].id)) {\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3(newAABB, this._entityList[i].aabb);\n\t\t\t}\n\t\t}\n\n\t\tfor (let a = 0; a < newAABB.length; a++) {\n\t\t\tthis._aabb[a] = newAABB[a];\n\t\t}\n\t\tthis._aabbDirty = false;\n\t\tthis._aabbUpdate = true;\n\t\tthis.scene._setAABBDirty();\n\t\tif (typeof callback === \"function\") callback();\n\t}\n\n\tcancelCullException(callback) {\n\t\tthis._exceptionIds = [];\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\t\tthis.aabb;\n\t\tthis.scene._aabbUpdate = false;\n\t\tthis.scene._setAABBDirty();\n\t\tif (typeof callback === \"function\") callback();\n\t}\n\n\t/**\n\t * 获取所有实体的aabb\n\t */\n\tget aabbs() {\n\t\tlet aabbArray = [];\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\taabbArray.push(this._entityList[i].aabb);\n\t\t}\n\t\treturn aabbArray;\n\t}\n\n\t/**\n\t * The approximate number of triangle primitives in this SceneModel.\n\t *\n\t * @type {Number}\n\t */\n\tget numTriangles() {\n\t\treturn this._numTriangles;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// Entity members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * The approximate number of line primitives in this SceneModel.\n\t *\n\t * @type {Number}\n\t */\n\tget numLines() {\n\t\treturn this._numLines;\n\t}\n\n\t/**\n\t * The approximate number of point primitives in this SceneModel.\n\t *\n\t * @type {Number}\n\t */\n\tget numPoints() {\n\t\treturn this._numPoints;\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are visible.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget visible() {\n\t\treturn this.numVisibleLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if this SceneModel is visible.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is ````true```` and {@link SceneModel#culled} is ````false````.\n\t **\n\t * @type {Boolean}\n\t */\n\tset visible(visible) {\n\t\tvisible = visible !== false;\n\t\tthis._visible = visible;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].visible = visible;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are xrayed.\n\t *\n\t * @type {Boolean}\n\t */\n\tget xrayed() {\n\t\treturn this.numXRayedLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel are xrayed.\n\t *\n\t * @type {Boolean}\n\t */\n\tset xrayed(xrayed) {\n\t\txrayed = !!xrayed;\n\t\tthis._xrayed = xrayed;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].xrayed = xrayed;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are highlighted.\n\t *\n\t * @type {Boolean}\n\t */\n\tget highlighted() {\n\t\treturn this.numHighlightedLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel are highlighted.\n\t *\n\t * @type {Boolean}\n\t */\n\tset highlighted(highlighted) {\n\t\thighlighted = !!highlighted;\n\t\tthis._highlighted = highlighted;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].highlighted = highlighted;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel are selected.\n\t *\n\t * @type {Boolean}\n\t */\n\tget selected() {\n\t\treturn this.numSelectedLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel are selected.\n\t *\n\t * @type {Boolean}\n\t */\n\tset selected(selected) {\n\t\tselected = !!selected;\n\t\tthis._selected = selected;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].selected = selected;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if any {@link SceneModelEntity}s in this SceneModel have edges emphasised.\n\t *\n\t * @type {Boolean}\n\t */\n\tget edges() {\n\t\treturn this.numEdgesLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if all {@link SceneModelEntity}s in this SceneModel have edges emphasised.\n\t *\n\t * @type {Boolean}\n\t */\n\tset edges(edges) {\n\t\tedges = !!edges;\n\t\tthis._edges = edges;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].edges = edges;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if this SceneModel is culled from view.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\n\t *\n\t * @type {Boolean}\n\t */\n\tget culled() {\n\t\treturn this._culled;\n\t}\n\n\t/**\n\t * Sets if this SceneModel is culled from view.\n\t *\n\t * The SceneModel is only rendered when {@link SceneModel#visible} is true and {@link SceneModel#culled} is false.\n\t *\n\t * @type {Boolean}\n\t */\n\tset culled(culled) {\n\t\tculled = !!culled;\n\t\tthis._culled = culled;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].culled = culled;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if {@link SceneModelEntity}s in this SceneModel are clippable.\n\t *\n\t * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget clippable() {\n\t\treturn this._clippable;\n\t}\n\n\t/**\n\t * Sets if {@link SceneModelEntity}s in this SceneModel are clippable.\n\t *\n\t * Clipping is done by the {@link SectionPlane}s in {@link Scene#sectionPlanes}.\n\t *\n\t * @type {Boolean}\n\t */\n\tset clippable(clippable) {\n\t\tclippable = clippable !== false;\n\t\tthis._clippable = clippable;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].clippable = clippable;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets if this SceneModel is collidable.\n\t *\n\t * @type {Boolean}\n\t */\n\tget collidable() {\n\t\treturn this._collidable;\n\t}\n\n\t/**\n\t * Sets if {@link SceneModelEntity}s in this SceneModel are collidable.\n\t *\n\t * @type {Boolean}\n\t */\n\tset collidable(collidable) {\n\t\tcollidable = collidable !== false;\n\t\tthis._collidable = collidable;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].collidable = collidable;\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this SceneModel is pickable.\n\t *\n\t * Picking is done via calls to {@link Scene#pick}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget pickable() {\n\t\treturn this.numPickableLayerPortions > 0;\n\t}\n\n\t/**\n\t * Sets if {@link SceneModelEntity}s in this SceneModel are pickable.\n\t *\n\t * Picking is done via calls to {@link Scene#pick}.\n\t *\n\t * @type {Boolean}\n\t */\n\tset pickable(pickable) {\n\t\tpickable = pickable !== false;\n\t\tthis._pickable = pickable;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].pickable = pickable;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the RGB colorize color for this SceneModel.\n\t *\n\t * Each element of the color is in range ````[0..1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget colorize() {\n\t\treturn this._colorize;\n\t}\n\n\t/**\n\t * Sets the RGB colorize color for this SceneModel.\n\t *\n\t * Multiplies by rendered fragment colors.\n\t *\n\t * Each element of the color is in range ````[0..1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset colorize(colorize) {\n\t\tthis._colorize = colorize;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].colorize = colorize;\n\t\t}\n\t}\n\n\t/**\n\t * Gets this SceneModel's opacity factor.\n\t *\n\t * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\n\t *\n\t * @type {Number}\n\t */\n\tget opacity() {\n\t\treturn this._opacity;\n\t}\n\n\t/**\n\t * Sets the opacity factor for this SceneModel.\n\t *\n\t * This is a factor in range ````[0..1]```` which multiplies by the rendered fragment alphas.\n\t *\n\t * @type {Number}\n\t */\n\tset opacity(opacity) {\n\t\tthis._opacity = opacity;\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i].opacity = opacity;\n\t\t}\n\t}\n\n\t/**\n\t * Gets if this SceneModel casts a shadow.\n\t *\n\t * @type {Boolean}\n\t */\n\tget castsShadow() {\n\t\treturn this._castsShadow;\n\t}\n\n\t/**\n\t * Sets if this SceneModel casts a shadow.\n\t *\n\t * @type {Boolean}\n\t */\n\tset castsShadow(castsShadow) {\n\t\tcastsShadow = castsShadow !== false;\n\t\tif (castsShadow !== this._castsShadow) {\n\t\t\tthis._castsShadow = castsShadow;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Sets if this SceneModel can have shadow cast upon it.\n\t *\n\t * @type {Boolean}\n\t */\n\tget receivesShadow() {\n\t\treturn this._receivesShadow;\n\t}\n\n\t/**\n\t * Sets if this SceneModel can have shadow cast upon it.\n\t *\n\t * @type {Boolean}\n\t */\n\tset receivesShadow(receivesShadow) {\n\t\treceivesShadow = receivesShadow !== false;\n\t\tif (receivesShadow !== this._receivesShadow) {\n\t\t\tthis._receivesShadow = receivesShadow;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Gets if Scalable Ambient Obscurance (SAO) will apply to this SceneModel.\n\t *\n\t * SAO is configured by the Scene's {@link SAO} component.\n\t *\n\t * Only works when {@link SAO#enabled} is also true.\n\t *\n\t * @type {Boolean}\n\t */\n\tget saoEnabled() {\n\t\treturn this._saoEnabled;\n\t}\n\n\t/**\n\t * Gets if physically-based rendering (PBR) is enabled for this SceneModel.\n\t *\n\t * Only works when {@link Scene#pbrEnabled} is also true.\n\t *\n\t * @type {Boolean}\n\t */\n\tget pbrEnabled() {\n\t\treturn this._pbrEnabled;\n\t}\n\n\t/**\n\t * Gets if color textures are enabled for this SceneModel.\n\t *\n\t * Only works when {@link Scene#colorTextureEnabled} is also true.\n\t *\n\t * @type {Boolean}\n\t */\n\tget colorTextureEnabled() {\n\t\treturn this._colorTextureEnabled;\n\t}\n\n\t/**\n\t * Returns true to indicate that SceneModel is implements {@link Drawable}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isDrawable() {\n\t\treturn true;\n\t}\n\n\t/** @private */\n\tget isStateSortable() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Configures the appearance of xrayed {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#xrayMaterial}.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget xrayMaterial() {\n\t\treturn this.scene.xrayMaterial;\n\t}\n\n\t/**\n\t * Configures the appearance of highlighted {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#highlightMaterial}.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget highlightMaterial() {\n\t\treturn this.scene.highlightMaterial;\n\t}\n\n\t/**\n\t * Configures the appearance of selected {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#selectedMaterial}.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget selectedMaterial() {\n\t\treturn this.scene.selectedMaterial;\n\t}\n\n\t/**\n\t * Configures the appearance of edges of {@link SceneModelEntity}s within this SceneModel.\n\t *\n\t * This is the {@link Scene#edgeMaterial}.\n\t *\n\t * @type {EdgeMaterial}\n\t */\n\tget edgeMaterial() {\n\t\treturn this.scene.edgeMaterial;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------\n\t// Drawable members\n\t//------------------------------------------------------------------------------------------------------------------\n\n\t/**\n\t * Called by private renderers in ./lib, returns the picking view matrix with which to\n\t * ray-pick on this SceneModel.\n\t *\n\t * @private\n\t */\n\tgetPickViewMatrix(pickViewMatrix) {\n\t\tif (!this._viewMatrix) {\n\t\t\treturn pickViewMatrix;\n\t\t}\n\t\treturn this._viewMatrix;\n\t}\n\n\t/**\n\t *\n\t * @param cfg\n\t */\n\tcreateQuantizationRange(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createQuantizationRange] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (cfg.aabb) {\n\t\t\tthis.error(\"[createQuantizationRange] Config missing: aabb\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._quantizationRanges[cfg.id]) {\n\t\t\tthis.error(\"[createQuantizationRange] QuantizationRange already created: \" + cfg.id);\n\t\t\treturn;\n\t\t}\n\t\tthis._quantizationRanges[cfg.id] = {\n\t\t\tid: cfg.id,\n\t\t\taabb: cfg.aabb,\n\t\t\tmatrix: (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.aabb, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4())\n\t\t};\n\t}\n\n\t/**\n\t * Creates a reusable geometry within this SceneModel.\n\t *\n\t * We can then supply the geometry ID to {@link SceneModel#createMesh} when we want to create meshes that\n\t * instance the geometry.\n\t *\n\t * @param {*} cfg Geometry properties.\n\t * @param {String|Number} cfg.id Mandatory ID for the geometry, to refer to with {@link SceneModel#createMesh}.\n\t * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\n\t * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\n\t * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\n\t * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\n\t * @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\t * @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\t * @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\t * @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\t * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n\t * @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\t * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\n\t * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\n\t * @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\t */\n\tcreateGeometry(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createGeometry] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._geometries[cfg.id]) {\n\t\t\tthis.error(\"[createGeometry] Geometry already created: \" + cfg.id);\n\t\t\treturn;\n\t\t}\n\t\tif (cfg.primitive === undefined || cfg.primitive === null) {\n\t\t\tcfg.primitive = \"triangles\";\n\t\t}\n\t\tif (\n\t\t\tcfg.primitive !== \"points\" &&\n\t\t\tcfg.primitive !== \"lines\" &&\n\t\t\tcfg.primitive !== \"triangles\" &&\n\t\t\tcfg.primitive !== \"solid\" &&\n\t\t\tcfg.primitive !== \"surface\"\n\t\t) {\n\t\t\tthis.error(\n\t\t\t\t`[createGeometry] Unsupported value for 'primitive': '${cfg.primitive}' - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'. Defaulting to 'triangles'.`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\n\t\t\tthis.error(\"[createGeometry] Param expected: `positions`, `positionsCompressed' or 'buckets\");\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\n\t\t\tthis.error(\n\t\t\t\t\"[createGeometry] Param expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\"\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.positionsDecodeMatrix && cfg.positionsDecodeBoundary) {\n\t\t\tthis.error(\n\t\t\t\t\"[createGeometry] Only one of these params expected: `positionsDecodeMatrix` or 'positionsDecodeBoundary' (required for `positionsCompressed')\"\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\n\t\t\tthis.error(\"[createGeometry] Param expected: `uvDecodeMatrix` (required for `uvCompressed')\");\n\t\t\treturn null;\n\t\t}\n\t\tif (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\n\t\t\tthis.error(`[createGeometry] Param expected: indices (required for '${cfg.primitive}' primitive type)`);\n\t\t\treturn null;\n\t\t}\n\t\tif (cfg.positionsDecodeBoundary) {\n\t\t\tcfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t}\n\t\tif (cfg.positions) {\n\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\tcfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n\t\t\tcfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\n\t\t\tcfg.aabb = aabb;\n\t\t} else if (cfg.positionsCompressed) {\n\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\tcfg.positionsDecodeMatrix = new Float64Array(cfg.positionsDecodeMatrix);\n\t\t\tcfg.positionsCompressed = new Uint16Array(cfg.positionsCompressed);\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\tcfg.aabb = aabb;\n\t\t} else if (cfg.buckets) {\n\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\tthis._dtxBuckets[cfg.id] = cfg.buckets;\n\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\tconst bucket = cfg.buckets[i];\n\t\t\t\tif (bucket.positions) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\n\t\t\t\t} else if (bucket.positionsCompressed) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (cfg.positionsDecodeMatrix) {\n\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t}\n\t\t\tcfg.aabb = aabb;\n\t\t}\n\t\tif (cfg.colorsCompressed && cfg.colorsCompressed.length > 0) {\n\t\t\tcfg.colorsCompressed = new Uint8Array(cfg.colorsCompressed);\n\t\t} else if (cfg.colors && cfg.colors.length > 0) {\n\t\t\tconst colors = cfg.colors;\n\t\t\tconst colorsCompressed = new Uint8Array(colors.length);\n\t\t\tfor (let i = 0, len = colors.length; i < len; i++) {\n\t\t\t\tcolorsCompressed[i] = colors[i] * 255;\n\t\t\t}\n\t\t\tcfg.colorsCompressed = colorsCompressed;\n\t\t}\n\t\tif (\n\t\t\t!cfg.buckets &&\n\t\t\t!cfg.edgeIndices &&\n\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")\n\t\t) {\n\t\t\tif (cfg.positions) {\n\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 5.0);\n\t\t\t} else {\n\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n\t\t\t}\n\t\t}\n\t\tif (cfg.uv) {\n\t\t\tconst bounds = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.getUVBounds(cfg.uv);\n\t\t\tconst result = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.compressUVs(cfg.uv, bounds.min, bounds.max);\n\t\t\tcfg.uvCompressed = result.quantized;\n\t\t\tcfg.uvDecodeMatrix = result.decodeMatrix;\n\t\t} else if (cfg.uvCompressed) {\n\t\t\tcfg.uvCompressed = new Uint16Array(cfg.uvCompressed);\n\t\t\tcfg.uvDecodeMatrix = new Float64Array(cfg.uvDecodeMatrix);\n\t\t}\n\t\tif (cfg.normals) {\n\t\t\t// HACK\n\t\t\tcfg.normals = null;\n\t\t}\n\t\tthis._geometries[cfg.id] = cfg;\n\t\tthis._numTriangles += cfg.indices ? Math.round(cfg.indices.length / 3) : 0;\n\t\tthis.numGeometries++;\n\t}\n\n\t/**\n\t * Creates a texture within this SceneModel.\n\t *\n\t * We can then supply the texture ID to {@link SceneModel#createTextureSet} when we want to create texture sets that use the texture.\n\t *\n\t * @param {*} cfg Texture properties.\n\t * @param {String|Number} cfg.id Mandatory ID for the texture, to refer to with {@link SceneModel#createTextureSet}.\n\t * @param {String} [cfg.src] Image file for the texture. Assumed to be transcoded if not having a recognized image file\n\t * extension (jpg, jpeg, png etc.). If transcoded, then assumes ````SceneModel```` is configured with a {@link TextureTranscoder}.\n\t * @param {ArrayBuffer[]} [cfg.buffers] Transcoded texture data. Assumes ````SceneModel```` is\n\t * 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\t * @param {HTMLImageElement} [cfg.image] HTML Image object to load into this texture. Overrides ````src```` and ````buffers````. Never transcoded.\n\t * @param {Number} [cfg.minFilter=LinearMipmapLinearFilter] How the texture is sampled when a texel covers less than one pixel.\n\t * Supported values are {@link LinearMipmapLinearFilter}, {@link LinearMipMapNearestFilter}, {@link NearestMipMapNearestFilter}, {@link NearestMipMapLinearFilter} and {@link LinearMipMapLinearFilter}.\n\t * @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\t * @param {Number} [cfg.wrapS=RepeatWrapping] Wrap parameter for texture coordinate *S*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\n\t * @param {Number} [cfg.wrapT=RepeatWrapping] Wrap parameter for texture coordinate *T*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}..\n\t * @param {Number} [cfg.wrapR=RepeatWrapping] Wrap parameter for texture coordinate *R*. Supported values are {@link ClampToEdgeWrapping}, {@link MirroredRepeatWrapping} and {@link RepeatWrapping}.\n\t * @param {Boolean} [cfg.flipY=false] Flips this Texture's source data along its vertical axis when ````true````.\n\t * @param {Number} [cfg.encoding=LinearEncoding] Encoding format. Supported values are {@link LinearEncoding} and {@link sRGBEncoding}.\n\t */\n\tcreateTexture(cfg) {\n\t\tconst textureId = cfg.id;\n\t\tif (textureId === undefined || textureId === null) {\n\t\t\tthis.error(\"[createTexture] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._textures[textureId]) {\n\t\t\tthis.error(\"[createTexture] Texture already created: \" + textureId);\n\t\t\treturn;\n\t\t}\n\t\tif (!cfg.src && !cfg.image && !cfg.buffers) {\n\t\t\tthis.error(\"[createTexture] Param expected: `src`, `image' or 'buffers'\");\n\t\t\treturn null;\n\t\t}\n\t\tlet minFilter = cfg.minFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\n\t\tif (\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipMapNearestFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapLinearFilter &&\n\t\t\tminFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestMipMapNearestFilter\n\t\t) {\n\t\t\tthis.error(`[createTexture] Unsupported value for 'minFilter' - \n supported values are LinearFilter, LinearMipMapNearestFilter, NearestMipMapNearestFilter, \n NearestMipMapLinearFilter and LinearMipmapLinearFilter. Defaulting to LinearMipmapLinearFilter.`);\n\t\t\tminFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearMipmapLinearFilter;\n\t\t}\n\t\tlet magFilter = cfg.magFilter || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\n\t\tif (magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter && magFilter !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.NearestFilter) {\n\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'magFilter' - supported values are LinearFilter and NearestFilter. Defaulting to LinearFilter.`\n\t\t\t);\n\t\t\tmagFilter = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearFilter;\n\t\t}\n\t\tlet wrapS = cfg.wrapS || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\tif (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\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'wrapS' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`\n\t\t\t);\n\t\t\twrapS = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\t}\n\t\tlet wrapT = cfg.wrapT || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\tif (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\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'wrapT' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`\n\t\t\t);\n\t\t\twrapT = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\t}\n\t\tlet wrapR = cfg.wrapR || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\tif (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\t\t\tthis.error(\n\t\t\t\t`[createTexture] Unsupported value for 'wrapR' - supported values are ClampToEdgeWrapping, MirroredRepeatWrapping and RepeatWrapping. Defaulting to RepeatWrapping.`\n\t\t\t);\n\t\t\twrapR = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.RepeatWrapping;\n\t\t}\n\t\tlet encoding = cfg.encoding || _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\n\t\tif (encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding && encoding !== _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.sRGBEncoding) {\n\t\t\tthis.error(\n\t\t\t\t\"[createTexture] Unsupported value for 'encoding' - supported values are LinearEncoding and sRGBEncoding. Defaulting to LinearEncoding.\"\n\t\t\t);\n\t\t\tencoding = _constants_constants_js__WEBPACK_IMPORTED_MODULE_21__.LinearEncoding;\n\t\t}\n\t\tconst texture = new _webgl_Texture2D_js__WEBPACK_IMPORTED_MODULE_18__.Texture2D({\n\t\t\tgl: this.scene.canvas.gl,\n\t\t\tminFilter,\n\t\t\tmagFilter,\n\t\t\twrapS,\n\t\t\twrapT,\n\t\t\twrapR,\n\t\t\t// flipY: cfg.flipY,\n\t\t\tencoding\n\t\t});\n\t\tif (cfg.preloadColor) {\n\t\t\ttexture.setPreloadColor(cfg.preloadColor);\n\t\t}\n\t\tif (cfg.image) {\n\t\t\t// Ignore transcoder for Images\n\t\t\tconst image = cfg.image;\n\t\t\timage.crossOrigin = \"Anonymous\";\n\t\t\ttexture.setImage(image, { minFilter, magFilter, wrapS, wrapT, wrapR, flipY: cfg.flipY, encoding });\n\t\t} else if (cfg.src) {\n\t\t\tconst ext = cfg.src.split(\".\").pop();\n\t\t\tswitch (\n\t\t\t\text // Don't transcode recognized image file types\n\t\t\t) {\n\t\t\t\tcase \"jpeg\":\n\t\t\t\tcase \"jpg\":\n\t\t\t\tcase \"png\":\n\t\t\t\tcase \"gif\":\n\t\t\t\t\tconst image = new Image();\n\t\t\t\t\timage.onload = () => {\n\t\t\t\t\t\ttexture.setImage(image, {\n\t\t\t\t\t\t\tminFilter,\n\t\t\t\t\t\t\tmagFilter,\n\t\t\t\t\t\t\twrapS,\n\t\t\t\t\t\t\twrapT,\n\t\t\t\t\t\t\twrapR,\n\t\t\t\t\t\t\tflipY: cfg.flipY,\n\t\t\t\t\t\t\tencoding\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.glRedraw();\n\t\t\t\t\t};\n\t\t\t\t\timage.src = cfg.src; // URL or Base64 string\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: // Assume other file types need transcoding\n\t\t\t\t\tif (!this._textureTranscoder) {\n\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t`[createTexture] Can't create texture from 'src' - SceneModel needs to be configured with a TextureTranscoder for this file type ('${ext}')`\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_utils_js__WEBPACK_IMPORTED_MODULE_19__.utils.loadArraybuffer(\n\t\t\t\t\t\t\tcfg.src,\n\t\t\t\t\t\t\t(arrayBuffer) => {\n\t\t\t\t\t\t\t\tif (!arrayBuffer.byteLength) {\n\t\t\t\t\t\t\t\t\tthis.error(`[createTexture] Can't create texture from 'src': file data is zero length`);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis._textureTranscoder.transcode([arrayBuffer], texture).then(() => {\n\t\t\t\t\t\t\t\t\tthis.glRedraw();\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfunction (errMsg) {\n\t\t\t\t\t\t\t\tthis.error(`[createTexture] Can't create texture from 'src': ${errMsg}`);\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\tbreak;\n\t\t\t}\n\t\t} else if (cfg.buffers) {\n\t\t\t// Buffers implicitly require transcoding\n\t\t\tif (!this._textureTranscoder) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTexture] Can't create texture from 'buffers' - SceneModel needs to be configured with a TextureTranscoder for this option`\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis._textureTranscoder.transcode(cfg.buffers, texture).then(() => {\n\t\t\t\t\tthis.glRedraw();\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis._textures[textureId] = new _SceneModelTexture_js__WEBPACK_IMPORTED_MODULE_17__.SceneModelTexture({ id: textureId, texture });\n\t}\n\n\t/**\n\t * Creates a texture set within this SceneModel.\n\t *\n\t * * Stores the new {@link SceneModelTextureSet} in {@link SceneModel#textureSets}.\n\t *\n\t * A texture set is a collection of textures that can be shared among meshes. We can then supply the texture set\n\t * ID to {@link SceneModel#createMesh} when we want to create meshes that use the texture set.\n\t *\n\t * The textures can work as a texture atlas, where each mesh can have geometry UVs that index\n\t * a different part of the textures. This allows us to minimize the number of textures in our models, which\n\t * means faster rendering.\n\t *\n\t * @param {*} cfg Texture set properties.\n\t * @param {String|Number} cfg.id Mandatory ID for the texture set, to refer to with {@link SceneModel#createMesh}.\n\t * @param {*} [cfg.colorTextureId] ID of *RGBA* base color texture, with color in *RGB* and alpha in *A*.\n\t * @param {*} [cfg.metallicRoughnessTextureId] ID of *RGBA* metal-roughness texture, with the metallic factor in *R*, and roughness factor in *G*.\n\t * @param {*} [cfg.normalsTextureId] ID of *RGBA* normal map texture, with normal map vectors in *RGB*.\n\t * @param {*} [cfg.emissiveTextureId] ID of *RGBA* emissive map texture, with emissive color in *RGB*.\n\t * @param {*} [cfg.occlusionTextureId] ID of *RGBA* occlusion map texture, with occlusion factor in *R*.\n\t * @returns {SceneModelTransform} The new texture set.\n\t */\n\tcreateTextureSet(cfg) {\n\t\tconst textureSetId = cfg.id;\n\t\tif (textureSetId === undefined || textureSetId === null) {\n\t\t\tthis.error(\"[createTextureSet] Config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._textureSets[textureSetId]) {\n\t\t\tthis.error(`[createTextureSet] Texture set already created: ${textureSetId}`);\n\t\t\treturn;\n\t\t}\n\t\tlet colorTexture;\n\t\tif (cfg.colorTextureId !== undefined && cfg.colorTextureId !== null) {\n\t\t\tcolorTexture = this._textures[cfg.colorTextureId];\n\t\t\tif (!colorTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.colorTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tcolorTexture = this._textures[DEFAULT_COLOR_TEXTURE_ID];\n\t\t}\n\t\tlet metallicRoughnessTexture;\n\t\tif (cfg.metallicRoughnessTextureId !== undefined && cfg.metallicRoughnessTextureId !== null) {\n\t\t\tmetallicRoughnessTexture = this._textures[cfg.metallicRoughnessTextureId];\n\t\t\tif (!metallicRoughnessTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.metallicRoughnessTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tmetallicRoughnessTexture = this._textures[DEFAULT_METAL_ROUGH_TEXTURE_ID];\n\t\t}\n\t\tlet normalsTexture;\n\t\tif (cfg.normalsTextureId !== undefined && cfg.normalsTextureId !== null) {\n\t\t\tnormalsTexture = this._textures[cfg.normalsTextureId];\n\t\t\tif (!normalsTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.normalsTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tnormalsTexture = this._textures[DEFAULT_NORMALS_TEXTURE_ID];\n\t\t}\n\t\tlet emissiveTexture;\n\t\tif (cfg.emissiveTextureId !== undefined && cfg.emissiveTextureId !== null) {\n\t\t\temissiveTexture = this._textures[cfg.emissiveTextureId];\n\t\t\tif (!emissiveTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.emissiveTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\temissiveTexture = this._textures[DEFAULT_EMISSIVE_TEXTURE_ID];\n\t\t}\n\t\tlet occlusionTexture;\n\t\tif (cfg.occlusionTextureId !== undefined && cfg.occlusionTextureId !== null) {\n\t\t\tocclusionTexture = this._textures[cfg.occlusionTextureId];\n\t\t\tif (!occlusionTexture) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createTextureSet] Texture not found: ${cfg.occlusionTextureId} - ensure that you create it first with createTexture()`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tocclusionTexture = this._textures[DEFAULT_OCCLUSION_TEXTURE_ID];\n\t\t}\n\t\tconst textureSet = new _SceneModelTextureSet_js__WEBPACK_IMPORTED_MODULE_16__.SceneModelTextureSet({\n\t\t\tid: textureSetId,\n\t\t\tmodel: this,\n\t\t\tcolorTexture,\n\t\t\tmetallicRoughnessTexture,\n\t\t\tnormalsTexture,\n\t\t\temissiveTexture,\n\t\t\tocclusionTexture\n\t\t});\n\t\tthis._textureSets[textureSetId] = textureSet;\n\t\treturn textureSet;\n\t}\n\n\t/**\n\t * Creates a new {@link SceneModelTransform} within this SceneModel.\n\t *\n\t * * Stores the new {@link SceneModelTransform} in {@link SceneModel#transforms}.\n\t * * Can be connected into hierarchies\n\t * * Each {@link SceneModelTransform} can be used by unlimited {@link SceneModelMesh}es\n\t *\n\t * @param {*} cfg Transform creation parameters.\n\t * @param {String} cfg.id Mandatory ID for the new transform. Must not clash with any existing components within the {@link Scene}.\n\t * @param {String} [cfg.parentTransformId] ID of a parent transform, previously created with {@link SceneModel#createTextureSet}.\n\t * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\n\t * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the transform.\n\t * @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\t * @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\t * @returns {SceneModelTransform} The new transform.\n\t */\n\tcreateTransform(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\n\t\t\treturn;\n\t\t}\n\t\tif (this._transforms[cfg.id]) {\n\t\t\tthis.error(`[createTransform] SceneModel already has a transform with this ID: ${cfg.id}`);\n\t\t\treturn;\n\t\t}\n\t\tlet parentTransform;\n\t\tif (this.parentTransformId) {\n\t\t\tparentTransform = this._transforms[cfg.parentTransformId];\n\t\t\tif (!parentTransform) {\n\t\t\t\tthis.error(\"[createTransform] SceneModel.createTransform() config missing: id\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tconst transform = new _SceneModelTransform_js__WEBPACK_IMPORTED_MODULE_27__.SceneModelTransform({\n\t\t\tid: cfg.id,\n\t\t\tmodel: this,\n\t\t\tparentTransform,\n\t\t\tmatrix: cfg.matrix,\n\t\t\tposition: cfg.position,\n\t\t\tscale: cfg.scale,\n\t\t\trotation: cfg.rotation,\n\t\t\tquaternion: cfg.quaternion\n\t\t});\n\t\tthis._transforms[transform.id] = transform;\n\t\treturn transform;\n\t}\n\n\t/**\n\t * Creates a new {@link SceneModelMesh} within this SceneModel.\n\t *\n\t * * 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\t * * The SceneModelMesh can either define its own geometry or share it with other SceneModelMeshes. To define own geometry, provide the\n\t * various geometry arrays to this method. To share a geometry, provide the ID of a geometry created earlier\n\t * with {@link SceneModel#createGeometry}.\n\t * * If you accompany the arrays with an ````origin````, then ````createMesh()```` will assume\n\t * that the geometry ````positions```` are in relative-to-center (RTC) coordinates, with ````origin```` being the\n\t * origin of their RTC coordinate system.\n\t *\n\t * @param {object} cfg Object properties.\n\t * @param {String} cfg.id Mandatory ID for the new mesh. Must not clash with any existing components within the {@link Scene}.\n\t * @param {String|Number} [cfg.textureSetId] ID of a {@link SceneModelTextureSet} previously created with {@link SceneModel#createTextureSet}.\n\t * @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\t * @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\t * @param {String} cfg.primitive The primitive type. Accepted values are 'points', 'lines', 'triangles', 'solid' and 'surface'.\n\t * @param {Number[]} [cfg.positions] Flat array of uncompressed 3D vertex positions positions. Required for all primitive types. Overridden by ````positionsCompressed````.\n\t * @param {Number[]} [cfg.positionsCompressed] Flat array of quantized 3D vertex positions. Overrides ````positions````, and must be accompanied by ````positionsDecodeMatrix````.\n\t * @param {Number[]} [cfg.positionsDecodeMatrix] A 4x4 matrix for decompressing ````positionsCompressed````. Must be accompanied by ````positionsCompressed````.\n\t * @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\t * @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\t * @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\t * @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\t * @param {Number[]} [cfg.uv] Flat array of uncompressed vertex UV coordinates. Only used with \"triangles\", \"solid\" and \"surface\" primitives. Required for textured rendering.\n\t * @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\t * @param {Number[]} [cfg.uvDecodeMatrix] A 3x3 matrix for decompressing ````uvCompressed````.\n\t * @param {Number[]} [cfg.indices] Array of primitive connectivity indices. Not required for `points` primitives.\n\t * @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\t * @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\t * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.\n\t * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.\n\t * @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\t * @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\t * @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\t * @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.\n\t * @param {Number} [cfg.metallic=0] Metallic factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\n\t * @param {Number} [cfg.roughness=1] Roughness factor in range ````[0..1]````. Overridden by texture set ````metallicRoughnessTexture````.\n\t * @returns {Boolean} True = successfully mesh was created. False = error during creation of a mesh.\n\t */\n\tcreateMesh(cfg) {\n\t\tif (cfg.id === undefined || cfg.id === null) {\n\t\t\tthis.error(\"[createMesh] SceneModel.createMesh() config missing: id\");\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this._scheduledMeshes[cfg.id]) {\n\t\t\tthis.error(`[createMesh] SceneModel already has a mesh with this ID: ${cfg.id}`);\n\t\t\treturn false;\n\t\t}\n\n\t\tconst instancing = cfg.geometryId !== undefined;\n\t\tconst batching = !instancing;\n\n\t\tif (batching) {\n\t\t\t// Batched geometry\n\n\t\t\tif (cfg.primitive === undefined || cfg.primitive === null) {\n\t\t\t\tcfg.primitive = \"triangles\";\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcfg.primitive !== \"points\" &&\n\t\t\t\tcfg.primitive !== \"lines\" &&\n\t\t\t\tcfg.primitive !== \"triangles\" &&\n\t\t\t\tcfg.primitive !== \"solid\" &&\n\t\t\t\tcfg.primitive !== \"surface\"\n\t\t\t) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`Unsupported value for 'primitive': '${primitive}' ('geometryId' is absent) - supported values are 'points', 'lines', 'triangles', 'solid' and 'surface'.`\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!cfg.positions && !cfg.positionsCompressed && !cfg.buckets) {\n\t\t\t\tthis.error(\"Param expected: 'positions', 'positionsCompressed' or `buckets` ('geometryId' is absent)\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cfg.positions && (cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Illegal params: 'positions' not expected with 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\"\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cfg.positionsCompressed && !cfg.positionsDecodeMatrix && !cfg.positionsDecodeBoundary) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Param expected: 'positionsCompressed' should be accompanied by 'positionsDecodeMatrix'/'positionsDecodeBoundary' ('geometryId' is absent)\"\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cfg.uvCompressed && !cfg.uvDecodeMatrix) {\n\t\t\t\tthis.error(\"Param expected: 'uvCompressed' should be accompanied by `uvDecodeMatrix` ('geometryId' is absent)\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!cfg.buckets && !cfg.indices && cfg.primitive !== \"points\") {\n\t\t\t\tthis.error(`Param expected: indices (required for '${cfg.primitive}' primitive type)`);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t(cfg.matrix || cfg.position || cfg.rotation || cfg.scale) &&\n\t\t\t\t(cfg.positionsCompressed || cfg.positionsDecodeBoundary)\n\t\t\t) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Unexpected params: 'matrix', 'rotation', 'scale', 'position' not allowed with 'positionsCompressed'\"\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst useDTX =\n\t\t\t\t!!this._dtxEnabled &&\n\t\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\");\n\n\t\t\tcfg.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\t\t\t// MATRIX - optional for batching\n\n\t\t\tif (cfg.matrix) {\n\t\t\t\tcfg.meshMatrix = cfg.matrix;\n\t\t\t} else if (cfg.scale || cfg.rotation || cfg.position) {\n\t\t\t\tconst scale = cfg.scale || DEFAULT_SCALE;\n\t\t\t\tconst position = cfg.position || DEFAULT_POSITION;\n\t\t\t\tconst rotation = cfg.rotation || DEFAULT_ROTATION;\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\n\t\t\t\tcfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t\t}\n\n\t\t\tif (cfg.positionsDecodeBoundary) {\n\t\t\t\tcfg.positionsDecodeMatrix = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.createPositionsDecodeMatrix)(cfg.positionsDecodeBoundary, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t\t}\n\n\t\t\tif (useDTX) {\n\t\t\t\t// DTX\n\n\t\t\t\tcfg.type = DTX;\n\n\t\t\t\t// NPR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: defaultCompressedColor;\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\n\t\t\t\t// RTC\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst rtcCenter = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\n\t\t\t\t\tconst rtcPositions = [];\n\t\t\t\t\tconst rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, rtcCenter);\n\t\t\t\t\tif (rtcNeeded) {\n\t\t\t\t\t\tcfg.positions = rtcPositions;\n\t\t\t\t\t\tcfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, rtcCenter, rtcCenter);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// COMPRESSION\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\tcfg.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n\t\t\t\t\tcfg.positionsCompressed = (0,_compression_js__WEBPACK_IMPORTED_MODULE_22__.quantizePositions)(cfg.positions, aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t} else if (cfg.positionsCompressed) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n\t\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t}\n\t\t\t\tif (cfg.buckets) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\tconst bucket = cfg.buckets[i];\n\t\t\t\t\t\tif (bucket.positions) {\n\t\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positions);\n\t\t\t\t\t\t} else if (bucket.positionsCompressed) {\n\t\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, bucket.positionsCompressed);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (cfg.positionsDecodeMatrix) {\n\t\t\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\t}\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t}\n\n\t\t\t\tif (cfg.meshMatrix) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\n\t\t\t\t}\n\n\t\t\t\t// EDGES\n\n\t\t\t\tif (\n\t\t\t\t\t!cfg.buckets &&\n\t\t\t\t\t!cfg.edgeIndices &&\n\t\t\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")\n\t\t\t\t) {\n\t\t\t\t\tif (cfg.positions) {\n\t\t\t\t\t\t// Faster\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// BUCKETING\n\n\t\t\t\tif (!cfg.buckets) {\n\t\t\t\t\tcfg.buckets = createDTXBuckets(cfg, this._enableVertexWelding && this._enableIndexBucketing);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// VBO\n\n\t\t\t\tcfg.type = VBO_BATCHED;\n\n\t\t\t\t// PBR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: [255, 255, 255];\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\t\t\t\tcfg.metallic = cfg.metallic !== undefined && cfg.metallic !== null ? Math.floor(cfg.metallic * 255) : 0;\n\t\t\t\tcfg.roughness = cfg.roughness !== undefined && cfg.roughness !== null ? Math.floor(cfg.roughness * 255) : 255;\n\n\t\t\t\t// RTC\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst rtcPositions = [];\n\t\t\t\t\tconst rtcNeeded = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_15__.worldToRTCPositions)(cfg.positions, rtcPositions, tempVec3a);\n\t\t\t\t\tif (rtcNeeded) {\n\t\t\t\t\t\tcfg.positions = rtcPositions;\n\t\t\t\t\t\tcfg.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.addVec3(cfg.origin, tempVec3a, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (cfg.positions) {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\tif (cfg.meshMatrix) {\n\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPositions3(cfg.meshMatrix, cfg.positions, cfg.positions);\n\t\t\t\t\t\tcfg.meshMatrix = null; // Positions now baked, don't need any more\n\t\t\t\t\t}\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positions);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t} else {\n\t\t\t\t\tconst aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(aabb, cfg.positionsCompressed);\n\t\t\t\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(aabb, cfg.positionsDecodeMatrix);\n\t\t\t\t\tcfg.aabb = aabb;\n\t\t\t\t}\n\n\t\t\t\tif (cfg.meshMatrix) {\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.aabb, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, cfg.aabb);\n\t\t\t\t}\n\n\t\t\t\t// EDGES\n\n\t\t\t\tif (\n\t\t\t\t\t!cfg.buckets &&\n\t\t\t\t\t!cfg.edgeIndices &&\n\t\t\t\t\t(cfg.primitive === \"triangles\" || cfg.primitive === \"solid\" || cfg.primitive === \"surface\")\n\t\t\t\t) {\n\t\t\t\t\tif (cfg.positions) {\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positions, cfg.indices, null, 2.0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcfg.edgeIndices = (0,_math_buildEdgeIndices_js__WEBPACK_IMPORTED_MODULE_2__.buildEdgeIndices)(cfg.positionsCompressed, cfg.indices, cfg.positionsDecodeMatrix, 2.0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// TEXTURE\n\n\t\t\t\t// cfg.textureSetId = cfg.textureSetId || DEFAULT_TEXTURE_SET_ID;\n\t\t\t\tif (cfg.textureSetId) {\n\t\t\t\t\tcfg.textureSet = this._textureSets[cfg.textureSetId];\n\t\t\t\t\tif (!cfg.textureSet) {\n\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// INSTANCING\n\n\t\t\tif (\n\t\t\t\tcfg.positions ||\n\t\t\t\tcfg.positionsCompressed ||\n\t\t\t\tcfg.indices ||\n\t\t\t\tcfg.edgeIndices ||\n\t\t\t\tcfg.normals ||\n\t\t\t\tcfg.normalsCompressed ||\n\t\t\t\tcfg.uv ||\n\t\t\t\tcfg.uvCompressed ||\n\t\t\t\tcfg.positionsDecodeMatrix\n\t\t\t) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`Mesh geometry parameters not expected when instancing a geometry (not expected: positions, positionsCompressed, indices, edgeIndices, normals, normalsCompressed, uv, uvCompressed, positionsDecodeMatrix)`\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tcfg.geometry = this._geometries[cfg.geometryId];\n\t\t\tif (!cfg.geometry) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`[createMesh] Geometry not found: ${cfg.geometryId} - ensure that you create it first with createGeometry()`\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tcfg.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\t\t\tcfg.positionsDecodeMatrix = cfg.geometry.positionsDecodeMatrix;\n\n\t\t\tif (cfg.transformId) {\n\t\t\t\t// TRANSFORM\n\n\t\t\t\tcfg.transform = this._transforms[cfg.transformId];\n\n\t\t\t\tif (!cfg.transform) {\n\t\t\t\t\tthis.error(\n\t\t\t\t\t\t`[createMesh] Transform not found: ${cfg.transformId} - ensure that you create it first with createTransform()`\n\t\t\t\t\t);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcfg.aabb = cfg.geometry.aabb;\n\t\t\t} else {\n\t\t\t\t// MATRIX\n\n\t\t\t\tif (cfg.matrix) {\n\t\t\t\t\tcfg.meshMatrix = cfg.matrix.slice();\n\t\t\t\t} else {\n\t\t\t\t\tconst scale = cfg.scale || DEFAULT_SCALE;\n\t\t\t\t\tconst position = cfg.position || DEFAULT_POSITION;\n\t\t\t\t\tconst rotation = cfg.rotation || DEFAULT_ROTATION;\n\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.eulerToQuaternion(rotation, \"XYZ\", DEFAULT_QUATERNION);\n\t\t\t\t\tcfg.meshMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.composeMat4(position, DEFAULT_QUATERNION, scale, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4());\n\t\t\t\t}\n\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);\n\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformOBB3(cfg.meshMatrix, tempOBB3);\n\t\t\t\tcfg.aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3ToAABB3(tempOBB3, _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3());\n\t\t\t}\n\n\t\t\tconst useDTX =\n\t\t\t\t!!this._dtxEnabled &&\n\t\t\t\t(cfg.geometry.primitive === \"triangles\" ||\n\t\t\t\t\tcfg.geometry.primitive === \"solid\" ||\n\t\t\t\t\tcfg.geometry.primitive === \"surface\");\n\n\t\t\tif (useDTX) {\n\t\t\t\t// DTX\n\n\t\t\t\tcfg.type = DTX;\n\n\t\t\t\t// NPR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: defaultCompressedColor;\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\n\t\t\t\t// BUCKETING - lazy generated, reused\n\n\t\t\t\tlet buckets = this._dtxBuckets[cfg.geometryId];\n\t\t\t\tif (!buckets) {\n\t\t\t\t\tbuckets = createDTXBuckets(cfg.geometry, this._enableVertexWelding, this._enableIndexBucketing);\n\t\t\t\t\tthis._dtxBuckets[cfg.geometryId] = buckets;\n\t\t\t\t}\n\t\t\t\tcfg.buckets = buckets;\n\t\t\t} else {\n\t\t\t\t// VBO\n\n\t\t\t\tcfg.type = VBO_INSTANCED;\n\n\t\t\t\t// PBR\n\n\t\t\t\tcfg.color = cfg.color\n\t\t\t\t\t? new Uint8Array([\n\t\t\t\t\t\t\tMath.floor(cfg.color[0] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[1] * 255),\n\t\t\t\t\t\t\tMath.floor(cfg.color[2] * 255)\n\t\t\t\t\t ])\n\t\t\t\t\t: defaultCompressedColor;\n\t\t\t\tcfg.opacity = cfg.opacity !== undefined && cfg.opacity !== null ? Math.floor(cfg.opacity * 255) : 255;\n\t\t\t\tcfg.metallic = cfg.metallic !== undefined && cfg.metallic !== null ? Math.floor(cfg.metallic * 255) : 0;\n\t\t\t\tcfg.roughness = cfg.roughness !== undefined && cfg.roughness !== null ? Math.floor(cfg.roughness * 255) : 255;\n\n\t\t\t\t// TEXTURE\n\n\t\t\t\tif (cfg.textureSetId) {\n\t\t\t\t\tcfg.textureSet = this._textureSets[cfg.textureSetId];\n\t\t\t\t\t// if (!cfg.textureSet) {\n\t\t\t\t\t// this.error(`[createMesh] Texture set not found: ${cfg.textureSetId} - ensure that you create it first with createTextureSet()`);\n\t\t\t\t\t// return false;\n\t\t\t\t\t// }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tcfg.numPrimitives = this._getNumPrimitives(cfg);\n\n\t\tthis._meshesCfgsBeforeMeshCreation[cfg.id] = cfg;\n\n\t\treturn true;\n\t}\n\n\t_createMesh(cfg) {\n\t\tconst mesh = new _SceneModelMesh_js__WEBPACK_IMPORTED_MODULE_3__.SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);\n\t\tmesh.pickId = this.scene._renderer.getPickID(mesh);\n\t\tconst pickId = mesh.pickId;\n\t\tconst a = (pickId >> 24) & 0xff;\n\t\tconst b = (pickId >> 16) & 0xff;\n\t\tconst g = (pickId >> 8) & 0xff;\n\t\tconst r = pickId & 0xff;\n\t\tcfg.pickColor = new Uint8Array([r, g, b, a]); // Quantized pick color\n\t\tcfg.solid = cfg.primitive === \"solid\";\n\t\tmesh.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3(cfg.origin);\n\t\tswitch (cfg.type) {\n\t\t\tcase DTX:\n\t\t\t\tmesh.layer = this._getDTXLayer(cfg);\n\t\t\t\tmesh.aabb = cfg.aabb;\n\t\t\t\tbreak;\n\t\t\tcase VBO_BATCHED:\n\t\t\t\tmesh.layer = this._getVBOBatchingLayer(cfg);\n\t\t\t\tmesh.aabb = cfg.aabb;\n\t\t\t\tbreak;\n\t\t\tcase VBO_INSTANCED:\n\t\t\t\tmesh.layer = this._getVBOInstancingLayer(cfg);\n\t\t\t\tmesh.aabb = cfg.aabb;\n\t\t\t\tbreak;\n\t\t}\n\t\tif (cfg.transform) {\n\t\t\tcfg.meshMatrix = cfg.transform.worldMatrix;\n\t\t}\n\t\tmesh.portionId = mesh.layer.createPortion(mesh, cfg);\n\t\treturn mesh;\n\t}\n\n\t_getNumPrimitives(cfg) {\n\t\tlet countIndices = 0;\n\t\tconst primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\n\t\tswitch (primitive) {\n\t\t\tcase \"triangles\":\n\t\t\tcase \"solid\":\n\t\t\tcase \"surface\":\n\t\t\t\tswitch (cfg.type) {\n\t\t\t\t\tcase DTX:\n\t\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\t\tcountIndices += cfg.buckets[i].indices.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_BATCHED:\n\t\t\t\t\t\tcountIndices += cfg.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_INSTANCED:\n\t\t\t\t\t\tcountIndices += cfg.geometry.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn Math.round(countIndices / 3);\n\t\t\tcase \"points\":\n\t\t\t\tswitch (cfg.type) {\n\t\t\t\t\tcase DTX:\n\t\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\t\tcountIndices += cfg.buckets[i].positionsCompressed.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_BATCHED:\n\t\t\t\t\t\tcountIndices += cfg.positions ? cfg.positions.length : cfg.positionsCompressed.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_INSTANCED:\n\t\t\t\t\t\tconst geometry = cfg.geometry;\n\t\t\t\t\t\tcountIndices += geometry.positions ? geometry.positions.length : geometry.positionsCompressed.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn Math.round(countIndices);\n\t\t\tcase \"lines\":\n\t\t\tcase \"line-strip\":\n\t\t\t\tswitch (cfg.type) {\n\t\t\t\t\tcase DTX:\n\t\t\t\t\t\tfor (let i = 0, len = cfg.buckets.length; i < len; i++) {\n\t\t\t\t\t\t\tcountIndices += cfg.buckets[i].indices.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_BATCHED:\n\t\t\t\t\t\tcountIndices += cfg.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VBO_INSTANCED:\n\t\t\t\t\t\tcountIndices += cfg.geometry.indices.length;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn Math.round(countIndices / 2);\n\t\t}\n\t\treturn 0;\n\t}\n\n\t_getDTXLayer(cfg) {\n\t\tconst origin = cfg.origin;\n\t\tconst primitive = cfg.geometry ? cfg.geometry.primitive : cfg.primitive;\n\t\tconst layerId = `.${primitive}.${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}`;\n\t\tlet dtxLayer = this._dtxLayers[layerId];\n\t\tif (dtxLayer) {\n\t\t\tif (!dtxLayer.canCreatePortion(cfg)) {\n\t\t\t\tdtxLayer.finalize();\n\t\t\t\tdelete this._dtxLayers[layerId];\n\t\t\t\tdtxLayer = null;\n\t\t\t} else {\n\t\t\t\treturn dtxLayer;\n\t\t\t}\n\t\t}\n\t\tswitch (primitive) {\n\t\t\tcase \"triangles\":\n\t\t\tcase \"solid\":\n\t\t\tcase \"surface\":\n\t\t\t\tdtxLayer = new _dtx_triangles_DTXTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_12__.DTXTrianglesLayer(this, { layerIndex: 0, origin }); // layerIndex is set in #finalize()\n\t\t\t\tbreak;\n\t\t\tcase \"lines\":\n\t\t\t\tdtxLayer = new _dtx_lines_DTXLinesLayer_js__WEBPACK_IMPORTED_MODULE_11__.DTXLinesLayer(this, { layerIndex: 0, origin }); // layerIndex is set in #finalize()\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t\tthis._dtxLayers[layerId] = dtxLayer;\n\t\tthis.layerList.push(dtxLayer);\n\t\treturn dtxLayer;\n\t}\n\n\t_getVBOBatchingLayer(cfg) {\n\t\tconst model = this;\n\t\tconst origin = cfg.origin;\n\t\tconst positionsDecodeHash =\n\t\t\tcfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary\n\t\t\t\t? this._createHashStringFromMatrix(cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)\n\t\t\t\t: \"-\";\n\t\tconst textureSetId = cfg.textureSetId || \"-\";\n\t\tconst layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(origin[2])}.${\n\t\t\tcfg.primitive\n\t\t}.${positionsDecodeHash}.${textureSetId}`;\n\t\tlet vboBatchingLayer = this._vboBatchingLayers[layerId];\n\t\tif (vboBatchingLayer) {\n\t\t\treturn vboBatchingLayer;\n\t\t}\n\t\tlet textureSet = cfg.textureSet;\n\t\twhile (!vboBatchingLayer) {\n\t\t\tswitch (cfg.primitive) {\n\t\t\t\tcase \"triangles\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\n\t\t\t\t\t\tsolid: cfg.primitive === \"solid\",\n\t\t\t\t\t\tautoNormals: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"solid\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\n\t\t\t\t\t\tsolid: cfg.primitive === \"solid\",\n\t\t\t\t\t\tautoNormals: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"surface\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesBatchingLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_triangles_VBOBatchingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_5__.VBOBatchingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\n\t\t\t\t\t\tsolid: cfg.primitive === \"solid\",\n\t\t\t\t\t\tautoNormals: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lines\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating VBOBatchingLinesLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_lines_VBOBatchingLinesLayer_js__WEBPACK_IMPORTED_MODULE_7__.VBOBatchingLinesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"points\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating VBOBatchingPointsLayer`);\n\t\t\t\t\tvboBatchingLayer = new _vbo_batching_points_VBOBatchingPointsLayer_js__WEBPACK_IMPORTED_MODULE_9__.VBOBatchingPointsLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tlayerIndex: 0, // This is set in #finalize()\n\t\t\t\t\t\tscratchMemory: this._vboBatchingLayerScratchMemory,\n\t\t\t\t\t\tpositionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined\n\t\t\t\t\t\tuvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst lenPositions = cfg.positionsCompressed ? cfg.positionsCompressed.length : cfg.positions.length;\n\t\t\tconst canCreatePortion =\n\t\t\t\tcfg.primitive === \"points\"\n\t\t\t\t\t? vboBatchingLayer.canCreatePortion(lenPositions)\n\t\t\t\t\t: vboBatchingLayer.canCreatePortion(lenPositions, cfg.indices.length);\n\t\t\tif (!canCreatePortion) {\n\t\t\t\tvboBatchingLayer.finalize();\n\t\t\t\tdelete this._vboBatchingLayers[layerId];\n\t\t\t\tvboBatchingLayer = null;\n\t\t\t}\n\t\t}\n\t\tthis._vboBatchingLayers[layerId] = vboBatchingLayer;\n\t\tthis.layerList.push(vboBatchingLayer);\n\t\treturn vboBatchingLayer;\n\t}\n\n\t_createHashStringFromMatrix(matrix) {\n\t\tconst matrixString = matrix.join(\"\");\n\t\tlet hash = 0;\n\t\tfor (let i = 0; i < matrixString.length; i++) {\n\t\t\tconst char = matrixString.charCodeAt(i);\n\t\t\thash = (hash << 5) - hash + char;\n\t\t\thash |= 0; // Convert to 32-bit integer\n\t\t}\n\t\tconst hashString = (hash >>> 0).toString(16);\n\t\treturn hashString;\n\t}\n\n\t_getVBOInstancingLayer(cfg) {\n\t\tconst model = this;\n\t\tconst origin = cfg.origin;\n\t\tconst textureSetId = cfg.textureSetId || \"-\";\n\t\tconst geometryId = cfg.geometryId;\n\t\tconst layerId = `${Math.round(origin[0])}.${Math.round(origin[1])}.${Math.round(\n\t\t\torigin[2]\n\t\t)}.${textureSetId}.${geometryId}`;\n\t\tlet vboInstancingLayer = this._vboInstancingLayers[layerId];\n\t\tif (vboInstancingLayer) {\n\t\t\treturn vboInstancingLayer;\n\t\t}\n\t\tlet textureSet = cfg.textureSet;\n\t\tconst geometry = cfg.geometry;\n\t\twhile (!vboInstancingLayer) {\n\t\t\tswitch (geometry.primitive) {\n\t\t\t\tcase \"triangles\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0,\n\t\t\t\t\t\tsolid: false\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"solid\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0,\n\t\t\t\t\t\tsolid: true\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"surface\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating TrianglesInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_triangles_VBOInstancingTrianglesLayer_js__WEBPACK_IMPORTED_MODULE_6__.VBOInstancingTrianglesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0,\n\t\t\t\t\t\tsolid: false\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lines\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating VBOInstancingLinesLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_lines_VBOInstancingLinesLayer_js__WEBPACK_IMPORTED_MODULE_8__.VBOInstancingLinesLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"points\":\n\t\t\t\t\t// console.info(`[SceneModel ${this.id}]: creating PointsInstancingLayer`);\n\t\t\t\t\tvboInstancingLayer = new _vbo_instancing_points_VBOInstancingPointsLayer_js__WEBPACK_IMPORTED_MODULE_10__.VBOInstancingPointsLayer({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttextureSet,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\torigin,\n\t\t\t\t\t\tlayerIndex: 0\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// const lenPositions = geometry.positionsCompressed.length;\n\t\t\t// if (!vboInstancingLayer.canCreatePortion(lenPositions, geometry.indices.length)) { // FIXME: indices should be optional\n\t\t\t// vboInstancingLayer.finalize();\n\t\t\t// delete this._vboInstancingLayers[layerId];\n\t\t\t// vboInstancingLayer = null;\n\t\t\t// }\n\t\t}\n\t\tthis._vboInstancingLayers[layerId] = vboInstancingLayer;\n\t\tthis.layerList.push(vboInstancingLayer);\n\t\treturn vboInstancingLayer;\n\t}\n\n\t/**\n\t * Creates a {@link SceneModelEntity} within this SceneModel.\n\t *\n\t * * Gives the SceneModelEntity one or more {@link SceneModelMesh}es previously created with\n\t * {@link SceneModel#createMesh}. A SceneModelMesh can only belong to one SceneModelEntity, so you'll get an\n\t * error if you try to reuse a mesh among multiple SceneModelEntitys.\n\t * * The SceneModelEntity can have a {@link SceneModelTextureSet}, previously created with\n\t * {@link SceneModel#createTextureSet}. A SceneModelTextureSet can belong to multiple SceneModelEntitys.\n\t * * The SceneModelEntity can have a geometry, previously created with\n\t * {@link SceneModel#createTextureSet}. A geometry is a \"virtual component\" and can belong to multiple SceneModelEntitys.\n\t *\n\t * @param {Object} cfg SceneModelEntity configuration.\n\t * @param {String} cfg.id Optional ID for the new SceneModelEntity. Must not clash with any existing components within the {@link Scene}.\n\t * @param {String[]} cfg.meshIds IDs of one or more meshes created previously with {@link SceneModel@createMesh}.\n\t * @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\t * @param {Boolean} [cfg.visible=true] Indicates if the SceneModelEntity is initially visible.\n\t * @param {Boolean} [cfg.culled=false] Indicates if the SceneModelEntity is initially culled from view.\n\t * @param {Boolean} [cfg.pickable=true] Indicates if the SceneModelEntity is initially pickable.\n\t * @param {Boolean} [cfg.clippable=true] Indicates if the SceneModelEntity is initially clippable.\n\t * @param {Boolean} [cfg.collidable=true] Indicates if the SceneModelEntity is initially included in boundary calculations.\n\t * @param {Boolean} [cfg.castsShadow=true] Indicates if the SceneModelEntity initially casts shadows.\n\t * @param {Boolean} [cfg.receivesShadow=true] Indicates if the SceneModelEntity initially receives shadows.\n\t * @param {Boolean} [cfg.xrayed=false] Indicates if the SceneModelEntity is initially xrayed. XRayed appearance is configured by {@link SceneModel#xrayMaterial}.\n\t * @param {Boolean} [cfg.highlighted=false] Indicates if the SceneModelEntity is initially highlighted. Highlighted appearance is configured by {@link SceneModel#highlightMaterial}.\n\t * @param {Boolean} [cfg.selected=false] Indicates if the SceneModelEntity is initially selected. Selected appearance is configured by {@link SceneModel#selectedMaterial}.\n\t * @param {Boolean} [cfg.edges=false] Indicates if the SceneModelEntity's edges are initially emphasized. Edges appearance is configured by {@link SceneModel#edgeMaterial}.\n\t * @returns {SceneModelEntity} The new SceneModelEntity.\n\t */\n\tcreateEntity(cfg) {\n\t\tif (cfg.id === undefined) {\n\t\t\tcfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\n\t\t} else if (this.scene.components[cfg.id]) {\n\t\t\tthis.error(`Scene already has a Component with this ID: ${cfg.id} - will assign random ID`);\n\t\t\tcfg.id = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.createUUID();\n\t\t}\n\t\tif (cfg.meshIds === undefined) {\n\t\t\tthis.error(\"Config missing: meshIds\");\n\t\t\treturn;\n\t\t}\n\t\tlet flags = 0;\n\t\tif (this._visible && cfg.visible !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.VISIBLE;\n\t\t}\n\t\tif (this._pickable && cfg.pickable !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.PICKABLE;\n\t\t}\n\t\tif (this._culled && cfg.culled !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CULLED;\n\t\t}\n\t\tif (this._clippable && cfg.clippable !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.CLIPPABLE;\n\t\t}\n\t\tif (this._collidable && cfg.collidable !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.COLLIDABLE;\n\t\t}\n\t\tif (this._edges && cfg.edges !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.EDGES;\n\t\t}\n\t\tif (this._xrayed && cfg.xrayed !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.XRAYED;\n\t\t}\n\t\tif (this._highlighted && cfg.highlighted !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.HIGHLIGHTED;\n\t\t}\n\t\tif (this._selected && cfg.selected !== false) {\n\t\t\tflags = flags | _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_13__.ENTITY_FLAGS.SELECTED;\n\t\t}\n\t\tcfg.flags = flags;\n\t\tthis._createEntity(cfg);\n\t}\n\n\t_createEntity(cfg) {\n\t\tlet meshes = [];\n\t\tfor (let i = 0, len = cfg.meshIds.length; i < len; i++) {\n\t\t\tconst meshId = cfg.meshIds[i];\n\t\t\tlet mesh = this._meshes[meshId]; // Trying to get already created mesh\n\t\t\tif (!mesh) {\n\t\t\t\t// Checks if there is already created mesh for this meshId\n\t\t\t\tlet meshCfg = this._meshesCfgsBeforeMeshCreation[meshId]; // Trying to get already created cfg\n\t\t\t\tif (!meshCfg) {\n\t\t\t\t\t// Checks if there is already created cfg for this meshId\n\t\t\t\t\tthis.error(`Mesh with this ID not found: \"${meshId}\" - ignoring this mesh`); // There is no such cfg\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tmesh = this._createMesh(meshCfg); // There is no such mesh yet, but there is already created cfg, so it creates this mesh\n\t\t\t\tthis._meshes[cfg.id] = mesh; // Now it will also add this mesh to dictionary of created meshes\n\t\t\t}\n\t\t\tif (mesh.parent) {\n\t\t\t\tthis.error(\n\t\t\t\t\t`Mesh with ID \"${meshId}\" already belongs to object with ID \"${mesh.parent.id}\" - ignoring this mesh`\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmeshes.push(mesh);\n\t\t}\n\t\tconst lodCullable = true;\n\t\tconst entity = new _SceneModelEntity_js__WEBPACK_IMPORTED_MODULE_25__.SceneModelEntity(this, cfg.isObject, cfg.id, meshes, cfg.flags, lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel\n\t\tthis._entityList.push(entity);\n\t\tthis._entities[cfg.id] = entity;\n\t\tthis.numEntities++;\n\t}\n\n\t/**\n\t * Finalizes this SceneModel.\n\t *\n\t * Once finalized, you can't add anything more to this SceneModel.\n\t */\n\tfinalize() {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\n\t\t\tconst layer = this.layerList[i];\n\t\t\tlayer.finalize();\n\t\t}\n\t\tthis._geometries = {};\n\t\tthis._dtxBuckets = {};\n\t\tthis._textures = {};\n\t\tthis._textureSets = {};\n\t\tthis._dtxLayers = {};\n\t\tthis._vboInstancingLayers = {};\n\t\tthis._vboBatchingLayers = {};\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tconst entity = this._entityList[i];\n\t\t\tentity._finalize();\n\t\t}\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tconst entity = this._entityList[i];\n\t\t\tentity._finalize2();\n\t\t}\n\t\t// Sort layers to reduce WebGL shader switching when rendering them\n\t\tthis.layerList.sort((a, b) => {\n\t\t\tif (a.sortId < b.sortId) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (a.sortId > b.sortId) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\treturn 0;\n\t\t});\n\t\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\n\t\t\tconst layer = this.layerList[i];\n\t\t\tlayer.layerIndex = i;\n\t\t}\n\t\tthis.glRedraw();\n\t\tthis.scene._aabbDirty = true;\n\t\tthis._viewMatrixDirty = true;\n\t\tthis._matrixDirty = true;\n\t\tthis._aabbDirty = true;\n\n\t\tthis._setWorldMatrixDirty();\n\t\tthis._sceneModelDirty();\n\n\t\tthis.position = this._position;\n\t}\n\n\t/** @private */\n\tstateSortCompare(drawable1, drawable2) {}\n\n\t/** @private */\n\trebuildRenderFlags() {\n\t\tthis.renderFlags.reset();\n\t\tthis._updateRenderFlagsVisibleLayers();\n\t\tif (this.renderFlags.numLayers > 0 && this.renderFlags.numVisibleLayers === 0) {\n\t\t\tthis.renderFlags.culled = true;\n\t\t\treturn;\n\t\t}\n\t\tthis._updateRenderFlags();\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_updateRenderFlagsVisibleLayers() {\n\t\tconst renderFlags = this.renderFlags;\n\t\trenderFlags.numLayers = this.layerList.length;\n\t\trenderFlags.numVisibleLayers = 0;\n\t\tfor (let layerIndex = 0, len = this.layerList.length; layerIndex < len; layerIndex++) {\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tconst layerVisible = this._getActiveSectionPlanesForLayer(layer);\n\t\t\tif (layerVisible) {\n\t\t\t\trenderFlags.visibleLayers[renderFlags.numVisibleLayers++] = layerIndex;\n\t\t\t}\n\t\t}\n\t}\n\n\t_getActiveSectionPlanesForLayer(layer) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tconst sectionPlanes = this.scene._sectionPlanesState.sectionPlanes;\n\t\tconst numSectionPlanes = sectionPlanes.length;\n\t\tconst baseIndex = layer.layerIndex * numSectionPlanes;\n\t\tif (numSectionPlanes > 0) {\n\t\t\tfor (let i = 0; i < numSectionPlanes; i++) {\n\t\t\t\tconst sectionPlane = sectionPlanes[i];\n\t\t\t\tif (!sectionPlane.active) {\n\t\t\t\t\trenderFlags.sectionPlanesActivePerLayer[baseIndex + i] = false;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.sectionPlanesActivePerLayer[baseIndex + i] = true;\n\t\t\t\t\trenderFlags.sectioned = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t_updateRenderFlags() {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.numCulledLayerPortions === this.numPortions) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\trenderFlags.colorOpaque = this.numTransparentLayerPortions < this.numPortions;\n\t\tif (this.numTransparentLayerPortions > 0) {\n\t\t\trenderFlags.colorTransparent = true;\n\t\t}\n\t\tif (this.numXRayedLayerPortions > 0) {\n\t\t\tconst xrayMaterial = this.scene.xrayMaterial._state;\n\t\t\tif (xrayMaterial.fill) {\n\t\t\t\tif (xrayMaterial.fillAlpha < 1.0) {\n\t\t\t\t\trenderFlags.xrayedSilhouetteTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.xrayedSilhouetteOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (xrayMaterial.edges) {\n\t\t\t\tif (xrayMaterial.edgeAlpha < 1.0) {\n\t\t\t\t\trenderFlags.xrayedEdgesTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.xrayedEdgesOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.numEdgesLayerPortions > 0) {\n\t\t\tconst edgeMaterial = this.scene.edgeMaterial._state;\n\t\t\tif (edgeMaterial.edges) {\n\t\t\t\trenderFlags.edgesOpaque = this.numTransparentLayerPortions < this.numPortions;\n\t\t\t\tif (this.numTransparentLayerPortions > 0) {\n\t\t\t\t\trenderFlags.edgesTransparent = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.numSelectedLayerPortions > 0) {\n\t\t\tconst selectedMaterial = this.scene.selectedMaterial._state;\n\t\t\tif (selectedMaterial.fill) {\n\t\t\t\tif (selectedMaterial.fillAlpha < 1.0) {\n\t\t\t\t\trenderFlags.selectedSilhouetteTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.selectedSilhouetteOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (selectedMaterial.edges) {\n\t\t\t\tif (selectedMaterial.edgeAlpha < 1.0) {\n\t\t\t\t\trenderFlags.selectedEdgesTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.selectedEdgesOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.numHighlightedLayerPortions > 0) {\n\t\t\tconst highlightMaterial = this.scene.highlightMaterial._state;\n\t\t\tif (highlightMaterial.fill) {\n\t\t\t\tif (highlightMaterial.fillAlpha < 1.0) {\n\t\t\t\t\trenderFlags.highlightedSilhouetteTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.highlightedSilhouetteOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (highlightMaterial.edges) {\n\t\t\t\tif (highlightMaterial.edgeAlpha < 1.0) {\n\t\t\t\t\trenderFlags.highlightedEdgesTransparent = true;\n\t\t\t\t} else {\n\t\t\t\t\trenderFlags.highlightedEdgesOpaque = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// -------------- RENDERING ---------------------------------------------------------------------------------------\n\n\t/** @private */\n\tdrawColorOpaque(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawColorOpaque(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawColorTransparent(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawColorTransparent(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawDepth(frameCtx) {\n\t\t// Dedicated to SAO because it skips transparent objects\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawDepth(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawNormals(frameCtx) {\n\t\t// Dedicated to SAO because it skips transparent objects\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawNormals(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawSilhouetteXRayed(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawSilhouetteXRayed(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawSilhouetteHighlighted(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawSilhouetteHighlighted(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawSilhouetteSelected(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawSilhouetteSelected(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesColorOpaque(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesColorOpaque(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesColorTransparent(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesColorTransparent(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesXRayed(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesXRayed(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesHighlighted(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesHighlighted(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawEdgesSelected(frameCtx) {\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawEdgesSelected(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawOcclusion(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawOcclusion(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawShadow(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawShadow(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/** @private */\n\tsetPickMatrices(pickViewMatrix, pickProjMatrix) {\n\t\tif (this._numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tif (layer.setPickMatrices) {\n\t\t\t\tlayer.setPickMatrices(pickViewMatrix, pickProjMatrix);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @private */\n\tdrawPickMesh(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawPickMesh(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * Called by SceneModelMesh.drawPickDepths()\n\t * @private\n\t */\n\tdrawPickDepths(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawPickDepths(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * Called by SceneModelMesh.drawPickNormals()\n\t * @private\n\t */\n\tdrawPickNormals(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tthis.layerList[layerIndex].drawPickNormals(renderFlags, frameCtx);\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawSnapInit(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tif (layer.drawSnapInit) {\n\t\t\t\tframeCtx.snapPickOrigin = [0, 0, 0];\n\t\t\t\tframeCtx.snapPickCoordinateScale = [1, 1, 1];\n\t\t\t\tframeCtx.snapPickLayerNumber++;\n\t\t\t\tlayer.drawSnapInit(renderFlags, frameCtx);\n\t\t\t\tframeCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\n\t\t\t\t\torigin: frameCtx.snapPickOrigin.slice(),\n\t\t\t\t\tcoordinateScale: frameCtx.snapPickCoordinateScale.slice()\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t */\n\tdrawSnap(frameCtx) {\n\t\tif (this.numVisibleLayerPortions === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst renderFlags = this.renderFlags;\n\t\tfor (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {\n\t\t\tconst layerIndex = renderFlags.visibleLayers[i];\n\t\t\tconst layer = this.layerList[layerIndex];\n\t\t\tif (layer.drawSnap) {\n\t\t\t\tframeCtx.snapPickOrigin = [0, 0, 0];\n\t\t\t\tframeCtx.snapPickCoordinateScale = [1, 1, 1];\n\t\t\t\tframeCtx.snapPickLayerNumber++;\n\t\t\t\tlayer.drawSnap(renderFlags, frameCtx);\n\t\t\t\tframeCtx.snapPickLayerParams[frameCtx.snapPickLayerNumber] = {\n\t\t\t\t\torigin: frameCtx.snapPickOrigin.slice(),\n\t\t\t\t\tcoordinateScale: frameCtx.snapPickCoordinateScale.slice()\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys this SceneModel.\n\t */\n\tdestroy() {\n\t\tfor (let layerId in this._vboBatchingLayers) {\n\t\t\tif (this._vboBatchingLayers.hasOwnProperty(layerId)) {\n\t\t\t\tthis._vboBatchingLayers[layerId].destroy();\n\t\t\t}\n\t\t}\n\t\tthis._vboBatchingLayers = {};\n\t\tfor (let layerId in this._vboInstancingLayers) {\n\t\t\tif (this._vboInstancingLayers.hasOwnProperty(layerId)) {\n\t\t\t\tthis._vboInstancingLayers[layerId].destroy();\n\t\t\t}\n\t\t}\n\t\tthis._vboInstancingLayers = {};\n\t\tthis.scene.camera.off(this._onCameraViewMatrix);\n\t\tthis.scene.off(this._onTick);\n\t\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\n\t\t\tthis.layerList[i].destroy();\n\t\t}\n\t\tthis.layerList = [];\n\t\tfor (let i = 0, len = this._entityList.length; i < len; i++) {\n\t\t\tthis._entityList[i]._destroy();\n\t\t}\n\t\t// Object.entries(this._geometries).forEach(([id, geometry]) => {\n\t\t// geometry.destroy();\n\t\t// });\n\t\tthis._geometries = {};\n\t\tthis._dtxBuckets = {};\n\t\tthis._textures = {};\n\t\tthis._textureSets = {};\n\t\tthis._meshes = {};\n\t\tthis._entities = {};\n\t\tthis.scene._aabbDirty = true;\n\t\tif (this._isModel) {\n\t\t\tthis.scene._deregisterModel(this);\n\t\t}\n\t\t(0,_vbo_ScratchMemory_js__WEBPACK_IMPORTED_MODULE_4__.putScratchMemory)();\n\t\tsuper.destroy();\n\t}\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\tlet uniquePositionsCompressed, uniqueIndices, uniqueEdgeIndices;\n\tif (enableVertexWelding || enableIndexBucketing) {\n\t\t// Expensive - careful!\n\t\t[uniquePositionsCompressed, uniqueIndices, uniqueEdgeIndices] = (0,_calculateUniquePositions_js__WEBPACK_IMPORTED_MODULE_23__.uniquifyPositions)({\n\t\t\tpositionsCompressed: geometry.positionsCompressed,\n\t\t\tindices: geometry.indices,\n\t\t\tedgeIndices: geometry.edgeIndices\n\t\t});\n\t} else {\n\t\tuniquePositionsCompressed = geometry.positionsCompressed;\n\t\tuniqueIndices = geometry.indices;\n\t\tuniqueEdgeIndices = geometry.edgeIndices;\n\t}\n\tlet buckets;\n\tif (enableIndexBucketing) {\n\t\tlet numUniquePositions = uniquePositionsCompressed.length / 3;\n\t\tbuckets = (0,_rebucketPositions_js__WEBPACK_IMPORTED_MODULE_24__.rebucketPositions)(\n\t\t\t{\n\t\t\t\tpositionsCompressed: uniquePositionsCompressed,\n\t\t\t\tindices: uniqueIndices,\n\t\t\t\tedgeIndices: uniqueEdgeIndices\n\t\t\t},\n\t\t\tnumUniquePositions > 1 << 16 ? 16 : 8\n\t\t\t// true\n\t\t);\n\t} else {\n\t\tbuckets = [\n\t\t\t{\n\t\t\t\tpositionsCompressed: uniquePositionsCompressed,\n\t\t\t\tindices: uniqueIndices,\n\t\t\t\tedgeIndices: uniqueEdgeIndices\n\t\t\t}\n\t\t];\n\t}\n\treturn buckets;\n}\n\nfunction createGeometryOBB(geometry) {\n\tgeometry.obb = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.OBB3();\n\tif (geometry.positionsCompressed && geometry.positionsCompressed.length > 0) {\n\t\tconst localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positionsCompressed);\n\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n\t} else if (geometry.positions && geometry.positions.length > 0) {\n\t\tconst localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, geometry.positions);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n\t} else if (geometry.buckets) {\n\t\tconst localAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.collapseAABB3();\n\t\tfor (let i = 0, len = geometry.buckets.length; i < len; i++) {\n\t\t\tconst bucket = geometry.buckets[i];\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.expandAABB3Points3(localAABB, bucket.positionsCompressed);\n\t\t}\n\t\t_math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_26__.geometryCompressionUtils.decompressAABB(localAABB, geometry.positionsDecodeMatrix);\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.AABB3ToOBB3(localAABB, geometry.obb);\n\t}\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/SceneModel.js?");
|
|
3548
3548
|
|
|
3549
3549
|
/***/ }),
|
|
3550
3550
|
|
|
@@ -3914,7 +3914,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3914
3914
|
\***************************************************/
|
|
3915
3915
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3916
3916
|
|
|
3917
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBORenderer: () => (/* binding */ VBORenderer)\n/* harmony export */ });\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.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 _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../webgl/Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _stats_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../stats.js */ \"./src/viewer/scene/stats.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst defaultColor = new Float32Array([1, 1, 1, 1]);\r\nconst edgesDefaultColor = new Float32Array([0, 0, 0, 1]);\r\n\r\nconst tempVec4 = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4();\r\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\nconst tempMat4a = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n\r\n/**\r\n * @private\r\n */\r\nclass VBORenderer {\r\n constructor(scene, withSAO = false, {instancing = false, edges = false} = {}) {\r\n this._scene = scene;\r\n this._withSAO = withSAO;\r\n this._instancing = instancing;\r\n this._edges = edges;\r\n this._hash = this._getHash();\r\n\r\n /**\r\n * Matrices Uniform Block Buffer\r\n *\r\n * In shaders, matrices in the Matrices Uniform Block MUST be set in this order:\r\n * - worldMatrix\r\n * - viewMatrix\r\n * - projMatrix\r\n * - positionsDecodeMatrix\r\n * - worldNormalMatrix\r\n * - viewNormalMatrix\r\n */\r\n this._matricesUniformBlockBufferBindingPoint = 0;\r\n\r\n this._matricesUniformBlockBuffer = this._scene.canvas.gl.createBuffer();\r\n this._matricesUniformBlockBufferData = new Float32Array(4 * 4 * 6); // there is 6 mat4\r\n\r\n /**\r\n * A Vertex Array Object by Layer\r\n */\r\n this._vaoCache = new WeakMap();\r\n\r\n this._allocate();\r\n }\r\n\r\n /**\r\n * Should be overrided by subclasses if it does not only \"depend\" on section planes state.\r\n * @returns { string }\r\n */\r\n _getHash() {\r\n return this._scene._sectionPlanesState.getHash();\r\n }\r\n\r\n _buildShader() {\r\n return {\r\n vertex: this._buildVertexShader(),\r\n fragment: this._buildFragmentShader()\r\n };\r\n }\r\n\r\n _buildVertexShader() {\r\n return [\"\"];\r\n }\r\n\r\n _buildFragmentShader() {\r\n return [\"\"];\r\n }\r\n\r\n _addMatricesUniformBlockLines(src, normals = false) {\r\n src.push(\"uniform Matrices {\");\r\n src.push(\" mat4 worldMatrix;\");\r\n src.push(\" mat4 viewMatrix;\");\r\n src.push(\" mat4 projMatrix;\");\r\n src.push(\" mat4 positionsDecodeMatrix;\");\r\n if (normals) {\r\n src.push(\" mat4 worldNormalMatrix;\");\r\n src.push(\" mat4 viewNormalMatrix;\");\r\n }\r\n src.push(\"};\");\r\n return src;\r\n }\r\n\r\n _addRemapClipPosLines(src, viewportSize = 1) {\r\n src.push(\"uniform vec2 drawingBufferSize;\");\r\n src.push(\"uniform vec2 pickClipPos;\");\r\n\r\n src.push(\"vec4 remapClipPos(vec4 clipPos) {\");\r\n src.push(\" clipPos.xy /= clipPos.w;\");\r\n if (viewportSize === 1) {\r\n src.push(\" clipPos.xy = (clipPos.xy - pickClipPos) * drawingBufferSize;\");\r\n } else {\r\n src.push(` clipPos.xy = (clipPos.xy - pickClipPos) * (drawingBufferSize / float(${viewportSize}));`);\r\n }\r\n src.push(\" clipPos.xy *= clipPos.w;\")\r\n src.push(\" return clipPos;\")\r\n src.push(\"}\");\r\n return src;\r\n }\r\n\r\n getValid() {\r\n return this._hash === this._getHash();\r\n }\r\n\r\n setSectionPlanesStateUniforms(layer) {\r\n const scene = this._scene;\r\n const {gl} = scene.canvas;\r\n const {model, layerIndex} = layer;\r\n\r\n const numAllocatedSectionPlanes = scene._sectionPlanesState.getNumAllocatedSectionPlanes();\r\n const numSectionPlanes = scene._sectionPlanesState.sectionPlanes.length;\r\n if (numAllocatedSectionPlanes > 0) {\r\n const sectionPlanes = scene._sectionPlanesState.sectionPlanes;\r\n const baseIndex = layerIndex * numSectionPlanes;\r\n const renderFlags = model.renderFlags;\r\n for (let sectionPlaneIndex = 0; sectionPlaneIndex < numAllocatedSectionPlanes; sectionPlaneIndex++) {\r\n const sectionPlaneUniforms = this._uSectionPlanes[sectionPlaneIndex];\r\n if (sectionPlaneUniforms) {\r\n if (sectionPlaneIndex < numSectionPlanes) {\r\n const active = renderFlags.sectionPlanesActivePerLayer[baseIndex + sectionPlaneIndex];\r\n gl.uniform1i(sectionPlaneUniforms.active, active ? 1 : 0);\r\n if (active) {\r\n const sectionPlane = sectionPlanes[sectionPlaneIndex];\r\n const origin = layer._state.origin;\r\n if (origin) {\r\n const rtcSectionPlanePos = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_0__.getPlaneRTCPos)(sectionPlane.dist, sectionPlane.dir, origin, tempVec3a);\r\n gl.uniform3fv(sectionPlaneUniforms.pos, rtcSectionPlanePos);\r\n } else {\r\n gl.uniform3fv(sectionPlaneUniforms.pos, sectionPlane.pos);\r\n }\r\n gl.uniform3fv(sectionPlaneUniforms.dir, sectionPlane.dir);\r\n }\r\n } else {\r\n gl.uniform1i(sectionPlaneUniforms.active, 0);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n\r\n _allocate() {\r\n const scene = this._scene;\r\n const gl = scene.canvas.gl;\r\n const lightsState = scene._lightsState;\r\n\r\n this._program = new _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__.Program(gl, this._buildShader());\r\n\r\n if (this._program.errors) {\r\n this.errors = this._program.errors;\r\n return;\r\n }\r\n\r\n const program = this._program;\r\n\r\n this._uRenderPass = program.getLocation(\"renderPass\");\r\n\r\n this._uColor = program.getLocation(\"color\");\r\n if (!this._uColor) {\r\n // some shader may have color as attribute, in this case the uniform must be renamed silhouetteColor\r\n this._uColor = program.getLocation(\"silhouetteColor\");\r\n }\r\n this._uUVDecodeMatrix = program.getLocation(\"uvDecodeMatrix\");\r\n this._uPickInvisible = program.getLocation(\"pickInvisible\");\r\n this._uGammaFactor = program.getLocation(\"gammaFactor\");\r\n\r\n gl.uniformBlockBinding(\r\n program.handle,\r\n gl.getUniformBlockIndex(program.handle, \"Matrices\"),\r\n this._matricesUniformBlockBufferBindingPoint\r\n );\r\n\r\n this._uShadowViewMatrix = program.getLocation(\"shadowViewMatrix\");\r\n this._uShadowProjMatrix = program.getLocation(\"shadowProjMatrix\");\r\n if (scene.logarithmicDepthBufferEnabled) {\r\n this._uZFar = program.getLocation(\"zFar\");\r\n }\r\n\r\n this._uLightAmbient = program.getLocation(\"lightAmbient\");\r\n this._uLightColor = [];\r\n this._uLightDir = [];\r\n this._uLightPos = [];\r\n this._uLightAttenuation = [];\r\n\r\n // TODO add a gard to prevent light params if not affected by light ?\r\n const lights = lightsState.lights;\r\n let light;\r\n\r\n for (let i = 0, len = lights.length; i < len; i++) {\r\n light = lights[i];\r\n switch (light.type) {\r\n case \"dir\":\r\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\r\n this._uLightPos[i] = null;\r\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\r\n break;\r\n case \"point\":\r\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\r\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\r\n this._uLightDir[i] = null;\r\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\r\n break;\r\n case \"spot\":\r\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\r\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\r\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\r\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\r\n break;\r\n }\r\n }\r\n\r\n if (lightsState.reflectionMaps.length > 0) {\r\n this._uReflectionMap = \"reflectionMap\";\r\n }\r\n\r\n if (lightsState.lightMaps.length > 0) {\r\n this._uLightMap = \"lightMap\";\r\n }\r\n\r\n this._uSectionPlanes = [];\r\n\r\n for (let i = 0, len = scene._sectionPlanesState.getNumAllocatedSectionPlanes(); i < len; i++) {\r\n this._uSectionPlanes.push({\r\n active: program.getLocation(\"sectionPlaneActive\" + i),\r\n pos: program.getLocation(\"sectionPlanePos\" + i),\r\n dir: program.getLocation(\"sectionPlaneDir\" + i)\r\n });\r\n }\r\n\r\n this._aPosition = program.getAttribute(\"position\");\r\n this._aOffset = program.getAttribute(\"offset\");\r\n this._aNormal = program.getAttribute(\"normal\");\r\n this._aUV = program.getAttribute(\"uv\");\r\n this._aColor = program.getAttribute(\"color\");\r\n this._aMetallicRoughness = program.getAttribute(\"metallicRoughness\");\r\n this._aFlags = program.getAttribute(\"flags\");\r\n this._aPickColor = program.getAttribute(\"pickColor\");\r\n this._uPickZNear = program.getLocation(\"pickZNear\");\r\n this._uPickZFar = program.getLocation(\"pickZFar\");\r\n this._uPickClipPos = program.getLocation(\"pickClipPos\");\r\n this._uDrawingBufferSize = program.getLocation(\"drawingBufferSize\");\r\n\r\n this._uColorMap = \"uColorMap\";\r\n this._uMetallicRoughMap = \"uMetallicRoughMap\";\r\n this._uEmissiveMap = \"uEmissiveMap\";\r\n this._uNormalMap = \"uNormalMap\";\r\n this._uAOMap = \"uAOMap\";\r\n\r\n if (this._instancing) {\r\n\r\n this._aModelMatrix = program.getAttribute(\"modelMatrix\");\r\n\r\n this._aModelMatrixCol0 = program.getAttribute(\"modelMatrixCol0\");\r\n this._aModelMatrixCol1 = program.getAttribute(\"modelMatrixCol1\");\r\n this._aModelMatrixCol2 = program.getAttribute(\"modelMatrixCol2\");\r\n\r\n this._aModelNormalMatrixCol0 = program.getAttribute(\"modelNormalMatrixCol0\");\r\n this._aModelNormalMatrixCol1 = program.getAttribute(\"modelNormalMatrixCol1\");\r\n this._aModelNormalMatrixCol2 = program.getAttribute(\"modelNormalMatrixCol2\");\r\n }\r\n\r\n if (this._withSAO) {\r\n this._uOcclusionTexture = \"uOcclusionTexture\";\r\n this._uSAOParams = program.getLocation(\"uSAOParams\");\r\n }\r\n\r\n if (scene.logarithmicDepthBufferEnabled) {\r\n this._uLogDepthBufFC = program.getLocation(\"logDepthBufFC\");\r\n }\r\n\r\n if (scene.pointsMaterial._state.filterIntensity) {\r\n this._uIntensityRange = program.getLocation(\"intensityRange\");\r\n }\r\n\r\n this._uPointSize = program.getLocation(\"pointSize\");\r\n this._uNearPlaneHeight = program.getLocation(\"nearPlaneHeight\");\r\n }\r\n\r\n _bindProgram(frameCtx) {\r\n const scene = this._scene;\r\n const gl = scene.canvas.gl;\r\n const program = this._program;\r\n const lightsState = scene._lightsState;\r\n const lights = lightsState.lights;\r\n\r\n program.bind();\r\n\r\n frameCtx.textureUnit = 0;\r\n\r\n if (this._uLightAmbient) {\r\n gl.uniform4fv(this._uLightAmbient, lightsState.getAmbientColorAndIntensity());\r\n }\r\n\r\n if (this._uGammaFactor) {\r\n gl.uniform1f(this._uGammaFactor, scene.gammaFactor);\r\n }\r\n\r\n for (let i = 0, len = lights.length; i < len; i++) {\r\n\r\n const light = lights[i];\r\n\r\n if (this._uLightColor[i]) {\r\n gl.uniform4f(this._uLightColor[i], light.color[0], light.color[1], light.color[2], light.intensity);\r\n }\r\n if (this._uLightPos[i]) {\r\n gl.uniform3fv(this._uLightPos[i], light.pos);\r\n if (this._uLightAttenuation[i]) {\r\n gl.uniform1f(this._uLightAttenuation[i], light.attenuation);\r\n }\r\n }\r\n if (this._uLightDir[i]) {\r\n gl.uniform3fv(this._uLightDir[i], light.dir);\r\n }\r\n }\r\n }\r\n\r\n _makeVAO(state) {\r\n const gl = this._scene.canvas.gl;\r\n const vao = gl.createVertexArray();\r\n gl.bindVertexArray(vao);\r\n\r\n if (this._instancing) {\r\n this._aModelMatrixCol0.bindArrayBuffer(state.modelMatrixCol0Buf);\r\n this._aModelMatrixCol1.bindArrayBuffer(state.modelMatrixCol1Buf);\r\n this._aModelMatrixCol2.bindArrayBuffer(state.modelMatrixCol2Buf);\r\n\r\n gl.vertexAttribDivisor(this._aModelMatrixCol0.location, 1);\r\n gl.vertexAttribDivisor(this._aModelMatrixCol1.location, 1);\r\n gl.vertexAttribDivisor(this._aModelMatrixCol2.location, 1);\r\n\r\n if (this._aModelNormalMatrixCol0) {\r\n this._aModelNormalMatrixCol0.bindArrayBuffer(state.modelNormalMatrixCol0Buf);\r\n gl.vertexAttribDivisor(this._aModelNormalMatrixCol0.location, 1);\r\n }\r\n if (this._aModelNormalMatrixCol1) {\r\n this._aModelNormalMatrixCol1.bindArrayBuffer(state.modelNormalMatrixCol1Buf);\r\n gl.vertexAttribDivisor(this._aModelNormalMatrixCol1.location, 1);\r\n }\r\n if (this._aModelNormalMatrixCol2) {\r\n this._aModelNormalMatrixCol2.bindArrayBuffer(state.modelNormalMatrixCol2Buf);\r\n gl.vertexAttribDivisor(this._aModelNormalMatrixCol2.location, 1);\r\n }\r\n\r\n }\r\n\r\n this._aPosition.bindArrayBuffer(state.positionsBuf);\r\n\r\n if (this._aUV) {\r\n this._aUV.bindArrayBuffer(state.uvBuf);\r\n }\r\n\r\n if (this._aNormal) {\r\n this._aNormal.bindArrayBuffer(state.normalsBuf);\r\n }\r\n\r\n if (this._aMetallicRoughness) {\r\n this._aMetallicRoughness.bindArrayBuffer(state.metallicRoughnessBuf);\r\n if (this._instancing) {\r\n gl.vertexAttribDivisor(this._aMetallicRoughness.location, 1);\r\n }\r\n }\r\n\r\n if (this._aColor) {\r\n this._aColor.bindArrayBuffer(state.colorsBuf);\r\n if (this._instancing && state.colorsBuf) {\r\n gl.vertexAttribDivisor(this._aColor.location, 1);\r\n }\r\n }\r\n\r\n if (this._aFlags) {\r\n this._aFlags.bindArrayBuffer(state.flagsBuf);\r\n if (this._instancing) {\r\n gl.vertexAttribDivisor(this._aFlags.location, 1);\r\n }\r\n }\r\n\r\n if (this._aOffset) {\r\n this._aOffset.bindArrayBuffer(state.offsetsBuf);\r\n if (this._instancing) {\r\n gl.vertexAttribDivisor(this._aOffset.location, 1);\r\n }\r\n }\r\n\r\n if (this._aPickColor) {\r\n this._aPickColor.bindArrayBuffer(state.pickColorsBuf);\r\n if (this._instancing) {\r\n gl.vertexAttribDivisor(this._aPickColor.location, 1);\r\n }\r\n }\r\n\r\n if (this._instancing) {\r\n if (this._edges) {\r\n state.edgeIndicesBuf.bind();\r\n } else {\r\n if (state.indicesBuf) {\r\n state.indicesBuf.bind();\r\n }\r\n }\r\n } else {\r\n if (this._edges) {\r\n state.edgeIndicesBuf.bind();\r\n } else {\r\n if (state.indicesBuf) {\r\n state.indicesBuf.bind();\r\n }\r\n }\r\n }\r\n\r\n return vao;\r\n }\r\n\r\n drawLayer(frameCtx, layer, renderPass, {colorUniform = false, incrementDrawState = false} = {}) {\r\n const maxTextureUnits = _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__.WEBGL_INFO.MAX_TEXTURE_IMAGE_UNITS;\r\n\r\n const scene = this._scene;\r\n const gl = scene.canvas.gl;\r\n const {_state: state, model} = layer;\r\n const {textureSet, origin, positionsDecodeMatrix} = state;\r\n const lightsState = scene._lightsState;\r\n const pointsMaterial = scene.pointsMaterial;\r\n const {camera} = model.scene;\r\n const {viewNormalMatrix, project} = camera;\r\n const viewMatrix = frameCtx.pickViewMatrix || camera.viewMatrix\r\n const {position, rotationMatrix, rotationMatrixConjugate, worldNormalMatrix} = model;\r\n\r\n if (!this._program) {\r\n this._allocate();\r\n if (this.errors) {\r\n return;\r\n }\r\n }\r\n\r\n if (frameCtx.lastProgramId !== this._program.id) {\r\n frameCtx.lastProgramId = this._program.id;\r\n this._bindProgram(frameCtx);\r\n }\r\n\r\n if (this._vaoCache.has(layer)) {\r\n gl.bindVertexArray(this._vaoCache.get(layer));\r\n } else {\r\n this._vaoCache.set(layer, this._makeVAO(state))\r\n }\r\n\r\n let offset = 0;\r\n const mat4Size = 4 * 4;\r\n\r\n this._matricesUniformBlockBufferData.set(rotationMatrixConjugate, 0);\r\n\r\n const gotOrigin = (origin[0] !== 0 || origin[1] !== 0 || origin[2] !== 0);\r\n const gotPosition = (position[0] !== 0 || position[1] !== 0 || position[2] !== 0);\r\n if (gotOrigin || gotPosition) {\r\n const rtcOrigin = tempVec3a;\r\n if (gotOrigin) {\r\n const rotatedOrigin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPoint3(rotationMatrix, origin, tempVec3c);\r\n rtcOrigin[0] = rotatedOrigin[0];\r\n rtcOrigin[1] = rotatedOrigin[1];\r\n rtcOrigin[2] = rotatedOrigin[2];\r\n } else {\r\n rtcOrigin[0] = 0;\r\n rtcOrigin[1] = 0;\r\n rtcOrigin[2] = 0;\r\n }\r\n rtcOrigin[0] += position[0];\r\n rtcOrigin[1] += position[1];\r\n rtcOrigin[2] += position[2];\r\n this._matricesUniformBlockBufferData.set((0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_0__.createRTCViewMat)(viewMatrix, rtcOrigin, tempMat4a), offset += mat4Size);\r\n } else {\r\n this._matricesUniformBlockBufferData.set(viewMatrix, offset += mat4Size);\r\n }\r\n\r\n this._matricesUniformBlockBufferData.set(frameCtx.pickProjMatrix || project.matrix, offset += mat4Size);\r\n this._matricesUniformBlockBufferData.set(positionsDecodeMatrix, offset += mat4Size);\r\n this._matricesUniformBlockBufferData.set(worldNormalMatrix, offset += mat4Size);\r\n this._matricesUniformBlockBufferData.set(viewNormalMatrix, offset += mat4Size);\r\n\r\n gl.bindBuffer(gl.UNIFORM_BUFFER, this._matricesUniformBlockBuffer);\r\n gl.bufferData(gl.UNIFORM_BUFFER, this._matricesUniformBlockBufferData, gl.DYNAMIC_DRAW);\r\n\r\n gl.bindBufferBase(\r\n gl.UNIFORM_BUFFER,\r\n this._matricesUniformBlockBufferBindingPoint,\r\n this._matricesUniformBlockBuffer);\r\n\r\n\r\n gl.uniform1i(this._uRenderPass, renderPass);\r\n\r\n this.setSectionPlanesStateUniforms(layer);\r\n\r\n if (scene.logarithmicDepthBufferEnabled) {\r\n if (this._uLogDepthBufFC) {\r\n const logDepthBufFC = 2.0 / (Math.log(frameCtx.pickZFar + 1.0) / Math.LN2); // TODO: Far from pick project matrix?\r\n gl.uniform1f(this._uLogDepthBufFC, logDepthBufFC);\r\n }\r\n if (this._uZFar) {\r\n gl.uniform1f(this._uZFar, scene.camera.project.far)\r\n }\r\n }\r\n\r\n if (this._uPickInvisible) {\r\n gl.uniform1i(this._uPickInvisible, frameCtx.pickInvisible);\r\n }\r\n\r\n if (this._uPickZNear) {\r\n gl.uniform1f(this._uPickZNear, frameCtx.pickZNear);\r\n }\r\n\r\n if (this._uPickZFar) {\r\n gl.uniform1f(this._uPickZFar, frameCtx.pickZFar);\r\n }\r\n\r\n if (this._uPickClipPos) {\r\n gl.uniform2fv(this._uPickClipPos, frameCtx.pickClipPos);\r\n }\r\n\r\n if (this._uDrawingBufferSize) {\r\n gl.uniform2f(this._uDrawingBufferSize, gl.drawingBufferWidth, gl.drawingBufferHeight);\r\n }\r\n\r\n if (this._uUVDecodeMatrix) {\r\n gl.uniformMatrix3fv(this._uUVDecodeMatrix, false, state.uvDecodeMatrix);\r\n }\r\n\r\n if (this._uIntensityRange && pointsMaterial.filterIntensity) {\r\n gl.uniform2f(this._uIntensityRange, pointsMaterial.minIntensity, pointsMaterial.maxIntensity);\r\n }\r\n\r\n if (this._uPointSize) {\r\n gl.uniform1f(this._uPointSize, pointsMaterial.pointSize);\r\n }\r\n\r\n if (this._uNearPlaneHeight) {\r\n const nearPlaneHeight = (scene.camera.projection === \"ortho\") ?\r\n 1.0\r\n : (gl.drawingBufferHeight / (2 * Math.tan(0.5 * scene.camera.perspective.fov * Math.PI / 180.0)));\r\n gl.uniform1f(this._uNearPlaneHeight, nearPlaneHeight);\r\n }\r\n\r\n if (textureSet) {\r\n const {\r\n colorTexture,\r\n metallicRoughnessTexture,\r\n emissiveTexture,\r\n normalsTexture,\r\n occlusionTexture,\r\n } = textureSet;\r\n\r\n if (this._uColorMap && colorTexture) {\r\n this._program.bindTexture(this._uColorMap, colorTexture.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n }\r\n if (this._uMetallicRoughMap && metallicRoughnessTexture) {\r\n this._program.bindTexture(this._uMetallicRoughMap, metallicRoughnessTexture.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n }\r\n if (this._uEmissiveMap && emissiveTexture) {\r\n this._program.bindTexture(this._uEmissiveMap, emissiveTexture.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n }\r\n if (this._uNormalMap && normalsTexture) {\r\n this._program.bindTexture(this._uNormalMap, normalsTexture.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n }\r\n if (this._uAOMap && occlusionTexture) {\r\n this._program.bindTexture(this._uAOMap, occlusionTexture.texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n }\r\n\r\n }\r\n\r\n if (lightsState.reflectionMaps.length > 0 && lightsState.reflectionMaps[0].texture && this._uReflectionMap) {\r\n this._program.bindTexture(this._uReflectionMap, lightsState.reflectionMaps[0].texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n }\r\n\r\n if (lightsState.lightMaps.length > 0 && lightsState.lightMaps[0].texture && this._uLightMap) {\r\n this._program.bindTexture(this._uLightMap, lightsState.lightMaps[0].texture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n }\r\n\r\n if (this._withSAO) {\r\n const sao = scene.sao;\r\n const saoEnabled = sao.possible;\r\n if (saoEnabled) {\r\n const viewportWidth = gl.drawingBufferWidth;\r\n const viewportHeight = gl.drawingBufferHeight;\r\n tempVec4[0] = viewportWidth;\r\n tempVec4[1] = viewportHeight;\r\n tempVec4[2] = sao.blendCutoff;\r\n tempVec4[3] = sao.blendFactor;\r\n gl.uniform4fv(this._uSAOParams, tempVec4);\r\n this._program.bindTexture(this._uOcclusionTexture, frameCtx.occlusionTexture, frameCtx.textureUnit);\r\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\r\n frameCtx.bindTexture++;\r\n }\r\n }\r\n\r\n if (colorUniform) {\r\n const colorKey = this._edges ? \"edgeColor\" : \"fillColor\";\r\n const alphaKey = this._edges ? \"edgeAlpha\" : \"fillAlpha\";\r\n\r\n if (renderPass === _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__.RENDER_PASSES[`${this._edges ? \"EDGES\" : \"SILHOUETTE\"}_XRAYED`]) {\r\n const material = scene.xrayMaterial._state;\r\n const color = material[colorKey];\r\n const alpha = material[alphaKey];\r\n gl.uniform4f(this._uColor, color[0], color[1], color[2], alpha);\r\n\r\n } else if (renderPass === _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__.RENDER_PASSES[`${this._edges ? \"EDGES\" : \"SILHOUETTE\"}_HIGHLIGHTED`]) {\r\n const material = scene.highlightMaterial._state;\r\n const color = material[colorKey];\r\n const alpha = material[alphaKey];\r\n gl.uniform4f(this._uColor, color[0], color[1], color[2], alpha);\r\n\r\n } else if (renderPass === _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__.RENDER_PASSES[`${this._edges ? \"EDGES\" : \"SILHOUETTE\"}_SELECTED`]) {\r\n const material = scene.selectedMaterial._state;\r\n const color = material[colorKey];\r\n const alpha = material[alphaKey];\r\n gl.uniform4f(this._uColor, color[0], color[1], color[2], alpha);\r\n\r\n } else {\r\n gl.uniform4fv(this._uColor, this._edges ? edgesDefaultColor : defaultColor);\r\n }\r\n }\r\n\r\n this._draw({state, frameCtx, incrementDrawState});\r\n\r\n gl.bindVertexArray(null);\r\n }\r\n\r\n webglContextRestored() {\r\n this._program = null;\r\n }\r\n\r\n destroy() {\r\n if (this._program) {\r\n this._program.destroy();\r\n }\r\n this._program = null;\r\n _stats_js__WEBPACK_IMPORTED_MODULE_3__.stats.memory.programs--;\r\n }\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/VBORenderer.js?");
|
|
3917
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBORenderer: () => (/* binding */ VBORenderer)\n/* harmony export */ });\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.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 _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../webgl/Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _stats_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../stats.js */ \"./src/viewer/scene/stats.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.js\");\n\n\n\n\n\n\n\nconst defaultColor = new Float32Array([1, 1, 1, 1]);\nconst edgesDefaultColor = new Float32Array([0, 0, 0, 1]);\n\nconst tempVec4 = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec4();\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\nconst tempMat4a = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\n\n/**\n * @private\n */\nclass VBORenderer {\n constructor(scene, withSAO = false, {instancing = false, edges = false} = {}) {\n this._scene = scene;\n this._withSAO = withSAO;\n this._instancing = instancing;\n this._edges = edges;\n this._hash = this._getHash();\n\n /**\n * Matrices Uniform Block Buffer\n *\n * In shaders, matrices in the Matrices Uniform Block MUST be set in this order:\n * - worldMatrix\n * - viewMatrix\n * - projMatrix\n * - positionsDecodeMatrix\n * - worldNormalMatrix\n * - viewNormalMatrix\n */\n this._matricesUniformBlockBufferBindingPoint = 0;\n\n this._matricesUniformBlockBuffer = this._scene.canvas.gl.createBuffer();\n this._matricesUniformBlockBufferData = new Float32Array(4 * 4 * 6); // there is 6 mat4\n\n /**\n * A Vertex Array Object by Layer\n */\n this._vaoCache = new WeakMap();\n\n this._allocate();\n }\n\n /**\n * Should be overrided by subclasses if it does not only \"depend\" on section planes state.\n * @returns { string }\n */\n _getHash() {\n return this._scene._sectionPlanesState.getHash();\n }\n\n _buildShader() {\n return {\n vertex: this._buildVertexShader(),\n fragment: this._buildFragmentShader()\n };\n }\n\n _buildVertexShader() {\n return [\"\"];\n }\n\n _buildFragmentShader() {\n return [\"\"];\n }\n\n _addMatricesUniformBlockLines(src, normals = false) {\n src.push(\"uniform Matrices {\");\n src.push(\" mat4 worldMatrix;\");\n src.push(\" mat4 viewMatrix;\");\n src.push(\" mat4 projMatrix;\");\n src.push(\" mat4 positionsDecodeMatrix;\");\n if (normals) {\n src.push(\" mat4 worldNormalMatrix;\");\n src.push(\" mat4 viewNormalMatrix;\");\n }\n src.push(\"};\");\n return src;\n }\n\n _addRemapClipPosLines(src, viewportSize = 1) {\n src.push(\"uniform vec2 drawingBufferSize;\");\n src.push(\"uniform vec2 pickClipPos;\");\n\n src.push(\"vec4 remapClipPos(vec4 clipPos) {\");\n src.push(\" clipPos.xy /= clipPos.w;\");\n if (viewportSize === 1) {\n src.push(\" clipPos.xy = (clipPos.xy - pickClipPos) * drawingBufferSize;\");\n } else {\n src.push(` clipPos.xy = (clipPos.xy - pickClipPos) * (drawingBufferSize / float(${viewportSize}));`);\n }\n src.push(\" clipPos.xy *= clipPos.w;\")\n src.push(\" return clipPos;\")\n src.push(\"}\");\n return src;\n }\n\n getValid() {\n return this._hash === this._getHash();\n }\n\n setSectionPlanesStateUniforms(layer) {\n const scene = this._scene;\n const {gl} = scene.canvas;\n const {model, layerIndex} = layer;\n\n const numAllocatedSectionPlanes = scene._sectionPlanesState.getNumAllocatedSectionPlanes();\n const numSectionPlanes = scene._sectionPlanesState.sectionPlanes.length;\n if (numAllocatedSectionPlanes > 0) {\n const sectionPlanes = scene._sectionPlanesState.sectionPlanes;\n const baseIndex = layerIndex * numSectionPlanes;\n const renderFlags = model.renderFlags;\n for (let sectionPlaneIndex = 0; sectionPlaneIndex < numAllocatedSectionPlanes; sectionPlaneIndex++) {\n const sectionPlaneUniforms = this._uSectionPlanes[sectionPlaneIndex];\n if (sectionPlaneUniforms) {\n if (sectionPlaneIndex < numSectionPlanes) {\n const active = renderFlags.sectionPlanesActivePerLayer[baseIndex + sectionPlaneIndex];\n gl.uniform1i(sectionPlaneUniforms.active, active ? 1 : 0);\n if (active) {\n const sectionPlane = sectionPlanes[sectionPlaneIndex];\n const origin = layer._state.origin;\n if (origin) {\n const rtcSectionPlanePos = (0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_0__.getPlaneRTCPos)(sectionPlane.dist, sectionPlane.dir, origin, tempVec3a);\n gl.uniform3fv(sectionPlaneUniforms.pos, rtcSectionPlanePos);\n } else {\n gl.uniform3fv(sectionPlaneUniforms.pos, sectionPlane.pos);\n }\n gl.uniform3fv(sectionPlaneUniforms.dir, sectionPlane.dir);\n }\n } else {\n gl.uniform1i(sectionPlaneUniforms.active, 0);\n }\n }\n }\n }\n }\n\n\n _allocate() {\n const scene = this._scene;\n const gl = scene.canvas.gl;\n const lightsState = scene._lightsState;\n\n this._program = new _webgl_Program_js__WEBPACK_IMPORTED_MODULE_2__.Program(gl, this._buildShader());\n\n if (this._program.errors) {\n this.errors = this._program.errors;\n return;\n }\n\n const program = this._program;\n\n this._uRenderPass = program.getLocation(\"renderPass\");\n\n this._uColor = program.getLocation(\"color\");\n if (!this._uColor) {\n // some shader may have color as attribute, in this case the uniform must be renamed silhouetteColor\n this._uColor = program.getLocation(\"silhouetteColor\");\n }\n this._uUVDecodeMatrix = program.getLocation(\"uvDecodeMatrix\");\n this._uPickInvisible = program.getLocation(\"pickInvisible\");\n this._uGammaFactor = program.getLocation(\"gammaFactor\");\n\n gl.uniformBlockBinding(\n program.handle,\n gl.getUniformBlockIndex(program.handle, \"Matrices\"),\n this._matricesUniformBlockBufferBindingPoint\n );\n\n this._uShadowViewMatrix = program.getLocation(\"shadowViewMatrix\");\n this._uShadowProjMatrix = program.getLocation(\"shadowProjMatrix\");\n if (scene.logarithmicDepthBufferEnabled) {\n this._uZFar = program.getLocation(\"zFar\");\n }\n\n this._uLightAmbient = program.getLocation(\"lightAmbient\");\n this._uLightColor = [];\n this._uLightDir = [];\n this._uLightPos = [];\n this._uLightAttenuation = [];\n\n // TODO add a gard to prevent light params if not affected by light ?\n const lights = lightsState.lights;\n let light;\n\n for (let i = 0, len = lights.length; i < len; i++) {\n light = lights[i];\n switch (light.type) {\n case \"dir\":\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\n this._uLightPos[i] = null;\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\n break;\n case \"point\":\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\n this._uLightDir[i] = null;\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\n break;\n case \"spot\":\n this._uLightColor[i] = program.getLocation(\"lightColor\" + i);\n this._uLightPos[i] = program.getLocation(\"lightPos\" + i);\n this._uLightDir[i] = program.getLocation(\"lightDir\" + i);\n this._uLightAttenuation[i] = program.getLocation(\"lightAttenuation\" + i);\n break;\n }\n }\n\n if (lightsState.reflectionMaps.length > 0) {\n this._uReflectionMap = \"reflectionMap\";\n }\n\n if (lightsState.lightMaps.length > 0) {\n this._uLightMap = \"lightMap\";\n }\n\n this._uSectionPlanes = [];\n\n for (let i = 0, len = scene._sectionPlanesState.getNumAllocatedSectionPlanes(); i < len; i++) {\n this._uSectionPlanes.push({\n active: program.getLocation(\"sectionPlaneActive\" + i),\n pos: program.getLocation(\"sectionPlanePos\" + i),\n dir: program.getLocation(\"sectionPlaneDir\" + i)\n });\n }\n\n this._aPosition = program.getAttribute(\"position\");\n this._aOffset = program.getAttribute(\"offset\");\n this._aNormal = program.getAttribute(\"normal\");\n this._aUV = program.getAttribute(\"uv\");\n this._aColor = program.getAttribute(\"color\");\n this._aMetallicRoughness = program.getAttribute(\"metallicRoughness\");\n this._aFlags = program.getAttribute(\"flags\");\n this._aPickColor = program.getAttribute(\"pickColor\");\n this._uPickZNear = program.getLocation(\"pickZNear\");\n this._uPickZFar = program.getLocation(\"pickZFar\");\n this._uPickClipPos = program.getLocation(\"pickClipPos\");\n this._uDrawingBufferSize = program.getLocation(\"drawingBufferSize\");\n\n this._uColorMap = \"uColorMap\";\n this._uMetallicRoughMap = \"uMetallicRoughMap\";\n this._uEmissiveMap = \"uEmissiveMap\";\n this._uNormalMap = \"uNormalMap\";\n this._uAOMap = \"uAOMap\";\n\n if (this._instancing) {\n\n this._aModelMatrix = program.getAttribute(\"modelMatrix\");\n\n this._aModelMatrixCol0 = program.getAttribute(\"modelMatrixCol0\");\n this._aModelMatrixCol1 = program.getAttribute(\"modelMatrixCol1\");\n this._aModelMatrixCol2 = program.getAttribute(\"modelMatrixCol2\");\n\n this._aModelNormalMatrixCol0 = program.getAttribute(\"modelNormalMatrixCol0\");\n this._aModelNormalMatrixCol1 = program.getAttribute(\"modelNormalMatrixCol1\");\n this._aModelNormalMatrixCol2 = program.getAttribute(\"modelNormalMatrixCol2\");\n }\n\n if (this._withSAO) {\n this._uOcclusionTexture = \"uOcclusionTexture\";\n this._uSAOParams = program.getLocation(\"uSAOParams\");\n }\n\n if (scene.logarithmicDepthBufferEnabled) {\n this._uLogDepthBufFC = program.getLocation(\"logDepthBufFC\");\n }\n\n if (scene.pointsMaterial._state.filterIntensity) {\n this._uIntensityRange = program.getLocation(\"intensityRange\");\n }\n\n this._uPointSize = program.getLocation(\"pointSize\");\n this._uNearPlaneHeight = program.getLocation(\"nearPlaneHeight\");\n }\n\n _bindProgram(frameCtx) {\n const scene = this._scene;\n const gl = scene.canvas.gl;\n const program = this._program;\n const lightsState = scene._lightsState;\n const lights = lightsState.lights;\n\n program.bind();\n\n frameCtx.textureUnit = 0;\n\n if (this._uLightAmbient) {\n gl.uniform4fv(this._uLightAmbient, lightsState.getAmbientColorAndIntensity());\n }\n\n if (this._uGammaFactor) {\n gl.uniform1f(this._uGammaFactor, scene.gammaFactor);\n }\n\n for (let i = 0, len = lights.length; i < len; i++) {\n\n const light = lights[i];\n\n if (this._uLightColor[i]) {\n gl.uniform4f(this._uLightColor[i], light.color[0], light.color[1], light.color[2], light.intensity);\n }\n if (this._uLightPos[i]) {\n gl.uniform3fv(this._uLightPos[i], light.pos);\n if (this._uLightAttenuation[i]) {\n gl.uniform1f(this._uLightAttenuation[i], light.attenuation);\n }\n }\n if (this._uLightDir[i]) {\n gl.uniform3fv(this._uLightDir[i], light.dir);\n }\n }\n }\n\n _makeVAO(state) {\n const gl = this._scene.canvas.gl;\n const vao = gl.createVertexArray();\n gl.bindVertexArray(vao);\n\n if (this._instancing) {\n this._aModelMatrixCol0.bindArrayBuffer(state.modelMatrixCol0Buf);\n this._aModelMatrixCol1.bindArrayBuffer(state.modelMatrixCol1Buf);\n this._aModelMatrixCol2.bindArrayBuffer(state.modelMatrixCol2Buf);\n\n gl.vertexAttribDivisor(this._aModelMatrixCol0.location, 1);\n gl.vertexAttribDivisor(this._aModelMatrixCol1.location, 1);\n gl.vertexAttribDivisor(this._aModelMatrixCol2.location, 1);\n\n if (this._aModelNormalMatrixCol0) {\n this._aModelNormalMatrixCol0.bindArrayBuffer(state.modelNormalMatrixCol0Buf);\n gl.vertexAttribDivisor(this._aModelNormalMatrixCol0.location, 1);\n }\n if (this._aModelNormalMatrixCol1) {\n this._aModelNormalMatrixCol1.bindArrayBuffer(state.modelNormalMatrixCol1Buf);\n gl.vertexAttribDivisor(this._aModelNormalMatrixCol1.location, 1);\n }\n if (this._aModelNormalMatrixCol2) {\n this._aModelNormalMatrixCol2.bindArrayBuffer(state.modelNormalMatrixCol2Buf);\n gl.vertexAttribDivisor(this._aModelNormalMatrixCol2.location, 1);\n }\n\n }\n\n this._aPosition.bindArrayBuffer(state.positionsBuf);\n\n if (this._aUV) {\n this._aUV.bindArrayBuffer(state.uvBuf);\n }\n\n if (this._aNormal) {\n this._aNormal.bindArrayBuffer(state.normalsBuf);\n }\n\n if (this._aMetallicRoughness) {\n this._aMetallicRoughness.bindArrayBuffer(state.metallicRoughnessBuf);\n if (this._instancing) {\n gl.vertexAttribDivisor(this._aMetallicRoughness.location, 1);\n }\n }\n\n if (this._aColor) {\n this._aColor.bindArrayBuffer(state.colorsBuf);\n if (this._instancing && state.colorsBuf) {\n gl.vertexAttribDivisor(this._aColor.location, 1);\n }\n }\n\n if (this._aFlags) {\n this._aFlags.bindArrayBuffer(state.flagsBuf);\n if (this._instancing) {\n gl.vertexAttribDivisor(this._aFlags.location, 1);\n }\n }\n\n if (this._aOffset) {\n this._aOffset.bindArrayBuffer(state.offsetsBuf);\n if (this._instancing) {\n gl.vertexAttribDivisor(this._aOffset.location, 1);\n }\n }\n\n if (this._aPickColor) {\n this._aPickColor.bindArrayBuffer(state.pickColorsBuf);\n if (this._instancing) {\n gl.vertexAttribDivisor(this._aPickColor.location, 1);\n }\n }\n\n if (this._instancing) {\n if (this._edges) {\n state.edgeIndicesBuf.bind();\n } else {\n if (state.indicesBuf) {\n state.indicesBuf.bind();\n }\n }\n } else {\n if (this._edges) {\n state.edgeIndicesBuf.bind();\n } else {\n if (state.indicesBuf) {\n state.indicesBuf.bind();\n }\n }\n }\n\n return vao;\n }\n\n drawLayer(frameCtx, layer, renderPass, {colorUniform = false, incrementDrawState = false} = {}) {\n const maxTextureUnits = _webglInfo_js__WEBPACK_IMPORTED_MODULE_4__.WEBGL_INFO.MAX_TEXTURE_IMAGE_UNITS;\n\n const scene = this._scene;\n const gl = scene.canvas.gl;\n const {_state: state, model} = layer;\n const {textureSet, origin, positionsDecodeMatrix} = state;\n const lightsState = scene._lightsState;\n const pointsMaterial = scene.pointsMaterial;\n const {camera} = model.scene;\n const {viewNormalMatrix, project} = camera;\n const viewMatrix = frameCtx.pickViewMatrix || camera.viewMatrix\n const {position, rotationMatrix, rotationMatrixConjugate, worldNormalMatrix} = model;\n\n if (!this._program) {\n this._allocate();\n if (this.errors) {\n return;\n }\n }\n\n if (frameCtx.lastProgramId !== this._program.id) {\n frameCtx.lastProgramId = this._program.id;\n this._bindProgram(frameCtx);\n }\n\n if (this._vaoCache.has(layer)) {\n gl.bindVertexArray(this._vaoCache.get(layer));\n } else {\n this._vaoCache.set(layer, this._makeVAO(state))\n }\n\n let offset = 0;\n const mat4Size = 4 * 4;\n\n this._matricesUniformBlockBufferData.set(rotationMatrixConjugate, 0);\n\n const gotOrigin = (origin[0] !== 0 || origin[1] !== 0 || origin[2] !== 0);\n const gotPosition = (position[0] !== 0 || position[1] !== 0 || position[2] !== 0);\n if (gotOrigin || gotPosition) {\n const rtcOrigin = tempVec3a;\n if (gotOrigin) {\n const rotatedOrigin = _math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPoint3(rotationMatrix, origin, tempVec3c);\n rtcOrigin[0] = rotatedOrigin[0];\n rtcOrigin[1] = rotatedOrigin[1];\n rtcOrigin[2] = rotatedOrigin[2];\n } else {\n rtcOrigin[0] = 0;\n rtcOrigin[1] = 0;\n rtcOrigin[2] = 0;\n }\n rtcOrigin[0] += position[0];\n rtcOrigin[1] += position[1];\n rtcOrigin[2] += position[2];\n this._matricesUniformBlockBufferData.set((0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_0__.createRTCViewMat)(viewMatrix, rtcOrigin, tempMat4a), offset += mat4Size);\n } else {\n this._matricesUniformBlockBufferData.set(viewMatrix, offset += mat4Size);\n }\n\n this._matricesUniformBlockBufferData.set(frameCtx.pickProjMatrix || project.matrix, offset += mat4Size);\n this._matricesUniformBlockBufferData.set(positionsDecodeMatrix, offset += mat4Size);\n this._matricesUniformBlockBufferData.set(worldNormalMatrix, offset += mat4Size);\n this._matricesUniformBlockBufferData.set(viewNormalMatrix, offset += mat4Size);\n\n gl.bindBuffer(gl.UNIFORM_BUFFER, this._matricesUniformBlockBuffer);\n gl.bufferData(gl.UNIFORM_BUFFER, this._matricesUniformBlockBufferData, gl.DYNAMIC_DRAW);\n\n gl.bindBufferBase(\n gl.UNIFORM_BUFFER,\n this._matricesUniformBlockBufferBindingPoint,\n this._matricesUniformBlockBuffer);\n\n\n gl.uniform1i(this._uRenderPass, renderPass);\n\n this.setSectionPlanesStateUniforms(layer);\n\n if (scene.logarithmicDepthBufferEnabled) {\n if (this._uLogDepthBufFC) {\n const logDepthBufFC = 2.0 / (Math.log(frameCtx.pickZFar + 1.0) / Math.LN2); // TODO: Far from pick project matrix?\n gl.uniform1f(this._uLogDepthBufFC, logDepthBufFC);\n }\n if (this._uZFar) {\n gl.uniform1f(this._uZFar, scene.camera.project.far)\n }\n }\n\n if (this._uPickInvisible) {\n gl.uniform1i(this._uPickInvisible, frameCtx.pickInvisible);\n }\n\n if (this._uPickZNear) {\n gl.uniform1f(this._uPickZNear, frameCtx.pickZNear);\n }\n\n if (this._uPickZFar) {\n gl.uniform1f(this._uPickZFar, frameCtx.pickZFar);\n }\n\n if (this._uPickClipPos) {\n gl.uniform2fv(this._uPickClipPos, frameCtx.pickClipPos);\n }\n\n if (this._uDrawingBufferSize) {\n gl.uniform2f(this._uDrawingBufferSize, gl.drawingBufferWidth, gl.drawingBufferHeight);\n }\n\n if (this._uUVDecodeMatrix) {\n gl.uniformMatrix3fv(this._uUVDecodeMatrix, false, state.uvDecodeMatrix);\n }\n\n if (this._uIntensityRange && pointsMaterial.filterIntensity) {\n gl.uniform2f(this._uIntensityRange, pointsMaterial.minIntensity, pointsMaterial.maxIntensity);\n }\n\n if (this._uPointSize) {\n gl.uniform1f(this._uPointSize, pointsMaterial.pointSize);\n }\n\n if (this._uNearPlaneHeight) {\n const nearPlaneHeight = (scene.camera.projection === \"ortho\") ?\n 1.0\n : (gl.drawingBufferHeight / (2 * Math.tan(0.5 * scene.camera.perspective.fov * Math.PI / 180.0)));\n gl.uniform1f(this._uNearPlaneHeight, nearPlaneHeight);\n }\n\n if (textureSet) {\n const {\n colorTexture,\n metallicRoughnessTexture,\n emissiveTexture,\n normalsTexture,\n occlusionTexture,\n } = textureSet;\n\n if (this._uColorMap && colorTexture) {\n this._program.bindTexture(this._uColorMap, colorTexture.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n }\n if (this._uMetallicRoughMap && metallicRoughnessTexture) {\n this._program.bindTexture(this._uMetallicRoughMap, metallicRoughnessTexture.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n }\n if (this._uEmissiveMap && emissiveTexture) {\n this._program.bindTexture(this._uEmissiveMap, emissiveTexture.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n }\n if (this._uNormalMap && normalsTexture) {\n this._program.bindTexture(this._uNormalMap, normalsTexture.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n }\n if (this._uAOMap && occlusionTexture) {\n this._program.bindTexture(this._uAOMap, occlusionTexture.texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n }\n\n }\n\n if (lightsState.reflectionMaps.length > 0 && lightsState.reflectionMaps[0].texture && this._uReflectionMap) {\n this._program.bindTexture(this._uReflectionMap, lightsState.reflectionMaps[0].texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n }\n\n if (lightsState.lightMaps.length > 0 && lightsState.lightMaps[0].texture && this._uLightMap) {\n this._program.bindTexture(this._uLightMap, lightsState.lightMaps[0].texture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n }\n\n if (this._withSAO) {\n const sao = scene.sao;\n const saoEnabled = sao.possible;\n if (saoEnabled) {\n const viewportWidth = gl.drawingBufferWidth;\n const viewportHeight = gl.drawingBufferHeight;\n tempVec4[0] = viewportWidth;\n tempVec4[1] = viewportHeight;\n tempVec4[2] = sao.blendCutoff;\n tempVec4[3] = sao.blendFactor;\n gl.uniform4fv(this._uSAOParams, tempVec4);\n this._program.bindTexture(this._uOcclusionTexture, frameCtx.occlusionTexture, frameCtx.textureUnit);\n frameCtx.textureUnit = (frameCtx.textureUnit + 1) % maxTextureUnits;\n frameCtx.bindTexture++;\n }\n }\n\n if (colorUniform) {\n const colorKey = this._edges ? \"edgeColor\" : \"fillColor\";\n const alphaKey = this._edges ? \"edgeAlpha\" : \"fillAlpha\";\n\n if (renderPass === _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__.RENDER_PASSES[`${this._edges ? \"EDGES\" : \"SILHOUETTE\"}_XRAYED`]) {\n const material = scene.xrayMaterial._state;\n const color = material[colorKey];\n const alpha = material[alphaKey];\n gl.uniform4f(this._uColor, color[0], color[1], color[2], alpha);\n\n } else if (renderPass === _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__.RENDER_PASSES[`${this._edges ? \"EDGES\" : \"SILHOUETTE\"}_HIGHLIGHTED`]) {\n const material = scene.highlightMaterial._state;\n const color = material[colorKey];\n const alpha = material[alphaKey];\n gl.uniform4f(this._uColor, color[0], color[1], color[2], alpha);\n\n } else if (renderPass === _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_5__.RENDER_PASSES[`${this._edges ? \"EDGES\" : \"SILHOUETTE\"}_SELECTED`]) {\n const material = scene.selectedMaterial._state;\n const color = material[colorKey];\n const alpha = material[alphaKey];\n gl.uniform4f(this._uColor, color[0], color[1], color[2], alpha);\n\n } else {\n gl.uniform4fv(this._uColor, this._edges ? edgesDefaultColor : defaultColor);\n }\n }\n\n this._draw({state, frameCtx, incrementDrawState});\n\n gl.bindVertexArray(null);\n }\n\n webglContextRestored() {\n this._program = null;\n }\n\n destroy() {\n if (this._program) {\n this._program.destroy();\n }\n this._program = null;\n _stats_js__WEBPACK_IMPORTED_MODULE_3__.stats.memory.programs--;\n }\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/VBORenderer.js?");
|
|
3918
3918
|
|
|
3919
3919
|
/***/ }),
|
|
3920
3920
|
|
|
@@ -3954,7 +3954,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3954
3954
|
\******************************************************************************************/
|
|
3955
3955
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3956
3956
|
|
|
3957
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getRenderers: () => (/* binding */ getRenderers)\n/* harmony export */ });\n/* harmony import */ var _VBOBatchingLinesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./VBOBatchingLinesColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesColorRenderer.js\");\n/* harmony import */ var _VBOBatchingLinesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VBOBatchingLinesSilhouetteRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSilhouetteRenderer.js\");\n/* harmony import */ var _VBOBatchingLinesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./VBOBatchingLinesSnapInitRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapInitRenderer.js\");\n/* harmony import */ var _VBOBatchingLinesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./VBOBatchingLinesSnapRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js\");\n\
|
|
3957
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getRenderers: () => (/* binding */ getRenderers)\n/* harmony export */ });\n/* harmony import */ var _VBOBatchingLinesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./VBOBatchingLinesColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesColorRenderer.js\");\n/* harmony import */ var _VBOBatchingLinesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VBOBatchingLinesSilhouetteRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSilhouetteRenderer.js\");\n/* harmony import */ var _VBOBatchingLinesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./VBOBatchingLinesSnapInitRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapInitRenderer.js\");\n/* harmony import */ var _VBOBatchingLinesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./VBOBatchingLinesSnapRenderer.js */ \"./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js\");\n\n\n\n\n\n/**\n * @private\n */\nclass VBOBatchingLinesRenderers {\n\n constructor(scene) {\n this._scene = scene;\n }\n\n _compile() {\n if (this._colorRenderer && (!this._colorRenderer.getValid())) {\n this._colorRenderer.destroy();\n this._colorRenderer = null;\n }\n if (this._silhouetteRenderer && (!this._silhouetteRenderer.getValid())) {\n this._silhouetteRenderer.destroy();\n this._silhouetteRenderer = null;\n }\n if (this._snapInitRenderer && (!this._snapInitRenderer.getValid())) {\n this._snapInitRenderer.destroy();\n this._snapInitRenderer = null;\n }\n if (this._snapRenderer && (!this._snapRenderer.getValid())) {\n this._snapRenderer.destroy();\n this._snapRenderer = null;\n }\n }\n\n get colorRenderer() {\n if (!this._colorRenderer) {\n this._colorRenderer = new _VBOBatchingLinesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__.VBOBatchingLinesColorRenderer(this._scene, false);\n }\n return this._colorRenderer;\n }\n\n get silhouetteRenderer() {\n if (!this._silhouetteRenderer) {\n this._silhouetteRenderer = new _VBOBatchingLinesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_1__.VBOBatchingLinesSilhouetteRenderer(this._scene);\n }\n return this._silhouetteRenderer;\n }\n\n get snapInitRenderer() {\n if (!this._snapInitRenderer) {\n this._snapInitRenderer = new _VBOBatchingLinesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_2__.VBOBatchingLinesSnapInitRenderer(this._scene, false);\n }\n return this._snapInitRenderer;\n }\n\n get snapRenderer() {\n if (!this._snapRenderer) {\n this._snapRenderer = new _VBOBatchingLinesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_3__.VBOBatchingLinesSnapRenderer(this._scene);\n }\n return this._snapRenderer;\n }\n\n _destroy() {\n if (this._colorRenderer) {\n this._colorRenderer.destroy();\n }\n if (this._silhouetteRenderer) {\n this._silhouetteRenderer.destroy();\n }\n if (this._snapInitRenderer) {\n this._snapInitRenderer.destroy();\n }\n if (this._snapRenderer) {\n this._snapRenderer.destroy();\n }\n }\n}\n\nconst cachedRenderers = {};\n\n/**\n * @private\n */\nfunction getRenderers(scene) {\n const sceneId = scene.id;\n let batchingRenderers = cachedRenderers[sceneId];\n if (!batchingRenderers) {\n batchingRenderers = new VBOBatchingLinesRenderers(scene);\n cachedRenderers[sceneId] = batchingRenderers;\n batchingRenderers._compile();\n scene.on(\"compile\", () => {\n batchingRenderers._compile();\n });\n scene.on(\"destroyed\", () => {\n delete cachedRenderers[sceneId];\n batchingRenderers._destroy();\n });\n }\n return batchingRenderers;\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesRenderers.js?");
|
|
3958
3958
|
|
|
3959
3959
|
/***/ }),
|
|
3960
3960
|
|
|
@@ -4014,7 +4014,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4014
4014
|
\******************************************************************************/
|
|
4015
4015
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4016
4016
|
|
|
4017
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBOBatchingPointsLayer: () => (/* binding */ VBOBatchingPointsLayer)\n/* harmony export */ });\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.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 _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../webgl/RenderState.js */ \"./src/viewer/scene/webgl/RenderState.js\");\n/* harmony import */ var _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../webgl/ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _renderers_VBOBatchingPointsRenderers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./renderers/VBOBatchingPointsRenderers.js */ \"./src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsRenderers.js\");\n/* harmony import */ var _VBOBatchingPointsBuffer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./VBOBatchingPointsBuffer.js */ \"./src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsBuffer.js\");\n/* harmony import */ var _compression_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../compression.js */ \"./src/viewer/scene/model/compression.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * @private\r\n */\r\nclass VBOBatchingPointsLayer {\r\n\r\n /**\r\n * @param model\r\n * @param cfg\r\n * @param cfg.layerIndex\r\n * @param cfg.positionsDecodeMatrix\r\n * @param cfg.maxGeometryBatchSize\r\n * @param cfg.origin\r\n * @param cfg.scratchMemory\r\n */\r\n constructor(cfg) {\r\n\r\n console.info(\"Creating VBOBatchingPointsLayer\");\r\n\r\n /**\r\n * Owner model\r\n * @type {VBOSceneModel}\r\n */\r\n this.model = cfg.model;\r\n\r\n /**\r\n * State sorting key.\r\n * @type {string}\r\n */\r\n this.sortId = \"PointsBatchingLayer\";\r\n\r\n /**\r\n * Index of this PointsBatchingLayer in {@link VBOSceneModel#_layerList}.\r\n * @type {Number}\r\n */\r\n this.layerIndex = cfg.layerIndex;\r\n\r\n this._renderers = (0,_renderers_VBOBatchingPointsRenderers_js__WEBPACK_IMPORTED_MODULE_5__.getRenderers)(cfg.model.scene);\r\n\r\n this._buffer = new _VBOBatchingPointsBuffer_js__WEBPACK_IMPORTED_MODULE_6__.VBOBatchingPointsBuffer(cfg.maxGeometryBatchSize);\r\n this._scratchMemory = cfg.scratchMemory;\r\n\r\n this._state = new _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__.RenderState({\r\n positionsBuf: null,\r\n offsetsBuf: null,\r\n colorsBuf: null,\r\n flagsBuf: null,\r\n positionsDecodeMatrix: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4(),\r\n origin: null\r\n });\r\n\r\n // These counts are used to avoid unnecessary render passes\r\n this._numPortions = 0;\r\n this._numVisibleLayerPortions = 0;\r\n this._numTransparentLayerPortions = 0;\r\n this._numXRayedLayerPortions = 0;\r\n this._numSelectedLayerPortions = 0;\r\n this._numHighlightedLayerPortions = 0;\r\n this._numClippableLayerPortions = 0;\r\n this._numPickableLayerPortions = 0;\r\n this._numCulledLayerPortions = 0;\r\n\r\n this._modelAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(); // Model-space AABB\r\n this._portions = [];\r\n this._meshes = [];\r\n\r\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\r\n this.aabbDirty = true;\r\n\r\n this._finalized = false;\r\n\r\n if (cfg.positionsDecodeMatrix) {\r\n this._state.positionsDecodeMatrix.set(cfg.positionsDecodeMatrix);\r\n this._preCompressedPositionsExpected = true;\r\n } else {\r\n this._preCompressedPositionsExpected = false;\r\n }\r\n\r\n if (cfg.origin) {\r\n this._state.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3(cfg.origin);\r\n }\r\n }\r\n\r\n get aabb() {\r\n if (this.aabbDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(this._aabb);\r\n for (let i = 0, len = this._meshes.length; i < len; i++) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._aabb, this._meshes[i].aabb);\r\n }\r\n this.aabbDirty = false;\r\n }\r\n return this._aabb;\r\n }\r\n\r\n /**\r\n * Tests if there is room for another portion in this PointsBatchingLayer.\r\n *\r\n * @param lenPositions Number of positions we'd like to create in the portion.\r\n * @returns {Boolean} True if OK to create another portion.\r\n */\r\n canCreatePortion(lenPositions) {\r\n if (this._finalized) {\r\n throw \"Already finalized\";\r\n }\r\n return ((this._buffer.positions.length + lenPositions) < (this._buffer.maxVerts * 3));\r\n }\r\n\r\n /**\r\n * Creates a new portion within this PointsBatchingLayer, returns the new portion ID.\r\n *\r\n * Gives the portion the specified geometry, color and matrix.\r\n *\r\n * @param mesh The SceneModelMesh that owns the portion\r\n * @param cfg.positions Flat float Local-space positions array.\r\n * @param cfg.positionsCompressed Flat quantized positions array - decompressed with PointsBatchingLayer positionsDecodeMatrix\r\n * @param [cfg.colorsCompressed] Quantized RGB colors [0..255,0..255,0..255,0..255]\r\n * @param [cfg.colors] Flat float colors array.\r\n * @param cfg.color Float RGB color [0..1,0..1,0..1]\r\n * @param [cfg.meshMatrix] Flat float 4x4 matrix\r\n * @param cfg.aabb Flat float AABB World-space AABB\r\n * @param cfg.pickColor Quantized pick color\r\n * @returns {number} Portion ID\r\n */\r\n createPortion(mesh, cfg) {\r\n\r\n if (this._finalized) {\r\n throw \"Already finalized\";\r\n }\r\n\r\n const positions = cfg.positions;\r\n const positionsCompressed = cfg.positionsCompressed;\r\n const color = cfg.color;\r\n const colorsCompressed = cfg.colorsCompressed;\r\n const colors = cfg.colors;\r\n const pickColor = cfg.pickColor;\r\n\r\n const buffer = this._buffer;\r\n const positionsIndex = buffer.positions.length;\r\n const vertsIndex = positionsIndex / 3;\r\n\r\n let numVerts;\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._modelAABB, cfg.aabb);\r\n\r\n if (this._preCompressedPositionsExpected) {\r\n\r\n if (!positionsCompressed) {\r\n throw \"positionsCompressed expected\";\r\n }\r\n\r\n for (let i = 0, len = positionsCompressed.length; i < len; i++) {\r\n buffer.positions.push(positionsCompressed[i]);\r\n }\r\n\r\n numVerts = positionsCompressed.length / 3;\r\n\r\n } else {\r\n\r\n if (!positions) {\r\n throw \"positions expected\";\r\n }\r\n\r\n numVerts = positions.length / 3;\r\n\r\n const lenPositions = positions.length;\r\n const positionsBase = buffer.positions.length;\r\n\r\n for (let i = 0, len = positions.length; i < len; i++) {\r\n buffer.positions.push(positions[i]);\r\n }\r\n }\r\n\r\n if (colorsCompressed) {\r\n for (let i = 0, len = colorsCompressed.length; i < len; i++) {\r\n buffer.colors.push(colorsCompressed[i]);\r\n }\r\n\r\n } else if (colors) {\r\n for (let i = 0, len = colors.length; i < len; i++) {\r\n buffer.colors.push(colors[i] * 255);\r\n }\r\n\r\n } else if (color) {\r\n\r\n const r = color[0]; // Color is pre-quantized by VBOSceneModel\r\n const g = color[1];\r\n const b = color[2];\r\n const a = 1.0;\r\n\r\n for (let i = 0; i < numVerts; i++) {\r\n buffer.colors.push(r);\r\n buffer.colors.push(g);\r\n buffer.colors.push(b);\r\n buffer.colors.push(a);\r\n }\r\n }\r\n\r\n {\r\n const pickColorsBase = buffer.pickColors.length;\r\n const lenPickColors = numVerts * 4;\r\n for (let i = pickColorsBase, len = pickColorsBase + lenPickColors; i < len; i += 4) {\r\n buffer.pickColors.push(pickColor[0]);\r\n buffer.pickColors.push(pickColor[1]);\r\n buffer.pickColors.push(pickColor[2]);\r\n buffer.pickColors.push(pickColor[3]);\r\n }\r\n }\r\n\r\n if (this.model.scene.entityOffsetsEnabled) {\r\n for (let i = 0; i < numVerts; i++) {\r\n buffer.offsets.push(0);\r\n buffer.offsets.push(0);\r\n buffer.offsets.push(0);\r\n }\r\n }\r\n\r\n const portionId = this._portions.length / 2;\r\n\r\n this._portions.push(vertsIndex);\r\n this._portions.push(numVerts);\r\n\r\n this._numPortions++;\r\n this.model.numPortions++;\r\n this._meshes.push(mesh);\r\n return portionId;\r\n }\r\n\r\n /**\r\n * Builds batch VBOs from appended geometries.\r\n * No more portions can then be created.\r\n */\r\n finalize() {\r\n\r\n if (this._finalized) {\r\n return;\r\n }\r\n\r\n const state = this._state;\r\n const gl = this.model.scene.canvas.gl;\r\n const buffer = this._buffer;\r\n\r\n if (buffer.positions.length > 0) {\r\n if (this._preCompressedPositionsExpected) {\r\n const positions = new Uint16Array(buffer.positions);\r\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, positions, buffer.positions.length, 3, gl.STATIC_DRAW);\r\n } else {\r\n const positions = new Float32Array(buffer.positions);\r\n const quantizedPositions = (0,_compression_js__WEBPACK_IMPORTED_MODULE_7__.quantizePositions)(positions, this._modelAABB, state.positionsDecodeMatrix);\r\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, buffer.positions.length, 3, gl.STATIC_DRAW);\r\n }\r\n }\r\n\r\n if (buffer.colors.length > 0) {\r\n const colors = new Uint8Array(buffer.colors);\r\n let normalized = false;\r\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, colors, buffer.colors.length, 4, gl.STATIC_DRAW, normalized);\r\n }\r\n\r\n if (buffer.positions.length > 0) { // Because we build flags arrays here, get their length from the positions array\r\n const flagsLength = buffer.positions.length / 3;\r\n const flags = new Float32Array(flagsLength);\r\n let notNormalized = false;\r\n state.flagsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, flags, flags.length, 1, gl.DYNAMIC_DRAW, notNormalized);\r\n }\r\n\r\n if (buffer.pickColors.length > 0) {\r\n const pickColors = new Uint8Array(buffer.pickColors);\r\n let normalized = false;\r\n state.pickColorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, pickColors, buffer.pickColors.length, 4, gl.STATIC_DRAW, normalized);\r\n }\r\n\r\n if (this.model.scene.entityOffsetsEnabled) {\r\n if (buffer.offsets.length > 0) {\r\n const offsets = new Float32Array(buffer.offsets);\r\n state.offsetsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, offsets, buffer.offsets.length, 3, gl.DYNAMIC_DRAW);\r\n }\r\n }\r\n\r\n this._buffer = null;\r\n this._finalized = true;\r\n }\r\n\r\n initFlags(portionId, flags, meshTransparent) {\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\r\n this._numVisibleLayerPortions++;\r\n this.model.numVisibleLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\r\n this._numHighlightedLayerPortions++;\r\n this.model.numHighlightedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\r\n this._numXRayedLayerPortions++;\r\n this.model.numXRayedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\r\n this._numSelectedLayerPortions++;\r\n this.model.numSelectedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\r\n this._numClippableLayerPortions++;\r\n this.model.numClippableLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\r\n this._numPickableLayerPortions++;\r\n this.model.numPickableLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\r\n this._numCulledLayerPortions++;\r\n this.model.numCulledLayerPortions++;\r\n }\r\n if (meshTransparent) {\r\n this._numTransparentLayerPortions++;\r\n this.model.numTransparentLayerPortions++;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setVisible(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\r\n this._numVisibleLayerPortions++;\r\n this.model.numVisibleLayerPortions++;\r\n } else {\r\n this._numVisibleLayerPortions--;\r\n this.model.numVisibleLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setHighlighted(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\r\n this._numHighlightedLayerPortions++;\r\n this.model.numHighlightedLayerPortions++;\r\n } else {\r\n this._numHighlightedLayerPortions--;\r\n this.model.numHighlightedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setXRayed(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\r\n this._numXRayedLayerPortions++;\r\n this.model.numXRayedLayerPortions++;\r\n } else {\r\n this._numXRayedLayerPortions--;\r\n this.model.numXRayedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setSelected(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\r\n this._numSelectedLayerPortions++;\r\n this.model.numSelectedLayerPortions++;\r\n } else {\r\n this._numSelectedLayerPortions--;\r\n this.model.numSelectedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setEdges(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n // Not applicable to point clouds\r\n }\r\n\r\n setClippable(portionId, flags) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\r\n this._numClippableLayerPortions++;\r\n this.model.numClippableLayerPortions++;\r\n } else {\r\n this._numClippableLayerPortions--;\r\n this.model.numClippableLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags);\r\n }\r\n\r\n setCulled(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\r\n this._numCulledLayerPortions++;\r\n this.model.numCulledLayerPortions++;\r\n } else {\r\n this._numCulledLayerPortions--;\r\n this.model.numCulledLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setCollidable(portionId, flags) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n }\r\n\r\n setPickable(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\r\n this._numPickableLayerPortions++;\r\n this.model.numPickableLayerPortions++;\r\n } else {\r\n this._numPickableLayerPortions--;\r\n this.model.numPickableLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setColor(portionId, color) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n const portionsIdx = portionId * 2;\r\n const vertexBase = this._portions[portionsIdx];\r\n const numVerts = this._portions[portionsIdx + 1];\r\n const firstColor = vertexBase * 4;\r\n const lenColor = numVerts * 4;\r\n const tempArray = this._scratchMemory.getUInt8Array(lenColor);\r\n const r = color[0];\r\n const g = color[1];\r\n const b = color[2];\r\n for (let i = 0; i < lenColor; i += 4) {\r\n tempArray[i + 0] = r;\r\n tempArray[i + 1] = g;\r\n tempArray[i + 2] = b;\r\n }\r\n this._state.colorsBuf.setData(tempArray, firstColor, lenColor);\r\n }\r\n\r\n setTransparent(portionId, flags, transparent) {\r\n if (transparent) {\r\n this._numTransparentLayerPortions++;\r\n this.model.numTransparentLayerPortions++;\r\n } else {\r\n this._numTransparentLayerPortions--;\r\n this.model.numTransparentLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n /**\r\n * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.\r\n */\r\n _setFlags(portionId, flags, transparent) {\r\n\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n\r\n const portionsIdx = portionId * 2;\r\n const vertexBase = this._portions[portionsIdx];\r\n const numVerts = this._portions[portionsIdx + 1];\r\n const firstFlag = vertexBase;\r\n const lenFlags = numVerts;\r\n const tempArray = this._scratchMemory.getFloat32Array(lenFlags);\r\n\r\n const visible = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE);\r\n const xrayed = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED);\r\n const highlighted = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED);\r\n const selected = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED);\r\n const pickable = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE);\r\n const culled = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED);\r\n\r\n let colorFlag;\r\n if (!visible || culled || xrayed\r\n || (highlighted && !this.model.scene.highlightMaterial.glowThrough)\r\n || (selected && !this.model.scene.selectedMaterial.glowThrough)) {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else {\r\n if (transparent) {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT;\r\n } else {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE;\r\n }\r\n }\r\n\r\n let silhouetteFlag;\r\n if (!visible || culled) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else if (selected) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED;\r\n } else if (highlighted) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;\r\n } else if (xrayed) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED;\r\n } else {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n }\r\n\r\n let pickFlag = (visible && !culled && pickable) ? _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK : _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n\r\n const clippableFlag = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;\r\n\r\n for (let i = 0; i < lenFlags; i++) {\r\n let vertFlag = 0;\r\n vertFlag |= colorFlag;\r\n vertFlag |= silhouetteFlag << 4;\r\n // no edges\r\n vertFlag |= pickFlag << 12;\r\n vertFlag |= clippableFlag << 16;\r\n\r\n tempArray[i] = vertFlag;\r\n }\r\n\r\n this._state.flagsBuf.setData(tempArray, firstFlag);\r\n }\r\n\r\n setOffset(portionId, offset) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (!this.model.scene.entityOffsetsEnabled) {\r\n this.model.error(\"Entity#offset not enabled for this Viewer\"); // See Viewer entityOffsetsEnabled\r\n return;\r\n }\r\n const portionsIdx = portionId * 2;\r\n const vertexBase = this._portions[portionsIdx];\r\n const numVerts = this._portions[portionsIdx + 1];\r\n const firstOffset = vertexBase * 3;\r\n const lenOffsets = numVerts * 3;\r\n const tempArray = this._scratchMemory.getFloat32Array(lenOffsets);\r\n const x = offset[0];\r\n const y = offset[1];\r\n const z = offset[2];\r\n for (let i = 0; i < lenOffsets; i += 3) {\r\n tempArray[i + 0] = x;\r\n tempArray[i + 1] = y;\r\n tempArray[i + 2] = z;\r\n }\r\n this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);\r\n }\r\n\r\n //-- NORMAL RENDERING ----------------------------------------------------------------------------------------------\r\n\r\n drawColorOpaque(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n if (this._renderers.colorRenderer) {\r\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n drawColorTransparent(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n if (this._renderers.colorRenderer) {\r\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n }\r\n\r\n // -- RENDERING SAO POST EFFECT TARGETS ----------------------------------------------------------------------------\r\n\r\n drawDepth(renderFlags, frameCtx) {\r\n }\r\n\r\n drawNormals(renderFlags, frameCtx) {\r\n }\r\n\r\n // -- EMPHASIS RENDERING -------------------------------------------------------------------------------------------\r\n\r\n drawSilhouetteXRayed(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED);\r\n }\r\n }\r\n\r\n drawSilhouetteHighlighted(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);\r\n }\r\n }\r\n\r\n drawSilhouetteSelected(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED);\r\n }\r\n }\r\n\r\n //-- EDGES RENDERING -----------------------------------------------------------------------------------------------\r\n\r\n drawEdgesColorOpaque(renderFlags, frameCtx) {\r\n }\r\n\r\n drawEdgesColorTransparent(renderFlags, frameCtx) {\r\n }\r\n\r\n drawEdgesHighlighted(renderFlags, frameCtx) {\r\n }\r\n\r\n drawEdgesSelected(renderFlags, frameCtx) {\r\n }\r\n\r\n drawEdgesXRayed(renderFlags, frameCtx) {\r\n }\r\n\r\n //---- PICKING ----------------------------------------------------------------------------------------------------\r\n\r\n drawPickMesh(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.pickMeshRenderer) {\r\n this._renderers.pickMeshRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawPickDepths(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.pickDepthRenderer) {\r\n this._renderers.pickDepthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawPickNormals(renderFlags, frameCtx) {\r\n }\r\n\r\n drawSnapInit(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.snapInitRenderer) {\r\n this._renderers.snapInitRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawSnap(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.snapRenderer) {\r\n this._renderers.snapRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n //---- OCCLUSION TESTING -------------------------------------------------------------------------------------------\r\n\r\n drawOcclusion(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.occlusionRenderer) {\r\n this._renderers.occlusionRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n //---- SHADOWS -----------------------------------------------------------------------------------------------------\r\n\r\n drawShadow(renderFlags, frameCtx) {\r\n }\r\n\r\n destroy() {\r\n const state = this._state;\r\n if (state.positionsBuf) {\r\n state.positionsBuf.destroy();\r\n state.positionsBuf = null;\r\n }\r\n if (state.offsetsBuf) {\r\n state.offsetsBuf.destroy();\r\n state.offsetsBuf = null;\r\n }\r\n if (state.colorsBuf) {\r\n state.colorsBuf.destroy();\r\n state.colorsBuf = null;\r\n }\r\n if (state.flagsBuf) {\r\n state.flagsBuf.destroy();\r\n state.flagsBuf = null;\r\n }\r\n if (state.pickColorsBuf) {\r\n state.pickColorsBuf.destroy();\r\n state.pickColorsBuf = null;\r\n }\r\n state.destroy();\r\n }\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js?");
|
|
4017
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBOBatchingPointsLayer: () => (/* binding */ VBOBatchingPointsLayer)\n/* harmony export */ });\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.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 _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../webgl/RenderState.js */ \"./src/viewer/scene/webgl/RenderState.js\");\n/* harmony import */ var _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../webgl/ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _renderers_VBOBatchingPointsRenderers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./renderers/VBOBatchingPointsRenderers.js */ \"./src/viewer/scene/model/vbo/batching/points/renderers/VBOBatchingPointsRenderers.js\");\n/* harmony import */ var _VBOBatchingPointsBuffer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./VBOBatchingPointsBuffer.js */ \"./src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsBuffer.js\");\n/* harmony import */ var _compression_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../compression.js */ \"./src/viewer/scene/model/compression.js\");\n\n\n\n\n\n\n\n\n\n\n/**\n * @private\n */\nclass VBOBatchingPointsLayer {\n\n /**\n * @param model\n * @param cfg\n * @param cfg.layerIndex\n * @param cfg.positionsDecodeMatrix\n * @param cfg.maxGeometryBatchSize\n * @param cfg.origin\n * @param cfg.scratchMemory\n */\n constructor(cfg) {\n\n console.info(\"Creating VBOBatchingPointsLayer\");\n\n /**\n * Owner model\n * @type {VBOSceneModel}\n */\n this.model = cfg.model;\n\n /**\n * State sorting key.\n * @type {string}\n */\n this.sortId = \"PointsBatchingLayer\";\n\n /**\n * Index of this PointsBatchingLayer in {@link VBOSceneModel#_layerList}.\n * @type {Number}\n */\n this.layerIndex = cfg.layerIndex;\n\n this._renderers = (0,_renderers_VBOBatchingPointsRenderers_js__WEBPACK_IMPORTED_MODULE_5__.getRenderers)(cfg.model.scene);\n\n this._buffer = new _VBOBatchingPointsBuffer_js__WEBPACK_IMPORTED_MODULE_6__.VBOBatchingPointsBuffer(cfg.maxGeometryBatchSize);\n this._scratchMemory = cfg.scratchMemory;\n\n this._state = new _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__.RenderState({\n positionsBuf: null,\n offsetsBuf: null,\n colorsBuf: null,\n flagsBuf: null,\n positionsDecodeMatrix: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4(),\n origin: null\n });\n\n // These counts are used to avoid unnecessary render passes\n this._numPortions = 0;\n this._numVisibleLayerPortions = 0;\n this._numTransparentLayerPortions = 0;\n this._numXRayedLayerPortions = 0;\n this._numSelectedLayerPortions = 0;\n this._numHighlightedLayerPortions = 0;\n this._numClippableLayerPortions = 0;\n this._numPickableLayerPortions = 0;\n this._numCulledLayerPortions = 0;\n\n this._modelAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(); // Model-space AABB\n this._portions = [];\n this._meshes = [];\n\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\n this.aabbDirty = true;\n\n this._finalized = false;\n\n if (cfg.positionsDecodeMatrix) {\n this._state.positionsDecodeMatrix.set(cfg.positionsDecodeMatrix);\n this._preCompressedPositionsExpected = true;\n } else {\n this._preCompressedPositionsExpected = false;\n }\n\n if (cfg.origin) {\n this._state.origin = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3(cfg.origin);\n }\n }\n\n get aabb() {\n if (this.aabbDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(this._aabb);\n for (let i = 0, len = this._meshes.length; i < len; i++) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._aabb, this._meshes[i].aabb);\n }\n this.aabbDirty = false;\n }\n return this._aabb;\n }\n\n /**\n * Tests if there is room for another portion in this PointsBatchingLayer.\n *\n * @param lenPositions Number of positions we'd like to create in the portion.\n * @returns {Boolean} True if OK to create another portion.\n */\n canCreatePortion(lenPositions) {\n if (this._finalized) {\n throw \"Already finalized\";\n }\n return ((this._buffer.positions.length + lenPositions) < (this._buffer.maxVerts * 3));\n }\n\n /**\n * Creates a new portion within this PointsBatchingLayer, returns the new portion ID.\n *\n * Gives the portion the specified geometry, color and matrix.\n *\n * @param mesh The SceneModelMesh that owns the portion\n * @param cfg.positions Flat float Local-space positions array.\n * @param cfg.positionsCompressed Flat quantized positions array - decompressed with PointsBatchingLayer positionsDecodeMatrix\n * @param [cfg.colorsCompressed] Quantized RGB colors [0..255,0..255,0..255,0..255]\n * @param [cfg.colors] Flat float colors array.\n * @param cfg.color Float RGB color [0..1,0..1,0..1]\n * @param [cfg.meshMatrix] Flat float 4x4 matrix\n * @param cfg.aabb Flat float AABB World-space AABB\n * @param cfg.pickColor Quantized pick color\n * @returns {number} Portion ID\n */\n createPortion(mesh, cfg) {\n\n if (this._finalized) {\n throw \"Already finalized\";\n }\n\n const positions = cfg.positions;\n const positionsCompressed = cfg.positionsCompressed;\n const color = cfg.color;\n const colorsCompressed = cfg.colorsCompressed;\n const colors = cfg.colors;\n const pickColor = cfg.pickColor;\n\n const buffer = this._buffer;\n const positionsIndex = buffer.positions.length;\n const vertsIndex = positionsIndex / 3;\n\n let numVerts;\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._modelAABB, cfg.aabb);\n\n if (this._preCompressedPositionsExpected) {\n\n if (!positionsCompressed) {\n throw \"positionsCompressed expected\";\n }\n\n for (let i = 0, len = positionsCompressed.length; i < len; i++) {\n buffer.positions.push(positionsCompressed[i]);\n }\n\n numVerts = positionsCompressed.length / 3;\n\n } else {\n\n if (!positions) {\n throw \"positions expected\";\n }\n\n numVerts = positions.length / 3;\n\n const lenPositions = positions.length;\n const positionsBase = buffer.positions.length;\n\n for (let i = 0, len = positions.length; i < len; i++) {\n buffer.positions.push(positions[i]);\n }\n }\n\n if (colorsCompressed) {\n for (let i = 0, len = colorsCompressed.length; i < len; i++) {\n buffer.colors.push(colorsCompressed[i]);\n }\n\n } else if (colors) {\n for (let i = 0, len = colors.length; i < len; i++) {\n buffer.colors.push(colors[i] * 255);\n }\n\n } else if (color) {\n\n const r = color[0]; // Color is pre-quantized by VBOSceneModel\n const g = color[1];\n const b = color[2];\n const a = 1.0;\n\n for (let i = 0; i < numVerts; i++) {\n buffer.colors.push(r);\n buffer.colors.push(g);\n buffer.colors.push(b);\n buffer.colors.push(a);\n }\n }\n\n {\n const pickColorsBase = buffer.pickColors.length;\n const lenPickColors = numVerts * 4;\n for (let i = pickColorsBase, len = pickColorsBase + lenPickColors; i < len; i += 4) {\n buffer.pickColors.push(pickColor[0]);\n buffer.pickColors.push(pickColor[1]);\n buffer.pickColors.push(pickColor[2]);\n buffer.pickColors.push(pickColor[3]);\n }\n }\n\n if (this.model.scene.entityOffsetsEnabled) {\n for (let i = 0; i < numVerts; i++) {\n buffer.offsets.push(0);\n buffer.offsets.push(0);\n buffer.offsets.push(0);\n }\n }\n\n const portionId = this._portions.length / 2;\n\n this._portions.push(vertsIndex);\n this._portions.push(numVerts);\n\n this._numPortions++;\n this.model.numPortions++;\n this._meshes.push(mesh);\n return portionId;\n }\n\n /**\n * Builds batch VBOs from appended geometries.\n * No more portions can then be created.\n */\n finalize() {\n\n if (this._finalized) {\n return;\n }\n\n const state = this._state;\n const gl = this.model.scene.canvas.gl;\n const buffer = this._buffer;\n\n if (buffer.positions.length > 0) {\n if (this._preCompressedPositionsExpected) {\n const positions = new Uint16Array(buffer.positions);\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, positions, buffer.positions.length, 3, gl.STATIC_DRAW);\n } else {\n const positions = new Float32Array(buffer.positions);\n const quantizedPositions = (0,_compression_js__WEBPACK_IMPORTED_MODULE_7__.quantizePositions)(positions, this._modelAABB, state.positionsDecodeMatrix);\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, buffer.positions.length, 3, gl.STATIC_DRAW);\n }\n }\n\n if (buffer.colors.length > 0) {\n const colors = new Uint8Array(buffer.colors);\n let normalized = false;\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, colors, buffer.colors.length, 4, gl.STATIC_DRAW, normalized);\n }\n\n if (buffer.positions.length > 0) { // Because we build flags arrays here, get their length from the positions array\n const flagsLength = buffer.positions.length / 3;\n const flags = new Float32Array(flagsLength);\n let notNormalized = false;\n state.flagsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, flags, flags.length, 1, gl.DYNAMIC_DRAW, notNormalized);\n }\n\n if (buffer.pickColors.length > 0) {\n const pickColors = new Uint8Array(buffer.pickColors);\n let normalized = false;\n state.pickColorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, pickColors, buffer.pickColors.length, 4, gl.STATIC_DRAW, normalized);\n }\n\n if (this.model.scene.entityOffsetsEnabled) {\n if (buffer.offsets.length > 0) {\n const offsets = new Float32Array(buffer.offsets);\n state.offsetsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, offsets, buffer.offsets.length, 3, gl.DYNAMIC_DRAW);\n }\n }\n\n this._buffer = null;\n this._finalized = true;\n }\n\n initFlags(portionId, flags, meshTransparent) {\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\n this._numVisibleLayerPortions++;\n this.model.numVisibleLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\n this._numHighlightedLayerPortions++;\n this.model.numHighlightedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\n this._numXRayedLayerPortions++;\n this.model.numXRayedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\n this._numSelectedLayerPortions++;\n this.model.numSelectedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\n this._numClippableLayerPortions++;\n this.model.numClippableLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\n this._numPickableLayerPortions++;\n this.model.numPickableLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\n this._numCulledLayerPortions++;\n this.model.numCulledLayerPortions++;\n }\n if (meshTransparent) {\n this._numTransparentLayerPortions++;\n this.model.numTransparentLayerPortions++;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setVisible(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\n this._numVisibleLayerPortions++;\n this.model.numVisibleLayerPortions++;\n } else {\n this._numVisibleLayerPortions--;\n this.model.numVisibleLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setHighlighted(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\n this._numHighlightedLayerPortions++;\n this.model.numHighlightedLayerPortions++;\n } else {\n this._numHighlightedLayerPortions--;\n this.model.numHighlightedLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setXRayed(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\n this._numXRayedLayerPortions++;\n this.model.numXRayedLayerPortions++;\n } else {\n this._numXRayedLayerPortions--;\n this.model.numXRayedLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setSelected(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\n this._numSelectedLayerPortions++;\n this.model.numSelectedLayerPortions++;\n } else {\n this._numSelectedLayerPortions--;\n this.model.numSelectedLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setEdges(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n // Not applicable to point clouds\n }\n\n setClippable(portionId, flags) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\n this._numClippableLayerPortions++;\n this.model.numClippableLayerPortions++;\n } else {\n this._numClippableLayerPortions--;\n this.model.numClippableLayerPortions--;\n }\n this._setFlags(portionId, flags);\n }\n\n setCulled(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\n this._numCulledLayerPortions++;\n this.model.numCulledLayerPortions++;\n } else {\n this._numCulledLayerPortions--;\n this.model.numCulledLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setCollidable(portionId, flags) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n }\n\n setPickable(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\n this._numPickableLayerPortions++;\n this.model.numPickableLayerPortions++;\n } else {\n this._numPickableLayerPortions--;\n this.model.numPickableLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setColor(portionId, color) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n const portionsIdx = portionId * 2;\n const vertexBase = this._portions[portionsIdx];\n const numVerts = this._portions[portionsIdx + 1];\n const firstColor = vertexBase * 4;\n const lenColor = numVerts * 4;\n const tempArray = this._scratchMemory.getUInt8Array(lenColor);\n const r = color[0];\n const g = color[1];\n const b = color[2];\n for (let i = 0; i < lenColor; i += 4) {\n tempArray[i + 0] = r;\n tempArray[i + 1] = g;\n tempArray[i + 2] = b;\n }\n this._state.colorsBuf.setData(tempArray, firstColor, lenColor);\n }\n\n setTransparent(portionId, flags, transparent) {\n if (transparent) {\n this._numTransparentLayerPortions++;\n this.model.numTransparentLayerPortions++;\n } else {\n this._numTransparentLayerPortions--;\n this.model.numTransparentLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n /**\n * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.\n */\n _setFlags(portionId, flags, transparent) {\n\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n\n const portionsIdx = portionId * 2;\n const vertexBase = this._portions[portionsIdx];\n const numVerts = this._portions[portionsIdx + 1];\n const firstFlag = vertexBase;\n const lenFlags = numVerts;\n const tempArray = this._scratchMemory.getFloat32Array(lenFlags);\n\n const visible = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE);\n const xrayed = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED);\n const highlighted = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED);\n const selected = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED);\n const pickable = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE);\n const culled = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED);\n\n let colorFlag;\n if (!visible || culled || xrayed\n || (highlighted && !this.model.scene.highlightMaterial.glowThrough)\n || (selected && !this.model.scene.selectedMaterial.glowThrough)) {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else {\n if (transparent) {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT;\n } else {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE;\n }\n }\n\n let silhouetteFlag;\n if (!visible || culled) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else if (selected) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED;\n } else if (highlighted) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;\n } else if (xrayed) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED;\n } else {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n }\n\n let pickFlag = (visible && !culled && pickable) ? _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK : _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n\n const clippableFlag = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;\n\n for (let i = 0; i < lenFlags; i++) {\n let vertFlag = 0;\n vertFlag |= colorFlag;\n vertFlag |= silhouetteFlag << 4;\n // no edges\n vertFlag |= pickFlag << 12;\n vertFlag |= clippableFlag << 16;\n\n tempArray[i] = vertFlag;\n }\n\n this._state.flagsBuf.setData(tempArray, firstFlag);\n }\n\n setOffset(portionId, offset) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (!this.model.scene.entityOffsetsEnabled) {\n this.model.error(\"Entity#offset not enabled for this Viewer\"); // See Viewer entityOffsetsEnabled\n return;\n }\n const portionsIdx = portionId * 2;\n const vertexBase = this._portions[portionsIdx];\n const numVerts = this._portions[portionsIdx + 1];\n const firstOffset = vertexBase * 3;\n const lenOffsets = numVerts * 3;\n const tempArray = this._scratchMemory.getFloat32Array(lenOffsets);\n const x = offset[0];\n const y = offset[1];\n const z = offset[2];\n for (let i = 0; i < lenOffsets; i += 3) {\n tempArray[i + 0] = x;\n tempArray[i + 1] = y;\n tempArray[i + 2] = z;\n }\n this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);\n }\n\n //-- NORMAL RENDERING ----------------------------------------------------------------------------------------------\n\n drawColorOpaque(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n if (this._renderers.colorRenderer) {\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n\n drawColorTransparent(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n if (this._renderers.colorRenderer) {\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n }\n\n // -- RENDERING SAO POST EFFECT TARGETS ----------------------------------------------------------------------------\n\n drawDepth(renderFlags, frameCtx) {\n }\n\n drawNormals(renderFlags, frameCtx) {\n }\n\n // -- EMPHASIS RENDERING -------------------------------------------------------------------------------------------\n\n drawSilhouetteXRayed(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\n return;\n }\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED);\n }\n }\n\n drawSilhouetteHighlighted(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\n return;\n }\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);\n }\n }\n\n drawSilhouetteSelected(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\n return;\n }\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED);\n }\n }\n\n //-- EDGES RENDERING -----------------------------------------------------------------------------------------------\n\n drawEdgesColorOpaque(renderFlags, frameCtx) {\n }\n\n drawEdgesColorTransparent(renderFlags, frameCtx) {\n }\n\n drawEdgesHighlighted(renderFlags, frameCtx) {\n }\n\n drawEdgesSelected(renderFlags, frameCtx) {\n }\n\n drawEdgesXRayed(renderFlags, frameCtx) {\n }\n\n //---- PICKING ----------------------------------------------------------------------------------------------------\n\n drawPickMesh(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n if (this._renderers.pickMeshRenderer) {\n this._renderers.pickMeshRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawPickDepths(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n if (this._renderers.pickDepthRenderer) {\n this._renderers.pickDepthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawPickNormals(renderFlags, frameCtx) {\n }\n\n drawSnapInit(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n if (this._renderers.snapInitRenderer) {\n this._renderers.snapInitRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawSnap(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n if (this._renderers.snapRenderer) {\n this._renderers.snapRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n //---- OCCLUSION TESTING -------------------------------------------------------------------------------------------\n\n drawOcclusion(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n if (this._renderers.occlusionRenderer) {\n this._renderers.occlusionRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n\n //---- SHADOWS -----------------------------------------------------------------------------------------------------\n\n drawShadow(renderFlags, frameCtx) {\n }\n\n destroy() {\n const state = this._state;\n if (state.positionsBuf) {\n state.positionsBuf.destroy();\n state.positionsBuf = null;\n }\n if (state.offsetsBuf) {\n state.offsetsBuf.destroy();\n state.offsetsBuf = null;\n }\n if (state.colorsBuf) {\n state.colorsBuf.destroy();\n state.colorsBuf = null;\n }\n if (state.flagsBuf) {\n state.flagsBuf.destroy();\n state.flagsBuf = null;\n }\n if (state.pickColorsBuf) {\n state.pickColorsBuf.destroy();\n state.pickColorsBuf = null;\n }\n state.destroy();\n }\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js?");
|
|
4018
4018
|
|
|
4019
4019
|
/***/ }),
|
|
4020
4020
|
|
|
@@ -4124,7 +4124,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4124
4124
|
\************************************************************************************/
|
|
4125
4125
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4126
4126
|
|
|
4127
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBOBatchingTrianglesLayer: () => (/* binding */ VBOBatchingTrianglesLayer)\n/* harmony export */ });\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.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 _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../webgl/RenderState.js */ \"./src/viewer/scene/webgl/RenderState.js\");\n/* harmony import */ var _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../webgl/ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../../math/geometryCompressionUtils.js */ \"./src/viewer/scene/math/geometryCompressionUtils.js\");\n/* harmony import */ var _renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./renderers/Renderers.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js\");\n/* harmony import */ var _VBOBatchingTrianglesBuffer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./VBOBatchingTrianglesBuffer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js\");\n/* harmony import */ var _compression_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../compression.js */ \"./src/viewer/scene/model/compression.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst tempMat4 = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\r\nconst tempMat4b = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\r\nconst tempVec4a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec4([0, 0, 0, 1]);\r\n\r\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3b = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3d = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3e = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3f = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3g = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\n\r\n/**\r\n * @private\r\n */\r\nclass VBOBatchingTrianglesLayer {\r\n\r\n /**\r\n * @param model\r\n * @param cfg.model\r\n * @param cfg.autoNormals\r\n * @param cfg.layerIndex\r\n * @param cfg.positionsDecodeMatrix\r\n * @param cfg.uvDecodeMatrix\r\n * @param cfg.maxGeometryBatchSize\r\n * @param cfg.origin\r\n * @param cfg.scratchMemory\r\n * @param cfg.textureSet\r\n * @param cfg.solid\r\n */\r\n constructor(cfg) {\r\n\r\n console.info(\"Creating VBOBatchingTrianglesLayer\");\r\n\r\n /**\r\n * Owner model\r\n * @type {VBOSceneModel}\r\n */\r\n this.model = cfg.model;\r\n\r\n /**\r\n * State sorting key.\r\n * @type {string}\r\n */\r\n this.sortId = \"TrianglesBatchingLayer\"\r\n + (cfg.solid ? \"-solid\" : \"-surface\")\r\n + (cfg.autoNormals ? \"-autonormals\" : \"-normals\")\r\n\r\n // TODO: These two parts need to be IDs (ie. unique):\r\n\r\n + (cfg.textureSet && cfg.textureSet.colorTexture ? \"-colorTexture\" : \"\")\r\n + (cfg.textureSet && cfg.textureSet.metallicRoughnessTexture ? \"-metallicRoughnessTexture\" : \"\");\r\n\r\n /**\r\n * Index of this TrianglesBatchingLayer in {@link VBOSceneModel#_layerList}.\r\n * @type {Number}\r\n */\r\n this.layerIndex = cfg.layerIndex;\r\n\r\n this._renderers = (0,_renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_6__.getRenderers)(cfg.model.scene);\r\n this._buffer = new _VBOBatchingTrianglesBuffer_js__WEBPACK_IMPORTED_MODULE_7__.VBOBatchingTrianglesBuffer(cfg.maxGeometryBatchSize);\r\n this._scratchMemory = cfg.scratchMemory;\r\n\r\n this._state = new _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__.RenderState({\r\n origin: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3(),\r\n positionsBuf: null,\r\n offsetsBuf: null,\r\n normalsBuf: null,\r\n colorsBuf: null,\r\n uvBuf: null,\r\n metallicRoughnessBuf: null,\r\n flagsBuf: null,\r\n indicesBuf: null,\r\n edgeIndicesBuf: null,\r\n positionsDecodeMatrix: null,\r\n uvDecodeMatrix: null,\r\n textureSet: cfg.textureSet,\r\n pbrSupported: false // Set in #finalize if we have enough to support quality rendering\r\n });\r\n\r\n // These counts are used to avoid unnecessary render passes\r\n this._numPortions = 0;\r\n this._numVisibleLayerPortions = 0;\r\n this._numTransparentLayerPortions = 0;\r\n this._numXRayedLayerPortions = 0;\r\n this._numSelectedLayerPortions = 0;\r\n this._numHighlightedLayerPortions = 0;\r\n this._numClippableLayerPortions = 0;\r\n this._numEdgesLayerPortions = 0;\r\n this._numPickableLayerPortions = 0;\r\n this._numCulledLayerPortions = 0;\r\n\r\n this._modelAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(); // Model-space AABB\r\n this._portions = [];\r\n this._meshes = [];\r\n this._numVerts = 0;\r\n\r\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\r\n this.aabbDirty = true;\r\n\r\n this._finalized = false;\r\n\r\n if (cfg.positionsDecodeMatrix) {\r\n this._state.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4(cfg.positionsDecodeMatrix);\r\n }\r\n\r\n if (cfg.uvDecodeMatrix) {\r\n this._state.uvDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat3(cfg.uvDecodeMatrix);\r\n this._preCompressedUVsExpected = true;\r\n } else {\r\n this._preCompressedUVsExpected = false;\r\n }\r\n\r\n if (cfg.origin) {\r\n this._state.origin.set(cfg.origin);\r\n }\r\n\r\n /**\r\n * When true, this layer contains solid triangle meshes, otherwise this layer contains surface triangle meshes\r\n * @type {boolean}\r\n */\r\n this.solid = !!cfg.solid;\r\n }\r\n\r\n get aabb() {\r\n if (this.aabbDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(this._aabb);\r\n for (let i = 0, len = this._meshes.length; i < len; i++) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._aabb, this._meshes[i].aabb);\r\n }\r\n this.aabbDirty = false;\r\n }\r\n return this._aabb;\r\n }\r\n\r\n /**\r\n * Tests if there is room for another portion in this TrianglesBatchingLayer.\r\n *\r\n * @param lenPositions Number of positions we'd like to create in the portion.\r\n * @param lenIndices Number of indices we'd like to create in this portion.\r\n * @returns {Boolean} True if OK to create another portion.\r\n */\r\n canCreatePortion(lenPositions, lenIndices) {\r\n if (this._finalized) {\r\n throw \"Already finalized\";\r\n }\r\n return ((this._buffer.positions.length + lenPositions) < (this._buffer.maxVerts * 3) && (this._buffer.indices.length + lenIndices) < (this._buffer.maxIndices));\r\n }\r\n\r\n /**\r\n * Creates a new portion within this TrianglesBatchingLayer, returns the new portion ID.\r\n *\r\n * Gives the portion the specified geometry, color and matrix.\r\n *\r\n * @param mesh The SceneModelMesh that owns the portion\r\n * @param cfg.positions Flat float Local-space positions array.\r\n * @param cfg.positionsCompressed Flat quantized positions array - decompressed with TrianglesBatchingLayer positionsDecodeMatrix\r\n * @param [cfg.normals] Flat float normals array.\r\n * @param [cfg.uv] Flat UVs array.\r\n * @param [cfg.uvCompressed]\r\n * @param [cfg.colors] Flat float colors array.\r\n * @param [cfg.colorsCompressed]\r\n * @param cfg.indices Flat int indices array.\r\n * @param [cfg.edgeIndices] Flat int edges indices array.\r\n * @param cfg.color Quantized RGB color [0..255,0..255,0..255,0..255]\r\n * @param cfg.metallic Metalness factor [0..255]\r\n * @param cfg.roughness Roughness factor [0..255]\r\n * @param cfg.opacity Opacity [0..255]\r\n * @param [cfg.meshMatrix] Flat float 4x4 matrix\r\n * @param cfg.aabb Flat float AABB World-space AABB\r\n * @param cfg.pickColor Quantized pick color\r\n * @returns {number} Portion ID\r\n */\r\n createPortion(mesh, cfg) {\r\n\r\n if (this._finalized) {\r\n throw \"Already finalized\";\r\n }\r\n\r\n const positions = cfg.positions;\r\n const positionsCompressed = cfg.positionsCompressed;\r\n const normals = cfg.normals;\r\n const normalsCompressed = cfg.normalsCompressed;\r\n const uv = cfg.uv;\r\n const uvCompressed = cfg.uvCompressed;\r\n const colors = cfg.colors;\r\n const colorsCompressed = cfg.colorsCompressed;\r\n const indices = cfg.indices;\r\n const edgeIndices = cfg.edgeIndices;\r\n const color = cfg.color;\r\n const metallic = cfg.metallic;\r\n const roughness = cfg.roughness;\r\n const opacity = cfg.opacity;\r\n const meshMatrix = cfg.meshMatrix;\r\n const pickColor = cfg.pickColor;\r\n\r\n const scene = this.model.scene;\r\n const buffer = this._buffer;\r\n const vertsBaseIndex = buffer.positions.length / 3;\r\n\r\n let numVerts;\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._modelAABB, cfg.aabb);\r\n\r\n if (this._state.positionsDecodeMatrix) {\r\n if (!positionsCompressed) {\r\n throw \"positionsCompressed expected\";\r\n }\r\n numVerts = positionsCompressed.length / 3;\r\n for (let i = 0, len = positionsCompressed.length; i < len; i++) {\r\n buffer.positions.push(positionsCompressed[i]);\r\n }\r\n } else {\r\n if (!positions) {\r\n throw \"positions expected\";\r\n }\r\n numVerts = positions.length / 3;\r\n for (let i = 0, len = positions.length; i < len; i++) {\r\n buffer.positions.push(positions[i]);\r\n }\r\n }\r\n\r\n if (normalsCompressed && normalsCompressed.length > 0) {\r\n for (let i = 0, len = normalsCompressed.length; i < len; i++) {\r\n buffer.normals.push(normalsCompressed[i]);\r\n }\r\n } else if (normals && normals.length > 0) {\r\n const worldNormalMatrix = tempMat4;\r\n if (meshMatrix) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transposeMat4(meshMatrix, tempMat4b), worldNormalMatrix); // Note: order of inverse and transpose doesn't matter\r\n } else {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.identityMat4(worldNormalMatrix, worldNormalMatrix);\r\n }\r\n (0,_compression_js__WEBPACK_IMPORTED_MODULE_8__.transformAndOctEncodeNormals)(worldNormalMatrix, normals, normals.length, buffer.normals, buffer.normals.length);\r\n }\r\n\r\n if (colors) {\r\n for (let i = 0, len = colors.length; i < len; i += 3) {\r\n buffer.colors.push(colors[i] * 255);\r\n buffer.colors.push(colors[i + 1] * 255);\r\n buffer.colors.push(colors[i + 2] * 255);\r\n buffer.colors.push(255);\r\n }\r\n } else if (colorsCompressed) {\r\n for (let i = 0, len = colors.length; i < len; i += 3) {\r\n buffer.colors.push(colors[i]);\r\n buffer.colors.push(colors[i + 1]);\r\n buffer.colors.push(colors[i + 2]);\r\n buffer.colors.push(255);\r\n }\r\n } else if (color) {\r\n const r = color[0]; // Color is pre-quantized by VBOSceneModel\r\n const g = color[1];\r\n const b = color[2];\r\n const a = opacity;\r\n for (let i = 0; i < numVerts; i++) {\r\n buffer.colors.push(r);\r\n buffer.colors.push(g);\r\n buffer.colors.push(b);\r\n buffer.colors.push(a);\r\n }\r\n }\r\n const metallicValue = (metallic !== null && metallic !== undefined) ? metallic : 0;\r\n const roughnessValue = (roughness !== null && roughness !== undefined) ? roughness : 255;\r\n for (let i = 0; i < numVerts; i++) {\r\n buffer.metallicRoughness.push(metallicValue);\r\n buffer.metallicRoughness.push(roughnessValue);\r\n }\r\n\r\n if (uv && uv.length > 0) {\r\n for (let i = 0, len = uv.length; i < len; i++) {\r\n buffer.uv.push(uv[i]);\r\n }\r\n } else if (uvCompressed && uvCompressed.length > 0) {\r\n for (let i = 0, len = uvCompressed.length; i < len; i++) {\r\n buffer.uv.push(uvCompressed[i]);\r\n }\r\n }\r\n\r\n for (let i = 0, len = indices.length; i < len; i++) {\r\n buffer.indices.push(vertsBaseIndex + indices[i]);\r\n }\r\n\r\n\r\n if (edgeIndices) {\r\n for (let i = 0, len = edgeIndices.length; i < len; i++) {\r\n buffer.edgeIndices.push(vertsBaseIndex + edgeIndices[i]);\r\n }\r\n }\r\n\r\n {\r\n const pickColorsBase = buffer.pickColors.length;\r\n const lenPickColors = numVerts * 4;\r\n for (let i = pickColorsBase, len = pickColorsBase + lenPickColors; i < len; i += 4) {\r\n buffer.pickColors.push(pickColor[0]);\r\n buffer.pickColors.push(pickColor[1]);\r\n buffer.pickColors.push(pickColor[2]);\r\n buffer.pickColors.push(pickColor[3]);\r\n }\r\n }\r\n\r\n if (scene.entityOffsetsEnabled) {\r\n for (let i = 0; i < numVerts; i++) {\r\n buffer.offsets.push(0);\r\n buffer.offsets.push(0);\r\n buffer.offsets.push(0);\r\n }\r\n }\r\n\r\n const portionId = this._portions.length;\r\n\r\n const portion = {\r\n vertsBaseIndex: vertsBaseIndex,\r\n numVerts: numVerts,\r\n indicesBaseIndex: buffer.indices.length - indices.length,\r\n numIndices: indices.length,\r\n };\r\n\r\n if (scene.pickSurfacePrecisionEnabled) {\r\n // Quantized in-memory positions are initialized in finalize()\r\n\r\n portion.indices = indices;\r\n\r\n if (scene.entityOffsetsEnabled) {\r\n portion.offset = new Float32Array(3);\r\n }\r\n }\r\n\r\n this._portions.push(portion);\r\n this._numPortions++;\r\n this.model.numPortions++;\r\n this._numVerts += portion.numVerts;\r\n this._meshes.push(mesh);\r\n return portionId;\r\n }\r\n\r\n /**\r\n * Builds batch VBOs from appended geometries.\r\n * No more portions can then be created.\r\n */\r\n finalize() {\r\n\r\n if (this._finalized) {\r\n return;\r\n }\r\n\r\n const state = this._state;\r\n const gl = this.model.scene.canvas.gl;\r\n const buffer = this._buffer;\r\n\r\n if (buffer.positions.length > 0) {\r\n const quantizedPositions = (this._state.positionsDecodeMatrix)\r\n ? new Uint16Array(buffer.positions)\r\n : (0,_compression_js__WEBPACK_IMPORTED_MODULE_8__.quantizePositions)(buffer.positions, this._modelAABB, this._state.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4()); // BOTTLENECK\r\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, quantizedPositions.length, 3, gl.STATIC_DRAW);\r\n if (this.model.scene.pickSurfacePrecisionEnabled) {\r\n for (let i = 0, numPortions = this._portions.length; i < numPortions; i++) {\r\n const portion = this._portions[i];\r\n const start = portion.vertsBaseIndex * 3;\r\n const end = start + (portion.numVerts * 3);\r\n portion.quantizedPositions = quantizedPositions.slice(start, end);\r\n }\r\n }\r\n }\r\n\r\n if (buffer.normals.length > 0) { // Normals are already oct-encoded\r\n const normals = new Int8Array(buffer.normals);\r\n let normalized = true; // For oct encoded UInts\r\n state.normalsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, normals, buffer.normals.length, 3, gl.STATIC_DRAW, normalized);\r\n }\r\n\r\n if (buffer.colors.length > 0) { // Colors are already compressed\r\n const colors = new Uint8Array(buffer.colors);\r\n let normalized = false;\r\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, colors, buffer.colors.length, 4, gl.DYNAMIC_DRAW, normalized);\r\n }\r\n\r\n if (buffer.uv.length > 0) {\r\n if (!state.uvDecodeMatrix) {\r\n const bounds = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_5__.geometryCompressionUtils.getUVBounds(buffer.uv);\r\n const result = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_5__.geometryCompressionUtils.compressUVs(buffer.uv, bounds.min, bounds.max);\r\n const uv = result.quantized;\r\n let notNormalized = false;\r\n state.uvDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat3(result.decodeMatrix);\r\n state.uvBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, uv, uv.length, 2, gl.STATIC_DRAW, notNormalized);\r\n } else {\r\n let notNormalized = false;\r\n state.uvBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, buffer.uv, buffer.uv.length, 2, gl.STATIC_DRAW, notNormalized);\r\n }\r\n }\r\n\r\n if (buffer.metallicRoughness.length > 0) {\r\n const metallicRoughness = new Uint8Array(buffer.metallicRoughness);\r\n let normalized = false;\r\n state.metallicRoughnessBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, metallicRoughness, buffer.metallicRoughness.length, 2, gl.STATIC_DRAW, normalized);\r\n }\r\n\r\n if (buffer.positions.length > 0) { // Because we build flags arrays here, get their length from the positions array\r\n const flagsLength = (buffer.positions.length / 3);\r\n const flags = new Float32Array(flagsLength);\r\n const notNormalized = false;\r\n state.flagsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, flags, flags.length, 1, gl.DYNAMIC_DRAW, notNormalized);\r\n }\r\n\r\n if (buffer.pickColors.length > 0) {\r\n const pickColors = new Uint8Array(buffer.pickColors);\r\n let normalized = false;\r\n state.pickColorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, pickColors, buffer.pickColors.length, 4, gl.STATIC_DRAW, normalized);\r\n }\r\n\r\n if (this.model.scene.entityOffsetsEnabled) {\r\n if (buffer.offsets.length > 0) {\r\n const offsets = new Float32Array(buffer.offsets);\r\n state.offsetsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, offsets, buffer.offsets.length, 3, gl.DYNAMIC_DRAW);\r\n }\r\n }\r\n\r\n if (buffer.indices.length > 0) {\r\n const indices = new Uint32Array(buffer.indices);\r\n state.indicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, buffer.indices.length, 1, gl.STATIC_DRAW);\r\n }\r\n if (buffer.edgeIndices.length > 0) {\r\n const edgeIndices = new Uint32Array(buffer.edgeIndices);\r\n state.edgeIndicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, edgeIndices, buffer.edgeIndices.length, 1, gl.STATIC_DRAW);\r\n }\r\n\r\n this._state.pbrSupported\r\n = !!state.metallicRoughnessBuf\r\n && !!state.uvBuf\r\n && !!state.normalsBuf\r\n && !!state.textureSet\r\n && !!state.textureSet.colorTexture\r\n && !!state.textureSet.metallicRoughnessTexture;\r\n\r\n this._state.colorTextureSupported\r\n = !!state.uvBuf\r\n && !!state.textureSet\r\n && !!state.textureSet.colorTexture;\r\n\r\n this._buffer = null;\r\n this._finalized = true;\r\n }\r\n\r\n isEmpty() {\r\n return (!this._state.indicesBuf);\r\n }\r\n\r\n initFlags(portionId, flags, meshTransparent) {\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\r\n this._numVisibleLayerPortions++;\r\n this.model.numVisibleLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\r\n this._numHighlightedLayerPortions++;\r\n this.model.numHighlightedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\r\n this._numXRayedLayerPortions++;\r\n this.model.numXRayedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\r\n this._numSelectedLayerPortions++;\r\n this.model.numSelectedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\r\n this._numClippableLayerPortions++;\r\n this.model.numClippableLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\r\n this._numEdgesLayerPortions++;\r\n this.model.numEdgesLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\r\n this._numPickableLayerPortions++;\r\n this.model.numPickableLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\r\n this._numCulledLayerPortions++;\r\n this.model.numCulledLayerPortions++;\r\n }\r\n if (meshTransparent) {\r\n this._numTransparentLayerPortions++;\r\n this.model.numTransparentLayerPortions++;\r\n }\r\n const deferred = true;\r\n this._setFlags(portionId, flags, meshTransparent, deferred);\r\n }\r\n\r\n flushInitFlags() {\r\n this._setDeferredFlags();\r\n }\r\n\r\n setVisible(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\r\n this._numVisibleLayerPortions++;\r\n this.model.numVisibleLayerPortions++;\r\n } else {\r\n this._numVisibleLayerPortions--;\r\n this.model.numVisibleLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setHighlighted(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\r\n this._numHighlightedLayerPortions++;\r\n this.model.numHighlightedLayerPortions++;\r\n } else {\r\n this._numHighlightedLayerPortions--;\r\n this.model.numHighlightedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setXRayed(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\r\n this._numXRayedLayerPortions++;\r\n this.model.numXRayedLayerPortions++;\r\n } else {\r\n this._numXRayedLayerPortions--;\r\n this.model.numXRayedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setSelected(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\r\n this._numSelectedLayerPortions++;\r\n this.model.numSelectedLayerPortions++;\r\n } else {\r\n this._numSelectedLayerPortions--;\r\n this.model.numSelectedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setEdges(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\r\n this._numEdgesLayerPortions++;\r\n this.model.numEdgesLayerPortions++;\r\n } else {\r\n this._numEdgesLayerPortions--;\r\n this.model.numEdgesLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setClippable(portionId, flags) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\r\n this._numClippableLayerPortions++;\r\n this.model.numClippableLayerPortions++;\r\n } else {\r\n this._numClippableLayerPortions--;\r\n this.model.numClippableLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags);\r\n }\r\n\r\n setCulled(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\r\n this._numCulledLayerPortions++;\r\n this.model.numCulledLayerPortions++;\r\n } else {\r\n this._numCulledLayerPortions--;\r\n this.model.numCulledLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setCollidable(portionId, flags) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n }\r\n\r\n setPickable(portionId, flags, transparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\r\n this._numPickableLayerPortions++;\r\n this.model.numPickableLayerPortions++;\r\n } else {\r\n this._numPickableLayerPortions--;\r\n this.model.numPickableLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n setColor(portionId, color) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n const portionsIdx = portionId;\r\n const portion = this._portions[portionsIdx];\r\n const vertsBaseIndex = portion.vertsBaseIndex;\r\n const numVerts = portion.numVerts;\r\n const firstColor = vertsBaseIndex * 4;\r\n const lenColor = numVerts * 4;\r\n const tempArray = this._scratchMemory.getUInt8Array(lenColor);\r\n const r = color[0];\r\n const g = color[1];\r\n const b = color[2];\r\n const a = color[3];\r\n for (let i = 0; i < lenColor; i += 4) {\r\n tempArray[i + 0] = r;\r\n tempArray[i + 1] = g;\r\n tempArray[i + 2] = b;\r\n tempArray[i + 3] = a;\r\n }\r\n if (this._state.colorsBuf) {\r\n this._state.colorsBuf.setData(tempArray, firstColor, lenColor);\r\n }\r\n }\r\n\r\n setTransparent(portionId, flags, transparent) {\r\n if (transparent) {\r\n this._numTransparentLayerPortions++;\r\n this.model.numTransparentLayerPortions++;\r\n } else {\r\n this._numTransparentLayerPortions--;\r\n this.model.numTransparentLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n /**\r\n * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.\r\n */\r\n _setFlags(portionId, flags, transparent, deferred = false) {\r\n\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n\r\n const portionsIdx = portionId;\r\n const portion = this._portions[portionsIdx];\r\n const vertsBaseIndex = portion.vertsBaseIndex;\r\n const numVerts = portion.numVerts;\r\n const firstFlag = vertsBaseIndex;\r\n const lenFlags = numVerts;\r\n\r\n const visible = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE);\r\n const xrayed = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED);\r\n const highlighted = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED);\r\n const selected = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED);\r\n const edges = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES);\r\n const pickable = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE);\r\n const culled = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED);\r\n\r\n let colorFlag;\r\n if (!visible || culled || xrayed\r\n || (highlighted && !this.model.scene.highlightMaterial.glowThrough)\r\n || (selected && !this.model.scene.selectedMaterial.glowThrough)) {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else {\r\n if (transparent) {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT;\r\n } else {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE;\r\n }\r\n }\r\n\r\n let silhouetteFlag;\r\n if (!visible || culled) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else if (selected) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED;\r\n } else if (highlighted) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;\r\n } else if (xrayed) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED;\r\n } else {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n }\r\n\r\n let edgeFlag = 0;\r\n if (!visible || culled) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else if (selected) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED;\r\n } else if (highlighted) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED;\r\n } else if (xrayed) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED;\r\n } else if (edges) {\r\n if (transparent) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT;\r\n } else {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE;\r\n }\r\n } else {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n }\r\n\r\n let pickFlag = (visible && !culled && pickable) ? _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK : _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n\r\n const clippableFlag = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;\r\n\r\n if (deferred) {\r\n // Avoid zillions of individual WebGL bufferSubData calls - buffer them to apply in one shot\r\n if (!this._deferredFlagValues) {\r\n this._deferredFlagValues = new Float32Array(this._numVerts);\r\n }\r\n for (let i = firstFlag, len = (firstFlag + lenFlags); i < len; i++) {\r\n let vertFlag = 0;\r\n vertFlag |= colorFlag;\r\n vertFlag |= silhouetteFlag << 4;\r\n vertFlag |= edgeFlag << 8;\r\n vertFlag |= pickFlag << 12;\r\n vertFlag |= clippableFlag << 16;\r\n\r\n this._deferredFlagValues[i] = vertFlag;\r\n }\r\n } else if (this._state.flagsBuf) {\r\n const tempArray = this._scratchMemory.getFloat32Array(lenFlags);\r\n for (let i = 0; i < lenFlags; i++) {\r\n let vertFlag = 0;\r\n vertFlag |= colorFlag;\r\n vertFlag |= silhouetteFlag << 4;\r\n vertFlag |= edgeFlag << 8;\r\n vertFlag |= pickFlag << 12;\r\n vertFlag |= clippableFlag << 16;\r\n\r\n tempArray[i] = vertFlag;\r\n }\r\n this._state.flagsBuf.setData(tempArray, firstFlag, lenFlags);\r\n }\r\n }\r\n\r\n _setDeferredFlags() {\r\n if (this._deferredFlagValues) {\r\n this._state.flagsBuf.setData(this._deferredFlagValues);\r\n this._deferredFlagValues = null;\r\n }\r\n }\r\n\r\n setOffset(portionId, offset) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (!this.model.scene.entityOffsetsEnabled) {\r\n this.model.error(\"Entity#offset not enabled for this Viewer\"); // See Viewer entityOffsetsEnabled\r\n return;\r\n }\r\n const portionsIdx = portionId;\r\n const portion = this._portions[portionsIdx];\r\n const vertsBaseIndex = portion.vertsBaseIndex;\r\n const numVerts = portion.numVerts;\r\n const firstOffset = vertsBaseIndex * 3;\r\n const lenOffsets = numVerts * 3;\r\n const tempArray = this._scratchMemory.getFloat32Array(lenOffsets);\r\n const x = offset[0];\r\n const y = offset[1];\r\n const z = offset[2];\r\n for (let i = 0; i < lenOffsets; i += 3) {\r\n tempArray[i + 0] = x;\r\n tempArray[i + 1] = y;\r\n tempArray[i + 2] = z;\r\n }\r\n if (this._state.offsetsBuf) {\r\n this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);\r\n }\r\n if (this.model.scene.pickSurfacePrecisionEnabled) {\r\n portion.offset[0] = offset[0];\r\n portion.offset[1] = offset[1];\r\n portion.offset[2] = offset[2];\r\n }\r\n }\r\n\r\n getEachVertex(portionId, callback) {\r\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\r\n return;\r\n }\r\n const state = this._state;\r\n const portion = this._portions[portionId];\r\n if (!portion) {\r\n this.model.error(\"portion not found: \" + portionId);\r\n return;\r\n }\r\n const positions = portion.quantizedPositions;\r\n const origin = state.origin;\r\n const offset = portion.offset;\r\n const offsetX = origin[0] + offset[0];\r\n const offsetY = origin[1] + offset[1];\r\n const offsetZ = origin[2] + offset[2];\r\n const worldPos = tempVec4a;\r\n for (let i = 0, len = positions.length; i < len; i += 3) {\r\n worldPos[0] = positions[i];\r\n worldPos[1] = positions[i + 1];\r\n worldPos[2] = positions[i + 2];\r\n worldPos[3] = 1.0;\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(worldPos, state.positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint4(this.model.worldMatrix, worldPos);\r\n worldPos[0] += offsetX;\r\n worldPos[1] += offsetY;\r\n worldPos[2] += offsetZ;\r\n callback(worldPos);\r\n }\r\n }\r\n\r\n getElementsCountAndOffset(portionId) {\r\n let count = null;\r\n let offset = null;\r\n const portion = this._portions[portionId];\r\n\r\n if (portion) {\r\n count = portion.numIndices;\r\n offset = portion.indicesBaseIndex;\r\n }\r\n\r\n return {count, offset}\r\n }\r\n\r\n // ---------------------- COLOR RENDERING -----------------------------------\r\n\r\n drawColorOpaque(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (frameCtx.withSAO && this.model.saoEnabled) {\r\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\r\n if (this._renderers.pbrRendererWithSAO) {\r\n this._renderers.pbrRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\r\n if (this._renderers.colorTextureRendererWithSAO) {\r\n this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (this._state.normalsBuf) {\r\n if (this._renderers.colorRendererWithSAO) {\r\n this._renderers.colorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else {\r\n if (this._renderers.flatColorRendererWithSAO) {\r\n this._renderers.flatColorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n } else {\r\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\r\n if (this._renderers.pbrRenderer) {\r\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\r\n if (this._renderers.colorTextureRenderer) {\r\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (this._state.normalsBuf) {\r\n if (this._renderers.colorRenderer) {\r\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else {\r\n if (this._renderers.flatColorRenderer) {\r\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n }\r\n }\r\n\r\n _updateBackfaceCull(renderFlags, frameCtx) {\r\n const backfaces = this.model.backfaces || (!this.solid) || renderFlags.sectioned;\r\n if (frameCtx.backfaces !== backfaces) {\r\n const gl = frameCtx.gl;\r\n if (backfaces) {\r\n gl.disable(gl.CULL_FACE);\r\n } else {\r\n gl.enable(gl.CULL_FACE);\r\n }\r\n frameCtx.backfaces = backfaces;\r\n }\r\n }\r\n\r\n drawColorTransparent(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\r\n if (this._renderers.pbrRenderer) {\r\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\r\n if (this._renderers.colorTextureRenderer) {\r\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n } else if (this._state.normalsBuf) {\r\n if (this._renderers.colorRenderer) {\r\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n } else {\r\n if (this._renderers.flatColorRenderer) {\r\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n }\r\n }\r\n\r\n // ---------------------- RENDERING SAO POST EFFECT TARGETS --------------\r\n\r\n drawDepth(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.depthRenderer) {\r\n this._renderers.depthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses depth (eg SAO) does not apply to transparent objects\r\n }\r\n }\r\n\r\n drawNormals(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.normalsRenderer) {\r\n this._renderers.normalsRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses normals (eg SAO) does not apply to transparent objects\r\n }\r\n }\r\n\r\n // ---------------------- SILHOUETTE RENDERING -----------------------------------\r\n\r\n drawSilhouetteXRayed(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED);\r\n }\r\n }\r\n\r\n drawSilhouetteHighlighted(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);\r\n }\r\n }\r\n\r\n drawSilhouetteSelected(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED);\r\n }\r\n }\r\n\r\n // ---------------------- EDGES RENDERING -----------------------------------\r\n\r\n drawEdgesColorOpaque(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesColorRenderer) {\r\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n drawEdgesColorTransparent(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0 || this._numTransparentLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesColorRenderer) {\r\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT);\r\n }\r\n }\r\n\r\n drawEdgesHighlighted(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesRenderer) {\r\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED);\r\n }\r\n }\r\n\r\n drawEdgesSelected(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesRenderer) {\r\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED);\r\n }\r\n }\r\n\r\n drawEdgesXRayed(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesRenderer) {\r\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED);\r\n }\r\n }\r\n\r\n // ---------------------- OCCLUSION CULL RENDERING -----------------------------------\r\n\r\n drawOcclusion(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.occlusionRenderer) {\r\n this._renderers.occlusionRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n // ---------------------- SHADOW BUFFER RENDERING -----------------------------------\r\n\r\n drawShadow(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.shadowRenderer) {\r\n this._renderers.shadowRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n //---- PICKING ----------------------------------------------------------------------------------------------------\r\n\r\n drawPickMesh(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.pickMeshRenderer) {\r\n this._renderers.pickMeshRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawPickDepths(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.pickDepthRenderer) {\r\n this._renderers.pickDepthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawPickNormals(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n\r\n ////////////////////////////////////////////////////////////////////////////////////////////////////\r\n // TODO\r\n // if (this._state.normalsBuf) {\r\n // if (this._renderers.pickNormalsRenderer) {\r\n // this._renderers.pickNormalsRenderer.drawLayer(frameCtx, this, RENDER_PASSES.PICK);\r\n // }\r\n ////////////////////////////////////////////////////////////////////////////////////////////////////\r\n // } else {\r\n if (this._renderers.pickNormalsFlatRenderer) {\r\n this._renderers.pickNormalsFlatRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n // }\r\n }\r\n\r\n drawSnapInit(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.snapInitRenderer) {\r\n this._renderers.snapInitRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawSnap(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.snapRenderer) {\r\n this._renderers.snapRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n //------------------------------------------------------------------------------------------------\r\n\r\n precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {\r\n\r\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\r\n return false;\r\n }\r\n\r\n const state = this._state;\r\n const portion = this._portions[portionId];\r\n\r\n if (!portion) {\r\n this.model.error(\"portion not found: \" + portionId);\r\n return false;\r\n }\r\n\r\n const positions = portion.quantizedPositions;\r\n const indices = portion.indices;\r\n const origin = state.origin;\r\n const offset = portion.offset;\r\n\r\n const rtcRayOrigin = tempVec3a;\r\n const rtcRayDir = tempVec3b;\r\n\r\n rtcRayOrigin.set(origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(worldRayOrigin, origin, tempVec3c) : worldRayOrigin); // World -> RTC\r\n rtcRayDir.set(worldRayDir);\r\n\r\n if (offset) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(rtcRayOrigin, offset);\r\n }\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformRay(this.model.worldNormalMatrix, rtcRayOrigin, rtcRayDir, rtcRayOrigin, rtcRayDir); // RTC -> local\r\n\r\n const a = tempVec3d;\r\n const b = tempVec3e;\r\n const c = tempVec3f;\r\n\r\n let gotIntersect = false;\r\n let closestDist = 0;\r\n const closestIntersectPos = tempVec3g;\r\n\r\n for (let i = 0, len = indices.length; i < len; i += 3) {\r\n\r\n const ia = indices[i] * 3;\r\n const ib = indices[i + 1] * 3;\r\n const ic = indices[i + 2] * 3;\r\n\r\n a[0] = positions[ia];\r\n a[1] = positions[ia + 1];\r\n a[2] = positions[ia + 2];\r\n\r\n b[0] = positions[ib];\r\n b[1] = positions[ib + 1];\r\n b[2] = positions[ib + 2];\r\n\r\n c[0] = positions[ic];\r\n c[1] = positions[ic + 1];\r\n c[2] = positions[ic + 2];\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(a, state.positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(b, state.positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(c, state.positionsDecodeMatrix);\r\n\r\n if (_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.rayTriangleIntersect(rtcRayOrigin, rtcRayDir, a, b, c, closestIntersectPos)) {\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(this.model.worldMatrix, closestIntersectPos, closestIntersectPos);\r\n\r\n if (offset) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, offset);\r\n }\r\n\r\n if (origin) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, origin);\r\n }\r\n\r\n const dist = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(closestIntersectPos, worldRayOrigin, [])));\r\n\r\n if (!gotIntersect || dist > closestDist) {\r\n closestDist = dist;\r\n worldSurfacePos.set(closestIntersectPos);\r\n if (worldNormal) { // Not that wasteful to eagerly compute - unlikely to hit >2 surfaces on most geometry\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.triangleNormal(a, b, c, worldNormal);\r\n }\r\n gotIntersect = true;\r\n }\r\n }\r\n }\r\n\r\n if (gotIntersect && worldNormal) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformVec3(this.model.worldNormalMatrix, worldNormal, worldNormal);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.normalizeVec3(worldNormal);\r\n }\r\n\r\n return gotIntersect;\r\n }\r\n\r\n // ---------\r\n\r\n destroy() {\r\n const state = this._state;\r\n if (state.positionsBuf) {\r\n state.positionsBuf.destroy();\r\n state.positionsBuf = null;\r\n }\r\n if (state.offsetsBuf) {\r\n state.offsetsBuf.destroy();\r\n state.offsetsBuf = null;\r\n }\r\n if (state.normalsBuf) {\r\n state.normalsBuf.destroy();\r\n state.normalsBuf = null;\r\n }\r\n if (state.colorsBuf) {\r\n state.colorsBuf.destroy();\r\n state.colorsBuf = null;\r\n }\r\n if (state.metallicRoughnessBuf) {\r\n state.metallicRoughnessBuf.destroy();\r\n state.metallicRoughnessBuf = null;\r\n }\r\n if (state.flagsBuf) {\r\n state.flagsBuf.destroy();\r\n state.flagsBuf = null;\r\n }\r\n if (state.pickColorsBuf) {\r\n state.pickColorsBuf.destroy();\r\n state.pickColorsBuf = null;\r\n }\r\n if (state.indicesBuf) {\r\n state.indicesBuf.destroy();\r\n state.indicessBuf = null;\r\n }\r\n if (state.edgeIndicesBuf) {\r\n state.edgeIndicesBuf.destroy();\r\n state.edgeIndicessBuf = null;\r\n }\r\n state.destroy();\r\n }\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js?");
|
|
4127
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBOBatchingTrianglesLayer: () => (/* binding */ VBOBatchingTrianglesLayer)\n/* harmony export */ });\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.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 _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../webgl/RenderState.js */ \"./src/viewer/scene/webgl/RenderState.js\");\n/* harmony import */ var _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../webgl/ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../../math/geometryCompressionUtils.js */ \"./src/viewer/scene/math/geometryCompressionUtils.js\");\n/* harmony import */ var _renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./renderers/Renderers.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js\");\n/* harmony import */ var _VBOBatchingTrianglesBuffer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./VBOBatchingTrianglesBuffer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js\");\n/* harmony import */ var _compression_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../compression.js */ \"./src/viewer/scene/model/compression.js\");\n\n\n\n\n\n\n\n\n\n\n\nconst tempMat4 = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\nconst tempMat4b = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\nconst tempVec4a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec4([0, 0, 0, 1]);\n\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3b = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3d = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3e = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3f = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3g = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\n\n/**\n * @private\n */\nclass VBOBatchingTrianglesLayer {\n\n /**\n * @param model\n * @param cfg.model\n * @param cfg.autoNormals\n * @param cfg.layerIndex\n * @param cfg.positionsDecodeMatrix\n * @param cfg.uvDecodeMatrix\n * @param cfg.maxGeometryBatchSize\n * @param cfg.origin\n * @param cfg.scratchMemory\n * @param cfg.textureSet\n * @param cfg.solid\n */\n constructor(cfg) {\n\n console.info(\"Creating VBOBatchingTrianglesLayer\");\n\n /**\n * Owner model\n * @type {VBOSceneModel}\n */\n this.model = cfg.model;\n\n /**\n * State sorting key.\n * @type {string}\n */\n this.sortId = \"TrianglesBatchingLayer\"\n + (cfg.solid ? \"-solid\" : \"-surface\")\n + (cfg.autoNormals ? \"-autonormals\" : \"-normals\")\n\n // TODO: These two parts need to be IDs (ie. unique):\n\n + (cfg.textureSet && cfg.textureSet.colorTexture ? \"-colorTexture\" : \"\")\n + (cfg.textureSet && cfg.textureSet.metallicRoughnessTexture ? \"-metallicRoughnessTexture\" : \"\");\n\n /**\n * Index of this TrianglesBatchingLayer in {@link VBOSceneModel#_layerList}.\n * @type {Number}\n */\n this.layerIndex = cfg.layerIndex;\n\n this._renderers = (0,_renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_6__.getRenderers)(cfg.model.scene);\n this._buffer = new _VBOBatchingTrianglesBuffer_js__WEBPACK_IMPORTED_MODULE_7__.VBOBatchingTrianglesBuffer(cfg.maxGeometryBatchSize);\n this._scratchMemory = cfg.scratchMemory;\n\n this._state = new _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__.RenderState({\n origin: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3(),\n positionsBuf: null,\n offsetsBuf: null,\n normalsBuf: null,\n colorsBuf: null,\n uvBuf: null,\n metallicRoughnessBuf: null,\n flagsBuf: null,\n indicesBuf: null,\n edgeIndicesBuf: null,\n positionsDecodeMatrix: null,\n uvDecodeMatrix: null,\n textureSet: cfg.textureSet,\n pbrSupported: false // Set in #finalize if we have enough to support quality rendering\n });\n\n // These counts are used to avoid unnecessary render passes\n this._numPortions = 0;\n this._numVisibleLayerPortions = 0;\n this._numTransparentLayerPortions = 0;\n this._numXRayedLayerPortions = 0;\n this._numSelectedLayerPortions = 0;\n this._numHighlightedLayerPortions = 0;\n this._numClippableLayerPortions = 0;\n this._numEdgesLayerPortions = 0;\n this._numPickableLayerPortions = 0;\n this._numCulledLayerPortions = 0;\n\n this._modelAABB = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(); // Model-space AABB\n this._portions = [];\n this._meshes = [];\n this._numVerts = 0;\n\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\n this.aabbDirty = true;\n\n this._finalized = false;\n\n if (cfg.positionsDecodeMatrix) {\n this._state.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4(cfg.positionsDecodeMatrix);\n }\n\n if (cfg.uvDecodeMatrix) {\n this._state.uvDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat3(cfg.uvDecodeMatrix);\n this._preCompressedUVsExpected = true;\n } else {\n this._preCompressedUVsExpected = false;\n }\n\n if (cfg.origin) {\n this._state.origin.set(cfg.origin);\n }\n\n /**\n * When true, this layer contains solid triangle meshes, otherwise this layer contains surface triangle meshes\n * @type {boolean}\n */\n this.solid = !!cfg.solid;\n }\n\n get aabb() {\n if (this.aabbDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(this._aabb);\n for (let i = 0, len = this._meshes.length; i < len; i++) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._aabb, this._meshes[i].aabb);\n }\n this.aabbDirty = false;\n }\n return this._aabb;\n }\n\n /**\n * Tests if there is room for another portion in this TrianglesBatchingLayer.\n *\n * @param lenPositions Number of positions we'd like to create in the portion.\n * @param lenIndices Number of indices we'd like to create in this portion.\n * @returns {Boolean} True if OK to create another portion.\n */\n canCreatePortion(lenPositions, lenIndices) {\n if (this._finalized) {\n throw \"Already finalized\";\n }\n return ((this._buffer.positions.length + lenPositions) < (this._buffer.maxVerts * 3) && (this._buffer.indices.length + lenIndices) < (this._buffer.maxIndices));\n }\n\n /**\n * Creates a new portion within this TrianglesBatchingLayer, returns the new portion ID.\n *\n * Gives the portion the specified geometry, color and matrix.\n *\n * @param mesh The SceneModelMesh that owns the portion\n * @param cfg.positions Flat float Local-space positions array.\n * @param cfg.positionsCompressed Flat quantized positions array - decompressed with TrianglesBatchingLayer positionsDecodeMatrix\n * @param [cfg.normals] Flat float normals array.\n * @param [cfg.uv] Flat UVs array.\n * @param [cfg.uvCompressed]\n * @param [cfg.colors] Flat float colors array.\n * @param [cfg.colorsCompressed]\n * @param cfg.indices Flat int indices array.\n * @param [cfg.edgeIndices] Flat int edges indices array.\n * @param cfg.color Quantized RGB color [0..255,0..255,0..255,0..255]\n * @param cfg.metallic Metalness factor [0..255]\n * @param cfg.roughness Roughness factor [0..255]\n * @param cfg.opacity Opacity [0..255]\n * @param [cfg.meshMatrix] Flat float 4x4 matrix\n * @param cfg.aabb Flat float AABB World-space AABB\n * @param cfg.pickColor Quantized pick color\n * @returns {number} Portion ID\n */\n createPortion(mesh, cfg) {\n\n if (this._finalized) {\n throw \"Already finalized\";\n }\n\n const positions = cfg.positions;\n const positionsCompressed = cfg.positionsCompressed;\n const normals = cfg.normals;\n const normalsCompressed = cfg.normalsCompressed;\n const uv = cfg.uv;\n const uvCompressed = cfg.uvCompressed;\n const colors = cfg.colors;\n const colorsCompressed = cfg.colorsCompressed;\n const indices = cfg.indices;\n const edgeIndices = cfg.edgeIndices;\n const color = cfg.color;\n const metallic = cfg.metallic;\n const roughness = cfg.roughness;\n const opacity = cfg.opacity;\n const meshMatrix = cfg.meshMatrix;\n const pickColor = cfg.pickColor;\n\n const scene = this.model.scene;\n const buffer = this._buffer;\n const vertsBaseIndex = buffer.positions.length / 3;\n\n let numVerts;\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._modelAABB, cfg.aabb);\n\n if (this._state.positionsDecodeMatrix) {\n if (!positionsCompressed) {\n throw \"positionsCompressed expected\";\n }\n numVerts = positionsCompressed.length / 3;\n for (let i = 0, len = positionsCompressed.length; i < len; i++) {\n buffer.positions.push(positionsCompressed[i]);\n }\n } else {\n if (!positions) {\n throw \"positions expected\";\n }\n numVerts = positions.length / 3;\n for (let i = 0, len = positions.length; i < len; i++) {\n buffer.positions.push(positions[i]);\n }\n }\n\n if (normalsCompressed && normalsCompressed.length > 0) {\n for (let i = 0, len = normalsCompressed.length; i < len; i++) {\n buffer.normals.push(normalsCompressed[i]);\n }\n } else if (normals && normals.length > 0) {\n const worldNormalMatrix = tempMat4;\n if (meshMatrix) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transposeMat4(meshMatrix, tempMat4b), worldNormalMatrix); // Note: order of inverse and transpose doesn't matter\n } else {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.identityMat4(worldNormalMatrix, worldNormalMatrix);\n }\n (0,_compression_js__WEBPACK_IMPORTED_MODULE_8__.transformAndOctEncodeNormals)(worldNormalMatrix, normals, normals.length, buffer.normals, buffer.normals.length);\n }\n\n if (colors) {\n for (let i = 0, len = colors.length; i < len; i += 3) {\n buffer.colors.push(colors[i] * 255);\n buffer.colors.push(colors[i + 1] * 255);\n buffer.colors.push(colors[i + 2] * 255);\n buffer.colors.push(255);\n }\n } else if (colorsCompressed) {\n for (let i = 0, len = colors.length; i < len; i += 3) {\n buffer.colors.push(colors[i]);\n buffer.colors.push(colors[i + 1]);\n buffer.colors.push(colors[i + 2]);\n buffer.colors.push(255);\n }\n } else if (color) {\n const r = color[0]; // Color is pre-quantized by VBOSceneModel\n const g = color[1];\n const b = color[2];\n const a = opacity;\n for (let i = 0; i < numVerts; i++) {\n buffer.colors.push(r);\n buffer.colors.push(g);\n buffer.colors.push(b);\n buffer.colors.push(a);\n }\n }\n const metallicValue = (metallic !== null && metallic !== undefined) ? metallic : 0;\n const roughnessValue = (roughness !== null && roughness !== undefined) ? roughness : 255;\n for (let i = 0; i < numVerts; i++) {\n buffer.metallicRoughness.push(metallicValue);\n buffer.metallicRoughness.push(roughnessValue);\n }\n\n if (uv && uv.length > 0) {\n for (let i = 0, len = uv.length; i < len; i++) {\n buffer.uv.push(uv[i]);\n }\n } else if (uvCompressed && uvCompressed.length > 0) {\n for (let i = 0, len = uvCompressed.length; i < len; i++) {\n buffer.uv.push(uvCompressed[i]);\n }\n }\n\n for (let i = 0, len = indices.length; i < len; i++) {\n buffer.indices.push(vertsBaseIndex + indices[i]);\n }\n\n\n if (edgeIndices) {\n for (let i = 0, len = edgeIndices.length; i < len; i++) {\n buffer.edgeIndices.push(vertsBaseIndex + edgeIndices[i]);\n }\n }\n\n {\n const pickColorsBase = buffer.pickColors.length;\n const lenPickColors = numVerts * 4;\n for (let i = pickColorsBase, len = pickColorsBase + lenPickColors; i < len; i += 4) {\n buffer.pickColors.push(pickColor[0]);\n buffer.pickColors.push(pickColor[1]);\n buffer.pickColors.push(pickColor[2]);\n buffer.pickColors.push(pickColor[3]);\n }\n }\n\n if (scene.entityOffsetsEnabled) {\n for (let i = 0; i < numVerts; i++) {\n buffer.offsets.push(0);\n buffer.offsets.push(0);\n buffer.offsets.push(0);\n }\n }\n\n const portionId = this._portions.length;\n\n const portion = {\n vertsBaseIndex: vertsBaseIndex,\n numVerts: numVerts,\n indicesBaseIndex: buffer.indices.length - indices.length,\n numIndices: indices.length,\n };\n\n if (scene.pickSurfacePrecisionEnabled) {\n // Quantized in-memory positions are initialized in finalize()\n\n portion.indices = indices;\n\n if (scene.entityOffsetsEnabled) {\n portion.offset = new Float32Array(3);\n }\n }\n\n this._portions.push(portion);\n this._numPortions++;\n this.model.numPortions++;\n this._numVerts += portion.numVerts;\n this._meshes.push(mesh);\n return portionId;\n }\n\n /**\n * Builds batch VBOs from appended geometries.\n * No more portions can then be created.\n */\n finalize() {\n\n if (this._finalized) {\n return;\n }\n\n const state = this._state;\n const gl = this.model.scene.canvas.gl;\n const buffer = this._buffer;\n\n if (buffer.positions.length > 0) {\n const quantizedPositions = (this._state.positionsDecodeMatrix)\n ? new Uint16Array(buffer.positions)\n : (0,_compression_js__WEBPACK_IMPORTED_MODULE_8__.quantizePositions)(buffer.positions, this._modelAABB, this._state.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4()); // BOTTLENECK\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, quantizedPositions.length, 3, gl.STATIC_DRAW);\n if (this.model.scene.pickSurfacePrecisionEnabled) {\n for (let i = 0, numPortions = this._portions.length; i < numPortions; i++) {\n const portion = this._portions[i];\n const start = portion.vertsBaseIndex * 3;\n const end = start + (portion.numVerts * 3);\n portion.quantizedPositions = quantizedPositions.slice(start, end);\n }\n }\n }\n\n if (buffer.normals.length > 0) { // Normals are already oct-encoded\n const normals = new Int8Array(buffer.normals);\n let normalized = true; // For oct encoded UInts\n state.normalsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, normals, buffer.normals.length, 3, gl.STATIC_DRAW, normalized);\n }\n\n if (buffer.colors.length > 0) { // Colors are already compressed\n const colors = new Uint8Array(buffer.colors);\n let normalized = false;\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, colors, buffer.colors.length, 4, gl.DYNAMIC_DRAW, normalized);\n }\n\n if (buffer.uv.length > 0) {\n if (!state.uvDecodeMatrix) {\n const bounds = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_5__.geometryCompressionUtils.getUVBounds(buffer.uv);\n const result = _math_geometryCompressionUtils_js__WEBPACK_IMPORTED_MODULE_5__.geometryCompressionUtils.compressUVs(buffer.uv, bounds.min, bounds.max);\n const uv = result.quantized;\n let notNormalized = false;\n state.uvDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat3(result.decodeMatrix);\n state.uvBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, uv, uv.length, 2, gl.STATIC_DRAW, notNormalized);\n } else {\n let notNormalized = false;\n state.uvBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, buffer.uv, buffer.uv.length, 2, gl.STATIC_DRAW, notNormalized);\n }\n }\n\n if (buffer.metallicRoughness.length > 0) {\n const metallicRoughness = new Uint8Array(buffer.metallicRoughness);\n let normalized = false;\n state.metallicRoughnessBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, metallicRoughness, buffer.metallicRoughness.length, 2, gl.STATIC_DRAW, normalized);\n }\n\n if (buffer.positions.length > 0) { // Because we build flags arrays here, get their length from the positions array\n const flagsLength = (buffer.positions.length / 3);\n const flags = new Float32Array(flagsLength);\n const notNormalized = false;\n state.flagsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, flags, flags.length, 1, gl.DYNAMIC_DRAW, notNormalized);\n }\n\n if (buffer.pickColors.length > 0) {\n const pickColors = new Uint8Array(buffer.pickColors);\n let normalized = false;\n state.pickColorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, pickColors, buffer.pickColors.length, 4, gl.STATIC_DRAW, normalized);\n }\n\n if (this.model.scene.entityOffsetsEnabled) {\n if (buffer.offsets.length > 0) {\n const offsets = new Float32Array(buffer.offsets);\n state.offsetsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, offsets, buffer.offsets.length, 3, gl.DYNAMIC_DRAW);\n }\n }\n\n if (buffer.indices.length > 0) {\n const indices = new Uint32Array(buffer.indices);\n state.indicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, buffer.indices.length, 1, gl.STATIC_DRAW);\n }\n if (buffer.edgeIndices.length > 0) {\n const edgeIndices = new Uint32Array(buffer.edgeIndices);\n state.edgeIndicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, edgeIndices, buffer.edgeIndices.length, 1, gl.STATIC_DRAW);\n }\n\n this._state.pbrSupported\n = !!state.metallicRoughnessBuf\n && !!state.uvBuf\n && !!state.normalsBuf\n && !!state.textureSet\n && !!state.textureSet.colorTexture\n && !!state.textureSet.metallicRoughnessTexture;\n\n this._state.colorTextureSupported\n = !!state.uvBuf\n && !!state.textureSet\n && !!state.textureSet.colorTexture;\n\n this._buffer = null;\n this._finalized = true;\n }\n\n isEmpty() {\n return (!this._state.indicesBuf);\n }\n\n initFlags(portionId, flags, meshTransparent) {\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\n this._numVisibleLayerPortions++;\n this.model.numVisibleLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\n this._numHighlightedLayerPortions++;\n this.model.numHighlightedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\n this._numXRayedLayerPortions++;\n this.model.numXRayedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\n this._numSelectedLayerPortions++;\n this.model.numSelectedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\n this._numClippableLayerPortions++;\n this.model.numClippableLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\n this._numEdgesLayerPortions++;\n this.model.numEdgesLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\n this._numPickableLayerPortions++;\n this.model.numPickableLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\n this._numCulledLayerPortions++;\n this.model.numCulledLayerPortions++;\n }\n if (meshTransparent) {\n this._numTransparentLayerPortions++;\n this.model.numTransparentLayerPortions++;\n }\n const deferred = true;\n this._setFlags(portionId, flags, meshTransparent, deferred);\n }\n\n flushInitFlags() {\n this._setDeferredFlags();\n }\n\n setVisible(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\n this._numVisibleLayerPortions++;\n this.model.numVisibleLayerPortions++;\n } else {\n this._numVisibleLayerPortions--;\n this.model.numVisibleLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setHighlighted(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\n this._numHighlightedLayerPortions++;\n this.model.numHighlightedLayerPortions++;\n } else {\n this._numHighlightedLayerPortions--;\n this.model.numHighlightedLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setXRayed(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\n this._numXRayedLayerPortions++;\n this.model.numXRayedLayerPortions++;\n } else {\n this._numXRayedLayerPortions--;\n this.model.numXRayedLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setSelected(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\n this._numSelectedLayerPortions++;\n this.model.numSelectedLayerPortions++;\n } else {\n this._numSelectedLayerPortions--;\n this.model.numSelectedLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setEdges(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\n this._numEdgesLayerPortions++;\n this.model.numEdgesLayerPortions++;\n } else {\n this._numEdgesLayerPortions--;\n this.model.numEdgesLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setClippable(portionId, flags) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\n this._numClippableLayerPortions++;\n this.model.numClippableLayerPortions++;\n } else {\n this._numClippableLayerPortions--;\n this.model.numClippableLayerPortions--;\n }\n this._setFlags(portionId, flags);\n }\n\n setCulled(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\n this._numCulledLayerPortions++;\n this.model.numCulledLayerPortions++;\n } else {\n this._numCulledLayerPortions--;\n this.model.numCulledLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setCollidable(portionId, flags) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n }\n\n setPickable(portionId, flags, transparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\n this._numPickableLayerPortions++;\n this.model.numPickableLayerPortions++;\n } else {\n this._numPickableLayerPortions--;\n this.model.numPickableLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n setColor(portionId, color) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n const portionsIdx = portionId;\n const portion = this._portions[portionsIdx];\n const vertsBaseIndex = portion.vertsBaseIndex;\n const numVerts = portion.numVerts;\n const firstColor = vertsBaseIndex * 4;\n const lenColor = numVerts * 4;\n const tempArray = this._scratchMemory.getUInt8Array(lenColor);\n const r = color[0];\n const g = color[1];\n const b = color[2];\n const a = color[3];\n for (let i = 0; i < lenColor; i += 4) {\n tempArray[i + 0] = r;\n tempArray[i + 1] = g;\n tempArray[i + 2] = b;\n tempArray[i + 3] = a;\n }\n if (this._state.colorsBuf) {\n this._state.colorsBuf.setData(tempArray, firstColor, lenColor);\n }\n }\n\n setTransparent(portionId, flags, transparent) {\n if (transparent) {\n this._numTransparentLayerPortions++;\n this.model.numTransparentLayerPortions++;\n } else {\n this._numTransparentLayerPortions--;\n this.model.numTransparentLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n /**\n * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.\n */\n _setFlags(portionId, flags, transparent, deferred = false) {\n\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n\n const portionsIdx = portionId;\n const portion = this._portions[portionsIdx];\n const vertsBaseIndex = portion.vertsBaseIndex;\n const numVerts = portion.numVerts;\n const firstFlag = vertsBaseIndex;\n const lenFlags = numVerts;\n\n const visible = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE);\n const xrayed = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED);\n const highlighted = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED);\n const selected = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED);\n const edges = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES);\n const pickable = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE);\n const culled = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED);\n\n let colorFlag;\n if (!visible || culled || xrayed\n || (highlighted && !this.model.scene.highlightMaterial.glowThrough)\n || (selected && !this.model.scene.selectedMaterial.glowThrough)) {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else {\n if (transparent) {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT;\n } else {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE;\n }\n }\n\n let silhouetteFlag;\n if (!visible || culled) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else if (selected) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED;\n } else if (highlighted) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;\n } else if (xrayed) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED;\n } else {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n }\n\n let edgeFlag = 0;\n if (!visible || culled) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else if (selected) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED;\n } else if (highlighted) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED;\n } else if (xrayed) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED;\n } else if (edges) {\n if (transparent) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT;\n } else {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE;\n }\n } else {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n }\n\n let pickFlag = (visible && !culled && pickable) ? _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK : _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n\n const clippableFlag = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;\n\n if (deferred) {\n // Avoid zillions of individual WebGL bufferSubData calls - buffer them to apply in one shot\n if (!this._deferredFlagValues) {\n this._deferredFlagValues = new Float32Array(this._numVerts);\n }\n for (let i = firstFlag, len = (firstFlag + lenFlags); i < len; i++) {\n let vertFlag = 0;\n vertFlag |= colorFlag;\n vertFlag |= silhouetteFlag << 4;\n vertFlag |= edgeFlag << 8;\n vertFlag |= pickFlag << 12;\n vertFlag |= clippableFlag << 16;\n\n this._deferredFlagValues[i] = vertFlag;\n }\n } else if (this._state.flagsBuf) {\n const tempArray = this._scratchMemory.getFloat32Array(lenFlags);\n for (let i = 0; i < lenFlags; i++) {\n let vertFlag = 0;\n vertFlag |= colorFlag;\n vertFlag |= silhouetteFlag << 4;\n vertFlag |= edgeFlag << 8;\n vertFlag |= pickFlag << 12;\n vertFlag |= clippableFlag << 16;\n\n tempArray[i] = vertFlag;\n }\n this._state.flagsBuf.setData(tempArray, firstFlag, lenFlags);\n }\n }\n\n _setDeferredFlags() {\n if (this._deferredFlagValues) {\n this._state.flagsBuf.setData(this._deferredFlagValues);\n this._deferredFlagValues = null;\n }\n }\n\n setOffset(portionId, offset) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (!this.model.scene.entityOffsetsEnabled) {\n this.model.error(\"Entity#offset not enabled for this Viewer\"); // See Viewer entityOffsetsEnabled\n return;\n }\n const portionsIdx = portionId;\n const portion = this._portions[portionsIdx];\n const vertsBaseIndex = portion.vertsBaseIndex;\n const numVerts = portion.numVerts;\n const firstOffset = vertsBaseIndex * 3;\n const lenOffsets = numVerts * 3;\n const tempArray = this._scratchMemory.getFloat32Array(lenOffsets);\n const x = offset[0];\n const y = offset[1];\n const z = offset[2];\n for (let i = 0; i < lenOffsets; i += 3) {\n tempArray[i + 0] = x;\n tempArray[i + 1] = y;\n tempArray[i + 2] = z;\n }\n if (this._state.offsetsBuf) {\n this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);\n }\n if (this.model.scene.pickSurfacePrecisionEnabled) {\n portion.offset[0] = offset[0];\n portion.offset[1] = offset[1];\n portion.offset[2] = offset[2];\n }\n }\n\n getEachVertex(portionId, callback) {\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\n return;\n }\n const state = this._state;\n const portion = this._portions[portionId];\n if (!portion) {\n this.model.error(\"portion not found: \" + portionId);\n return;\n }\n const positions = portion.quantizedPositions;\n const origin = state.origin;\n const offset = portion.offset;\n const offsetX = origin[0] + offset[0];\n const offsetY = origin[1] + offset[1];\n const offsetZ = origin[2] + offset[2];\n const worldPos = tempVec4a;\n for (let i = 0, len = positions.length; i < len; i += 3) {\n worldPos[0] = positions[i];\n worldPos[1] = positions[i + 1];\n worldPos[2] = positions[i + 2];\n worldPos[3] = 1.0;\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(worldPos, state.positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint4(this.model.worldMatrix, worldPos);\n worldPos[0] += offsetX;\n worldPos[1] += offsetY;\n worldPos[2] += offsetZ;\n callback(worldPos);\n }\n }\n\n getElementsCountAndOffset(portionId) {\n let count = null;\n let offset = null;\n const portion = this._portions[portionId];\n\n if (portion) {\n count = portion.numIndices;\n offset = portion.indicesBaseIndex;\n }\n\n return {count, offset}\n }\n\n // ---------------------- COLOR RENDERING -----------------------------------\n\n drawColorOpaque(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (frameCtx.withSAO && this.model.saoEnabled) {\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\n if (this._renderers.pbrRendererWithSAO) {\n this._renderers.pbrRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\n if (this._renderers.colorTextureRendererWithSAO) {\n this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (this._state.normalsBuf) {\n if (this._renderers.colorRendererWithSAO) {\n this._renderers.colorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else {\n if (this._renderers.flatColorRendererWithSAO) {\n this._renderers.flatColorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n } else {\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\n if (this._renderers.pbrRenderer) {\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\n if (this._renderers.colorTextureRenderer) {\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (this._state.normalsBuf) {\n if (this._renderers.colorRenderer) {\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else {\n if (this._renderers.flatColorRenderer) {\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n }\n }\n\n _updateBackfaceCull(renderFlags, frameCtx) {\n const backfaces = this.model.backfaces || (!this.solid) || renderFlags.sectioned;\n if (frameCtx.backfaces !== backfaces) {\n const gl = frameCtx.gl;\n if (backfaces) {\n gl.disable(gl.CULL_FACE);\n } else {\n gl.enable(gl.CULL_FACE);\n }\n frameCtx.backfaces = backfaces;\n }\n }\n\n drawColorTransparent(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\n if (this._renderers.pbrRenderer) {\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\n if (this._renderers.colorTextureRenderer) {\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n } else if (this._state.normalsBuf) {\n if (this._renderers.colorRenderer) {\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n } else {\n if (this._renderers.flatColorRenderer) {\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n }\n }\n\n // ---------------------- RENDERING SAO POST EFFECT TARGETS --------------\n\n drawDepth(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.depthRenderer) {\n this._renderers.depthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses depth (eg SAO) does not apply to transparent objects\n }\n }\n\n drawNormals(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.normalsRenderer) {\n this._renderers.normalsRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses normals (eg SAO) does not apply to transparent objects\n }\n }\n\n // ---------------------- SILHOUETTE RENDERING -----------------------------------\n\n drawSilhouetteXRayed(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED);\n }\n }\n\n drawSilhouetteHighlighted(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);\n }\n }\n\n drawSilhouetteSelected(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED);\n }\n }\n\n // ---------------------- EDGES RENDERING -----------------------------------\n\n drawEdgesColorOpaque(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesColorRenderer) {\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE);\n }\n }\n\n drawEdgesColorTransparent(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0 || this._numTransparentLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesColorRenderer) {\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT);\n }\n }\n\n drawEdgesHighlighted(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesRenderer) {\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED);\n }\n }\n\n drawEdgesSelected(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesRenderer) {\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED);\n }\n }\n\n drawEdgesXRayed(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesRenderer) {\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED);\n }\n }\n\n // ---------------------- OCCLUSION CULL RENDERING -----------------------------------\n\n drawOcclusion(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.occlusionRenderer) {\n this._renderers.occlusionRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n\n // ---------------------- SHADOW BUFFER RENDERING -----------------------------------\n\n drawShadow(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.shadowRenderer) {\n this._renderers.shadowRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n\n //---- PICKING ----------------------------------------------------------------------------------------------------\n\n drawPickMesh(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.pickMeshRenderer) {\n this._renderers.pickMeshRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawPickDepths(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.pickDepthRenderer) {\n this._renderers.pickDepthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawPickNormals(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n\n ////////////////////////////////////////////////////////////////////////////////////////////////////\n // TODO\n // if (this._state.normalsBuf) {\n // if (this._renderers.pickNormalsRenderer) {\n // this._renderers.pickNormalsRenderer.drawLayer(frameCtx, this, RENDER_PASSES.PICK);\n // }\n ////////////////////////////////////////////////////////////////////////////////////////////////////\n // } else {\n if (this._renderers.pickNormalsFlatRenderer) {\n this._renderers.pickNormalsFlatRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n // }\n }\n\n drawSnapInit(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.snapInitRenderer) {\n this._renderers.snapInitRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawSnap(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.snapRenderer) {\n this._renderers.snapRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n //------------------------------------------------------------------------------------------------\n\n precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {\n\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\n return false;\n }\n\n const state = this._state;\n const portion = this._portions[portionId];\n\n if (!portion) {\n this.model.error(\"portion not found: \" + portionId);\n return false;\n }\n\n const positions = portion.quantizedPositions;\n const indices = portion.indices;\n const origin = state.origin;\n const offset = portion.offset;\n\n const rtcRayOrigin = tempVec3a;\n const rtcRayDir = tempVec3b;\n\n rtcRayOrigin.set(origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(worldRayOrigin, origin, tempVec3c) : worldRayOrigin); // World -> RTC\n rtcRayDir.set(worldRayDir);\n\n if (offset) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(rtcRayOrigin, offset);\n }\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformRay(this.model.worldNormalMatrix, rtcRayOrigin, rtcRayDir, rtcRayOrigin, rtcRayDir); // RTC -> local\n\n const a = tempVec3d;\n const b = tempVec3e;\n const c = tempVec3f;\n\n let gotIntersect = false;\n let closestDist = 0;\n const closestIntersectPos = tempVec3g;\n\n for (let i = 0, len = indices.length; i < len; i += 3) {\n\n const ia = indices[i] * 3;\n const ib = indices[i + 1] * 3;\n const ic = indices[i + 2] * 3;\n\n a[0] = positions[ia];\n a[1] = positions[ia + 1];\n a[2] = positions[ia + 2];\n\n b[0] = positions[ib];\n b[1] = positions[ib + 1];\n b[2] = positions[ib + 2];\n\n c[0] = positions[ic];\n c[1] = positions[ic + 1];\n c[2] = positions[ic + 2];\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(a, state.positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(b, state.positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(c, state.positionsDecodeMatrix);\n\n if (_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.rayTriangleIntersect(rtcRayOrigin, rtcRayDir, a, b, c, closestIntersectPos)) {\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(this.model.worldMatrix, closestIntersectPos, closestIntersectPos);\n\n if (offset) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, offset);\n }\n\n if (origin) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, origin);\n }\n\n const dist = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(closestIntersectPos, worldRayOrigin, [])));\n\n if (!gotIntersect || dist > closestDist) {\n closestDist = dist;\n worldSurfacePos.set(closestIntersectPos);\n if (worldNormal) { // Not that wasteful to eagerly compute - unlikely to hit >2 surfaces on most geometry\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.triangleNormal(a, b, c, worldNormal);\n }\n gotIntersect = true;\n }\n }\n }\n\n if (gotIntersect && worldNormal) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformVec3(this.model.worldNormalMatrix, worldNormal, worldNormal);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.normalizeVec3(worldNormal);\n }\n\n return gotIntersect;\n }\n\n // ---------\n\n destroy() {\n const state = this._state;\n if (state.positionsBuf) {\n state.positionsBuf.destroy();\n state.positionsBuf = null;\n }\n if (state.offsetsBuf) {\n state.offsetsBuf.destroy();\n state.offsetsBuf = null;\n }\n if (state.normalsBuf) {\n state.normalsBuf.destroy();\n state.normalsBuf = null;\n }\n if (state.colorsBuf) {\n state.colorsBuf.destroy();\n state.colorsBuf = null;\n }\n if (state.metallicRoughnessBuf) {\n state.metallicRoughnessBuf.destroy();\n state.metallicRoughnessBuf = null;\n }\n if (state.flagsBuf) {\n state.flagsBuf.destroy();\n state.flagsBuf = null;\n }\n if (state.pickColorsBuf) {\n state.pickColorsBuf.destroy();\n state.pickColorsBuf = null;\n }\n if (state.indicesBuf) {\n state.indicesBuf.destroy();\n state.indicessBuf = null;\n }\n if (state.edgeIndicesBuf) {\n state.edgeIndicesBuf.destroy();\n state.edgeIndicessBuf = null;\n }\n state.destroy();\n }\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js?");
|
|
4128
4128
|
|
|
4129
4129
|
/***/ }),
|
|
4130
4130
|
|
|
@@ -4164,7 +4164,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4164
4164
|
\******************************************************************************/
|
|
4165
4165
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4166
4166
|
|
|
4167
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getRenderers: () => (/* binding */ getRenderers)\n/* harmony export */ });\n/* harmony import */ var _TrianglesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./TrianglesColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js\");\n/* harmony import */ var _TrianglesFlatColorRenderer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TrianglesFlatColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js\");\n/* harmony import */ var _TrianglesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TrianglesSilhouetteRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSilhouetteRenderer.js\");\n/* harmony import */ var _EdgesEmphasisRenderer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./EdgesEmphasisRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesEmphasisRenderer.js\");\n/* harmony import */ var _EdgesColorRenderer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./EdgesColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesColorRenderer.js\");\n/* harmony import */ var _TrianglesPickMeshRenderer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./TrianglesPickMeshRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickMeshRenderer.js\");\n/* harmony import */ var _TrianglesPickDepthRenderer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./TrianglesPickDepthRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickDepthRenderer.js\");\n/* harmony import */ var _TrianglesPickNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./TrianglesPickNormalsRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsRenderer.js\");\n/* harmony import */ var _TrianglesOcclusionRenderer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./TrianglesOcclusionRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesOcclusionRenderer.js\");\n/* harmony import */ var _TrianglesDepthRenderer_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TrianglesDepthRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesDepthRenderer.js\");\n/* harmony import */ var _TrianglesNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./TrianglesNormalsRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesNormalsRenderer.js\");\n/* harmony import */ var _TrianglesShadowRenderer_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./TrianglesShadowRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesShadowRenderer.js\");\n/* harmony import */ var _TrianglesPBRRenderer_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./TrianglesPBRRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPBRRenderer.js\");\n/* harmony import */ var _TrianglesPickNormalsFlatRenderer_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./TrianglesPickNormalsFlatRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsFlatRenderer.js\");\n/* harmony import */ var _TrianglesColorTextureRenderer_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./TrianglesColorTextureRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js\");\n/* harmony import */ var _TrianglesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./TrianglesSnapInitRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapInitRenderer.js\");\n/* harmony import */ var _TrianglesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./TrianglesSnapRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.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 * @private\r\n */\r\nclass Renderers {\r\n\r\n constructor(scene) {\r\n this._scene = scene;\r\n }\r\n\r\n _compile() {\r\n if (this._colorRenderer && (!this._colorRenderer.getValid())) {\r\n this._colorRenderer.destroy();\r\n this._colorRenderer = null;\r\n }\r\n if (this._colorRendererWithSAO && (!this._colorRendererWithSAO.getValid())) {\r\n this._colorRendererWithSAO.destroy();\r\n this._colorRendererWithSAO = null;\r\n }\r\n if (this._flatColorRenderer && (!this._flatColorRenderer.getValid())) {\r\n this._flatColorRenderer.destroy();\r\n this._flatColorRenderer = null;\r\n }\r\n if (this._flatColorRendererWithSAO && (!this._flatColorRendererWithSAO.getValid())) {\r\n this._flatColorRendererWithSAO.destroy();\r\n this._flatColorRendererWithSAO = null;\r\n }\r\n if (this._colorTextureRenderer && (!this._colorTextureRenderer.getValid())) {\r\n this._colorTextureRenderer.destroy();\r\n this._colorTextureRenderer = null;\r\n }\r\n if (this._colorTextureRendererWithSAO && (!this._colorTextureRendererWithSAO.getValid())) {\r\n this._colorTextureRendererWithSAO.destroy();\r\n this._colorTextureRendererWithSAO = null;\r\n }\r\n if (this._pbrRenderer && (!this._pbrRenderer.getValid())) {\r\n this._pbrRenderer.destroy();\r\n this._pbrRenderer = null;\r\n }\r\n if (this._pbrRendererWithSAO && (!this._pbrRendererWithSAO.getValid())) {\r\n this._pbrRendererWithSAO.destroy();\r\n this._pbrRendererWithSAO = null;\r\n }\r\n if (this._depthRenderer && (!this._depthRenderer.getValid())) {\r\n this._depthRenderer.destroy();\r\n this._depthRenderer = null;\r\n }\r\n if (this._normalsRenderer && (!this._normalsRenderer.getValid())) {\r\n this._normalsRenderer.destroy();\r\n this._normalsRenderer = null;\r\n }\r\n if (this._silhouetteRenderer && (!this._silhouetteRenderer.getValid())) {\r\n this._silhouetteRenderer.destroy();\r\n this._silhouetteRenderer = null;\r\n }\r\n if (this._edgesRenderer && (!this._edgesRenderer.getValid())) {\r\n this._edgesRenderer.destroy();\r\n this._edgesRenderer = null;\r\n }\r\n if (this._edgesColorRenderer && (!this._edgesColorRenderer.getValid())) {\r\n this._edgesColorRenderer.destroy();\r\n this._edgesColorRenderer = null;\r\n }\r\n if (this._pickMeshRenderer && (!this._pickMeshRenderer.getValid())) {\r\n this._pickMeshRenderer.destroy();\r\n this._pickMeshRenderer = null;\r\n }\r\n if (this._pickDepthRenderer && (!this._pickDepthRenderer.getValid())) {\r\n this._pickDepthRenderer.destroy();\r\n this._pickDepthRenderer = null;\r\n }\r\n if (this._pickNormalsRenderer && this._pickNormalsRenderer.getValid() === false) {\r\n this._pickNormalsRenderer.destroy();\r\n this._pickNormalsRenderer = null;\r\n }\r\n if (this._pickNormalsFlatRenderer && this._pickNormalsFlatRenderer.getValid() === false) {\r\n this._pickNormalsFlatRenderer.destroy();\r\n this._pickNormalsFlatRenderer = null;\r\n }\r\n if (this._occlusionRenderer && this._occlusionRenderer.getValid() === false) {\r\n this._occlusionRenderer.destroy();\r\n this._occlusionRenderer = null;\r\n }\r\n if (this._shadowRenderer && (!this._shadowRenderer.getValid())) {\r\n this._shadowRenderer.destroy();\r\n this._shadowRenderer = null;\r\n }\r\n if (this._snapInitRenderer && (!this._snapInitRenderer.getValid())) {\r\n this._snapInitRenderer.destroy();\r\n this._snapInitRenderer = null;\r\n }\r\n if (this._snapRenderer && (!this._snapRenderer.getValid())) {\r\n this._snapRenderer.destroy();\r\n this._snapRenderer = null;\r\n }\r\n }\r\n\r\n eagerCreateRenders() {\r\n\r\n // Pre-initialize certain renderers that would otherwise be lazy-initialised\r\n // on user interaction, such as picking or emphasis, so that there is no delay\r\n // when user first begins interacting with the viewer.\r\n\r\n if (!this._silhouetteRenderer) { // Used for highlighting and selection\r\n this._silhouetteRenderer = new _TrianglesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_2__.TrianglesSilhouetteRenderer(this._scene);\r\n }\r\n if (!this._pickMeshRenderer) {\r\n this._pickMeshRenderer = new _TrianglesPickMeshRenderer_js__WEBPACK_IMPORTED_MODULE_5__.TrianglesPickMeshRenderer(this._scene);\r\n }\r\n if (!this._pickDepthRenderer) {\r\n this._pickDepthRenderer = new _TrianglesPickDepthRenderer_js__WEBPACK_IMPORTED_MODULE_6__.TrianglesPickDepthRenderer(this._scene);\r\n }\r\n if (!this._snapInitRenderer) {\r\n this._snapInitRenderer = new _TrianglesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_15__.TrianglesSnapInitRenderer(this._scene, false);\r\n }\r\n if (!this._snapRenderer) {\r\n this._snapRenderer = new _TrianglesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_16__.TrianglesSnapRenderer(this._scene);\r\n }\r\n }\r\n\r\n get colorRenderer() {\r\n if (!this._colorRenderer) {\r\n this._colorRenderer = new _TrianglesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__.TrianglesColorRenderer(this._scene, false);\r\n }\r\n return this._colorRenderer;\r\n }\r\n\r\n get colorRendererWithSAO() {\r\n if (!this._colorRendererWithSAO) {\r\n this._colorRendererWithSAO = new _TrianglesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__.TrianglesColorRenderer(this._scene, true);\r\n }\r\n return this._colorRendererWithSAO;\r\n }\r\n\r\n get flatColorRenderer() {\r\n if (!this._flatColorRenderer) {\r\n this._flatColorRenderer = new _TrianglesFlatColorRenderer_js__WEBPACK_IMPORTED_MODULE_1__.TrianglesFlatColorRenderer(this._scene, false);\r\n }\r\n return this._flatColorRenderer;\r\n }\r\n\r\n get flatColorRendererWithSAO() {\r\n if (!this._flatColorRendererWithSAO) {\r\n this._flatColorRendererWithSAO = new _TrianglesFlatColorRenderer_js__WEBPACK_IMPORTED_MODULE_1__.TrianglesFlatColorRenderer(this._scene, true);\r\n }\r\n return this._flatColorRendererWithSAO;\r\n }\r\n\r\n get colorTextureRenderer() {\r\n if (!this._colorTextureRenderer) {\r\n this._colorTextureRenderer = new _TrianglesColorTextureRenderer_js__WEBPACK_IMPORTED_MODULE_14__.TrianglesColorTextureRenderer(this._scene, false);\r\n }\r\n return this._colorTextureRenderer;\r\n }\r\n\r\n get colorTextureRendererWithSAO() {\r\n if (!this._colorTextureRendererWithSAO) {\r\n this._colorTextureRendererWithSAO = new _TrianglesColorTextureRenderer_js__WEBPACK_IMPORTED_MODULE_14__.TrianglesColorTextureRenderer(this._scene, true);\r\n }\r\n return this._colorTextureRendererWithSAO;\r\n }\r\n\r\n get pbrRenderer() {\r\n if (!this._pbrRenderer) {\r\n this._pbrRenderer = new _TrianglesPBRRenderer_js__WEBPACK_IMPORTED_MODULE_12__.TrianglesPBRRenderer(this._scene, false);\r\n }\r\n return this._pbrRenderer;\r\n }\r\n\r\n get pbrRendererWithSAO() {\r\n if (!this._pbrRendererWithSAO) {\r\n this._pbrRendererWithSAO = new _TrianglesPBRRenderer_js__WEBPACK_IMPORTED_MODULE_12__.TrianglesPBRRenderer(this._scene, true);\r\n }\r\n return this._pbrRendererWithSAO;\r\n }\r\n\r\n get silhouetteRenderer() {\r\n if (!this._silhouetteRenderer) {\r\n this._silhouetteRenderer = new _TrianglesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_2__.TrianglesSilhouetteRenderer(this._scene);\r\n }\r\n return this._silhouetteRenderer;\r\n }\r\n\r\n get depthRenderer() {\r\n if (!this._depthRenderer) {\r\n this._depthRenderer = new _TrianglesDepthRenderer_js__WEBPACK_IMPORTED_MODULE_9__.TrianglesDepthRenderer(this._scene);\r\n }\r\n return this._depthRenderer;\r\n }\r\n\r\n get normalsRenderer() {\r\n if (!this._normalsRenderer) {\r\n this._normalsRenderer = new _TrianglesNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_10__.TrianglesNormalsRenderer(this._scene);\r\n }\r\n return this._normalsRenderer;\r\n }\r\n\r\n get edgesRenderer() {\r\n if (!this._edgesRenderer) {\r\n this._edgesRenderer = new _EdgesEmphasisRenderer_js__WEBPACK_IMPORTED_MODULE_3__.EdgesEmphasisRenderer(this._scene);\r\n }\r\n return this._edgesRenderer;\r\n }\r\n\r\n get edgesColorRenderer() {\r\n if (!this._edgesColorRenderer) {\r\n this._edgesColorRenderer = new _EdgesColorRenderer_js__WEBPACK_IMPORTED_MODULE_4__.EdgesColorRenderer(this._scene);\r\n }\r\n return this._edgesColorRenderer;\r\n }\r\n\r\n get pickMeshRenderer() {\r\n if (!this._pickMeshRenderer) {\r\n this._pickMeshRenderer = new _TrianglesPickMeshRenderer_js__WEBPACK_IMPORTED_MODULE_5__.TrianglesPickMeshRenderer(this._scene);\r\n }\r\n return this._pickMeshRenderer;\r\n }\r\n\r\n get pickNormalsRenderer() {\r\n if (!this._pickNormalsRenderer) {\r\n this._pickNormalsRenderer = new _TrianglesPickNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_7__.TrianglesPickNormalsRenderer(this._scene);\r\n }\r\n return this._pickNormalsRenderer;\r\n }\r\n\r\n get pickNormalsFlatRenderer() {\r\n if (!this._pickNormalsFlatRenderer) {\r\n this._pickNormalsFlatRenderer = new _TrianglesPickNormalsFlatRenderer_js__WEBPACK_IMPORTED_MODULE_13__.TrianglesPickNormalsFlatRenderer(this._scene);\r\n }\r\n return this._pickNormalsFlatRenderer;\r\n }\r\n\r\n get pickDepthRenderer() {\r\n if (!this._pickDepthRenderer) {\r\n this._pickDepthRenderer = new _TrianglesPickDepthRenderer_js__WEBPACK_IMPORTED_MODULE_6__.TrianglesPickDepthRenderer(this._scene);\r\n }\r\n return this._pickDepthRenderer;\r\n }\r\n\r\n get occlusionRenderer() {\r\n if (!this._occlusionRenderer) {\r\n this._occlusionRenderer = new _TrianglesOcclusionRenderer_js__WEBPACK_IMPORTED_MODULE_8__.TrianglesOcclusionRenderer(this._scene);\r\n }\r\n return this._occlusionRenderer;\r\n }\r\n\r\n get shadowRenderer() {\r\n if (!this._shadowRenderer) {\r\n this._shadowRenderer = new _TrianglesShadowRenderer_js__WEBPACK_IMPORTED_MODULE_11__.TrianglesShadowRenderer(this._scene);\r\n }\r\n return this._shadowRenderer;\r\n }\r\n\r\n get snapRenderer() {\r\n if (!this._snapRenderer) {\r\n this._snapRenderer = new _TrianglesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_16__.TrianglesSnapRenderer(this._scene);\r\n }\r\n return this._snapRenderer;\r\n }\r\n\r\n get snapInitRenderer() {\r\n if (!this._snapInitRenderer) {\r\n this._snapInitRenderer = new _TrianglesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_15__.TrianglesSnapInitRenderer(this._scene);\r\n }\r\n return this._snapInitRenderer;\r\n }\r\n\r\n _destroy() {\r\n if (this._colorRenderer) {\r\n this._colorRenderer.destroy();\r\n }\r\n if (this._colorRendererWithSAO) {\r\n this._colorRendererWithSAO.destroy();\r\n }\r\n if (this._flatColorRenderer) {\r\n this._flatColorRenderer.destroy();\r\n }\r\n if (this._flatColorRendererWithSAO) {\r\n this._flatColorRendererWithSAO.destroy();\r\n }\r\n if (this._colorTextureRenderer) {\r\n this._colorTextureRenderer.destroy();\r\n }\r\n if (this._colorTextureRendererWithSAO) {\r\n this._colorTextureRendererWithSAO.destroy();\r\n }\r\n if (this._pbrRenderer) {\r\n this._pbrRenderer.destroy();\r\n }\r\n if (this._pbrRendererWithSAO) {\r\n this._pbrRendererWithSAO.destroy();\r\n }\r\n if (this._depthRenderer) {\r\n this._depthRenderer.destroy();\r\n }\r\n if (this._normalsRenderer) {\r\n this._normalsRenderer.destroy();\r\n }\r\n if (this._silhouetteRenderer) {\r\n this._silhouetteRenderer.destroy();\r\n }\r\n if (this._edgesRenderer) {\r\n this._edgesRenderer.destroy();\r\n }\r\n if (this._edgesColorRenderer) {\r\n this._edgesColorRenderer.destroy();\r\n }\r\n if (this._pickMeshRenderer) {\r\n this._pickMeshRenderer.destroy();\r\n }\r\n if (this._pickDepthRenderer) {\r\n this._pickDepthRenderer.destroy();\r\n }\r\n if (this._pickNormalsRenderer) {\r\n this._pickNormalsRenderer.destroy();\r\n }\r\n if (this._pickNormalsFlatRenderer) {\r\n this._pickNormalsFlatRenderer.destroy();\r\n }\r\n if (this._occlusionRenderer) {\r\n this._occlusionRenderer.destroy();\r\n }\r\n if (this._shadowRenderer) {\r\n this._shadowRenderer.destroy();\r\n }\r\n if (this._snapInitRenderer) {\r\n this._snapInitRenderer.destroy();\r\n }\r\n if (this._snapRenderer) {\r\n this._snapRenderer.destroy();\r\n }\r\n }\r\n}\r\n\r\nconst cachdRenderers = {};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction getRenderers(scene) {\r\n const sceneId = scene.id;\r\n let batchingRenderers = cachdRenderers[sceneId];\r\n if (!batchingRenderers) {\r\n batchingRenderers = new Renderers(scene);\r\n cachdRenderers[sceneId] = batchingRenderers;\r\n batchingRenderers._compile();\r\n batchingRenderers.eagerCreateRenders();\r\n scene.on(\"compile\", () => {\r\n batchingRenderers._compile();\r\n batchingRenderers.eagerCreateRenders();\r\n });\r\n scene.on(\"destroyed\", () => {\r\n delete cachdRenderers[sceneId];\r\n batchingRenderers._destroy();\r\n });\r\n }\r\n return batchingRenderers;\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js?");
|
|
4167
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getRenderers: () => (/* binding */ getRenderers)\n/* harmony export */ });\n/* harmony import */ var _TrianglesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./TrianglesColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js\");\n/* harmony import */ var _TrianglesFlatColorRenderer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TrianglesFlatColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js\");\n/* harmony import */ var _TrianglesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TrianglesSilhouetteRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSilhouetteRenderer.js\");\n/* harmony import */ var _EdgesEmphasisRenderer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./EdgesEmphasisRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesEmphasisRenderer.js\");\n/* harmony import */ var _EdgesColorRenderer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./EdgesColorRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/EdgesColorRenderer.js\");\n/* harmony import */ var _TrianglesPickMeshRenderer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./TrianglesPickMeshRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickMeshRenderer.js\");\n/* harmony import */ var _TrianglesPickDepthRenderer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./TrianglesPickDepthRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickDepthRenderer.js\");\n/* harmony import */ var _TrianglesPickNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./TrianglesPickNormalsRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsRenderer.js\");\n/* harmony import */ var _TrianglesOcclusionRenderer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./TrianglesOcclusionRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesOcclusionRenderer.js\");\n/* harmony import */ var _TrianglesDepthRenderer_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TrianglesDepthRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesDepthRenderer.js\");\n/* harmony import */ var _TrianglesNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./TrianglesNormalsRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesNormalsRenderer.js\");\n/* harmony import */ var _TrianglesShadowRenderer_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./TrianglesShadowRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesShadowRenderer.js\");\n/* harmony import */ var _TrianglesPBRRenderer_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./TrianglesPBRRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPBRRenderer.js\");\n/* harmony import */ var _TrianglesPickNormalsFlatRenderer_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./TrianglesPickNormalsFlatRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesPickNormalsFlatRenderer.js\");\n/* harmony import */ var _TrianglesColorTextureRenderer_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./TrianglesColorTextureRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js\");\n/* harmony import */ var _TrianglesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./TrianglesSnapInitRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapInitRenderer.js\");\n/* harmony import */ var _TrianglesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./TrianglesSnapRenderer.js */ \"./src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @private\n */\nclass Renderers {\n\n constructor(scene) {\n this._scene = scene;\n }\n\n _compile() {\n if (this._colorRenderer && (!this._colorRenderer.getValid())) {\n this._colorRenderer.destroy();\n this._colorRenderer = null;\n }\n if (this._colorRendererWithSAO && (!this._colorRendererWithSAO.getValid())) {\n this._colorRendererWithSAO.destroy();\n this._colorRendererWithSAO = null;\n }\n if (this._flatColorRenderer && (!this._flatColorRenderer.getValid())) {\n this._flatColorRenderer.destroy();\n this._flatColorRenderer = null;\n }\n if (this._flatColorRendererWithSAO && (!this._flatColorRendererWithSAO.getValid())) {\n this._flatColorRendererWithSAO.destroy();\n this._flatColorRendererWithSAO = null;\n }\n if (this._colorTextureRenderer && (!this._colorTextureRenderer.getValid())) {\n this._colorTextureRenderer.destroy();\n this._colorTextureRenderer = null;\n }\n if (this._colorTextureRendererWithSAO && (!this._colorTextureRendererWithSAO.getValid())) {\n this._colorTextureRendererWithSAO.destroy();\n this._colorTextureRendererWithSAO = null;\n }\n if (this._pbrRenderer && (!this._pbrRenderer.getValid())) {\n this._pbrRenderer.destroy();\n this._pbrRenderer = null;\n }\n if (this._pbrRendererWithSAO && (!this._pbrRendererWithSAO.getValid())) {\n this._pbrRendererWithSAO.destroy();\n this._pbrRendererWithSAO = null;\n }\n if (this._depthRenderer && (!this._depthRenderer.getValid())) {\n this._depthRenderer.destroy();\n this._depthRenderer = null;\n }\n if (this._normalsRenderer && (!this._normalsRenderer.getValid())) {\n this._normalsRenderer.destroy();\n this._normalsRenderer = null;\n }\n if (this._silhouetteRenderer && (!this._silhouetteRenderer.getValid())) {\n this._silhouetteRenderer.destroy();\n this._silhouetteRenderer = null;\n }\n if (this._edgesRenderer && (!this._edgesRenderer.getValid())) {\n this._edgesRenderer.destroy();\n this._edgesRenderer = null;\n }\n if (this._edgesColorRenderer && (!this._edgesColorRenderer.getValid())) {\n this._edgesColorRenderer.destroy();\n this._edgesColorRenderer = null;\n }\n if (this._pickMeshRenderer && (!this._pickMeshRenderer.getValid())) {\n this._pickMeshRenderer.destroy();\n this._pickMeshRenderer = null;\n }\n if (this._pickDepthRenderer && (!this._pickDepthRenderer.getValid())) {\n this._pickDepthRenderer.destroy();\n this._pickDepthRenderer = null;\n }\n if (this._pickNormalsRenderer && this._pickNormalsRenderer.getValid() === false) {\n this._pickNormalsRenderer.destroy();\n this._pickNormalsRenderer = null;\n }\n if (this._pickNormalsFlatRenderer && this._pickNormalsFlatRenderer.getValid() === false) {\n this._pickNormalsFlatRenderer.destroy();\n this._pickNormalsFlatRenderer = null;\n }\n if (this._occlusionRenderer && this._occlusionRenderer.getValid() === false) {\n this._occlusionRenderer.destroy();\n this._occlusionRenderer = null;\n }\n if (this._shadowRenderer && (!this._shadowRenderer.getValid())) {\n this._shadowRenderer.destroy();\n this._shadowRenderer = null;\n }\n if (this._snapInitRenderer && (!this._snapInitRenderer.getValid())) {\n this._snapInitRenderer.destroy();\n this._snapInitRenderer = null;\n }\n if (this._snapRenderer && (!this._snapRenderer.getValid())) {\n this._snapRenderer.destroy();\n this._snapRenderer = null;\n }\n }\n\n eagerCreateRenders() {\n\n // Pre-initialize certain renderers that would otherwise be lazy-initialised\n // on user interaction, such as picking or emphasis, so that there is no delay\n // when user first begins interacting with the viewer.\n\n if (!this._silhouetteRenderer) { // Used for highlighting and selection\n this._silhouetteRenderer = new _TrianglesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_2__.TrianglesSilhouetteRenderer(this._scene);\n }\n if (!this._pickMeshRenderer) {\n this._pickMeshRenderer = new _TrianglesPickMeshRenderer_js__WEBPACK_IMPORTED_MODULE_5__.TrianglesPickMeshRenderer(this._scene);\n }\n if (!this._pickDepthRenderer) {\n this._pickDepthRenderer = new _TrianglesPickDepthRenderer_js__WEBPACK_IMPORTED_MODULE_6__.TrianglesPickDepthRenderer(this._scene);\n }\n if (!this._snapInitRenderer) {\n this._snapInitRenderer = new _TrianglesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_15__.TrianglesSnapInitRenderer(this._scene, false);\n }\n if (!this._snapRenderer) {\n this._snapRenderer = new _TrianglesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_16__.TrianglesSnapRenderer(this._scene);\n }\n }\n\n get colorRenderer() {\n if (!this._colorRenderer) {\n this._colorRenderer = new _TrianglesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__.TrianglesColorRenderer(this._scene, false);\n }\n return this._colorRenderer;\n }\n\n get colorRendererWithSAO() {\n if (!this._colorRendererWithSAO) {\n this._colorRendererWithSAO = new _TrianglesColorRenderer_js__WEBPACK_IMPORTED_MODULE_0__.TrianglesColorRenderer(this._scene, true);\n }\n return this._colorRendererWithSAO;\n }\n\n get flatColorRenderer() {\n if (!this._flatColorRenderer) {\n this._flatColorRenderer = new _TrianglesFlatColorRenderer_js__WEBPACK_IMPORTED_MODULE_1__.TrianglesFlatColorRenderer(this._scene, false);\n }\n return this._flatColorRenderer;\n }\n\n get flatColorRendererWithSAO() {\n if (!this._flatColorRendererWithSAO) {\n this._flatColorRendererWithSAO = new _TrianglesFlatColorRenderer_js__WEBPACK_IMPORTED_MODULE_1__.TrianglesFlatColorRenderer(this._scene, true);\n }\n return this._flatColorRendererWithSAO;\n }\n\n get colorTextureRenderer() {\n if (!this._colorTextureRenderer) {\n this._colorTextureRenderer = new _TrianglesColorTextureRenderer_js__WEBPACK_IMPORTED_MODULE_14__.TrianglesColorTextureRenderer(this._scene, false);\n }\n return this._colorTextureRenderer;\n }\n\n get colorTextureRendererWithSAO() {\n if (!this._colorTextureRendererWithSAO) {\n this._colorTextureRendererWithSAO = new _TrianglesColorTextureRenderer_js__WEBPACK_IMPORTED_MODULE_14__.TrianglesColorTextureRenderer(this._scene, true);\n }\n return this._colorTextureRendererWithSAO;\n }\n\n get pbrRenderer() {\n if (!this._pbrRenderer) {\n this._pbrRenderer = new _TrianglesPBRRenderer_js__WEBPACK_IMPORTED_MODULE_12__.TrianglesPBRRenderer(this._scene, false);\n }\n return this._pbrRenderer;\n }\n\n get pbrRendererWithSAO() {\n if (!this._pbrRendererWithSAO) {\n this._pbrRendererWithSAO = new _TrianglesPBRRenderer_js__WEBPACK_IMPORTED_MODULE_12__.TrianglesPBRRenderer(this._scene, true);\n }\n return this._pbrRendererWithSAO;\n }\n\n get silhouetteRenderer() {\n if (!this._silhouetteRenderer) {\n this._silhouetteRenderer = new _TrianglesSilhouetteRenderer_js__WEBPACK_IMPORTED_MODULE_2__.TrianglesSilhouetteRenderer(this._scene);\n }\n return this._silhouetteRenderer;\n }\n\n get depthRenderer() {\n if (!this._depthRenderer) {\n this._depthRenderer = new _TrianglesDepthRenderer_js__WEBPACK_IMPORTED_MODULE_9__.TrianglesDepthRenderer(this._scene);\n }\n return this._depthRenderer;\n }\n\n get normalsRenderer() {\n if (!this._normalsRenderer) {\n this._normalsRenderer = new _TrianglesNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_10__.TrianglesNormalsRenderer(this._scene);\n }\n return this._normalsRenderer;\n }\n\n get edgesRenderer() {\n if (!this._edgesRenderer) {\n this._edgesRenderer = new _EdgesEmphasisRenderer_js__WEBPACK_IMPORTED_MODULE_3__.EdgesEmphasisRenderer(this._scene);\n }\n return this._edgesRenderer;\n }\n\n get edgesColorRenderer() {\n if (!this._edgesColorRenderer) {\n this._edgesColorRenderer = new _EdgesColorRenderer_js__WEBPACK_IMPORTED_MODULE_4__.EdgesColorRenderer(this._scene);\n }\n return this._edgesColorRenderer;\n }\n\n get pickMeshRenderer() {\n if (!this._pickMeshRenderer) {\n this._pickMeshRenderer = new _TrianglesPickMeshRenderer_js__WEBPACK_IMPORTED_MODULE_5__.TrianglesPickMeshRenderer(this._scene);\n }\n return this._pickMeshRenderer;\n }\n\n get pickNormalsRenderer() {\n if (!this._pickNormalsRenderer) {\n this._pickNormalsRenderer = new _TrianglesPickNormalsRenderer_js__WEBPACK_IMPORTED_MODULE_7__.TrianglesPickNormalsRenderer(this._scene);\n }\n return this._pickNormalsRenderer;\n }\n\n get pickNormalsFlatRenderer() {\n if (!this._pickNormalsFlatRenderer) {\n this._pickNormalsFlatRenderer = new _TrianglesPickNormalsFlatRenderer_js__WEBPACK_IMPORTED_MODULE_13__.TrianglesPickNormalsFlatRenderer(this._scene);\n }\n return this._pickNormalsFlatRenderer;\n }\n\n get pickDepthRenderer() {\n if (!this._pickDepthRenderer) {\n this._pickDepthRenderer = new _TrianglesPickDepthRenderer_js__WEBPACK_IMPORTED_MODULE_6__.TrianglesPickDepthRenderer(this._scene);\n }\n return this._pickDepthRenderer;\n }\n\n get occlusionRenderer() {\n if (!this._occlusionRenderer) {\n this._occlusionRenderer = new _TrianglesOcclusionRenderer_js__WEBPACK_IMPORTED_MODULE_8__.TrianglesOcclusionRenderer(this._scene);\n }\n return this._occlusionRenderer;\n }\n\n get shadowRenderer() {\n if (!this._shadowRenderer) {\n this._shadowRenderer = new _TrianglesShadowRenderer_js__WEBPACK_IMPORTED_MODULE_11__.TrianglesShadowRenderer(this._scene);\n }\n return this._shadowRenderer;\n }\n\n get snapRenderer() {\n if (!this._snapRenderer) {\n this._snapRenderer = new _TrianglesSnapRenderer_js__WEBPACK_IMPORTED_MODULE_16__.TrianglesSnapRenderer(this._scene);\n }\n return this._snapRenderer;\n }\n\n get snapInitRenderer() {\n if (!this._snapInitRenderer) {\n this._snapInitRenderer = new _TrianglesSnapInitRenderer_js__WEBPACK_IMPORTED_MODULE_15__.TrianglesSnapInitRenderer(this._scene);\n }\n return this._snapInitRenderer;\n }\n\n _destroy() {\n if (this._colorRenderer) {\n this._colorRenderer.destroy();\n }\n if (this._colorRendererWithSAO) {\n this._colorRendererWithSAO.destroy();\n }\n if (this._flatColorRenderer) {\n this._flatColorRenderer.destroy();\n }\n if (this._flatColorRendererWithSAO) {\n this._flatColorRendererWithSAO.destroy();\n }\n if (this._colorTextureRenderer) {\n this._colorTextureRenderer.destroy();\n }\n if (this._colorTextureRendererWithSAO) {\n this._colorTextureRendererWithSAO.destroy();\n }\n if (this._pbrRenderer) {\n this._pbrRenderer.destroy();\n }\n if (this._pbrRendererWithSAO) {\n this._pbrRendererWithSAO.destroy();\n }\n if (this._depthRenderer) {\n this._depthRenderer.destroy();\n }\n if (this._normalsRenderer) {\n this._normalsRenderer.destroy();\n }\n if (this._silhouetteRenderer) {\n this._silhouetteRenderer.destroy();\n }\n if (this._edgesRenderer) {\n this._edgesRenderer.destroy();\n }\n if (this._edgesColorRenderer) {\n this._edgesColorRenderer.destroy();\n }\n if (this._pickMeshRenderer) {\n this._pickMeshRenderer.destroy();\n }\n if (this._pickDepthRenderer) {\n this._pickDepthRenderer.destroy();\n }\n if (this._pickNormalsRenderer) {\n this._pickNormalsRenderer.destroy();\n }\n if (this._pickNormalsFlatRenderer) {\n this._pickNormalsFlatRenderer.destroy();\n }\n if (this._occlusionRenderer) {\n this._occlusionRenderer.destroy();\n }\n if (this._shadowRenderer) {\n this._shadowRenderer.destroy();\n }\n if (this._snapInitRenderer) {\n this._snapInitRenderer.destroy();\n }\n if (this._snapRenderer) {\n this._snapRenderer.destroy();\n }\n }\n}\n\nconst cachdRenderers = {};\n\n/**\n * @private\n */\nfunction getRenderers(scene) {\n const sceneId = scene.id;\n let batchingRenderers = cachdRenderers[sceneId];\n if (!batchingRenderers) {\n batchingRenderers = new Renderers(scene);\n cachdRenderers[sceneId] = batchingRenderers;\n batchingRenderers._compile();\n batchingRenderers.eagerCreateRenders();\n scene.on(\"compile\", () => {\n batchingRenderers._compile();\n batchingRenderers.eagerCreateRenders();\n });\n scene.on(\"destroyed\", () => {\n delete cachdRenderers[sceneId];\n batchingRenderers._destroy();\n });\n }\n return batchingRenderers;\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js?");
|
|
4168
4168
|
|
|
4169
4169
|
/***/ }),
|
|
4170
4170
|
|
|
@@ -4524,7 +4524,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4524
4524
|
\****************************************************************************************/
|
|
4525
4525
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4526
4526
|
|
|
4527
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBOInstancingTrianglesLayer: () => (/* binding */ VBOInstancingTrianglesLayer)\n/* harmony export */ });\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.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 _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../webgl/RenderState.js */ \"./src/viewer/scene/webgl/RenderState.js\");\n/* harmony import */ var _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../webgl/ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./renderers/Renderers.js */ \"./src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst tempUint8Vec4 = new Uint8Array(4);\r\nconst tempFloat32 = new Float32Array(1);\r\nconst tempVec4a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec4([0, 0, 0, 1]);\r\nconst tempVec3fa = new Float32Array(3);\r\n\r\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3b = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3d = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3e = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3f = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\nconst tempVec3g = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\r\n\r\nconst tempFloat32Vec4 = new Float32Array(4);\r\n\r\n/**\r\n * @private\r\n */\r\nclass VBOInstancingTrianglesLayer {\r\n\r\n /**\r\n * @param cfg\r\n * @param cfg.layerIndex\r\n * @param cfg.model\r\n * @param cfg.geometry\r\n * @param cfg.textureSet\r\n * @param cfg.origin\r\n */\r\n constructor(cfg) {\r\n\r\n console.info(\"Creating VBOInstancingTrianglesLayer\");\r\n\r\n /**\r\n * Owner model\r\n * @type {VBOSceneModel}\r\n */\r\n this.model = cfg.model;\r\n\r\n /**\r\n * State sorting key.\r\n * @type {string}\r\n */\r\n this.sortId = \"TrianglesInstancingLayer\" + (cfg.solid ? \"-solid\" : \"-surface\") + (cfg.normals ? \"-normals\" : \"-autoNormals\");\r\n\r\n /**\r\n * Index of this InstancingLayer in VBOSceneModel#_layerList\r\n * @type {Number}\r\n */\r\n this.layerIndex = cfg.layerIndex;\r\n\r\n this._renderers = (0,_renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_5__.getRenderers)(cfg.model.scene);\r\n\r\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\r\n\r\n this._state = new _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__.RenderState({\r\n numInstances: 0,\r\n obb: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.OBB3(),\r\n origin: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3(),\r\n geometry: cfg.geometry,\r\n textureSet: cfg.textureSet,\r\n pbrSupported: false, // Set in #finalize if we have enough to support quality rendering\r\n positionsDecodeMatrix: cfg.geometry.positionsDecodeMatrix, // So we can null the geometry for GC\r\n colorsBuf: null,\r\n metallicRoughnessBuf: null,\r\n flagsBuf: null,\r\n offsetsBuf: null,\r\n modelMatrixBuf: null,\r\n modelMatrixCol0Buf: null,\r\n modelMatrixCol1Buf: null,\r\n modelMatrixCol2Buf: null,\r\n modelNormalMatrixCol0Buf: null,\r\n modelNormalMatrixCol1Buf: null,\r\n modelNormalMatrixCol2Buf: null,\r\n pickColorsBuf: null\r\n });\r\n\r\n // These counts are used to avoid unnecessary render passes\r\n this._numPortions = 0;\r\n this._numVisibleLayerPortions = 0;\r\n this._numTransparentLayerPortions = 0;\r\n this._numXRayedLayerPortions = 0;\r\n this._numHighlightedLayerPortions = 0;\r\n this._numSelectedLayerPortions = 0;\r\n this._numClippableLayerPortions = 0;\r\n this._numEdgesLayerPortions = 0;\r\n this._numPickableLayerPortions = 0;\r\n this._numCulledLayerPortions = 0;\r\n\r\n /** @private */\r\n this.numIndices = cfg.geometry.numIndices;\r\n\r\n // Vertex arrays\r\n this._colors = [];\r\n this._metallicRoughness = [];\r\n this._pickColors = [];\r\n this._offsets = [];\r\n\r\n // Modeling matrix per instance, array for each column\r\n\r\n this._modelMatrix = [];\r\n\r\n this._modelMatrixCol0 = [];\r\n this._modelMatrixCol1 = [];\r\n this._modelMatrixCol2 = [];\r\n\r\n // Modeling normal matrix per instance, array for each column\r\n this._modelNormalMatrixCol0 = [];\r\n this._modelNormalMatrixCol1 = [];\r\n this._modelNormalMatrixCol2 = [];\r\n\r\n this._portions = [];\r\n this._meshes = [];\r\n\r\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\r\n this.aabbDirty = true;\r\n\r\n if (cfg.origin) {\r\n this._state.origin.set(cfg.origin);\r\n }\r\n\r\n this._finalized = false;\r\n\r\n /**\r\n * When true, this layer contains solid triangle meshes, otherwise this layer contains surface triangle meshes\r\n * @type {boolean}\r\n */\r\n this.solid = !!cfg.solid;\r\n\r\n /**\r\n * The number of indices in this layer.\r\n * @type {number|*}\r\n */\r\n this.numIndices = cfg.geometry.numIndices;\r\n }\r\n\r\n get aabb() {\r\n if (this.aabbDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(this._aabb);\r\n for (let i = 0, len = this._meshes.length; i < len; i++) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._aabb, this._meshes[i].aabb);\r\n }\r\n this.aabbDirty = false;\r\n }\r\n return this._aabb;\r\n }\r\n\r\n /**\r\n * Creates a new portion within this InstancingLayer, returns the new portion ID.\r\n *\r\n * The portion will instance this InstancingLayer's geometry.\r\n *\r\n * Gives the portion the specified color and matrix.\r\n *\r\n * @param mesh The SceneModelMesh that owns the portion\r\n * @param cfg Portion params\r\n * @param cfg.color Color [0..255,0..255,0..255]\r\n * @param cfg.metallic Metalness factor [0..255]\r\n * @param cfg.roughness Roughness factor [0..255]\r\n * @param cfg.opacity Opacity [0..255].\r\n * @param cfg.meshMatrix Flat float 4x4 matrix.\r\n * @param [cfg.worldMatrix] Flat float 4x4 matrix.\r\n * @param cfg.pickColor Quantized pick color\r\n * @returns {number} Portion ID.\r\n */\r\n createPortion(mesh, cfg) {\r\n\r\n const color = cfg.color;\r\n const metallic = cfg.metallic;\r\n const roughness = cfg.roughness;\r\n const opacity = cfg.opacity !== null && cfg.opacity !== undefined ? cfg.opacity : 255;\r\n const meshMatrix = cfg.meshMatrix;\r\n const pickColor = cfg.pickColor;\r\n\r\n if (this._finalized) {\r\n throw \"Already finalized\";\r\n }\r\n\r\n const r = color[0]; // Color is pre-quantized by SceneModel\r\n const g = color[1];\r\n const b = color[2];\r\n\r\n this._colors.push(r);\r\n this._colors.push(g);\r\n this._colors.push(b);\r\n this._colors.push(opacity);\r\n\r\n this._metallicRoughness.push((metallic !== null && metallic !== undefined) ? metallic : 0);\r\n this._metallicRoughness.push((roughness !== null && roughness !== undefined) ? roughness : 255);\r\n\r\n if (this.model.scene.entityOffsetsEnabled) {\r\n this._offsets.push(0);\r\n this._offsets.push(0);\r\n this._offsets.push(0);\r\n }\r\n\r\n this._modelMatrixCol0.push(meshMatrix[0]);\r\n this._modelMatrixCol0.push(meshMatrix[4]);\r\n this._modelMatrixCol0.push(meshMatrix[8]);\r\n this._modelMatrixCol0.push(meshMatrix[12]);\r\n\r\n this._modelMatrixCol1.push(meshMatrix[1]);\r\n this._modelMatrixCol1.push(meshMatrix[5]);\r\n this._modelMatrixCol1.push(meshMatrix[9]);\r\n this._modelMatrixCol1.push(meshMatrix[13]);\r\n\r\n this._modelMatrixCol2.push(meshMatrix[2]);\r\n this._modelMatrixCol2.push(meshMatrix[6]);\r\n this._modelMatrixCol2.push(meshMatrix[10]);\r\n this._modelMatrixCol2.push(meshMatrix[14]);\r\n\r\n if (this._state.geometry.normals) {\r\n\r\n // Note: order of inverse and transpose doesn't matter\r\n\r\n let transposedMat = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transposeMat4(meshMatrix, _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4()); // TODO: Use cached matrix\r\n let normalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(transposedMat);\r\n\r\n this._modelNormalMatrixCol0.push(normalMatrix[0]);\r\n this._modelNormalMatrixCol0.push(normalMatrix[4]);\r\n this._modelNormalMatrixCol0.push(normalMatrix[8]);\r\n this._modelNormalMatrixCol0.push(normalMatrix[12]);\r\n\r\n this._modelNormalMatrixCol1.push(normalMatrix[1]);\r\n this._modelNormalMatrixCol1.push(normalMatrix[5]);\r\n this._modelNormalMatrixCol1.push(normalMatrix[9]);\r\n this._modelNormalMatrixCol1.push(normalMatrix[13]);\r\n\r\n this._modelNormalMatrixCol2.push(normalMatrix[2]);\r\n this._modelNormalMatrixCol2.push(normalMatrix[6]);\r\n this._modelNormalMatrixCol2.push(normalMatrix[10]);\r\n this._modelNormalMatrixCol2.push(normalMatrix[14]);\r\n }\r\n\r\n // Per-vertex pick colors\r\n\r\n this._pickColors.push(pickColor[0]);\r\n this._pickColors.push(pickColor[1]);\r\n this._pickColors.push(pickColor[2]);\r\n this._pickColors.push(pickColor[3]);\r\n\r\n this._state.numInstances++;\r\n\r\n const portionId = this._portions.length;\r\n\r\n const portion = {};\r\n\r\n if (this.model.scene.pickSurfacePrecisionEnabled) {\r\n portion.matrix = meshMatrix.slice();\r\n portion.inverseMatrix = null; // Lazy-computed in precisionRayPickSurface\r\n portion.normalMatrix = null; // Lazy-computed in precisionRayPickSurface\r\n }\r\n\r\n this._portions.push(portion);\r\n\r\n this._numPortions++;\r\n this.model.numPortions++;\r\n this._meshes.push(mesh);\r\n return portionId;\r\n }\r\n\r\n finalize() {\r\n\r\n if (this._finalized) {\r\n return;\r\n }\r\n\r\n const state = this._state;\r\n const geometry = state.geometry;\r\n const textureSet = state.textureSet;\r\n const gl = this.model.scene.canvas.gl;\r\n const colorsLength = this._colors.length;\r\n const flagsLength = colorsLength / 4;\r\n\r\n if (colorsLength > 0) {\r\n let notNormalized = false;\r\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Uint8Array(this._colors), this._colors.length, 4, gl.DYNAMIC_DRAW, notNormalized);\r\n this._colors = []; // Release memory\r\n }\r\n\r\n if (this._metallicRoughness.length > 0) {\r\n const metallicRoughness = new Uint8Array(this._metallicRoughness);\r\n let normalized = false;\r\n state.metallicRoughnessBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, metallicRoughness, this._metallicRoughness.length, 2, gl.STATIC_DRAW, normalized);\r\n }\r\n\r\n if (flagsLength > 0) {\r\n // Because we only build flags arrays here,\r\n // get their length from the colors array\r\n let notNormalized = false;\r\n state.flagsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(flagsLength), flagsLength, 1, gl.DYNAMIC_DRAW, notNormalized);\r\n }\r\n\r\n if (this.model.scene.entityOffsetsEnabled) {\r\n if (this._offsets.length > 0) {\r\n const notNormalized = false;\r\n state.offsetsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._offsets), this._offsets.length, 3, gl.DYNAMIC_DRAW, notNormalized);\r\n this._offsets = []; // Release memory\r\n }\r\n }\r\n\r\n if (geometry.positionsCompressed && geometry.positionsCompressed.length > 0) {\r\n const normalized = false;\r\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, geometry.positionsCompressed, geometry.positionsCompressed.length, 3, gl.STATIC_DRAW, normalized);\r\n state.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4(geometry.positionsDecodeMatrix);\r\n }\r\n // if (geometry.normalsCompressed && geometry.normalsCompressed.length > 0) {\r\n // const normalized = true; // For oct-encoded UInt8\r\n // state.normalsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, geometry.normalsCompressed, geometry.normalsCompressed.length, 3, gl.STATIC_DRAW, normalized);\r\n // }\r\n if (geometry.colorsCompressed && geometry.colorsCompressed.length > 0) {\r\n const colorsCompressed = new Uint8Array(geometry.colorsCompressed);\r\n const notNormalized = false;\r\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, colorsCompressed, colorsCompressed.length, 4, gl.STATIC_DRAW, notNormalized);\r\n }\r\n if (geometry.uvCompressed && geometry.uvCompressed.length > 0) {\r\n const uvCompressed = geometry.uvCompressed;\r\n state.uvDecodeMatrix = geometry.uvDecodeMatrix;\r\n state.uvBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, uvCompressed, uvCompressed.length, 2, gl.STATIC_DRAW, false);\r\n }\r\n if (geometry.indices && geometry.indices.length > 0) {\r\n state.indicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.indices), geometry.indices.length, 1, gl.STATIC_DRAW);\r\n state.numIndices = geometry.indices.length;\r\n }\r\n if (geometry.primitive === \"triangles\" || geometry.primitive === \"solid\" || geometry.primitive === \"surface\") {\r\n state.edgeIndicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.edgeIndices), geometry.edgeIndices.length, 1, gl.STATIC_DRAW);\r\n }\r\n\r\n if (this._modelMatrixCol0.length > 0) {\r\n\r\n const normalized = false;\r\n\r\n state.modelMatrixCol0Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelMatrixCol0), this._modelMatrixCol0.length, 4, gl.STATIC_DRAW, normalized);\r\n state.modelMatrixCol1Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelMatrixCol1), this._modelMatrixCol1.length, 4, gl.STATIC_DRAW, normalized);\r\n state.modelMatrixCol2Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelMatrixCol2), this._modelMatrixCol2.length, 4, gl.STATIC_DRAW, normalized);\r\n this._modelMatrixCol0 = [];\r\n this._modelMatrixCol1 = [];\r\n this._modelMatrixCol2 = [];\r\n\r\n if (state.normalsBuf) {\r\n state.modelNormalMatrixCol0Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelNormalMatrixCol0), this._modelNormalMatrixCol0.length, 4, gl.STATIC_DRAW, normalized);\r\n state.modelNormalMatrixCol1Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelNormalMatrixCol1), this._modelNormalMatrixCol1.length, 4, gl.STATIC_DRAW, normalized);\r\n state.modelNormalMatrixCol2Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelNormalMatrixCol2), this._modelNormalMatrixCol2.length, 4, gl.STATIC_DRAW, normalized);\r\n this._modelNormalMatrixCol0 = [];\r\n this._modelNormalMatrixCol1 = [];\r\n this._modelNormalMatrixCol2 = [];\r\n }\r\n }\r\n\r\n if (this._pickColors.length > 0) {\r\n const normalized = false;\r\n state.pickColorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Uint8Array(this._pickColors), this._pickColors.length, 4, gl.STATIC_DRAW, normalized);\r\n this._pickColors = []; // Release memory\r\n }\r\n\r\n state.pbrSupported\r\n = !!state.metallicRoughnessBuf\r\n && !!state.uvBuf\r\n && !!state.normalsBuf\r\n && !!textureSet\r\n && !!textureSet.colorTexture\r\n && !!textureSet.metallicRoughnessTexture;\r\n\r\n state.colorTextureSupported\r\n = !!state.uvBuf\r\n && !!textureSet\r\n && !!textureSet.colorTexture;\r\n\r\n this._state.geometry = null;\r\n\r\n this._finalized = true;\r\n }\r\n\r\n // The following setters are called by VBOSceneModelMesh, in turn called by VBOSceneModelNode, only after the layer is finalized.\r\n // It's important that these are called after finalize() in order to maintain integrity of counts like _numVisibleLayerPortions etc.\r\n\r\n initFlags(portionId, flags, meshTransparent) {\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\r\n this._numVisibleLayerPortions++;\r\n this.model.numVisibleLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\r\n this._numHighlightedLayerPortions++;\r\n this.model.numHighlightedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\r\n this._numXRayedLayerPortions++;\r\n this.model.numXRayedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\r\n this._numSelectedLayerPortions++;\r\n this.model.numSelectedLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\r\n this._numClippableLayerPortions++;\r\n this.model.numClippableLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\r\n this._numEdgesLayerPortions++;\r\n this.model.numEdgesLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\r\n this._numPickableLayerPortions++;\r\n this.model.numPickableLayerPortions++;\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\r\n this._numCulledLayerPortions++;\r\n this.model.numCulledLayerPortions++;\r\n }\r\n if (meshTransparent) {\r\n this._numTransparentLayerPortions++;\r\n this.model.numTransparentLayerPortions++;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setVisible(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\r\n this._numVisibleLayerPortions++;\r\n this.model.numVisibleLayerPortions++;\r\n } else {\r\n this._numVisibleLayerPortions--;\r\n this.model.numVisibleLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setHighlighted(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\r\n this._numHighlightedLayerPortions++;\r\n this.model.numHighlightedLayerPortions++;\r\n } else {\r\n this._numHighlightedLayerPortions--;\r\n this.model.numHighlightedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setXRayed(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\r\n this._numXRayedLayerPortions++;\r\n this.model.numXRayedLayerPortions++;\r\n } else {\r\n this._numXRayedLayerPortions--;\r\n this.model.numXRayedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setSelected(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\r\n this._numSelectedLayerPortions++;\r\n this.model.numSelectedLayerPortions++;\r\n } else {\r\n this._numSelectedLayerPortions--;\r\n this.model.numSelectedLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setEdges(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\r\n this._numEdgesLayerPortions++;\r\n this.model.numEdgesLayerPortions++;\r\n } else {\r\n this._numEdgesLayerPortions--;\r\n this.model.numEdgesLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setClippable(portionId, flags) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\r\n this._numClippableLayerPortions++;\r\n this.model.numClippableLayerPortions++;\r\n } else {\r\n this._numClippableLayerPortions--;\r\n this.model.numClippableLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags);\r\n }\r\n\r\n setCollidable(portionId, flags) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n }\r\n\r\n setPickable(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\r\n this._numPickableLayerPortions++;\r\n this.model.numPickableLayerPortions++;\r\n } else {\r\n this._numPickableLayerPortions--;\r\n this.model.numPickableLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setCulled(portionId, flags, meshTransparent) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\r\n this._numCulledLayerPortions++;\r\n this.model.numCulledLayerPortions++;\r\n } else {\r\n this._numCulledLayerPortions--;\r\n this.model.numCulledLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, meshTransparent);\r\n }\r\n\r\n setColor(portionId, color) { // RGBA color is normalized as ints\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n tempUint8Vec4[0] = color[0];\r\n tempUint8Vec4[1] = color[1];\r\n tempUint8Vec4[2] = color[2];\r\n tempUint8Vec4[3] = color[3];\r\n if (this._state.colorsBuf) {\r\n this._state.colorsBuf.setData(tempUint8Vec4, portionId * 4);\r\n }\r\n }\r\n\r\n setTransparent(portionId, flags, transparent) {\r\n if (transparent) {\r\n this._numTransparentLayerPortions++;\r\n this.model.numTransparentLayerPortions++;\r\n } else {\r\n this._numTransparentLayerPortions--;\r\n this.model.numTransparentLayerPortions--;\r\n }\r\n this._setFlags(portionId, flags, transparent);\r\n }\r\n\r\n // setMatrix(portionId, matrix) {\r\n //\r\n // if (!this._finalized) {\r\n // throw \"Not finalized\";\r\n // }\r\n //\r\n // var offset = portionId * 4;\r\n //\r\n // tempFloat32Vec4[0] = matrix[0];\r\n // tempFloat32Vec4[1] = matrix[4];\r\n // tempFloat32Vec4[2] = matrix[8];\r\n // tempFloat32Vec4[3] = matrix[12];\r\n //\r\n // this._state.modelMatrixCol0Buf.setData(tempFloat32Vec4, offset);\r\n //\r\n // tempFloat32Vec4[0] = matrix[1];\r\n // tempFloat32Vec4[1] = matrix[5];\r\n // tempFloat32Vec4[2] = matrix[9];\r\n // tempFloat32Vec4[3] = matrix[13];\r\n //\r\n // this._state.modelMatrixCol1Buf.setData(tempFloat32Vec4, offset);\r\n //\r\n // tempFloat32Vec4[0] = matrix[2];\r\n // tempFloat32Vec4[1] = matrix[6];\r\n // tempFloat32Vec4[2] = matrix[10];\r\n // tempFloat32Vec4[3] = matrix[14];\r\n //\r\n // this._state.modelMatrixCol2Buf.setData(tempFloat32Vec4, offset);\r\n // }\r\n\r\n /**\r\n * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.\r\n */\r\n _setFlags(portionId, flags, meshTransparent) {\r\n\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n\r\n const visible = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE);\r\n const xrayed = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED);\r\n const highlighted = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED);\r\n const selected = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED);\r\n const edges = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES);\r\n const pickable = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE);\r\n const culled = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED);\r\n\r\n let colorFlag;\r\n if (!visible || culled || xrayed\r\n || (highlighted && !this.model.scene.highlightMaterial.glowThrough)\r\n || (selected && !this.model.scene.selectedMaterial.glowThrough)) {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else {\r\n if (meshTransparent) {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT;\r\n } else {\r\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE;\r\n }\r\n }\r\n\r\n let silhouetteFlag;\r\n if (!visible || culled) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else if (selected) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED;\r\n } else if (highlighted) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;\r\n } else if (xrayed) {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED;\r\n } else {\r\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n }\r\n\r\n let edgeFlag = 0;\r\n if (!visible || culled) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n } else if (selected) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED;\r\n } else if (highlighted) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED;\r\n } else if (xrayed) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED;\r\n } else if (edges) {\r\n if (meshTransparent) {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT;\r\n } else {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE;\r\n }\r\n } else {\r\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n }\r\n\r\n const pickFlag = (visible && !culled && pickable) ? _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK : _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\r\n\r\n const clippableFlag = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;\r\n\r\n let vertFlag = 0;\r\n vertFlag |= colorFlag;\r\n vertFlag |= silhouetteFlag << 4;\r\n vertFlag |= edgeFlag << 8;\r\n vertFlag |= pickFlag << 12;\r\n vertFlag |= clippableFlag << 16;\r\n\r\n tempFloat32[0] = vertFlag;\r\n\r\n if (this._state.flagsBuf) {\r\n this._state.flagsBuf.setData(tempFloat32, portionId);\r\n }\r\n }\r\n\r\n setOffset(portionId, offset) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n if (!this.model.scene.entityOffsetsEnabled) {\r\n this.model.error(\"Entity#offset not enabled for this Viewer\"); // See Viewer entityOffsetsEnabled\r\n return;\r\n }\r\n tempVec3fa[0] = offset[0];\r\n tempVec3fa[1] = offset[1];\r\n tempVec3fa[2] = offset[2];\r\n if (this._state.offsetsBuf) {\r\n this._state.offsetsBuf.setData(tempVec3fa, portionId * 3);\r\n }\r\n }\r\n\r\n getEachVertex(portionId, callback) {\r\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\r\n return false;\r\n }\r\n const state = this._state;\r\n const geometry = state.geometry;\r\n const portion = this._portions[portionId];\r\n if (!portion) {\r\n this.model.error(\"portion not found: \" + portionId);\r\n return;\r\n }\r\n const positions = geometry.quantizedPositions;\r\n const origin = state.origin;\r\n const offset = portion.offset;\r\n const offsetX = origin[0] + offset[0];\r\n const offsetY = origin[1] + offset[1];\r\n const offsetZ = origin[2] + offset[2];\r\n const worldPos = tempVec4a;\r\n const portionMatrix = portion.matrix;\r\n const sceneModelPatrix = this.model.sceneModelMatrix;\r\n const positionsDecodeMatrix = state.positionsDecodeMatrix;\r\n for (let i = 0, len = positions.length; i < len; i += 3) {\r\n worldPos[0] = positions[i];\r\n worldPos[1] = positions[i + 1];\r\n worldPos[2] = positions[i + 2];\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(worldPos, positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(portionMatrix, worldPos);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(sceneModelPatrix, worldPos);\r\n worldPos[0] += offsetX;\r\n worldPos[1] += offsetY;\r\n worldPos[2] += offsetZ;\r\n callback(worldPos);\r\n }\r\n }\r\n\r\n setMatrix(portionId, matrix) {\r\n if (!this._finalized) {\r\n throw \"Not finalized\";\r\n }\r\n\r\n ////////////////////////////////////////\r\n // TODO: Update portion matrix\r\n ////////////////////////////////////////\r\n\r\n var offset = portionId * 4;\r\n\r\n tempFloat32Vec4[0] = matrix[0];\r\n tempFloat32Vec4[1] = matrix[4];\r\n tempFloat32Vec4[2] = matrix[8];\r\n tempFloat32Vec4[3] = matrix[12];\r\n\r\n this._state.modelMatrixCol0Buf.setData(tempFloat32Vec4, offset);\r\n\r\n tempFloat32Vec4[0] = matrix[1];\r\n tempFloat32Vec4[1] = matrix[5];\r\n tempFloat32Vec4[2] = matrix[9];\r\n tempFloat32Vec4[3] = matrix[13];\r\n\r\n this._state.modelMatrixCol1Buf.setData(tempFloat32Vec4, offset);\r\n\r\n tempFloat32Vec4[0] = matrix[2];\r\n tempFloat32Vec4[1] = matrix[6];\r\n tempFloat32Vec4[2] = matrix[10];\r\n tempFloat32Vec4[3] = matrix[14];\r\n\r\n this._state.modelMatrixCol2Buf.setData(tempFloat32Vec4, offset);\r\n }\r\n\r\n // ---------------------- COLOR RENDERING -----------------------------------\r\n\r\n drawColorOpaque(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (frameCtx.withSAO && this.model.saoEnabled) {\r\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\r\n if (this._renderers.pbrRendererWithSAO) {\r\n this._renderers.pbrRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\r\n if (this._renderers.colorTextureRendererWithSAO) {\r\n this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (this._state.normalsBuf) {\r\n if (this._renderers.colorRendererWithSAO) {\r\n this._renderers.colorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else {\r\n if (this._renderers.flatColorRendererWithSAO) {\r\n this._renderers.flatColorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n } else if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\r\n if (this._renderers.pbrRenderer) {\r\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\r\n if (this._renderers.colorTextureRenderer) {\r\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else if (this._state.normalsBuf) {\r\n if (this._renderers.colorRenderer) {\r\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n } else {\r\n if (this._renderers.flatColorRenderer) {\r\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n }\r\n\r\n _updateBackfaceCull(renderFlags, frameCtx) {\r\n const backfaces = this.model.backfaces || (!this.solid) || renderFlags.sectioned;\r\n if (frameCtx.backfaces !== backfaces) {\r\n const gl = frameCtx.gl;\r\n if (backfaces) {\r\n gl.disable(gl.CULL_FACE);\r\n } else {\r\n gl.enable(gl.CULL_FACE);\r\n }\r\n frameCtx.backfaces = backfaces;\r\n }\r\n }\r\n\r\n drawColorTransparent(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\r\n if (this._renderers.pbrRenderer) {\r\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\r\n if (this._renderers.colorTextureRenderer) {\r\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n } else if (this._state.normalsBuf) {\r\n if (this._renderers.colorRenderer) {\r\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n } else {\r\n if (this._renderers.flatColorRenderer) {\r\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\r\n }\r\n }\r\n }\r\n\r\n // ---------------------- RENDERING SAO POST EFFECT TARGETS --------------\r\n\r\n drawDepth(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.depthRenderer) {\r\n this._renderers.depthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses depth (eg SAO) does not apply to transparent objects\r\n }\r\n }\r\n\r\n drawNormals(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.normalsRenderer) {\r\n this._renderers.normalsRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses normals (eg SAO) does not apply to transparent objects\r\n }\r\n }\r\n\r\n // ---------------------- SILHOUETTE RENDERING -----------------------------------\r\n\r\n drawSilhouetteXRayed(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED);\r\n }\r\n }\r\n\r\n drawSilhouetteHighlighted(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);\r\n }\r\n }\r\n\r\n drawSilhouetteSelected(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.silhouetteRenderer) {\r\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED);\r\n }\r\n }\r\n\r\n // ---------------------- EDGES RENDERING -----------------------------------\r\n\r\n drawEdgesColorOpaque(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesColorRenderer) {\r\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n drawEdgesColorTransparent(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesColorRenderer) {\r\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT);\r\n }\r\n }\r\n\r\n drawEdgesXRayed(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesRenderer) {\r\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED);\r\n }\r\n }\r\n\r\n drawEdgesHighlighted(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesRenderer) {\r\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED);\r\n }\r\n }\r\n\r\n drawEdgesSelected(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\r\n return;\r\n }\r\n if (this._renderers.edgesRenderer) {\r\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED);\r\n }\r\n }\r\n\r\n // ---------------------- OCCLUSION CULL RENDERING -----------------------------------\r\n\r\n drawOcclusion(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.occlusionRenderer) {\r\n // Only opaque, filled objects can be occluders\r\n this._renderers.occlusionRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n // ---------------------- SHADOW BUFFER RENDERING -----------------------------------\r\n\r\n drawShadow(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.shadowRenderer) {\r\n this._renderers.shadowRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\r\n }\r\n }\r\n\r\n //---- PICKING ----------------------------------------------------------------------------------------------------\r\n\r\n drawPickMesh(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.pickMeshRenderer) {\r\n this._renderers.pickMeshRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawPickDepths(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.pickDepthRenderer) {\r\n this._renderers.pickDepthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawPickNormals(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n\r\n ////////////////////////////////////////////////////////////////////////////////////////////////////\r\n // TODO\r\n // if (this._state.normalsBuf) {\r\n // if (this._renderers.pickNormalsRenderer) {\r\n // this._renderers.pickNormalsRenderer.drawLayer(frameCtx, this, RENDER_PASSES.PICK);\r\n // }\r\n ////////////////////////////////////////////////////////////////////////////////////////////////////\r\n // } else {\r\n if (this._renderers.pickNormalsFlatRenderer) {\r\n this._renderers.pickNormalsFlatRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n // }\r\n }\r\n\r\n drawSnapInit(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.snapInitRenderer) {\r\n this._renderers.snapInitRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n drawSnap(renderFlags, frameCtx) {\r\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\r\n return;\r\n }\r\n this._updateBackfaceCull(renderFlags, frameCtx);\r\n if (this._renderers.snapRenderer) {\r\n this._renderers.snapRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\r\n }\r\n }\r\n\r\n //-----------------------------------------------------------------------------------------\r\n\r\n precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {\r\n\r\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\r\n return false;\r\n }\r\n\r\n const geometry = this._state.geometry;\r\n const state = this._state;\r\n const portion = this._portions[portionId];\r\n\r\n if (!portion) {\r\n this.model.error(\"portion not found: \" + portionId);\r\n return false;\r\n }\r\n\r\n if (!portion.inverseMatrix) {\r\n portion.inverseMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(portion.matrix, _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4());\r\n }\r\n\r\n if (worldNormal && !portion.normalMatrix) {\r\n portion.normalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transposeMat4(portion.inverseMatrix, _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4());\r\n }\r\n\r\n const quantizedPositions = geometry.quantizedPositions;\r\n const indices = geometry.indices;\r\n const origin = state.origin;\r\n const offset = portion.offset;\r\n\r\n const rtcRayOrigin = tempVec3a;\r\n const rtcRayDir = tempVec3b;\r\n\r\n rtcRayOrigin.set(origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(worldRayOrigin, origin, tempVec3c) : worldRayOrigin); // World -> RTC\r\n rtcRayDir.set(worldRayDir);\r\n\r\n if (offset) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(rtcRayOrigin, offset);\r\n }\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformRay(this.model.worldNormalMatrix, rtcRayOrigin, rtcRayDir, rtcRayOrigin, rtcRayDir);\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformRay(portion.inverseMatrix, rtcRayOrigin, rtcRayDir, rtcRayOrigin, rtcRayDir);\r\n\r\n const a = tempVec3d;\r\n const b = tempVec3e;\r\n const c = tempVec3f;\r\n\r\n let gotIntersect = false;\r\n let closestDist = 0;\r\n const closestIntersectPos = tempVec3g;\r\n\r\n for (let i = 0, len = indices.length; i < len; i += 3) {\r\n\r\n const ia = indices[i + 0] * 3;\r\n const ib = indices[i + 1] * 3;\r\n const ic = indices[i + 2] * 3;\r\n\r\n a[0] = quantizedPositions[ia];\r\n a[1] = quantizedPositions[ia + 1];\r\n a[2] = quantizedPositions[ia + 2];\r\n\r\n b[0] = quantizedPositions[ib];\r\n b[1] = quantizedPositions[ib + 1];\r\n b[2] = quantizedPositions[ib + 2];\r\n\r\n c[0] = quantizedPositions[ic];\r\n c[1] = quantizedPositions[ic + 1];\r\n c[2] = quantizedPositions[ic + 2];\r\n\r\n const {positionsDecodeMatrix} = state.geometry;\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(a, positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(b, positionsDecodeMatrix);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(c, positionsDecodeMatrix);\r\n\r\n if (_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.rayTriangleIntersect(rtcRayOrigin, rtcRayDir, a, b, c, closestIntersectPos)) {\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(portion.matrix, closestIntersectPos, closestIntersectPos);\r\n\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(this.model.worldMatrix, closestIntersectPos, closestIntersectPos);\r\n\r\n if (offset) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, offset);\r\n }\r\n\r\n if (origin) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, origin);\r\n }\r\n\r\n const dist = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(closestIntersectPos, worldRayOrigin, [])));\r\n\r\n if (!gotIntersect || dist > closestDist) {\r\n closestDist = dist;\r\n worldSurfacePos.set(closestIntersectPos);\r\n if (worldNormal) { // Not that wasteful to eagerly compute - unlikely to hit >2 surfaces on most geometry\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.triangleNormal(a, b, c, worldNormal);\r\n }\r\n gotIntersect = true;\r\n }\r\n }\r\n }\r\n\r\n if (gotIntersect && worldNormal) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformVec3(portion.normalMatrix, worldNormal, worldNormal);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformVec3(this.model.worldNormalMatrix, worldNormal, worldNormal);\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.normalizeVec3(worldNormal);\r\n }\r\n\r\n return gotIntersect;\r\n }\r\n\r\n destroy() {\r\n const state = this._state;\r\n if (state.colorsBuf) {\r\n state.colorsBuf.destroy();\r\n state.colorsBuf = null;\r\n }\r\n if (state.metallicRoughnessBuf) {\r\n state.metallicRoughnessBuf.destroy();\r\n state.metallicRoughnessBuf = null;\r\n }\r\n if (state.flagsBuf) {\r\n state.flagsBuf.destroy();\r\n state.flagsBuf = null;\r\n }\r\n if (state.offsetsBuf) {\r\n state.offsetsBuf.destroy();\r\n state.offsetsBuf = null;\r\n }\r\n if (state.modelMatrixCol0Buf) {\r\n state.modelMatrixCol0Buf.destroy();\r\n state.modelMatrixCol0Buf = null;\r\n }\r\n if (state.modelMatrixCol1Buf) {\r\n state.modelMatrixCol1Buf.destroy();\r\n state.modelMatrixCol1Buf = null;\r\n }\r\n if (state.modelMatrixCol2Buf) {\r\n state.modelMatrixCol2Buf.destroy();\r\n state.modelMatrixCol2Buf = null;\r\n }\r\n if (state.modelNormalMatrixCol0Buf) {\r\n state.modelNormalMatrixCol0Buf.destroy();\r\n state.modelNormalMatrixCol0Buf = null;\r\n }\r\n if (state.modelNormalMatrixCol1Buf) {\r\n state.modelNormalMatrixCol1Buf.destroy();\r\n state.modelNormalMatrixCol1Buf = null;\r\n }\r\n if (state.modelNormalMatrixCol2Buf) {\r\n state.modelNormalMatrixCol2Buf.destroy();\r\n state.modelNormalMatrixCol2Buf = null;\r\n }\r\n if (state.pickColorsBuf) {\r\n state.pickColorsBuf.destroy();\r\n state.pickColorsBuf = null;\r\n }\r\n state.destroy();\r\n this._state = null;\r\n }\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js?");
|
|
4527
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VBOInstancingTrianglesLayer: () => (/* binding */ VBOInstancingTrianglesLayer)\n/* harmony export */ });\n/* harmony import */ var _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../ENTITY_FLAGS.js */ \"./src/viewer/scene/model/ENTITY_FLAGS.js\");\n/* harmony import */ var _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../RENDER_PASSES.js */ \"./src/viewer/scene/model/RENDER_PASSES.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 _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../webgl/RenderState.js */ \"./src/viewer/scene/webgl/RenderState.js\");\n/* harmony import */ var _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../webgl/ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./renderers/Renderers.js */ \"./src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js\");\n\n\n\n\n\n\n\n\nconst tempUint8Vec4 = new Uint8Array(4);\nconst tempFloat32 = new Float32Array(1);\nconst tempVec4a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec4([0, 0, 0, 1]);\nconst tempVec3fa = new Float32Array(3);\n\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3b = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3d = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3e = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3f = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\nconst tempVec3g = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3();\n\nconst tempFloat32Vec4 = new Float32Array(4);\n\n/**\n * @private\n */\nclass VBOInstancingTrianglesLayer {\n\n /**\n * @param cfg\n * @param cfg.layerIndex\n * @param cfg.model\n * @param cfg.geometry\n * @param cfg.textureSet\n * @param cfg.origin\n */\n constructor(cfg) {\n\n console.info(\"Creating VBOInstancingTrianglesLayer\");\n\n /**\n * Owner model\n * @type {VBOSceneModel}\n */\n this.model = cfg.model;\n\n /**\n * State sorting key.\n * @type {string}\n */\n this.sortId = \"TrianglesInstancingLayer\" + (cfg.solid ? \"-solid\" : \"-surface\") + (cfg.normals ? \"-normals\" : \"-autoNormals\");\n\n /**\n * Index of this InstancingLayer in VBOSceneModel#_layerList\n * @type {Number}\n */\n this.layerIndex = cfg.layerIndex;\n\n this._renderers = (0,_renderers_Renderers_js__WEBPACK_IMPORTED_MODULE_5__.getRenderers)(cfg.model.scene);\n\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\n\n this._state = new _webgl_RenderState_js__WEBPACK_IMPORTED_MODULE_3__.RenderState({\n numInstances: 0,\n obb: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.OBB3(),\n origin: _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.vec3(),\n geometry: cfg.geometry,\n textureSet: cfg.textureSet,\n pbrSupported: false, // Set in #finalize if we have enough to support quality rendering\n positionsDecodeMatrix: cfg.geometry.positionsDecodeMatrix, // So we can null the geometry for GC\n colorsBuf: null,\n metallicRoughnessBuf: null,\n flagsBuf: null,\n offsetsBuf: null,\n modelMatrixBuf: null,\n modelMatrixCol0Buf: null,\n modelMatrixCol1Buf: null,\n modelMatrixCol2Buf: null,\n modelNormalMatrixCol0Buf: null,\n modelNormalMatrixCol1Buf: null,\n modelNormalMatrixCol2Buf: null,\n pickColorsBuf: null\n });\n\n // These counts are used to avoid unnecessary render passes\n this._numPortions = 0;\n this._numVisibleLayerPortions = 0;\n this._numTransparentLayerPortions = 0;\n this._numXRayedLayerPortions = 0;\n this._numHighlightedLayerPortions = 0;\n this._numSelectedLayerPortions = 0;\n this._numClippableLayerPortions = 0;\n this._numEdgesLayerPortions = 0;\n this._numPickableLayerPortions = 0;\n this._numCulledLayerPortions = 0;\n\n /** @private */\n this.numIndices = cfg.geometry.numIndices;\n\n // Vertex arrays\n this._colors = [];\n this._metallicRoughness = [];\n this._pickColors = [];\n this._offsets = [];\n\n // Modeling matrix per instance, array for each column\n\n this._modelMatrix = [];\n\n this._modelMatrixCol0 = [];\n this._modelMatrixCol1 = [];\n this._modelMatrixCol2 = [];\n\n // Modeling normal matrix per instance, array for each column\n this._modelNormalMatrixCol0 = [];\n this._modelNormalMatrixCol1 = [];\n this._modelNormalMatrixCol2 = [];\n\n this._portions = [];\n this._meshes = [];\n\n this._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3();\n this.aabbDirty = true;\n\n if (cfg.origin) {\n this._state.origin.set(cfg.origin);\n }\n\n this._finalized = false;\n\n /**\n * When true, this layer contains solid triangle meshes, otherwise this layer contains surface triangle meshes\n * @type {boolean}\n */\n this.solid = !!cfg.solid;\n\n /**\n * The number of indices in this layer.\n * @type {number|*}\n */\n this.numIndices = cfg.geometry.numIndices;\n }\n\n get aabb() {\n if (this.aabbDirty) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.collapseAABB3(this._aabb);\n for (let i = 0, len = this._meshes.length; i < len; i++) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.expandAABB3(this._aabb, this._meshes[i].aabb);\n }\n this.aabbDirty = false;\n }\n return this._aabb;\n }\n\n /**\n * Creates a new portion within this InstancingLayer, returns the new portion ID.\n *\n * The portion will instance this InstancingLayer's geometry.\n *\n * Gives the portion the specified color and matrix.\n *\n * @param mesh The SceneModelMesh that owns the portion\n * @param cfg Portion params\n * @param cfg.color Color [0..255,0..255,0..255]\n * @param cfg.metallic Metalness factor [0..255]\n * @param cfg.roughness Roughness factor [0..255]\n * @param cfg.opacity Opacity [0..255].\n * @param cfg.meshMatrix Flat float 4x4 matrix.\n * @param [cfg.worldMatrix] Flat float 4x4 matrix.\n * @param cfg.pickColor Quantized pick color\n * @returns {number} Portion ID.\n */\n createPortion(mesh, cfg) {\n\n const color = cfg.color;\n const metallic = cfg.metallic;\n const roughness = cfg.roughness;\n const opacity = cfg.opacity !== null && cfg.opacity !== undefined ? cfg.opacity : 255;\n const meshMatrix = cfg.meshMatrix;\n const pickColor = cfg.pickColor;\n\n if (this._finalized) {\n throw \"Already finalized\";\n }\n\n const r = color[0]; // Color is pre-quantized by SceneModel\n const g = color[1];\n const b = color[2];\n\n this._colors.push(r);\n this._colors.push(g);\n this._colors.push(b);\n this._colors.push(opacity);\n\n this._metallicRoughness.push((metallic !== null && metallic !== undefined) ? metallic : 0);\n this._metallicRoughness.push((roughness !== null && roughness !== undefined) ? roughness : 255);\n\n if (this.model.scene.entityOffsetsEnabled) {\n this._offsets.push(0);\n this._offsets.push(0);\n this._offsets.push(0);\n }\n\n this._modelMatrixCol0.push(meshMatrix[0]);\n this._modelMatrixCol0.push(meshMatrix[4]);\n this._modelMatrixCol0.push(meshMatrix[8]);\n this._modelMatrixCol0.push(meshMatrix[12]);\n\n this._modelMatrixCol1.push(meshMatrix[1]);\n this._modelMatrixCol1.push(meshMatrix[5]);\n this._modelMatrixCol1.push(meshMatrix[9]);\n this._modelMatrixCol1.push(meshMatrix[13]);\n\n this._modelMatrixCol2.push(meshMatrix[2]);\n this._modelMatrixCol2.push(meshMatrix[6]);\n this._modelMatrixCol2.push(meshMatrix[10]);\n this._modelMatrixCol2.push(meshMatrix[14]);\n\n if (this._state.geometry.normals) {\n\n // Note: order of inverse and transpose doesn't matter\n\n let transposedMat = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transposeMat4(meshMatrix, _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4()); // TODO: Use cached matrix\n let normalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(transposedMat);\n\n this._modelNormalMatrixCol0.push(normalMatrix[0]);\n this._modelNormalMatrixCol0.push(normalMatrix[4]);\n this._modelNormalMatrixCol0.push(normalMatrix[8]);\n this._modelNormalMatrixCol0.push(normalMatrix[12]);\n\n this._modelNormalMatrixCol1.push(normalMatrix[1]);\n this._modelNormalMatrixCol1.push(normalMatrix[5]);\n this._modelNormalMatrixCol1.push(normalMatrix[9]);\n this._modelNormalMatrixCol1.push(normalMatrix[13]);\n\n this._modelNormalMatrixCol2.push(normalMatrix[2]);\n this._modelNormalMatrixCol2.push(normalMatrix[6]);\n this._modelNormalMatrixCol2.push(normalMatrix[10]);\n this._modelNormalMatrixCol2.push(normalMatrix[14]);\n }\n\n // Per-vertex pick colors\n\n this._pickColors.push(pickColor[0]);\n this._pickColors.push(pickColor[1]);\n this._pickColors.push(pickColor[2]);\n this._pickColors.push(pickColor[3]);\n\n this._state.numInstances++;\n\n const portionId = this._portions.length;\n\n const portion = {};\n\n if (this.model.scene.pickSurfacePrecisionEnabled) {\n portion.matrix = meshMatrix.slice();\n portion.inverseMatrix = null; // Lazy-computed in precisionRayPickSurface\n portion.normalMatrix = null; // Lazy-computed in precisionRayPickSurface\n }\n\n this._portions.push(portion);\n\n this._numPortions++;\n this.model.numPortions++;\n this._meshes.push(mesh);\n return portionId;\n }\n\n finalize() {\n\n if (this._finalized) {\n return;\n }\n\n const state = this._state;\n const geometry = state.geometry;\n const textureSet = state.textureSet;\n const gl = this.model.scene.canvas.gl;\n const colorsLength = this._colors.length;\n const flagsLength = colorsLength / 4;\n\n if (colorsLength > 0) {\n let notNormalized = false;\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Uint8Array(this._colors), this._colors.length, 4, gl.DYNAMIC_DRAW, notNormalized);\n this._colors = []; // Release memory\n }\n\n if (this._metallicRoughness.length > 0) {\n const metallicRoughness = new Uint8Array(this._metallicRoughness);\n let normalized = false;\n state.metallicRoughnessBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, metallicRoughness, this._metallicRoughness.length, 2, gl.STATIC_DRAW, normalized);\n }\n\n if (flagsLength > 0) {\n // Because we only build flags arrays here,\n // get their length from the colors array\n let notNormalized = false;\n state.flagsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(flagsLength), flagsLength, 1, gl.DYNAMIC_DRAW, notNormalized);\n }\n\n if (this.model.scene.entityOffsetsEnabled) {\n if (this._offsets.length > 0) {\n const notNormalized = false;\n state.offsetsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._offsets), this._offsets.length, 3, gl.DYNAMIC_DRAW, notNormalized);\n this._offsets = []; // Release memory\n }\n }\n\n if (geometry.positionsCompressed && geometry.positionsCompressed.length > 0) {\n const normalized = false;\n state.positionsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, geometry.positionsCompressed, geometry.positionsCompressed.length, 3, gl.STATIC_DRAW, normalized);\n state.positionsDecodeMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4(geometry.positionsDecodeMatrix);\n }\n // if (geometry.normalsCompressed && geometry.normalsCompressed.length > 0) {\n // const normalized = true; // For oct-encoded UInt8\n // state.normalsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, geometry.normalsCompressed, geometry.normalsCompressed.length, 3, gl.STATIC_DRAW, normalized);\n // }\n if (geometry.colorsCompressed && geometry.colorsCompressed.length > 0) {\n const colorsCompressed = new Uint8Array(geometry.colorsCompressed);\n const notNormalized = false;\n state.colorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, colorsCompressed, colorsCompressed.length, 4, gl.STATIC_DRAW, notNormalized);\n }\n if (geometry.uvCompressed && geometry.uvCompressed.length > 0) {\n const uvCompressed = geometry.uvCompressed;\n state.uvDecodeMatrix = geometry.uvDecodeMatrix;\n state.uvBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, uvCompressed, uvCompressed.length, 2, gl.STATIC_DRAW, false);\n }\n if (geometry.indices && geometry.indices.length > 0) {\n state.indicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.indices), geometry.indices.length, 1, gl.STATIC_DRAW);\n state.numIndices = geometry.indices.length;\n }\n if (geometry.primitive === \"triangles\" || geometry.primitive === \"solid\" || geometry.primitive === \"surface\") {\n state.edgeIndicesBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.edgeIndices), geometry.edgeIndices.length, 1, gl.STATIC_DRAW);\n }\n\n if (this._modelMatrixCol0.length > 0) {\n\n const normalized = false;\n\n state.modelMatrixCol0Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelMatrixCol0), this._modelMatrixCol0.length, 4, gl.STATIC_DRAW, normalized);\n state.modelMatrixCol1Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelMatrixCol1), this._modelMatrixCol1.length, 4, gl.STATIC_DRAW, normalized);\n state.modelMatrixCol2Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelMatrixCol2), this._modelMatrixCol2.length, 4, gl.STATIC_DRAW, normalized);\n this._modelMatrixCol0 = [];\n this._modelMatrixCol1 = [];\n this._modelMatrixCol2 = [];\n\n if (state.normalsBuf) {\n state.modelNormalMatrixCol0Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelNormalMatrixCol0), this._modelNormalMatrixCol0.length, 4, gl.STATIC_DRAW, normalized);\n state.modelNormalMatrixCol1Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelNormalMatrixCol1), this._modelNormalMatrixCol1.length, 4, gl.STATIC_DRAW, normalized);\n state.modelNormalMatrixCol2Buf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Float32Array(this._modelNormalMatrixCol2), this._modelNormalMatrixCol2.length, 4, gl.STATIC_DRAW, normalized);\n this._modelNormalMatrixCol0 = [];\n this._modelNormalMatrixCol1 = [];\n this._modelNormalMatrixCol2 = [];\n }\n }\n\n if (this._pickColors.length > 0) {\n const normalized = false;\n state.pickColorsBuf = new _webgl_ArrayBuf_js__WEBPACK_IMPORTED_MODULE_4__.ArrayBuf(gl, gl.ARRAY_BUFFER, new Uint8Array(this._pickColors), this._pickColors.length, 4, gl.STATIC_DRAW, normalized);\n this._pickColors = []; // Release memory\n }\n\n state.pbrSupported\n = !!state.metallicRoughnessBuf\n && !!state.uvBuf\n && !!state.normalsBuf\n && !!textureSet\n && !!textureSet.colorTexture\n && !!textureSet.metallicRoughnessTexture;\n\n state.colorTextureSupported\n = !!state.uvBuf\n && !!textureSet\n && !!textureSet.colorTexture;\n\n this._state.geometry = null;\n\n this._finalized = true;\n }\n\n // The following setters are called by VBOSceneModelMesh, in turn called by VBOSceneModelNode, only after the layer is finalized.\n // It's important that these are called after finalize() in order to maintain integrity of counts like _numVisibleLayerPortions etc.\n\n initFlags(portionId, flags, meshTransparent) {\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\n this._numVisibleLayerPortions++;\n this.model.numVisibleLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\n this._numHighlightedLayerPortions++;\n this.model.numHighlightedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\n this._numXRayedLayerPortions++;\n this.model.numXRayedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\n this._numSelectedLayerPortions++;\n this.model.numSelectedLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\n this._numClippableLayerPortions++;\n this.model.numClippableLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\n this._numEdgesLayerPortions++;\n this.model.numEdgesLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\n this._numPickableLayerPortions++;\n this.model.numPickableLayerPortions++;\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\n this._numCulledLayerPortions++;\n this.model.numCulledLayerPortions++;\n }\n if (meshTransparent) {\n this._numTransparentLayerPortions++;\n this.model.numTransparentLayerPortions++;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setVisible(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE) {\n this._numVisibleLayerPortions++;\n this.model.numVisibleLayerPortions++;\n } else {\n this._numVisibleLayerPortions--;\n this.model.numVisibleLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setHighlighted(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED) {\n this._numHighlightedLayerPortions++;\n this.model.numHighlightedLayerPortions++;\n } else {\n this._numHighlightedLayerPortions--;\n this.model.numHighlightedLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setXRayed(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED) {\n this._numXRayedLayerPortions++;\n this.model.numXRayedLayerPortions++;\n } else {\n this._numXRayedLayerPortions--;\n this.model.numXRayedLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setSelected(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED) {\n this._numSelectedLayerPortions++;\n this.model.numSelectedLayerPortions++;\n } else {\n this._numSelectedLayerPortions--;\n this.model.numSelectedLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setEdges(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES) {\n this._numEdgesLayerPortions++;\n this.model.numEdgesLayerPortions++;\n } else {\n this._numEdgesLayerPortions--;\n this.model.numEdgesLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setClippable(portionId, flags) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) {\n this._numClippableLayerPortions++;\n this.model.numClippableLayerPortions++;\n } else {\n this._numClippableLayerPortions--;\n this.model.numClippableLayerPortions--;\n }\n this._setFlags(portionId, flags);\n }\n\n setCollidable(portionId, flags) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n }\n\n setPickable(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE) {\n this._numPickableLayerPortions++;\n this.model.numPickableLayerPortions++;\n } else {\n this._numPickableLayerPortions--;\n this.model.numPickableLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setCulled(portionId, flags, meshTransparent) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED) {\n this._numCulledLayerPortions++;\n this.model.numCulledLayerPortions++;\n } else {\n this._numCulledLayerPortions--;\n this.model.numCulledLayerPortions--;\n }\n this._setFlags(portionId, flags, meshTransparent);\n }\n\n setColor(portionId, color) { // RGBA color is normalized as ints\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n tempUint8Vec4[0] = color[0];\n tempUint8Vec4[1] = color[1];\n tempUint8Vec4[2] = color[2];\n tempUint8Vec4[3] = color[3];\n if (this._state.colorsBuf) {\n this._state.colorsBuf.setData(tempUint8Vec4, portionId * 4);\n }\n }\n\n setTransparent(portionId, flags, transparent) {\n if (transparent) {\n this._numTransparentLayerPortions++;\n this.model.numTransparentLayerPortions++;\n } else {\n this._numTransparentLayerPortions--;\n this.model.numTransparentLayerPortions--;\n }\n this._setFlags(portionId, flags, transparent);\n }\n\n // setMatrix(portionId, matrix) {\n //\n // if (!this._finalized) {\n // throw \"Not finalized\";\n // }\n //\n // var offset = portionId * 4;\n //\n // tempFloat32Vec4[0] = matrix[0];\n // tempFloat32Vec4[1] = matrix[4];\n // tempFloat32Vec4[2] = matrix[8];\n // tempFloat32Vec4[3] = matrix[12];\n //\n // this._state.modelMatrixCol0Buf.setData(tempFloat32Vec4, offset);\n //\n // tempFloat32Vec4[0] = matrix[1];\n // tempFloat32Vec4[1] = matrix[5];\n // tempFloat32Vec4[2] = matrix[9];\n // tempFloat32Vec4[3] = matrix[13];\n //\n // this._state.modelMatrixCol1Buf.setData(tempFloat32Vec4, offset);\n //\n // tempFloat32Vec4[0] = matrix[2];\n // tempFloat32Vec4[1] = matrix[6];\n // tempFloat32Vec4[2] = matrix[10];\n // tempFloat32Vec4[3] = matrix[14];\n //\n // this._state.modelMatrixCol2Buf.setData(tempFloat32Vec4, offset);\n // }\n\n /**\n * flags are 4bits values encoded on a 32bit base. color flag on the first 4 bits, silhouette flag on the next 4 bits and so on for edge, pick and clippable.\n */\n _setFlags(portionId, flags, meshTransparent) {\n\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n\n const visible = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.VISIBLE);\n const xrayed = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.XRAYED);\n const highlighted = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.HIGHLIGHTED);\n const selected = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.SELECTED);\n const edges = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.EDGES);\n const pickable = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.PICKABLE);\n const culled = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CULLED);\n\n let colorFlag;\n if (!visible || culled || xrayed\n || (highlighted && !this.model.scene.highlightMaterial.glowThrough)\n || (selected && !this.model.scene.selectedMaterial.glowThrough)) {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else {\n if (meshTransparent) {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT;\n } else {\n colorFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE;\n }\n }\n\n let silhouetteFlag;\n if (!visible || culled) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else if (selected) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED;\n } else if (highlighted) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED;\n } else if (xrayed) {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED;\n } else {\n silhouetteFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n }\n\n let edgeFlag = 0;\n if (!visible || culled) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n } else if (selected) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED;\n } else if (highlighted) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED;\n } else if (xrayed) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED;\n } else if (edges) {\n if (meshTransparent) {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT;\n } else {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE;\n }\n } else {\n edgeFlag = _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n }\n\n const pickFlag = (visible && !culled && pickable) ? _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK : _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.NOT_RENDERED;\n\n const clippableFlag = !!(flags & _ENTITY_FLAGS_js__WEBPACK_IMPORTED_MODULE_0__.ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;\n\n let vertFlag = 0;\n vertFlag |= colorFlag;\n vertFlag |= silhouetteFlag << 4;\n vertFlag |= edgeFlag << 8;\n vertFlag |= pickFlag << 12;\n vertFlag |= clippableFlag << 16;\n\n tempFloat32[0] = vertFlag;\n\n if (this._state.flagsBuf) {\n this._state.flagsBuf.setData(tempFloat32, portionId);\n }\n }\n\n setOffset(portionId, offset) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n if (!this.model.scene.entityOffsetsEnabled) {\n this.model.error(\"Entity#offset not enabled for this Viewer\"); // See Viewer entityOffsetsEnabled\n return;\n }\n tempVec3fa[0] = offset[0];\n tempVec3fa[1] = offset[1];\n tempVec3fa[2] = offset[2];\n if (this._state.offsetsBuf) {\n this._state.offsetsBuf.setData(tempVec3fa, portionId * 3);\n }\n }\n\n getEachVertex(portionId, callback) {\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\n return false;\n }\n const state = this._state;\n const geometry = state.geometry;\n const portion = this._portions[portionId];\n if (!portion) {\n this.model.error(\"portion not found: \" + portionId);\n return;\n }\n const positions = geometry.quantizedPositions;\n const origin = state.origin;\n const offset = portion.offset;\n const offsetX = origin[0] + offset[0];\n const offsetY = origin[1] + offset[1];\n const offsetZ = origin[2] + offset[2];\n const worldPos = tempVec4a;\n const portionMatrix = portion.matrix;\n const sceneModelPatrix = this.model.sceneModelMatrix;\n const positionsDecodeMatrix = state.positionsDecodeMatrix;\n for (let i = 0, len = positions.length; i < len; i += 3) {\n worldPos[0] = positions[i];\n worldPos[1] = positions[i + 1];\n worldPos[2] = positions[i + 2];\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(worldPos, positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(portionMatrix, worldPos);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(sceneModelPatrix, worldPos);\n worldPos[0] += offsetX;\n worldPos[1] += offsetY;\n worldPos[2] += offsetZ;\n callback(worldPos);\n }\n }\n\n setMatrix(portionId, matrix) {\n if (!this._finalized) {\n throw \"Not finalized\";\n }\n\n ////////////////////////////////////////\n // TODO: Update portion matrix\n ////////////////////////////////////////\n\n var offset = portionId * 4;\n\n tempFloat32Vec4[0] = matrix[0];\n tempFloat32Vec4[1] = matrix[4];\n tempFloat32Vec4[2] = matrix[8];\n tempFloat32Vec4[3] = matrix[12];\n\n this._state.modelMatrixCol0Buf.setData(tempFloat32Vec4, offset);\n\n tempFloat32Vec4[0] = matrix[1];\n tempFloat32Vec4[1] = matrix[5];\n tempFloat32Vec4[2] = matrix[9];\n tempFloat32Vec4[3] = matrix[13];\n\n this._state.modelMatrixCol1Buf.setData(tempFloat32Vec4, offset);\n\n tempFloat32Vec4[0] = matrix[2];\n tempFloat32Vec4[1] = matrix[6];\n tempFloat32Vec4[2] = matrix[10];\n tempFloat32Vec4[3] = matrix[14];\n\n this._state.modelMatrixCol2Buf.setData(tempFloat32Vec4, offset);\n }\n\n // ---------------------- COLOR RENDERING -----------------------------------\n\n drawColorOpaque(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (frameCtx.withSAO && this.model.saoEnabled) {\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\n if (this._renderers.pbrRendererWithSAO) {\n this._renderers.pbrRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\n if (this._renderers.colorTextureRendererWithSAO) {\n this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (this._state.normalsBuf) {\n if (this._renderers.colorRendererWithSAO) {\n this._renderers.colorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else {\n if (this._renderers.flatColorRendererWithSAO) {\n this._renderers.flatColorRendererWithSAO.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n } else if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\n if (this._renderers.pbrRenderer) {\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\n if (this._renderers.colorTextureRenderer) {\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else if (this._state.normalsBuf) {\n if (this._renderers.colorRenderer) {\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n } else {\n if (this._renderers.flatColorRenderer) {\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n }\n\n _updateBackfaceCull(renderFlags, frameCtx) {\n const backfaces = this.model.backfaces || (!this.solid) || renderFlags.sectioned;\n if (frameCtx.backfaces !== backfaces) {\n const gl = frameCtx.gl;\n if (backfaces) {\n gl.disable(gl.CULL_FACE);\n } else {\n gl.enable(gl.CULL_FACE);\n }\n frameCtx.backfaces = backfaces;\n }\n }\n\n drawColorTransparent(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === 0 || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {\n if (this._renderers.pbrRenderer) {\n this._renderers.pbrRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {\n if (this._renderers.colorTextureRenderer) {\n this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n } else if (this._state.normalsBuf) {\n if (this._renderers.colorRenderer) {\n this._renderers.colorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n } else {\n if (this._renderers.flatColorRenderer) {\n this._renderers.flatColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_TRANSPARENT);\n }\n }\n }\n\n // ---------------------- RENDERING SAO POST EFFECT TARGETS --------------\n\n drawDepth(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.depthRenderer) {\n this._renderers.depthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses depth (eg SAO) does not apply to transparent objects\n }\n }\n\n drawNormals(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numTransparentLayerPortions === this._numPortions || this._numXRayedLayerPortions === this._numPortions) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.normalsRenderer) {\n this._renderers.normalsRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE); // Assume whatever post-effect uses normals (eg SAO) does not apply to transparent objects\n }\n }\n\n // ---------------------- SILHOUETTE RENDERING -----------------------------------\n\n drawSilhouetteXRayed(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_XRAYED);\n }\n }\n\n drawSilhouetteHighlighted(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_HIGHLIGHTED);\n }\n }\n\n drawSilhouetteSelected(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.silhouetteRenderer) {\n this._renderers.silhouetteRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.SILHOUETTE_SELECTED);\n }\n }\n\n // ---------------------- EDGES RENDERING -----------------------------------\n\n drawEdgesColorOpaque(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesColorRenderer) {\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_OPAQUE);\n }\n }\n\n drawEdgesColorTransparent(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numEdgesLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesColorRenderer) {\n this._renderers.edgesColorRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_COLOR_TRANSPARENT);\n }\n }\n\n drawEdgesXRayed(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numXRayedLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesRenderer) {\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_XRAYED);\n }\n }\n\n drawEdgesHighlighted(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numHighlightedLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesRenderer) {\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_HIGHLIGHTED);\n }\n }\n\n drawEdgesSelected(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0 || this._numSelectedLayerPortions === 0) {\n return;\n }\n if (this._renderers.edgesRenderer) {\n this._renderers.edgesRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.EDGES_SELECTED);\n }\n }\n\n // ---------------------- OCCLUSION CULL RENDERING -----------------------------------\n\n drawOcclusion(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.occlusionRenderer) {\n // Only opaque, filled objects can be occluders\n this._renderers.occlusionRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n\n // ---------------------- SHADOW BUFFER RENDERING -----------------------------------\n\n drawShadow(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.shadowRenderer) {\n this._renderers.shadowRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.COLOR_OPAQUE);\n }\n }\n\n //---- PICKING ----------------------------------------------------------------------------------------------------\n\n drawPickMesh(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.pickMeshRenderer) {\n this._renderers.pickMeshRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawPickDepths(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.pickDepthRenderer) {\n this._renderers.pickDepthRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawPickNormals(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n\n ////////////////////////////////////////////////////////////////////////////////////////////////////\n // TODO\n // if (this._state.normalsBuf) {\n // if (this._renderers.pickNormalsRenderer) {\n // this._renderers.pickNormalsRenderer.drawLayer(frameCtx, this, RENDER_PASSES.PICK);\n // }\n ////////////////////////////////////////////////////////////////////////////////////////////////////\n // } else {\n if (this._renderers.pickNormalsFlatRenderer) {\n this._renderers.pickNormalsFlatRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n // }\n }\n\n drawSnapInit(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.snapInitRenderer) {\n this._renderers.snapInitRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n drawSnap(renderFlags, frameCtx) {\n if (this._numCulledLayerPortions === this._numPortions || this._numVisibleLayerPortions === 0) {\n return;\n }\n this._updateBackfaceCull(renderFlags, frameCtx);\n if (this._renderers.snapRenderer) {\n this._renderers.snapRenderer.drawLayer(frameCtx, this, _RENDER_PASSES_js__WEBPACK_IMPORTED_MODULE_1__.RENDER_PASSES.PICK);\n }\n }\n\n //-----------------------------------------------------------------------------------------\n\n precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {\n\n if (!this.model.scene.pickSurfacePrecisionEnabled) {\n return false;\n }\n\n const geometry = this._state.geometry;\n const state = this._state;\n const portion = this._portions[portionId];\n\n if (!portion) {\n this.model.error(\"portion not found: \" + portionId);\n return false;\n }\n\n if (!portion.inverseMatrix) {\n portion.inverseMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(portion.matrix, _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4());\n }\n\n if (worldNormal && !portion.normalMatrix) {\n portion.normalMatrix = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transposeMat4(portion.inverseMatrix, _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4());\n }\n\n const quantizedPositions = geometry.quantizedPositions;\n const indices = geometry.indices;\n const origin = state.origin;\n const offset = portion.offset;\n\n const rtcRayOrigin = tempVec3a;\n const rtcRayDir = tempVec3b;\n\n rtcRayOrigin.set(origin ? _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(worldRayOrigin, origin, tempVec3c) : worldRayOrigin); // World -> RTC\n rtcRayDir.set(worldRayDir);\n\n if (offset) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(rtcRayOrigin, offset);\n }\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformRay(this.model.worldNormalMatrix, rtcRayOrigin, rtcRayDir, rtcRayOrigin, rtcRayDir);\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformRay(portion.inverseMatrix, rtcRayOrigin, rtcRayDir, rtcRayOrigin, rtcRayDir);\n\n const a = tempVec3d;\n const b = tempVec3e;\n const c = tempVec3f;\n\n let gotIntersect = false;\n let closestDist = 0;\n const closestIntersectPos = tempVec3g;\n\n for (let i = 0, len = indices.length; i < len; i += 3) {\n\n const ia = indices[i + 0] * 3;\n const ib = indices[i + 1] * 3;\n const ic = indices[i + 2] * 3;\n\n a[0] = quantizedPositions[ia];\n a[1] = quantizedPositions[ia + 1];\n a[2] = quantizedPositions[ia + 2];\n\n b[0] = quantizedPositions[ib];\n b[1] = quantizedPositions[ib + 1];\n b[2] = quantizedPositions[ib + 2];\n\n c[0] = quantizedPositions[ic];\n c[1] = quantizedPositions[ic + 1];\n c[2] = quantizedPositions[ic + 2];\n\n const {positionsDecodeMatrix} = state.geometry;\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(a, positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(b, positionsDecodeMatrix);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.decompressPosition(c, positionsDecodeMatrix);\n\n if (_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.rayTriangleIntersect(rtcRayOrigin, rtcRayDir, a, b, c, closestIntersectPos)) {\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(portion.matrix, closestIntersectPos, closestIntersectPos);\n\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformPoint3(this.model.worldMatrix, closestIntersectPos, closestIntersectPos);\n\n if (offset) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, offset);\n }\n\n if (origin) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.addVec3(closestIntersectPos, origin);\n }\n\n const dist = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.subVec3(closestIntersectPos, worldRayOrigin, [])));\n\n if (!gotIntersect || dist > closestDist) {\n closestDist = dist;\n worldSurfacePos.set(closestIntersectPos);\n if (worldNormal) { // Not that wasteful to eagerly compute - unlikely to hit >2 surfaces on most geometry\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.triangleNormal(a, b, c, worldNormal);\n }\n gotIntersect = true;\n }\n }\n }\n\n if (gotIntersect && worldNormal) {\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformVec3(portion.normalMatrix, worldNormal, worldNormal);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.transformVec3(this.model.worldNormalMatrix, worldNormal, worldNormal);\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.normalizeVec3(worldNormal);\n }\n\n return gotIntersect;\n }\n\n destroy() {\n const state = this._state;\n if (state.colorsBuf) {\n state.colorsBuf.destroy();\n state.colorsBuf = null;\n }\n if (state.metallicRoughnessBuf) {\n state.metallicRoughnessBuf.destroy();\n state.metallicRoughnessBuf = null;\n }\n if (state.flagsBuf) {\n state.flagsBuf.destroy();\n state.flagsBuf = null;\n }\n if (state.offsetsBuf) {\n state.offsetsBuf.destroy();\n state.offsetsBuf = null;\n }\n if (state.modelMatrixCol0Buf) {\n state.modelMatrixCol0Buf.destroy();\n state.modelMatrixCol0Buf = null;\n }\n if (state.modelMatrixCol1Buf) {\n state.modelMatrixCol1Buf.destroy();\n state.modelMatrixCol1Buf = null;\n }\n if (state.modelMatrixCol2Buf) {\n state.modelMatrixCol2Buf.destroy();\n state.modelMatrixCol2Buf = null;\n }\n if (state.modelNormalMatrixCol0Buf) {\n state.modelNormalMatrixCol0Buf.destroy();\n state.modelNormalMatrixCol0Buf = null;\n }\n if (state.modelNormalMatrixCol1Buf) {\n state.modelNormalMatrixCol1Buf.destroy();\n state.modelNormalMatrixCol1Buf = null;\n }\n if (state.modelNormalMatrixCol2Buf) {\n state.modelNormalMatrixCol2Buf.destroy();\n state.modelNormalMatrixCol2Buf = null;\n }\n if (state.pickColorsBuf) {\n state.pickColorsBuf.destroy();\n state.pickColorsBuf = null;\n }\n state.destroy();\n this._state = null;\n }\n}\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js?");
|
|
4528
4528
|
|
|
4529
4529
|
/***/ }),
|
|
4530
4530
|
|
|
@@ -4824,7 +4824,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4824
4824
|
\*****************************************/
|
|
4825
4825
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4826
4826
|
|
|
4827
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Scene: () => (/* binding */ Scene)\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 _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lod/LOD.js */ \"./src/viewer/scene/lod/LOD.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../canvas/Canvas.js */ \"./src/viewer/scene/canvas/Canvas.js\");\n/* harmony import */ var _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../webgl/Renderer.js */ \"./src/viewer/scene/webgl/Renderer.js\");\n/* harmony import */ var _input_Input_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../input/Input.js */ \"./src/viewer/scene/input/Input.js\");\n/* harmony import */ var _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../viewport/Viewport.js */ \"./src/viewer/scene/viewport/Viewport.js\");\n/* harmony import */ var _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../camera/Camera.js */ \"./src/viewer/scene/camera/Camera.js\");\n/* harmony import */ var _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../lights/AmbientLight.js */ \"./src/viewer/scene/lights/AmbientLight.js\");\n/* harmony import */ var _geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../geometry/builders/buildBoxGeometry.js */ \"./src/viewer/scene/geometry/builders/buildBoxGeometry.js\");\n/* harmony import */ var _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../materials/EdgeMaterial.js */ \"./src/viewer/scene/materials/EdgeMaterial.js\");\n/* harmony import */ var _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../metriqs/Metriqs.js */ \"./src/viewer/scene/metriqs/Metriqs.js\");\n/* harmony import */ var _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../postfx/SAO.js */ \"./src/viewer/scene/postfx/SAO.js\");\n/* harmony import */ var _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../materials/PointsMaterial.js */ \"./src/viewer/scene/materials/PointsMaterial.js\");\n/* harmony import */ var _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../materials/LinesMaterial.js */ \"./src/viewer/scene/materials/LinesMaterial.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// Enables runtime check for redundant calls to object state update methods, eg. Scene#_objectVisibilityUpdated\nconst ASSERT_OBJECT_STATE_UPDATE = false;\n\n// Cached vars to avoid garbage collection\n\nfunction getEntityIDMap(scene, entityIds) {\n\tconst map = {};\n\tlet entityId;\n\tlet entity;\n\tfor (let i = 0, len = entityIds.length; i < len; i++) {\n\t\tentityId = entityIds[i];\n\t\tentity = scene.components[entityId];\n\t\tif (!entity) {\n\t\t\tscene.warn(\"pick(): Component not found: \" + entityId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!entity.isEntity) {\n\t\t\tscene.warn(\"pick(): Component is not an Entity: \" + entityId);\n\t\t\tcontinue;\n\t\t}\n\t\tmap[entityId] = true;\n\t}\n\treturn map;\n}\n\n/**\n * Fired whenever a debug message is logged on a component within this Scene.\n * @event log\n * @param {String} value The debug message\n */\n\n/**\n * Fired whenever an error is logged on a component within this Scene.\n * @event error\n * @param {String} value The error message\n */\n\n/**\n * Fired whenever a warning is logged on a component within this Scene.\n * @event warn\n * @param {String} value The warning message\n */\n\n/**\n * @desc Contains the components that comprise a 3D scene.\n *\n * * A {@link Viewer} has a single Scene, which it provides in {@link Viewer#scene}.\n * * Plugins like {@link AxisGizmoPlugin} also have their own private Scenes.\n * * Each Scene has a corresponding {@link MetaScene}, which the Viewer provides in {@link Viewer#metaScene}.\n *\n * ## Getting a Viewer's Scene\n *\n * ````javascript\n * var scene = viewer.scene;\n * ````\n *\n * ## Creating and accessing Scene components\n *\n * As a brief introduction to creating Scene components, we'll create a {@link Mesh} that has a\n * {@link buildTorusGeometry} and a {@link PhongMaterial}:\n *\n * ````javascript\n * var teapotMesh = new Mesh(scene, {\n * id: \"myMesh\", // <<---------- ID automatically generated if not provided\n * geometry: new TorusGeometry(scene),\n * material: new PhongMaterial(scene, {\n * id: \"myMaterial\",\n * diffuse: [0.2, 0.2, 1.0]\n * })\n * });\n *\n * teapotMesh.scene.camera.eye = [45, 45, 45];\n * ````\n *\n * Find components by ID in their Scene's {@link Scene#components} map:\n *\n * ````javascript\n * var teapotMesh = scene.components[\"myMesh\"];\n * teapotMesh.visible = false;\n *\n * var teapotMaterial = scene.components[\"myMaterial\"];\n * teapotMaterial.diffuse = [1,0,0]; // Change to red\n * ````\n *\n * A Scene also has a map of component instances for each {@link Component} subtype:\n *\n * ````javascript\n * var meshes = scene.types[\"Mesh\"];\n * var teapotMesh = meshes[\"myMesh\"];\n * teapotMesh.xrayed = true;\n *\n * var phongMaterials = scene.types[\"PhongMaterial\"];\n * var teapotMaterial = phongMaterials[\"myMaterial\"];\n * teapotMaterial.diffuse = [0,1,0]; // Change to green\n * ````\n *\n * See {@link Node}, {@link Node} and {@link Model} for how to create and access more sophisticated content.\n *\n * ## Controlling the camera\n *\n * Use the Scene's {@link Camera} to control the current viewpoint and projection:\n *\n * ````javascript\n * var camera = myScene.camera;\n *\n * camera.eye = [-10,0,0];\n * camera.look = [-10,0,0];\n * camera.up = [0,1,0];\n *\n * camera.projection = \"perspective\";\n * camera.perspective.fov = 45;\n * //...\n * ````\n *\n * ## Managing the canvas\n *\n * The Scene's {@link Canvas} component provides various conveniences relevant to the WebGL canvas, such\n * as firing resize events etc:\n *\n * ````javascript\n * var canvas = scene.canvas;\n *\n * canvas.on(\"boundary\", function(boundary) {\n * //...\n * });\n * ````\n *\n * ## Picking\n *\n * Use {@link Scene#pick} to pick and raycast entites.\n *\n * For example, to pick a point on the surface of the closest entity at the given canvas coordinates:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true,\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an entity\n *\n * var entity = pickResult.entity;\n *\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Mesh's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult. ; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var normal = pickResult.normal; // Float64Array containing the interpolated normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n * }\n * ````\n *\n * ## Pick masking\n *\n * We can use {@link Scene#pick}'s ````includeEntities```` and ````excludeEntities```` options to mask which {@link Mesh}es we attempt to pick.\n *\n * This is useful for picking through things, to pick only the Entities of interest.\n *\n * To pick only Entities ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through any other Entities that are\n * in the way, as if they weren't there:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131],\n * includeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\n * });\n *\n * if (pickResult) {\n * // Entity will always be either \"gearbox#77.0\" or \"gearbox#79.0\"\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * To pick any pickable Entity, except for ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through those\n * Entities if they happen to be in the way:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131],\n * excludeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\n * });\n *\n * if (pickResult) {\n * // Entity will never be \"gearbox#77.0\" or \"gearbox#79.0\"\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * See {@link Scene#pick} for more info on picking.\n *\n * ## Querying and tracking boundaries\n *\n * Getting a Scene's World-space axis-aligned boundary (AABB):\n *\n * ````javascript\n * var aabb = scene.aabb; // [xmin, ymin, zmin, xmax, ymax, zmax]\n * ````\n *\n * Subscribing to updates to the AABB, which occur whenever {@link Entity}s are transformed, their\n * {@link ReadableGeometry}s have been updated, or the {@link Camera} has moved:\n *\n * ````javascript\n * scene.on(\"boundary\", function() {\n * var aabb = scene.aabb;\n * });\n * ````\n *\n * Getting the AABB of the {@link Entity}s with the given IDs:\n *\n * ````JavaScript\n * scene.getAABB(); // Gets collective boundary of all Entities in the scene\n * scene.getAABB(\"saw\"); // Gets boundary of an Object\n * scene.getAABB([\"saw\", \"gearbox\"]); // Gets collective boundary of two Objects\n * ````\n *\n * See {@link Scene#getAABB} and {@link Entity} for more info on querying and tracking boundaries.\n *\n * ## Managing the viewport\n *\n * The Scene's {@link Viewport} component manages the WebGL viewport:\n *\n * ````javascript\n * var viewport = scene.viewport\n * viewport.boundary = [0, 0, 500, 400];;\n * ````\n *\n * ## Controlling rendering\n *\n * You can configure a Scene to perform multiple \"passes\" (renders) per frame. This is useful when we want to render the\n * scene to multiple viewports, such as for stereo effects.\n *\n * In the example, below, we'll configure the Scene to render twice on each frame, each time to different viewport. We'll do this\n * with a callback that intercepts the Scene before each render and sets its {@link Viewport} to a\n * different portion of the canvas. By default, the Scene will clear the canvas only before the first render, allowing the\n * two views to be shown on the canvas at the same time.\n *\n * ````Javascript\n * var viewport = scene.viewport;\n *\n * // Configure Scene to render twice for each frame\n * scene.passes = 2; // Default is 1\n * scene.clearEachPass = false; // Default is false\n *\n * // Render to a separate viewport on each render\n *\n * var viewport = scene.viewport;\n * viewport.autoBoundary = false;\n *\n * scene.on(\"rendering\", function (e) {\n * switch (e.pass) {\n * case 0:\n * viewport.boundary = [0, 0, 200, 200]; // xmin, ymin, width, height\n * break;\n *\n * case 1:\n * viewport.boundary = [200, 0, 200, 200];\n * break;\n * }\n * });\n *\n * // We can also intercept the Scene after each render,\n * // (though we're not using this for anything here)\n * scene.on(\"rendered\", function (e) {\n * switch (e.pass) {\n * case 0:\n * break;\n *\n * case 1:\n * break;\n * }\n * });\n * ````\n *\n * ## Gamma correction\n *\n * Within its shaders, xeokit performs shading calculations in linear space.\n *\n * By default, the Scene expects color textures (eg. {@link PhongMaterial#diffuseMap},\n * {@link MetallicMaterial#baseColorMap} and {@link SpecularMaterial#diffuseMap}) to\n * be in pre-multipled gamma space, so will convert those to linear space before they are used in shaders. Other textures are\n * always expected to be in linear space.\n *\n * By default, the Scene will also gamma-correct its rendered output.\n *\n * You can configure the Scene to expect all those color textures to be linear space, so that it does not gamma-correct them:\n *\n * ````javascript\n * scene.gammaInput = false;\n * ````\n *\n * You would still need to gamma-correct the output, though, if it's going straight to the canvas, so normally we would\n * leave that enabled:\n *\n * ````javascript\n * scene.gammaOutput = true;\n * ````\n *\n * See {@link Texture} for more information on texture encoding and gamma.\n *\n * @class Scene\n */\nclass Scene extends _Component_js__WEBPACK_IMPORTED_MODULE_4__.Component {\n\t/**\n @private\n */\n\tget type() {\n\t\treturn \"Scene\";\n\t}\n\n\t/**\n\t * @private\n\t * @constructor\n\t * @param {Viewer} viewer The Viewer this Scene belongs to.\n\t * @param {Object} cfg Scene configuration.\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\n\t * @param {HTMLElement} [cfg.keyboardEventsElement] Optional reference to HTML element on which key events should be handled. Defaults to the HTML Document.\n\t * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane imposes rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.\n\t */\n\tconstructor(viewer, cfg = {}) {\n\t\tsuper(null, cfg);\n\n\t\tconst canvas = cfg.canvasElement || document.getElementById(cfg.canvasId);\n\n\t\tif (!(canvas instanceof HTMLCanvasElement)) {\n\t\t\tthrow \"Mandatory config expected: valid canvasId or canvasElement\";\n\t\t}\n\n\t\t/**\n\t\t * @type {{[key: string]: {wrapperFunc: Function, tickSubId: string}}}\n\t\t */\n\t\tthis._tickifiedFunctions = {};\n\n\t\tthis._transparent = !!cfg.transparent;\n\t\tconst alphaDepthMask = !!cfg.alphaDepthMask;\n\t\tthis._edgesEnabled = !!cfg.edgesEnabled;\n\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\n\t\t/**\n\t\t * The {@link Viewer} this Scene belongs to.\n\t\t * @type {Viewer}\n\t\t */\n\t\tthis.viewer = viewer;\n\n\t\t/** Decremented each frame, triggers occlusion test for occludable {@link Marker}s when zero.\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis.occlusionTestCountdown = 0;\n\n\t\t/**\n The number of models currently loading.\n\n @property loading\n @final\n @type {Number}\n */\n\t\tthis.loading = 0;\n\n\t\t/**\n The epoch time (in milliseconds since 1970) when this Scene was instantiated.\n\n @property timeCreated\n @final\n @type {Number}\n */\n\t\tthis.startTime = new Date().getTime();\n\n\t\t/**\n\t\t * Map of {@link SceneModel}s that represent models.\n\t\t *\n\t\t * Each {@link SceneModel} is mapped here by {@link SceneModel#id} when {@link SceneModel#isModel} is ````true````.\n\t\t *\n\t\t * @property models\n\t\t * @final\n\t\t * @type {{String:SceneModel}}\n\t\t */\n\t\tthis.models = {};\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represents objects.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * @property objects\n\t\t * @final\n\t\t * @type {{String:Entity}}\n\t\t */\n\t\tthis.objects = {};\n\t\tthis._numObjects = 0;\n\n\t\t/**\n\t\t * Map of currently visible {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is visible when {@link Entity#visible} is true.\n\t\t *\n\t\t * @property visibleObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.visibleObjects = {};\n\t\tthis._numVisibleObjects = 0;\n\n\t\t/**\n\t\t * Map of currently xrayed {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is xrayed when {@link Entity#xrayed} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property xrayedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.xrayedObjects = {};\n\t\tthis._numXRayedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently highlighted {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true```` is true, and is highlighted when {@link Entity#highlighted} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property highlightedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.highlightedObjects = {};\n\t\tthis._numHighlightedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently selected {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is true, and is selected while {@link Entity#selected} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property selectedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.selectedObjects = {};\n\t\tthis._numSelectedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently colorized {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property colorizedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.colorizedObjects = {};\n\t\tthis._numColorizedObjects = 0;\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent objects whose opacity was updated.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property opacityObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.opacityObjects = {};\n\t\tthis._numOpacityObjects = 0;\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent objects whose {@link Entity#offset}s were updated.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property offsetObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.offsetObjects = {};\n\t\tthis._numOffsetObjects = 0;\n\n\t\t// Cached ID arrays, lazy-rebuilt as needed when stale after map updates\n\n\t\t/**\n Lazy-regenerated ID lists.\n */\n\t\tthis._modelIds = null;\n\t\tthis._objectIds = null;\n\t\tthis._visibleObjectIds = null;\n\t\tthis._xrayedObjectIds = null;\n\t\tthis._highlightedObjectIds = null;\n\t\tthis._selectedObjectIds = null;\n\t\tthis._colorizedObjectIds = null;\n\t\tthis._opacityObjectIds = null;\n\t\tthis._offsetObjectIds = null;\n\n\t\tthis._collidables = {}; // Components that contribute to the Scene AABB\n\t\tthis._compilables = {}; // Components that require shader compilation\n\n\t\tthis._needRecompile = false;\n\n\t\t/**\n\t\t * For each {@link Component} type, a map of IDs to {@link Component} instances of that type.\n\t\t *\n\t\t * @type {{String:{String:Component}}}\n\t\t */\n\t\tthis.types = {};\n\n\t\t/**\n\t\t * The {@link Component}s within this Scene, each mapped to its {@link Component#id}.\n\t\t *\n\t\t * *@type {{String:Component}}\n\t\t */\n\t\tthis.components = {};\n\n\t\t/**\n\t\t * The {@link SectionPlane}s in this Scene, each mapped to its {@link SectionPlane#id}.\n\t\t *\n\t\t * @type {{String:SectionPlane}}\n\t\t */\n\t\tthis.sectionPlanes = {};\n\n\t\t/**\n\t\t * The {@link Light}s in this Scene, each mapped to its {@link Light#id}.\n\t\t *\n\t\t * @type {{String:Light}}\n\t\t */\n\t\tthis.lights = {};\n\n\t\t/**\n\t\t * The {@link LightMap}s in this Scene, each mapped to its {@link LightMap#id}.\n\t\t *\n\t\t * @type {{String:LightMap}}\n\t\t */\n\t\tthis.lightMaps = {};\n\n\t\t/**\n\t\t * The {@link ReflectionMap}s in this Scene, each mapped to its {@link ReflectionMap#id}.\n\t\t *\n\t\t * @type {{String:ReflectionMap}}\n\t\t */\n\t\tthis.reflectionMaps = {};\n\n\t\t/**\n\t\t * The {@link Bitmap}s in this Scene, each mapped to its {@link Bitmap#id}.\n\t\t *\n\t\t * @type {{String:Bitmap}}\n\t\t */\n\t\tthis.bitmaps = {};\n\n\t\t/**\n\t\t * The {@link LineSet}s in this Scene, each mapped to its {@link LineSet#id}.\n\t\t *\n\t\t * @type {{String:LineSet}}\n\t\t */\n\t\tthis.lineSets = {};\n\n\t\t/**\n\t\t * The real world offset for this Scene\n\t\t *\n\t\t * @type {Number[]}\n\t\t */\n\t\tthis.realWorldOffset = cfg.realWorldOffset || new Float64Array([0, 0, 0]);\n\n\t\t/**\n\t\t * Manages the HTML5 canvas for this Scene.\n\t\t *\n\t\t * @type {Canvas}\n\t\t */\n\t\tthis.canvas = new _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__.Canvas(this, {\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\n\t\t\tcanvas: canvas,\n\t\t\tspinnerElementId: cfg.spinnerElementId,\n\t\t\ttransparent: this._transparent,\n\t\t\twebgl2: cfg.webgl2 !== false,\n\t\t\tcontextAttr: cfg.contextAttr || {},\n\t\t\tbackgroundColor: cfg.backgroundColor,\n\t\t\tbackgroundColorFromAmbientLight: cfg.backgroundColorFromAmbientLight,\n\t\t\tpremultipliedAlpha: cfg.premultipliedAlpha,\n\t\t\tresolutionScale: cfg.resolutionScale\n\t\t});\n\n\t\tthis.canvas.on(\"boundary\", () => {\n\t\t\tthis.glRedraw();\n\t\t});\n\n\t\tthis.canvas.on(\"webglContextFailed\", () => {\n\t\t\talert(\"tctwins failed to find WebGL!\");\n\t\t});\n\n\t\tthis._renderer = new _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__.Renderer(this, {\n\t\t\ttransparent: this._transparent,\n\t\t\talphaDepthMask: alphaDepthMask,\n\t\t\tedgesEnabled: this._edgesEnabled\n\t\t});\n\n\t\tthis._sectionPlanesState = new (function () {\n\t\t\tthis.sectionPlanes = [];\n\n\t\t\tthis.clippingCaps = false;\n\n\t\t\tthis._numCachedSectionPlanes = 0;\n\n\t\t\tlet hash = null;\n\n\t\t\tthis.getHash = function () {\n\t\t\t\tif (hash) {\n\t\t\t\t\treturn hash;\n\t\t\t\t}\n\t\t\t\tconst numAllocatedSectionPlanes = this.getNumAllocatedSectionPlanes();\n\t\t\t\tconst sectionPlanes = this.sectionPlanes;\n\t\t\t\tif (numAllocatedSectionPlanes === 0) {\n\t\t\t\t\treturn (this.hash = \";\");\n\t\t\t\t}\n\t\t\t\tlet sectionPlane;\n\n\t\t\t\tconst hashParts = [];\n\t\t\t\tfor (let i = 0, len = numAllocatedSectionPlanes; i < len; i++) {\n\t\t\t\t\tsectionPlane = sectionPlanes[i];\n\t\t\t\t\thashParts.push(\"cp\");\n\t\t\t\t}\n\t\t\t\thashParts.push(\";\");\n\t\t\t\thash = hashParts.join(\"\");\n\t\t\t\treturn hash;\n\t\t\t};\n\n\t\t\tthis.addSectionPlane = function (sectionPlane) {\n\t\t\t\tthis.sectionPlanes.push(sectionPlane);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeSectionPlane = function (sectionPlane) {\n\t\t\t\tfor (let i = 0, len = this.sectionPlanes.length; i < len; i++) {\n\t\t\t\t\tif (this.sectionPlanes[i].id === sectionPlane.id) {\n\t\t\t\t\t\tthis.sectionPlanes.splice(i, 1);\n\t\t\t\t\t\thash = null;\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.setNumCachedSectionPlanes = function (numCachedSectionPlanes) {\n\t\t\t\tthis._numCachedSectionPlanes = numCachedSectionPlanes;\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.getNumCachedSectionPlanes = function () {\n\t\t\t\treturn this._numCachedSectionPlanes;\n\t\t\t};\n\n\t\t\tthis.getNumAllocatedSectionPlanes = function () {\n\t\t\t\tconst num = this.sectionPlanes.length;\n\t\t\t\treturn num > this._numCachedSectionPlanes ? num : this._numCachedSectionPlanes;\n\t\t\t};\n\t\t})();\n\n\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(cfg.numCachedSectionPlanes || 0);\n\n\t\tthis._lightsState = new (function () {\n\t\t\tconst DEFAULT_AMBIENT = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 0]);\n\t\t\tconst ambientColorIntensity = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4();\n\n\t\t\tthis.lights = [];\n\t\t\tthis.reflectionMaps = [];\n\t\t\tthis.lightMaps = [];\n\n\t\t\tlet hash = null;\n\t\t\tlet ambientLight = null;\n\n\t\t\tthis.getHash = function () {\n\t\t\t\tif (hash) {\n\t\t\t\t\treturn hash;\n\t\t\t\t}\n\t\t\t\tconst hashParts = [];\n\t\t\t\tconst lights = this.lights;\n\t\t\t\tlet light;\n\t\t\t\tfor (let i = 0, len = lights.length; i < len; i++) {\n\t\t\t\t\tlight = lights[i];\n\t\t\t\t\thashParts.push(\"/\");\n\t\t\t\t\thashParts.push(light.type);\n\t\t\t\t\thashParts.push(light.space === \"world\" ? \"w\" : \"v\");\n\t\t\t\t\tif (light.castsShadow) {\n\t\t\t\t\t\thashParts.push(\"sh\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.lightMaps.length > 0) {\n\t\t\t\t\thashParts.push(\"/lm\");\n\t\t\t\t}\n\t\t\t\tif (this.reflectionMaps.length > 0) {\n\t\t\t\t\thashParts.push(\"/rm\");\n\t\t\t\t}\n\t\t\t\thashParts.push(\";\");\n\t\t\t\thash = hashParts.join(\"\");\n\t\t\t\treturn hash;\n\t\t\t};\n\n\t\t\tthis.addLight = function (state) {\n\t\t\t\tthis.lights.push(state);\n\t\t\t\tambientLight = null;\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeLight = function (state) {\n\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\n\t\t\t\t\tconst light = this.lights[i];\n\t\t\t\t\tif (light.id === state.id) {\n\t\t\t\t\t\tthis.lights.splice(i, 1);\n\t\t\t\t\t\tif (ambientLight && ambientLight.id === state.id) {\n\t\t\t\t\t\t\tambientLight = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\thash = null;\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.addReflectionMap = function (state) {\n\t\t\t\tthis.reflectionMaps.push(state);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeReflectionMap = function (state) {\n\t\t\t\tfor (let i = 0, len = this.reflectionMaps.length; i < len; i++) {\n\t\t\t\t\tif (this.reflectionMaps[i].id === state.id) {\n\t\t\t\t\t\tthis.reflectionMaps.splice(i, 1);\n\t\t\t\t\t\thash = null;\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.addLightMap = function (state) {\n\t\t\t\tthis.lightMaps.push(state);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeLightMap = function (state) {\n\t\t\t\tfor (let i = 0, len = this.lightMaps.length; i < len; i++) {\n\t\t\t\t\tif (this.lightMaps[i].id === state.id) {\n\t\t\t\t\t\tthis.lightMaps.splice(i, 1);\n\t\t\t\t\t\thash = null;\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.getAmbientColorAndIntensity = function () {\n\t\t\t\tif (!ambientLight) {\n\t\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\n\t\t\t\t\t\tconst light = this.lights[i];\n\t\t\t\t\t\tif (light.type === \"ambient\") {\n\t\t\t\t\t\t\tambientLight = light;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (ambientLight) {\n\t\t\t\t\tconst color = ambientLight.color;\n\t\t\t\t\tconst intensity = ambientLight.intensity;\n\t\t\t\t\tambientColorIntensity[0] = color[0];\n\t\t\t\t\tambientColorIntensity[1] = color[1];\n\t\t\t\t\tambientColorIntensity[2] = color[2];\n\t\t\t\t\tambientColorIntensity[3] = intensity;\n\t\t\t\t\treturn ambientColorIntensity;\n\t\t\t\t} else {\n\t\t\t\t\treturn DEFAULT_AMBIENT;\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\t/**\n\t\t * Publishes input events that occur on this Scene's canvas.\n\t\t * @property input\n\t\t * @type {Input}\n\t\t * @final\n\t\t */\n\t\tthis.input = new _input_Input_js__WEBPACK_IMPORTED_MODULE_7__.Input(this, {\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\n\t\t\telement: this.canvas.canvas,\n\t\t\tkeyboardEventsElement: cfg.keyboardEventsElement\n\t\t});\n\n\t\t/**\n\t\t * Configures this Scene's units of measurement and coordinate mapping between Real-space and World-space 3D coordinate systems.\n\t\t *\n\t\t * @property metrics\n\t\t * @type {Metrics}\n\t\t * @final\n\t\t */\n\t\tthis.metrics = new _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__.Metrics(this, {\n\t\t\tunits: cfg.units,\n\t\t\tscale: cfg.scale,\n\t\t\torigin: cfg.origin\n\t\t});\n\n\t\t/** Configures Scalable Ambient Obscurance (SAO) for this Scene.\n\t\t * @type {SAO}\n\t\t * @final\n\t\t */\n\t\tthis.sao = new _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__.SAO(this, {\n\t\t\tenabled: cfg.saoEnabled\n\t\t});\n\n\t\tthis.ticksPerRender = cfg.ticksPerRender;\n\t\tthis.ticksPerOcclusionTest = cfg.ticksPerOcclusionTest;\n\t\tthis.passes = cfg.passes;\n\t\tthis.clearEachPass = cfg.clearEachPass;\n\t\tthis.gammaInput = cfg.gammaInput;\n\t\tthis.gammaOutput = cfg.gammaOutput;\n\t\tthis.gammaFactor = cfg.gammaFactor;\n\n\t\tthis._entityOffsetsEnabled = !!cfg.entityOffsetsEnabled;\n\t\tthis._logarithmicDepthBufferEnabled = !!cfg.logarithmicDepthBufferEnabled;\n\n\t\tthis._dtxEnabled = cfg.dtxEnabled !== false;\n\t\tthis._pbrEnabled = !!cfg.pbrEnabled;\n\t\tthis._colorTextureEnabled = cfg.colorTextureEnabled !== false;\n\t\tthis._dtxEnabled = !!cfg.dtxEnabled;\n\t\tthis._lodEnabled = cfg.lodEnabled !== false;\n\n\t\t// Register Scene on xeokit\n\t\t// Do this BEFORE we add components below\n\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core._addScene(this);\n\n\t\tthis._initDefaults();\n\n\t\t// Global components\n\n\t\tthis._viewport = new _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__.Viewport(this, {\n\t\t\tid: \"default.viewport\",\n\t\t\tautoBoundary: true,\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\n\t\t});\n\n\t\tthis._camera = new _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__.Camera(this, {\n\t\t\tid: \"default.camera\",\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\n\t\t});\n\n\t\t// Default lights\n\n\t\tnew _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__.AmbientLight(this, {\n\t\t\tcolor: [1.0, 1.0, 1.0],\n\t\t\tintensity: 0.6\n\t\t});\n\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\n\t\t\tdir: [0.8, -0.5, -0.5],\n\t\t\tcolor: [0.67, 0.67, 1.0],\n\t\t\tintensity: 0.6,\n\t\t\tspace: \"world\"\n\t\t});\n\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\n\t\t\tdir: [-0.8, -1.0, 0.5],\n\t\t\tcolor: [1, 1, 0.9],\n\t\t\tintensity: 0.8,\n\t\t\tspace: \"world\"\n\t\t});\n\n\t\tthis._camera.on(\"dirty\", () => {\n\t\t\tthis._renderer.imageDirty();\n\t\t});\n\n\t\tthis._lod = new _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__.LOD(this, {\n\t\t\tenabled: this._lodEnabled,\n\t\t\ttargetFPS: 30\n\t\t});\n\t}\n\n\t_initDefaults() {\n\t\t// Call this Scene's property accessors to lazy-init their properties\n\n\t\tlet dummy; // Keeps Codacy happy\n\n\t\tdummy = this.geometry;\n\t\tdummy = this.material;\n\t\tdummy = this.xrayMaterial;\n\t\tdummy = this.edgeMaterial;\n\t\tdummy = this.selectedMaterial;\n\t\tdummy = this.highlightMaterial;\n\t}\n\n\t_addComponent(component) {\n\t\tif (component.id) {\n\t\t\t// Manual ID\n\t\t\tif (this.components[component.id]) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Component \" +\n\t\t\t\t\t\t_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.inQuotes(component.id) +\n\t\t\t\t\t\t\" already exists in Scene - ignoring ID, will randomly-generate instead\"\n\t\t\t\t);\n\t\t\t\tcomponent.id = null;\n\t\t\t}\n\t\t}\n\t\tif (!component.id) {\n\t\t\t// Auto ID\n\t\t\tif (window.nextID === undefined) {\n\t\t\t\twindow.nextID = 0;\n\t\t\t}\n\t\t\t//component.id = math.createUUID();\n\t\t\tcomponent.id = \"__\" + window.nextID++;\n\t\t\twhile (this.components[component.id]) {\n\t\t\t\tcomponent.id = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.createUUID();\n\t\t\t}\n\t\t}\n\t\tthis.components[component.id] = component;\n\n\t\t// Register for class type\n\t\tconst type = component.type;\n\t\tlet types = this.types[component.type];\n\t\tif (!types) {\n\t\t\ttypes = this.types[type] = {};\n\t\t}\n\t\ttypes[component.id] = component;\n\n\t\tif (component.compile) {\n\t\t\tthis._compilables[component.id] = component;\n\t\t}\n\t\tif (component.isDrawable) {\n\t\t\tthis._renderer.addDrawable(component.id, component);\n\t\t\tthis._collidables[component.id] = component;\n\t\t}\n\t}\n\n\t_removeComponent(component) {\n\t\tvar id = component.id;\n\t\tvar type = component.type;\n\t\tdelete this.components[id];\n\t\t// Unregister for types\n\t\tconst types = this.types[type];\n\t\tif (types) {\n\t\t\tdelete types[id];\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isEmptyObject(types)) {\n\t\t\t\tdelete this.types[type];\n\t\t\t}\n\t\t}\n\t\tif (component.compile) {\n\t\t\tdelete this._compilables[component.id];\n\t\t}\n\t\tif (component.isDrawable) {\n\t\t\tthis._renderer.removeDrawable(component.id);\n\t\t\tdelete this._collidables[component.id];\n\t\t}\n\t}\n\n\t// Methods below are called by various component types to register themselves on their\n\t// Scene. Violates Hollywood Principle, where we could just filter on type in _addComponent,\n\t// but this is faster than checking the type of each component in such a filter.\n\n\t_sectionPlaneCreated(sectionPlane) {\n\t\tthis.sectionPlanes[sectionPlane.id] = sectionPlane;\n\t\tthis.scene._sectionPlanesState.addSectionPlane(sectionPlane._state);\n\t\tthis.scene.fire(\"sectionPlaneCreated\", sectionPlane, true /* Don't retain event */);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_bitmapCreated(bitmap) {\n\t\tthis.bitmaps[bitmap.id] = bitmap;\n\t\tthis.scene.fire(\"bitmapCreated\", bitmap, true /* Don't retain event */);\n\t}\n\n\t_lineSetCreated(lineSet) {\n\t\tthis.lineSets[lineSet.id] = lineSet;\n\t\tthis.scene.fire(\"lineSetCreated\", lineSet, true /* Don't retain event */);\n\t}\n\n\t_lightCreated(light) {\n\t\tthis.lights[light.id] = light;\n\t\tthis.scene._lightsState.addLight(light._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_lightMapCreated(lightMap) {\n\t\tthis.lightMaps[lightMap.id] = lightMap;\n\t\tthis.scene._lightsState.addLightMap(lightMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_reflectionMapCreated(reflectionMap) {\n\t\tthis.reflectionMaps[reflectionMap.id] = reflectionMap;\n\t\tthis.scene._lightsState.addReflectionMap(reflectionMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_sectionPlaneDestroyed(sectionPlane) {\n\t\tdelete this.sectionPlanes[sectionPlane.id];\n\t\tthis.scene._sectionPlanesState.removeSectionPlane(sectionPlane._state);\n\t\tthis.scene.fire(\"sectionPlaneDestroyed\", sectionPlane, true /* Don't retain event */);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_bitmapDestroyed(bitmap) {\n\t\tdelete this.bitmaps[bitmap.id];\n\t\tthis.scene.fire(\"bitmapDestroyed\", bitmap, true /* Don't retain event */);\n\t}\n\n\t_lineSetDestroyed(lineSet) {\n\t\tdelete this.lineSets[lineSet.id];\n\t\tthis.scene.fire(\"lineSetDestroyed\", lineSet, true /* Don't retain event */);\n\t}\n\n\t_lightDestroyed(light) {\n\t\tdelete this.lights[light.id];\n\t\tthis.scene._lightsState.removeLight(light._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_lightMapDestroyed(lightMap) {\n\t\tdelete this.lightMaps[lightMap.id];\n\t\tthis.scene._lightsState.removeLightMap(lightMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_reflectionMapDestroyed(reflectionMap) {\n\t\tdelete this.reflectionMaps[reflectionMap.id];\n\t\tthis.scene._lightsState.removeReflectionMap(reflectionMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_registerModel(model) {\n\t\tthis.models[model.id] = model;\n\t\tthis._modelIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterModel(model) {\n\t\tconst modelId = model.id;\n\t\tdelete this.models[modelId];\n\t\tthis._modelIds = null; // Lazy regenerate\n\t\tthis.fire(\"modelUnloaded\", modelId);\n\t}\n\n\t_registerObject(entity) {\n\t\tthis.objects[entity.id] = entity;\n\t\tthis._numObjects++;\n\t\tthis._objectIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterObject(entity) {\n\t\tdelete this.objects[entity.id];\n\t\tthis._numObjects--;\n\t\tthis._objectIds = null; // Lazy regenerate\n\t}\n\n\t_objectVisibilityUpdated(entity, notify = true) {\n\t\tif (entity.visible) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.visibleObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.visibleObjects[entity.id] = entity;\n\t\t\tthis._numVisibleObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.visibleObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.visibleObjects[entity.id];\n\t\t\tthis._numVisibleObjects--;\n\t\t}\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectVisibility\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterVisibleObject(entity) {\n\t\tdelete this.visibleObjects[entity.id];\n\t\tthis._numVisibleObjects--;\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectXRayedUpdated(entity, notify = true) {\n\t\tif (entity.xrayed) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.xrayedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.xrayedObjects[entity.id] = entity;\n\t\t\tthis._numXRayedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.xrayedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.xrayedObjects[entity.id];\n\t\t\tthis._numXRayedObjects--;\n\t\t}\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectXRayed\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterXRayedObject(entity) {\n\t\tdelete this.xrayedObjects[entity.id];\n\t\tthis._numXRayedObjects--;\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectHighlightedUpdated(entity) {\n\t\tif (entity.highlighted) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.highlightedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.highlightedObjects[entity.id] = entity;\n\t\t\tthis._numHighlightedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.highlightedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.highlightedObjects[entity.id];\n\t\t\tthis._numHighlightedObjects--;\n\t\t}\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterHighlightedObject(entity) {\n\t\tdelete this.highlightedObjects[entity.id];\n\t\tthis._numHighlightedObjects--;\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectSelectedUpdated(entity, notify = true) {\n\t\tif (entity.selected) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.selectedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object select update (selected=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.selectedObjects[entity.id] = entity;\n\t\t\tthis._numSelectedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.selectedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object select update (selected=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.selectedObjects[entity.id];\n\t\t\tthis._numSelectedObjects--;\n\t\t}\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectSelected\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterSelectedObject(entity) {\n\t\tdelete this.selectedObjects[entity.id];\n\t\tthis._numSelectedObjects--;\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectColorizeUpdated(entity, colorized) {\n\t\tif (colorized) {\n\t\t\tthis.colorizedObjects[entity.id] = entity;\n\t\t\tthis._numColorizedObjects++;\n\t\t} else {\n\t\t\tdelete this.colorizedObjects[entity.id];\n\t\t\tthis._numColorizedObjects--;\n\t\t}\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterColorizedObject(entity) {\n\t\tdelete this.colorizedObjects[entity.id];\n\t\tthis._numColorizedObjects--;\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectOpacityUpdated(entity, opacityUpdated) {\n\t\tif (opacityUpdated) {\n\t\t\tthis.opacityObjects[entity.id] = entity;\n\t\t\tthis._numOpacityObjects++;\n\t\t} else {\n\t\t\tdelete this.opacityObjects[entity.id];\n\t\t\tthis._numOpacityObjects--;\n\t\t}\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterOpacityObject(entity) {\n\t\tdelete this.opacityObjects[entity.id];\n\t\tthis._numOpacityObjects--;\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectOffsetUpdated(entity, offset) {\n\t\tif (!offset || (offset[0] === 0 && offset[1] === 0 && offset[2] === 0)) {\n\t\t\tthis.offsetObjects[entity.id] = entity;\n\t\t\tthis._numOffsetObjects++;\n\t\t} else {\n\t\t\tdelete this.offsetObjects[entity.id];\n\t\t\tthis._numOffsetObjects--;\n\t\t}\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterOffsetObject(entity) {\n\t\tdelete this.offsetObjects[entity.id];\n\t\tthis._numOffsetObjects--;\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\n\t}\n\n\t_webglContextLost() {\n\t\t// this.loading++;\n\t\tthis.canvas.spinner.processes++;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tconst component = this.components[id];\n\t\t\t\tif (component._webglContextLost) {\n\t\t\t\t\tcomponent._webglContextLost();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._renderer.webglContextLost();\n\t}\n\n\t_webglContextRestored() {\n\t\tconst gl = this.canvas.gl;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tconst component = this.components[id];\n\t\t\t\tif (component._webglContextRestored) {\n\t\t\t\t\tcomponent._webglContextRestored(gl);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._renderer.webglContextRestored(gl);\n\t\t//this.loading--;\n\t\tthis.canvas.spinner.processes--;\n\t}\n\n\t/**\n\t * Returns the capabilities of this Scene.\n\t *\n\t * @private\n\t * @returns {{astcSupported: boolean, etc1Supported: boolean, pvrtcSupported: boolean, etc2Supported: boolean, dxtSupported: boolean, bptcSupported: boolean}}\n\t */\n\tget capabilities() {\n\t\treturn this._renderer.capabilities;\n\t}\n\n\t/**\n\t * Whether {@link Entity#offset} is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * @returns {Boolean} True if {@link Entity#offset} is enabled.\n\t */\n\tget entityOffsetsEnabled() {\n\t\treturn this._entityOffsetsEnabled;\n\t}\n\n\t/**\n\t * Whether precision surface picking is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.\n\t *\n\t * Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer.\n\t *\n\t * @returns {Boolean} True if precision picking is enabled.\n\t */\n\tget pickSurfacePrecisionEnabled() {\n\t\treturn false; // Removed\n\t}\n\n\t/**\n\t * Whether logarithmic depth buffer is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * @returns {Boolean} True if logarithmic depth buffer is enabled.\n\t */\n\tget logarithmicDepthBufferEnabled() {\n\t\treturn this._logarithmicDepthBufferEnabled;\n\t}\n\n\t/**\n\t * Sets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t *\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t *\n\t * Default is ````0````.\n\t */\n\tset numCachedSectionPlanes(numCachedSectionPlanes) {\n\t\tnumCachedSectionPlanes = numCachedSectionPlanes || 0;\n\t\tif (this._sectionPlanesState.getNumCachedSectionPlanes() !== numCachedSectionPlanes) {\n\t\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(numCachedSectionPlanes);\n\t\t\tthis._needRecompile = true;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t *\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @returns {number} The number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t */\n\tget numCachedSectionPlanes() {\n\t\treturn this._sectionPlanesState.getNumCachedSectionPlanes();\n\t}\n\n\t/**\n\t * Sets whether physically-based rendering is enabled.\n\t *\n\t * Default is ````false````.\n\t */\n\tset pbrEnabled(pbrEnabled) {\n\t\tthis._pbrEnabled = !!pbrEnabled;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether physically-based rendering is enabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} True if quality rendering is enabled.\n\t */\n\tget pbrEnabled() {\n\t\treturn this._pbrEnabled;\n\t}\n\n\t/**\n\t * Sets whether data texture scene representation (DTX) is enabled for the {@link Scene}.\n\t *\n\t * Even when enabled, DTX will only work if supported.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset dtxEnabled(value) {\n\t\tvalue = !!value;\n\t\tif (this._dtxEnabled === value) {\n\t\t\treturn;\n\t\t}\n\t\tthis._dtxEnabled = value;\n\t}\n\n\t/**\n\t * Gets whether data texture-based scene representation (DTX) is enabled for the {@link Scene}.\n\t *\n\t * Even when enabled, DTX will only apply if supported.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget dtxEnabled() {\n\t\treturn this._dtxEnabled;\n\t}\n\n\t/**\n\t * set showedges enable\n\t * @param {boolean} edgesEnabled\n\t */\n\tset edgesEnabled(edgesEnabled) {\n\t\tedgesEnabled = !!edgesEnabled;\n\t\tif (this._edgesEnabled === edgesEnabled) {\n\t\t\treturn;\n\t\t}\n\t\tthis._edgesEnabled = edgesEnabled;\n\t\tthis._renderer.setEdgesEnabled(edgesEnabled);\n\t}\n\n\t/**\n\t * @param {boolean} trans\n\t */\n\tget edgesEnabled() {\n\t\treturn this._edgesEnabled;\n\t}\n\n\t/**\n\t * set whether transparent of canvas background\n\t * @param {boolean} trans\n\t */\n\tset backgroundTransparent(trans) {\n\t\ttrans = !!trans;\n\t\t// if (this._transparent == trans) {\n\t\t// return;\n\t\t// }\n\t\tthis._transparent = trans;\n\t\tthis._renderer.setTransparentEnabled(trans);\n\t}\n\n\t/**\n\t * @returns {boolean} backgroundTransparent\n\t */\n\tget backgroundTransparent() {\n\t\treturn this._transparent;\n\t}\n\n\t/**\n\t * set background color\n\t * @param {[]} color\n\t */\n\tset backgroundColor(color) {\n\t\tthis.canvas.backgroundColor = color;\n\t\tthis._renderer.render({ force: true });\n\t}\n\n\t/**\n\t * return backgroundColor\n\t * @returns {boolean} backgroundColor\n\t */\n\tget backgroundColor() {\n\t\treturn this.canvas.backgroundColor();\n\t}\n\n\t/**\n\t * Sets whether basic color texture rendering is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\n\t */\n\tset colorTextureEnabled(colorTextureEnabled) {\n\t\tthis._colorTextureEnabled = !!colorTextureEnabled;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether basic color texture rendering is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\n\t */\n\tget colorTextureEnabled() {\n\t\treturn this._colorTextureEnabled;\n\t}\n\n\t/**\n\t * Performs an occlusion test on all {@link Marker}s in this {@link Scene}.\n\t *\n\t * Sets each {@link Marker#visible} ````true```` if the Marker is currently not occluded by any opaque {@link Entity}s\n\t * in the Scene, or ````false```` if an Entity is occluding it.\n\t */\n\tdoOcclusionTest() {\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\t\tthis._renderer.doOcclusionTest();\n\t}\n\n\t/**\n\t * Renders a single frame of this Scene.\n\t *\n\t * The Scene will periodically render itself after any updates, but you can call this method to force a render\n\t * if required.\n\t *\n\t * @param {Boolean} [forceRender=false] Forces a render when true, otherwise only renders if something has changed in this Scene\n\t * since the last render.\n\t */\n\trender(forceRender) {\n\t\tif (forceRender) {\n\t\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.runTasks();\n\t\t}\n\n\t\tconst renderEvent = {\n\t\t\tsceneId: null,\n\t\t\tpass: 0\n\t\t};\n\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\n\t\tif (!forceRender && !this._renderer.needsRender()) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderEvent.sceneId = this.id;\n\n\t\tconst passes = this._passes;\n\t\tconst clearEachPass = this._clearEachPass;\n\t\tlet pass;\n\t\tlet clear;\n\n\t\tfor (pass = 0; pass < passes; pass++) {\n\t\t\trenderEvent.pass = pass;\n\n\t\t\t/**\n\t\t\t * Fired when about to render a frame for a Scene.\n\t\t\t *\n\t\t\t * @event rendering\n\t\t\t * @param {String} sceneID The ID of this Scene.\n\t\t\t * @param {Number} pass Index of the pass we are about to render (see {@link Scene#passes}).\n\t\t\t */\n\t\t\tthis.fire(\"rendering\", renderEvent, true);\n\n\t\t\tclear = clearEachPass || pass === 0;\n\n\t\t\tthis._renderer.render({ pass: pass, clear: clear, force: forceRender });\n\n\t\t\t/**\n\t\t\t * Fired when we have just rendered a frame for a Scene.\n\t\t\t *\n\t\t\t * @event rendering\n\t\t\t * @param {String} sceneID The ID of this Scene.\n\t\t\t * @param {Number} pass Index of the pass we rendered (see {@link Scene#passes}).\n\t\t\t */\n\t\t\tthis.fire(\"rendered\", renderEvent, true);\n\t\t}\n\n\t\tthis._saveAmbientColor();\n\t}\n\n\t/**\n\t * @private\n\t */\n\tcompile() {\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\t}\n\n\t_recompile() {\n\t\tfor (const id in this._compilables) {\n\t\t\tif (this._compilables.hasOwnProperty(id)) {\n\t\t\t\tthis._compilables[id].compile();\n\t\t\t}\n\t\t}\n\t\tthis._renderer.shadowsDirty();\n\t\tthis.fire(\"compile\", this, true);\n\t}\n\n\t_saveAmbientColor() {\n\t\tconst canvas = this.canvas;\n\t\tif (!canvas.transparent && !canvas.backgroundImage && !canvas.backgroundColor) {\n\t\t\tconst ambientColorIntensity = this._lightsState.getAmbientColorAndIntensity();\n\t\t\tif (\n\t\t\t\t!this._lastAmbientColor ||\n\t\t\t\tthis._lastAmbientColor[0] !== ambientColorIntensity[0] ||\n\t\t\t\tthis._lastAmbientColor[1] !== ambientColorIntensity[1] ||\n\t\t\t\tthis._lastAmbientColor[2] !== ambientColorIntensity[2] ||\n\t\t\t\tthis._lastAmbientColor[3] !== ambientColorIntensity[3]\n\t\t\t) {\n\t\t\t\tcanvas.backgroundColor = ambientColorIntensity;\n\t\t\t\tif (!this._lastAmbientColor) {\n\t\t\t\t\tthis._lastAmbientColor = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 1]);\n\t\t\t\t}\n\t\t\t\tthis._lastAmbientColor.set(ambientColorIntensity);\n\t\t\t}\n\t\t} else {\n\t\t\tthis._lastAmbientColor = null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#models}.\n\t *\n\t * @type {String[]}\n\t */\n\tget modelIds() {\n\t\tif (!this._modelIds) {\n\t\t\tthis._modelIds = Object.keys(this.models);\n\t\t}\n\t\treturn this._modelIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#objects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numObjects() {\n\t\treturn this._numObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#objects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget objectIds() {\n\t\tif (!this._objectIds) {\n\t\t\tthis._objectIds = Object.keys(this.objects);\n\t\t}\n\t\treturn this._objectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#visibleObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numVisibleObjects() {\n\t\treturn this._numVisibleObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#visibleObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget visibleObjectIds() {\n\t\tif (!this._visibleObjectIds) {\n\t\t\tthis._visibleObjectIds = Object.keys(this.visibleObjects);\n\t\t}\n\t\treturn this._visibleObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#xrayedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numXRayedObjects() {\n\t\treturn this._numXRayedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#xrayedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget xrayedObjectIds() {\n\t\tif (!this._xrayedObjectIds) {\n\t\t\tthis._xrayedObjectIds = Object.keys(this.xrayedObjects);\n\t\t}\n\t\treturn this._xrayedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#highlightedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numHighlightedObjects() {\n\t\treturn this._numHighlightedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#highlightedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget highlightedObjectIds() {\n\t\tif (!this._highlightedObjectIds) {\n\t\t\tthis._highlightedObjectIds = Object.keys(this.highlightedObjects);\n\t\t}\n\t\treturn this._highlightedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#selectedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numSelectedObjects() {\n\t\treturn this._numSelectedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#selectedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget selectedObjectIds() {\n\t\tif (!this._selectedObjectIds) {\n\t\t\tthis._selectedObjectIds = Object.keys(this.selectedObjects);\n\t\t}\n\t\treturn this._selectedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#colorizedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numColorizedObjects() {\n\t\treturn this._numColorizedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#colorizedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget colorizedObjectIds() {\n\t\tif (!this._colorizedObjectIds) {\n\t\t\tthis._colorizedObjectIds = Object.keys(this.colorizedObjects);\n\t\t}\n\t\treturn this._colorizedObjectIds;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#opacityObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget opacityObjectIds() {\n\t\tif (!this._opacityObjectIds) {\n\t\t\tthis._opacityObjectIds = Object.keys(this.opacityObjects);\n\t\t}\n\t\treturn this._opacityObjectIds;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#offsetObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget offsetObjectIds() {\n\t\tif (!this._offsetObjectIds) {\n\t\t\tthis._offsetObjectIds = Object.keys(this.offsetObjects);\n\t\t}\n\t\treturn this._offsetObjectIds;\n\t}\n\n\t/**\n\t * Sets the number of \"ticks\" that happen between each render or this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tset ticksPerRender(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 1;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\"Unsupported value for 'ticksPerRender': '\" + value + \"' - should be an integer greater than zero.\");\n\t\t\tvalue = 1;\n\t\t}\n\t\tif (value === this._ticksPerRender) {\n\t\t\treturn;\n\t\t}\n\t\tthis._ticksPerRender = value;\n\t}\n\n\t/**\n\t * Gets the number of \"ticks\" that happen between each render or this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget ticksPerRender() {\n\t\treturn this._ticksPerRender;\n\t}\n\n\t/**\n\t * Sets the number of \"ticks\" that happen between occlusion testing for {@link Marker}s.\n\t *\n\t * Default value is ````20````.\n\t *\n\t * @type {Number}\n\t */\n\tset ticksPerOcclusionTest(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 20;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\n\t\t\t\t\"Unsupported value for 'ticksPerOcclusionTest': '\" + value + \"' - should be an integer greater than zero.\"\n\t\t\t);\n\t\t\tvalue = 20;\n\t\t}\n\t\tif (value === this._ticksPerOcclusionTest) {\n\t\t\treturn;\n\t\t}\n\t\tthis._ticksPerOcclusionTest = value;\n\t}\n\n\t/**\n\t * Gets the number of \"ticks\" that happen between each render of this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget ticksPerOcclusionTest() {\n\t\treturn this._ticksPerOcclusionTest;\n\t}\n\n\t/**\n\t * Sets the number of times this Scene renders per frame.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tset passes(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 1;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\"Unsupported value for 'passes': '\" + value + \"' - should be an integer greater than zero.\");\n\t\t\tvalue = 1;\n\t\t}\n\t\tif (value === this._passes) {\n\t\t\treturn;\n\t\t}\n\t\tthis._passes = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the number of times this Scene renders per frame.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget passes() {\n\t\treturn this._passes;\n\t}\n\n\t/**\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset clearEachPass(value) {\n\t\tvalue = !!value;\n\t\tif (value === this._clearEachPass) {\n\t\t\treturn;\n\t\t}\n\t\tthis._clearEachPass = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget clearEachPass() {\n\t\treturn this._clearEachPass;\n\t}\n\n\t/**\n\t * Sets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset gammaInput(value) {\n\t\tvalue = value !== false;\n\t\tif (value === this._renderer.gammaInput) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaInput = value;\n\t\tthis._needRecompile = true;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget gammaInput() {\n\t\treturn this._renderer.gammaInput;\n\t}\n\n\t/**\n\t * Sets whether or not to render pixels with pre-multiplied gama.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset gammaOutput(value) {\n\t\tvalue = !!value;\n\t\tif (value === this._renderer.gammaOutput) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaOutput = value;\n\t\tthis._needRecompile = true;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether or not to render pixels with pre-multiplied gama.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget gammaOutput() {\n\t\treturn this._renderer.gammaOutput;\n\t}\n\n\t/**\n\t * Sets the gamma factor to use when {@link Scene#gammaOutput} is set true.\n\t *\n\t * Default value is ````2.2````.\n\t *\n\t * @type {Number}\n\t */\n\tset gammaFactor(value) {\n\t\tvalue = value === undefined || value === null ? 2.2 : value;\n\t\tif (value === this._renderer.gammaFactor) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaFactor = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the gamma factor to use when {@link Scene#gammaOutput} is set true.\n\t *\n\t * Default value is ````2.2````.\n\t *\n\t * @type {Number}\n\t */\n\tget gammaFactor() {\n\t\treturn this._renderer.gammaFactor;\n\t}\n\n\t/**\n\t * Gets the default {@link Geometry} for this Scene, which is a {@link ReadableGeometry} with a unit-sized box shape.\n\t *\n\t * Has {@link ReadableGeometry#id} set to \"default.geometry\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#geometry} set to this {@link ReadableGeometry} by default.\n\t *\n\t * @type {ReadableGeometry}\n\t */\n\tget geometry() {\n\t\treturn (\n\t\t\tthis.components[\"default.geometry\"] ||\n\t\t\t(0,_geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__.buildBoxGeometry)(_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__.ReadableGeometry, this, {\n\t\t\t\tid: \"default.geometry\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default {@link Material} for this Scene, which is a {@link PhongMaterial}.\n\t *\n\t * Has {@link PhongMaterial#id} set to \"default.material\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#material} set to this {@link PhongMaterial} by default.\n\t *\n\t * @type {PhongMaterial}\n\t */\n\tget material() {\n\t\treturn (\n\t\t\tthis.components[\"default.material\"] ||\n\t\t\tnew _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__.PhongMaterial(this, {\n\t\t\t\tid: \"default.material\",\n\t\t\t\temissive: [0.4, 0.4, 0.4], // Visible by default on geometry without normals\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default xraying {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.xrayMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#xrayMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are xrayed while {@link Mesh#xrayed} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget xrayMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.xrayMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.xrayMaterial\",\n\t\t\t\tpreset: \"sepia\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default highlight {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.highlightMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget highlightMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.highlightMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.highlightMaterial\",\n\t\t\t\tpreset: \"yellowHighlight\",\n\t\t\t\tfillAlpha: 0.1,\n\t\t\t\tfillColor: [0.7, 0.9, 0.9],\n\t\t\t\tdontClear: false,\n\t\t\t\tedges: false,\n\t\t\t\tglowThrough: false\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default selection {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.selectedMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget selectedMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.selectedMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.selectedMaterial\",\n\t\t\t\tpreset: \"greenSelected\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default {@link EdgeMaterial} for this Scene.\n\t *\n\t * Has {@link EdgeMaterial#id} set to \"default.edgeMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#edgeMaterial} set to this {@link EdgeMaterial} by default.\n\t *\n\t * {@link Mesh}s have their edges emphasized while {@link Mesh#edges} is ````true````.\n\t *\n\t * @type {EdgeMaterial}\n\t */\n\tget edgeMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.edgeMaterial\"] ||\n\t\t\tnew _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__.EdgeMaterial(this, {\n\t\t\t\tid: \"default.edgeMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tedgeColor: [0.0, 0.0, 0.0],\n\t\t\t\tedgeAlpha: 1.0,\n\t\t\t\tedgeWidth: 1,\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link PointsMaterial} for this Scene.\n\t *\n\t * @type {PointsMaterial}\n\t */\n\tget pointsMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.pointsMaterial\"] ||\n\t\t\tnew _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__.PointsMaterial(this, {\n\t\t\t\tid: \"default.pointsMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link LinesMaterial} for this Scene.\n\t *\n\t * @type {LinesMaterial}\n\t */\n\tget linesMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.linesMaterial\"] ||\n\t\t\tnew _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__.LinesMaterial(this, {\n\t\t\t\tid: \"default.linesMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link Viewport} for this Scene.\n\t *\n\t * @type Viewport\n\t */\n\tget viewport() {\n\t\treturn this._viewport;\n\t}\n\n\t/**\n\t * Gets the {@link Camera} for this Scene.\n\t *\n\t * @type {Camera}\n\t */\n\tget camera() {\n\t\treturn this._camera;\n\t}\n\n\t/**\n\t * Gets the World-space 3D center of this Scene.\n\t *\n\t *@type {Number[]}\n\t */\n\tget center() {\n\t\tif (this._aabbDirty || !this._center) {\n\t\t\tif (!this._center || !this._center) {\n\t\t\t\tthis._center = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec3();\n\t\t\t}\n\t\t\tconst aabb = this.aabb;\n\t\t\tthis._center[0] = (aabb[0] + aabb[3]) / 2;\n\t\t\tthis._center[1] = (aabb[1] + aabb[4]) / 2;\n\t\t\tthis._center[2] = (aabb[2] + aabb[5]) / 2;\n\t\t}\n\t\treturn this._center;\n\t}\n\n\t/**\n\t * Gets the World-space axis-aligned 3D boundary (AABB) of this Scene.\n\t *\n\t * The AABB is represented by a six-element Float64Array containing the min/max extents of the axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\n\t *\n\t * When the Scene has no content, will be ````[-100,-100,-100,100,100,100]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget aabb() {\n\t\tif (this._aabbDirty) {\n\t\t\tif (this._aabbUpdate) {\n\t\t\t\treturn this._aabb;\n\t\t\t}\n\t\t\tif (!this._aabb) {\n\t\t\t\tthis._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\n\t\t\t}\n\t\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet aabb;\n\t\t\tconst collidables = this._collidables;\n\t\t\tlet collidable;\n\t\t\tlet valid = false;\n\t\t\tfor (const collidableId in collidables) {\n\t\t\t\tif (collidables.hasOwnProperty(collidableId)) {\n\t\t\t\t\tcollidable = collidables[collidableId];\n\t\t\t\t\tif (collidable.collidable === false) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\taabb = collidable.aabb;\n\t\t\t\t\tif (aabb[0] < xmin) {\n\t\t\t\t\t\txmin = aabb[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[1] < ymin) {\n\t\t\t\t\t\tymin = aabb[1];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[2] < zmin) {\n\t\t\t\t\t\tzmin = aabb[2];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[3] > xmax) {\n\t\t\t\t\t\txmax = aabb[3];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[4] > ymax) {\n\t\t\t\t\t\tymax = aabb[4];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[5] > zmax) {\n\t\t\t\t\t\tzmax = aabb[5];\n\t\t\t\t\t}\n\t\t\t\t\tvalid = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!valid) {\n\t\t\t\txmin = -100;\n\t\t\t\tymin = -100;\n\t\t\t\tzmin = -100;\n\t\t\t\txmax = 100;\n\t\t\t\tymax = 100;\n\t\t\t\tzmax = 100;\n\t\t\t}\n\t\t\tthis._aabb[0] = xmin;\n\t\t\tthis._aabb[1] = ymin;\n\t\t\tthis._aabb[2] = zmin;\n\t\t\tthis._aabb[3] = xmax;\n\t\t\tthis._aabb[4] = ymax;\n\t\t\tthis._aabb[5] = zmax;\n\t\t\tthis._aabbDirty = false;\n\t\t}\n\t\treturn this._aabb;\n\t}\n\n\tget aabbs() {\n\t\tconst collidables = this._collidables;\n\t\tfor (const collidableId in collidables) {\n\t\t\treturn collidables[collidableId].aabbs;\n\t\t}\n\t}\n\n\tcalculateBoxCenter(boxs) {\n\t\tlet points = [];\n\t\tfor (let i = 0; i < boxs.length; i++) {\n\t\t\tlet box = boxs[i];\n\t\t\tlet center = [(box[0] + box[3]) / 2, (box[1] + box[4]) / 2, (box[2] + box[5]) / 2];\n\t\t\tpoints.push(_math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec3(center));\n\t\t}\n\t\treturn points;\n\t}\n\n\t_setAABBDirty() {\n\t\tthis._aabbDirty = true;\n\t\tthis.center;\n\t\t// this.fire(\"boundary\");\n\t}\n\n\t/**\n * Attempts to pick an {@link Entity} in this Scene.\n *\n * Ignores {@link Entity}s with {@link Entity#pickable} set ````false````.\n *\n * When an {@link Entity} is picked, fires a \"pick\" event on the {@link Entity} with the pick result as parameters.\n *\n * Picking the {@link Entity} at the given canvas coordinates:\n\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an Entity\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * Picking, with a ray cast through the canvas, hits an {@link Entity}:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true,\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an Entity\n *\n * var entity = pickResult.entity;\n *\n * if (pickResult.primitive === \"triangle\") {\n *\n * // Picked a triangle on the entity surface\n *\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n *\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\n *\n * // Picked a point and normal on the entity surface\n *\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\n * }\n * }\n * ````\n *\n * Picking the {@link Entity} that intersects an arbitrarily-aligned World-space ray:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true, // Picking with arbitrarily-positioned ray\n * origin: [0,0,-5], // Ray origin\n * direction: [0,0,1] // Ray direction\n * });\n *\n * if (pickResult) { // Picked an Entity with the ray\n *\n * var entity = pickResult.entity;\n *\n * if (pickResult.primitive == \"triangle\") {\n *\n * // Picked a triangle on the entity surface\n *\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n * var origin = pickResult.origin; // Float64Array containing the World-space ray origin\n * var direction = pickResult.direction; // Float64Array containing the World-space ray direction\n *\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\n *\n * // Picked a point and normal on the entity surface\n *\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\n * }\n * }\n * ````\n *\n * @param {*} params Picking parameters.\n * @param {Boolean} [params.pickSurface=false] Whether to find the picked position on the surface of the Entity.\n * @param {Boolean} [params.pickSurfacePrecision=false] When picking an Entity surface position, indicates whether or not we want full-precision {@link PickResult#worldPos}. Only works when {@link Scene#pickSurfacePrecisionEnabled} is ````true````. If pick succeeds, the returned {@link PickResult} will have {@link PickResult#precision} set ````true````, to indicate that it contains full-precision surface pick results.\n * @param {Boolean} [params.pickSurfaceNormal=false] Whether to find the picked normal on the surface of the Entity. Only works if ````pickSurface```` is given.\n * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\n * @param {Number[]} [params.origin] World-space ray origin when ray-picking. Ignored when canvasPos given.\n * @param {Number[]} [params.direction] World-space ray direction when ray-picking. Also indicates the length of the ray. Ignored when canvasPos given.\n * @param {Number[]} [params.matrix] 4x4 transformation matrix to define the World-space ray origin and direction, as an alternative to ````origin```` and ````direction````.\n * @param {String[]} [params.includeEntities] IDs of {@link Entity}s to restrict picking to. When given, ignores {@link Entity}s whose IDs are not in this list.\n * @param {String[]} [params.excludeEntities] IDs of {@link Entity}s to ignore. When given, will pick *through* these {@link Entity}s, as if they were not there.\n * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\n * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\n * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\n * @param {PickResult} [pickResult] Holds the results of the pick attempt. Will use the Scene's singleton PickResult if you don't supply your own.\n * @returns {PickResult} Holds results of the pick attempt, returned when an {@link Entity} is picked, else null. See method comments for description.\n */\n\tpick(params, pickResult) {\n\t\tif (this.canvas.boundary[2] === 0 || this.canvas.boundary[3] === 0) {\n\t\t\tthis.error(\"Picking not allowed while canvas has zero width or height\");\n\t\t\treturn null;\n\t\t}\n\n\t\tparams = params || {};\n\n\t\tparams.pickSurface = params.pickSurface || params.rayPick; // Backwards compatibility\n\n\t\tif (!params.canvasPos && !params.matrix && (!params.origin || !params.direction)) {\n\t\t\tthis.warn(\"picking without canvasPos, matrix, or ray origin and direction\");\n\t\t}\n\n\t\tconst includeEntities = params.includeEntities || params.include; // Backwards compat\n\t\tif (includeEntities) {\n\t\t\tparams.includeEntityIds = getEntityIDMap(this, includeEntities);\n\t\t}\n\n\t\tconst excludeEntities = params.excludeEntities || params.exclude; // Backwards compat\n\t\tif (excludeEntities) {\n\t\t\tparams.excludeEntityIds = getEntityIDMap(this, excludeEntities);\n\t\t}\n\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\n\t\tif (params.snapToEdge || params.snapToVertex) {\n\t\t\tpickResult = this._renderer.snapPick(\n\t\t\t\tparams.canvasPos,\n\t\t\t\tparams.snapRadius || 30,\n\t\t\t\tparams.snapToVertex,\n\t\t\t\tparams.snapToEdge,\n\t\t\t\tpickResult\n\t\t\t);\n\t\t} else {\n\t\t\tpickResult = this._renderer.pick(params, pickResult);\n\t\t}\n\n\t\tif (pickResult) {\n\t\t\tif (pickResult.entity && pickResult.entity.fire) {\n\t\t\t\tpickResult.entity.fire(\"picked\", pickResult); // TODO: SceneModelEntity doesn't fire events\n\t\t\t}\n\t\t}\n\n\t\treturn pickResult;\n\t}\n\n\t/**\n\t * @param {Object} params Picking parameters.\n\t * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\n\t * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\n\t * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\n\t * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\n\t * @deprecated\n\t */\n\tsnapPick(params) {\n\t\tif (undefined === this._warnSnapPickDeprecated) {\n\t\t\tthis._warnSnapPickDeprecated = true;\n\t\t\tthis.warn(\"Scene.snapPick() is deprecated since v2.4.2 - use Scene.pick() instead\");\n\t\t}\n\t\treturn this._renderer.snapPick(params.canvasPos, params.snapRadius || 30, params.snapToVertex, params.snapToEdge);\n\t}\n\n\t/**\n\t * Destroys all non-default {@link Component}s in this Scene.\n\t */\n\tclear() {\n\t\tvar component;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tcomponent = this.components[id];\n\t\t\t\tif (!component._dontClear) {\n\t\t\t\t\t// Don't destroy components like Camera, Input, Viewport etc.\n\t\t\t\t\tcomponent.destroy();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Light}s in this Scene..\n\t */\n\tclearLights() {\n\t\tconst ids = Object.keys(this.lights);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.lights[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link SectionPlane}s in this Scene.\n\t */\n\tclearSectionPlanes() {\n\t\tconst ids = Object.keys(this.sectionPlanes);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.sectionPlanes[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Line}s in this Scene.\n\t */\n\tclearBitmaps() {\n\t\tconst ids = Object.keys(this.bitmaps);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.bitmaps[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Line}s in this Scene.\n\t */\n\tclearLines() {\n\t\tconst ids = Object.keys(this.lineSets);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.lineSets[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the collective axis-aligned boundary (AABB) of a batch of {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which {@link Entity#isObject} is registered by {@link Entity#id} in {@link Scene#visibleObjects}.\n\t *\n\t * Each {@link Entity} is only included in the AABB when {@link Entity#collidable} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @returns {[Number, Number, Number, Number, Number, Number]} An axis-aligned World-space bounding box, given as elements ````[xmin, ymin, zmin, xmax, ymax, zmax]````.\n\t */\n\tgetAABB(ids) {\n\t\tif (ids === undefined) {\n\t\t\treturn this.aabb;\n\t\t}\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\n\t\t\tconst entity = this.objects[ids];\n\t\t\tif (entity && entity.aabb) {\n\t\t\t\t// A Component subclass with an AABB\n\t\t\t\treturn entity.aabb;\n\t\t\t}\n\t\t\tids = [ids]; // Must be an entity type\n\t\t}\n\t\tif (ids.length === 0) {\n\t\t\treturn this.aabb;\n\t\t}\n\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet valid;\n\t\tthis.withObjects(ids, (entity) => {\n\t\t\tif (entity.collidable) {\n\t\t\t\tconst aabb = entity.aabb;\n\t\t\t\tif (aabb[0] < xmin) {\n\t\t\t\t\txmin = aabb[0];\n\t\t\t\t}\n\t\t\t\tif (aabb[1] < ymin) {\n\t\t\t\t\tymin = aabb[1];\n\t\t\t\t}\n\t\t\t\tif (aabb[2] < zmin) {\n\t\t\t\t\tzmin = aabb[2];\n\t\t\t\t}\n\t\t\t\tif (aabb[3] > xmax) {\n\t\t\t\t\txmax = aabb[3];\n\t\t\t\t}\n\t\t\t\tif (aabb[4] > ymax) {\n\t\t\t\t\tymax = aabb[4];\n\t\t\t\t}\n\t\t\t\tif (aabb[5] > zmax) {\n\t\t\t\t\tzmax = aabb[5];\n\t\t\t\t}\n\t\t\t\tvalid = true;\n\t\t\t}\n\t\t});\n\t\tif (valid) {\n\t\t\tconst aabb2 = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\n\t\t\taabb2[0] = xmin;\n\t\t\taabb2[1] = ymin;\n\t\t\taabb2[2] = zmin;\n\t\t\taabb2[3] = xmax;\n\t\t\taabb2[4] = ymax;\n\t\t\taabb2[5] = zmax;\n\t\t\treturn aabb2;\n\t\t} else {\n\t\t\treturn this.aabb; // Scene AABB\n\t\t}\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#visible} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#visible} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#visibleObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} visible Whether or not to set visible.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsVisible(ids, visible) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.visible !== visible;\n\t\t\tentity.visible = visible;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#collidable} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} collidable Whether or not to set collidable.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsCollidable(ids, collidable) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.collidable !== collidable;\n\t\t\tentity.collidable = collidable;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#culled} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} culled Whether or not to cull.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsCulled(ids, culled) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.culled !== culled;\n\t\t\tentity.culled = culled;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#selected} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#selected} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#selectedObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} selected Whether or not to select.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsSelected(ids, selected) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.selected !== selected;\n\t\t\tentity.selected = selected;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#highlighted} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#highlighted} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#highlightedObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} highlighted Whether or not to highlight.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsHighlighted(ids, highlighted) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.highlighted !== highlighted;\n\t\t\tentity.highlighted = highlighted;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#xrayed} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} xrayed Whether or not to xray.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsXRayed(ids, xrayed) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.xrayed !== xrayed;\n\t\t\tentity.xrayed = xrayed;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#edges} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} edges Whether or not to show edges.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsEdges(ids, edges) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.edges !== edges;\n\t\t\tentity.edges = edges;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#colorize} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number[]} [colorize=(1,1,1)] RGB colorize factors, multiplied by the rendered pixel colors.\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsColorized(ids, colorize) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tentity.colorize = colorize;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#opacity} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number} [opacity=1.0] Opacity factor, multiplied by the rendered pixel alphas.\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsOpacity(ids, opacity) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.opacity !== opacity;\n\t\t\tentity.opacity = opacity;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#pickable} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} pickable Whether or not to set pickable.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsPickable(ids, pickable) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.pickable !== pickable;\n\t\t\tentity.pickable = pickable;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#offset} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number[]} [offset] 3D offset vector.\n\t */\n\tsetObjectsOffset(ids, offset) {\n\t\tthis.withObjects(ids, (entity) => {\n\t\t\tentity.offset = offset;\n\t\t});\n\t}\n\n\t/**\n\t * Iterates with a callback over {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Function} callback Callback to execute on eacn {@link Entity}.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\twithObjects(ids, callback) {\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\n\t\t\tids = [ids];\n\t\t}\n\t\tlet changed = false;\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tconst id = ids[i];\n\t\t\tlet entity = this.objects[id];\n\t\t\tif (entity) {\n\t\t\t\tchanged = callback(entity) || changed;\n\t\t\t} else {\n\t\t\t\tconst modelIds = this.modelIds;\n\t\t\t\tfor (let i = 0, len = modelIds.length; i < len; i++) {\n\t\t\t\t\tconst modelId = modelIds[i];\n\t\t\t\t\tconst globalObjectId = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.globalizeObjectId(modelId, id);\n\t\t\t\t\tentity = this.objects[globalObjectId];\n\t\t\t\t\tif (entity) {\n\t\t\t\t\t\tchanged = callback(entity) || changed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn changed;\n\t}\n\n\t/**\n\t * This method will \"tickify\" the provided `cb` function.\n\t *\n\t * This means, the function will be wrapped so:\n\t *\n\t * - it runs time-aligned to scene ticks\n\t * - it runs maximum once per scene-tick\n\t *\n\t * @param {Function} cb The function to tickify\n\t * @returns {Function}\n\t */\n\ttickify(cb) {\n\t\tconst cbString = cb.toString();\n\n\t\t/**\n\t\t * Check if the function is already tickified, and if so return the cached one.\n\t\t */\n\t\tif (cbString in this._tickifiedFunctions) {\n\t\t\treturn this._tickifiedFunctions[cbString].wrapperFunc;\n\t\t}\n\n\t\tlet alreadyRun = 0;\n\t\tlet needToRun = 0;\n\n\t\tlet lastArgs;\n\n\t\t/**\n\t\t * The provided `cb` function is replaced with a \"set-dirty\" function\n\t\t *\n\t\t * @type {Function}\n\t\t */\n\t\tconst wrapperFunc = function (...args) {\n\t\t\tlastArgs = args;\n\t\t\tneedToRun++;\n\t\t};\n\n\t\t/**\n\t\t * An each scene tick, if the \"dirty-flag\" is set, run the `cb` function.\n\t\t *\n\t\t * This will make it run time-aligned to the scene tick.\n\t\t */\n\t\tconst tickSubId = this.on(\"tick\", () => {\n\t\t\tconst tmp = needToRun;\n\t\t\tif (tmp > alreadyRun) {\n\t\t\t\talreadyRun = tmp;\n\t\t\t\tcb(...lastArgs);\n\t\t\t}\n\t\t});\n\n\t\t/**\n\t\t * And, store the list of subscribers.\n\t\t */\n\t\tthis._tickifiedFunctions[cbString] = { tickSubId, wrapperFunc };\n\n\t\treturn wrapperFunc;\n\t}\n\n\t/**\n\t * Destroys this Scene.\n\t */\n\tdestroy(callback) {\n\t\tsuper.destroy();\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tthis.components[id].destroy();\n\t\t\t}\n\t\t}\n\t\t// this.canvas.destroy(); // canvas是scene的其中一个component,所有以不必再destroy\n\n\t\t// Memory leak prevention\n\t\tthis.components = null;\n\t\tthis.models = null;\n\t\tthis.objects = null;\n\t\tthis.visibleObjects = null;\n\t\tthis.xrayedObjects = null;\n\t\tthis.highlightedObjects = null;\n\t\tthis.selectedObjects = null;\n\t\tthis.colorizedObjects = null;\n\t\tthis.opacityObjects = null;\n\t\tthis.sectionPlanes = null;\n\t\tthis.lights = null;\n\t\tthis.lightMaps = null;\n\t\tthis.reflectionMaps = null;\n\t\tthis._objectIds = null;\n\t\tthis._visibleObjectIds = null;\n\t\tthis._xrayedObjectIds = null;\n\t\tthis._highlightedObjectIds = null;\n\t\tthis._selectedObjectIds = null;\n\t\tthis._colorizedObjectIds = null;\n\t\tthis.types = null;\n\t\tthis._renderer = null;\n\t\tthis.input = null;\n\t\tthis._viewport = null;\n\t\tthis._camera = null;\n\t\tthis.canvas = null;\n\t\tif (typeof callback === \"function\") {\n\t\t\tcallback();\n\t\t}\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/scene/Scene.js?");
|
|
4827
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Scene: () => (/* binding */ Scene)\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 _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lod/LOD.js */ \"./src/viewer/scene/lod/LOD.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../canvas/Canvas.js */ \"./src/viewer/scene/canvas/Canvas.js\");\n/* harmony import */ var _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../webgl/Renderer.js */ \"./src/viewer/scene/webgl/Renderer.js\");\n/* harmony import */ var _input_Input_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../input/Input.js */ \"./src/viewer/scene/input/Input.js\");\n/* harmony import */ var _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../viewport/Viewport.js */ \"./src/viewer/scene/viewport/Viewport.js\");\n/* harmony import */ var _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../camera/Camera.js */ \"./src/viewer/scene/camera/Camera.js\");\n/* harmony import */ var _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../lights/AmbientLight.js */ \"./src/viewer/scene/lights/AmbientLight.js\");\n/* harmony import */ var _geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../geometry/builders/buildBoxGeometry.js */ \"./src/viewer/scene/geometry/builders/buildBoxGeometry.js\");\n/* harmony import */ var _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../materials/EdgeMaterial.js */ \"./src/viewer/scene/materials/EdgeMaterial.js\");\n/* harmony import */ var _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../metriqs/Metriqs.js */ \"./src/viewer/scene/metriqs/Metriqs.js\");\n/* harmony import */ var _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../postfx/SAO.js */ \"./src/viewer/scene/postfx/SAO.js\");\n/* harmony import */ var _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../materials/PointsMaterial.js */ \"./src/viewer/scene/materials/PointsMaterial.js\");\n/* harmony import */ var _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../materials/LinesMaterial.js */ \"./src/viewer/scene/materials/LinesMaterial.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// Enables runtime check for redundant calls to object state update methods, eg. Scene#_objectVisibilityUpdated\nconst ASSERT_OBJECT_STATE_UPDATE = false;\n\n// Cached vars to avoid garbage collection\n\nfunction getEntityIDMap(scene, entityIds) {\n\tconst map = {};\n\tlet entityId;\n\tlet entity;\n\tfor (let i = 0, len = entityIds.length; i < len; i++) {\n\t\tentityId = entityIds[i];\n\t\tentity = scene.components[entityId];\n\t\tif (!entity) {\n\t\t\tscene.warn(\"pick(): Component not found: \" + entityId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!entity.isEntity) {\n\t\t\tscene.warn(\"pick(): Component is not an Entity: \" + entityId);\n\t\t\tcontinue;\n\t\t}\n\t\tmap[entityId] = true;\n\t}\n\treturn map;\n}\n\n/**\n * Fired whenever a debug message is logged on a component within this Scene.\n * @event log\n * @param {String} value The debug message\n */\n\n/**\n * Fired whenever an error is logged on a component within this Scene.\n * @event error\n * @param {String} value The error message\n */\n\n/**\n * Fired whenever a warning is logged on a component within this Scene.\n * @event warn\n * @param {String} value The warning message\n */\n\n/**\n * @desc Contains the components that comprise a 3D scene.\n *\n * * A {@link Viewer} has a single Scene, which it provides in {@link Viewer#scene}.\n * * Plugins like {@link AxisGizmoPlugin} also have their own private Scenes.\n * * Each Scene has a corresponding {@link MetaScene}, which the Viewer provides in {@link Viewer#metaScene}.\n *\n * ## Getting a Viewer's Scene\n *\n * ````javascript\n * var scene = viewer.scene;\n * ````\n *\n * ## Creating and accessing Scene components\n *\n * As a brief introduction to creating Scene components, we'll create a {@link Mesh} that has a\n * {@link buildTorusGeometry} and a {@link PhongMaterial}:\n *\n * ````javascript\n * var teapotMesh = new Mesh(scene, {\n * id: \"myMesh\", // <<---------- ID automatically generated if not provided\n * geometry: new TorusGeometry(scene),\n * material: new PhongMaterial(scene, {\n * id: \"myMaterial\",\n * diffuse: [0.2, 0.2, 1.0]\n * })\n * });\n *\n * teapotMesh.scene.camera.eye = [45, 45, 45];\n * ````\n *\n * Find components by ID in their Scene's {@link Scene#components} map:\n *\n * ````javascript\n * var teapotMesh = scene.components[\"myMesh\"];\n * teapotMesh.visible = false;\n *\n * var teapotMaterial = scene.components[\"myMaterial\"];\n * teapotMaterial.diffuse = [1,0,0]; // Change to red\n * ````\n *\n * A Scene also has a map of component instances for each {@link Component} subtype:\n *\n * ````javascript\n * var meshes = scene.types[\"Mesh\"];\n * var teapotMesh = meshes[\"myMesh\"];\n * teapotMesh.xrayed = true;\n *\n * var phongMaterials = scene.types[\"PhongMaterial\"];\n * var teapotMaterial = phongMaterials[\"myMaterial\"];\n * teapotMaterial.diffuse = [0,1,0]; // Change to green\n * ````\n *\n * See {@link Node}, {@link Node} and {@link Model} for how to create and access more sophisticated content.\n *\n * ## Controlling the camera\n *\n * Use the Scene's {@link Camera} to control the current viewpoint and projection:\n *\n * ````javascript\n * var camera = myScene.camera;\n *\n * camera.eye = [-10,0,0];\n * camera.look = [-10,0,0];\n * camera.up = [0,1,0];\n *\n * camera.projection = \"perspective\";\n * camera.perspective.fov = 45;\n * //...\n * ````\n *\n * ## Managing the canvas\n *\n * The Scene's {@link Canvas} component provides various conveniences relevant to the WebGL canvas, such\n * as firing resize events etc:\n *\n * ````javascript\n * var canvas = scene.canvas;\n *\n * canvas.on(\"boundary\", function(boundary) {\n * //...\n * });\n * ````\n *\n * ## Picking\n *\n * Use {@link Scene#pick} to pick and raycast entites.\n *\n * For example, to pick a point on the surface of the closest entity at the given canvas coordinates:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true,\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an entity\n *\n * var entity = pickResult.entity;\n *\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Mesh's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult. ; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var normal = pickResult.normal; // Float64Array containing the interpolated normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n * }\n * ````\n *\n * ## Pick masking\n *\n * We can use {@link Scene#pick}'s ````includeEntities```` and ````excludeEntities```` options to mask which {@link Mesh}es we attempt to pick.\n *\n * This is useful for picking through things, to pick only the Entities of interest.\n *\n * To pick only Entities ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through any other Entities that are\n * in the way, as if they weren't there:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131],\n * includeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\n * });\n *\n * if (pickResult) {\n * // Entity will always be either \"gearbox#77.0\" or \"gearbox#79.0\"\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * To pick any pickable Entity, except for ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through those\n * Entities if they happen to be in the way:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131],\n * excludeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\n * });\n *\n * if (pickResult) {\n * // Entity will never be \"gearbox#77.0\" or \"gearbox#79.0\"\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * See {@link Scene#pick} for more info on picking.\n *\n * ## Querying and tracking boundaries\n *\n * Getting a Scene's World-space axis-aligned boundary (AABB):\n *\n * ````javascript\n * var aabb = scene.aabb; // [xmin, ymin, zmin, xmax, ymax, zmax]\n * ````\n *\n * Subscribing to updates to the AABB, which occur whenever {@link Entity}s are transformed, their\n * {@link ReadableGeometry}s have been updated, or the {@link Camera} has moved:\n *\n * ````javascript\n * scene.on(\"boundary\", function() {\n * var aabb = scene.aabb;\n * });\n * ````\n *\n * Getting the AABB of the {@link Entity}s with the given IDs:\n *\n * ````JavaScript\n * scene.getAABB(); // Gets collective boundary of all Entities in the scene\n * scene.getAABB(\"saw\"); // Gets boundary of an Object\n * scene.getAABB([\"saw\", \"gearbox\"]); // Gets collective boundary of two Objects\n * ````\n *\n * See {@link Scene#getAABB} and {@link Entity} for more info on querying and tracking boundaries.\n *\n * ## Managing the viewport\n *\n * The Scene's {@link Viewport} component manages the WebGL viewport:\n *\n * ````javascript\n * var viewport = scene.viewport\n * viewport.boundary = [0, 0, 500, 400];;\n * ````\n *\n * ## Controlling rendering\n *\n * You can configure a Scene to perform multiple \"passes\" (renders) per frame. This is useful when we want to render the\n * scene to multiple viewports, such as for stereo effects.\n *\n * In the example, below, we'll configure the Scene to render twice on each frame, each time to different viewport. We'll do this\n * with a callback that intercepts the Scene before each render and sets its {@link Viewport} to a\n * different portion of the canvas. By default, the Scene will clear the canvas only before the first render, allowing the\n * two views to be shown on the canvas at the same time.\n *\n * ````Javascript\n * var viewport = scene.viewport;\n *\n * // Configure Scene to render twice for each frame\n * scene.passes = 2; // Default is 1\n * scene.clearEachPass = false; // Default is false\n *\n * // Render to a separate viewport on each render\n *\n * var viewport = scene.viewport;\n * viewport.autoBoundary = false;\n *\n * scene.on(\"rendering\", function (e) {\n * switch (e.pass) {\n * case 0:\n * viewport.boundary = [0, 0, 200, 200]; // xmin, ymin, width, height\n * break;\n *\n * case 1:\n * viewport.boundary = [200, 0, 200, 200];\n * break;\n * }\n * });\n *\n * // We can also intercept the Scene after each render,\n * // (though we're not using this for anything here)\n * scene.on(\"rendered\", function (e) {\n * switch (e.pass) {\n * case 0:\n * break;\n *\n * case 1:\n * break;\n * }\n * });\n * ````\n *\n * ## Gamma correction\n *\n * Within its shaders, xeokit performs shading calculations in linear space.\n *\n * By default, the Scene expects color textures (eg. {@link PhongMaterial#diffuseMap},\n * {@link MetallicMaterial#baseColorMap} and {@link SpecularMaterial#diffuseMap}) to\n * be in pre-multipled gamma space, so will convert those to linear space before they are used in shaders. Other textures are\n * always expected to be in linear space.\n *\n * By default, the Scene will also gamma-correct its rendered output.\n *\n * You can configure the Scene to expect all those color textures to be linear space, so that it does not gamma-correct them:\n *\n * ````javascript\n * scene.gammaInput = false;\n * ````\n *\n * You would still need to gamma-correct the output, though, if it's going straight to the canvas, so normally we would\n * leave that enabled:\n *\n * ````javascript\n * scene.gammaOutput = true;\n * ````\n *\n * See {@link Texture} for more information on texture encoding and gamma.\n *\n * @class Scene\n */\nclass Scene extends _Component_js__WEBPACK_IMPORTED_MODULE_4__.Component {\n\t/**\n @private\n */\n\tget type() {\n\t\treturn \"Scene\";\n\t}\n\n\t/**\n\t * @private\n\t * @constructor\n\t * @param {Viewer} viewer The Viewer this Scene belongs to.\n\t * @param {Object} cfg Scene configuration.\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\n\t * @param {HTMLElement} [cfg.keyboardEventsElement] Optional reference to HTML element on which key events should be handled. Defaults to the HTML Document.\n\t * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane imposes rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.\n\t */\n\tconstructor(viewer, cfg = {}) {\n\t\tsuper(null, cfg);\n\n\t\tconst canvas = cfg.canvasElement || document.getElementById(cfg.canvasId);\n\n\t\tif (!(canvas instanceof HTMLCanvasElement)) {\n\t\t\tthrow \"Mandatory config expected: valid canvasId or canvasElement\";\n\t\t}\n\n\t\t/**\n\t\t * @type {{[key: string]: {wrapperFunc: Function, tickSubId: string}}}\n\t\t */\n\t\tthis._tickifiedFunctions = {};\n\n\t\tthis._transparent = !!cfg.transparent;\n\t\tconst alphaDepthMask = !!cfg.alphaDepthMask;\n\t\tthis._edgesEnabled = !!cfg.edgesEnabled;\n\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\n\t\t/**\n\t\t * The {@link Viewer} this Scene belongs to.\n\t\t * @type {Viewer}\n\t\t */\n\t\tthis.viewer = viewer;\n\n\t\t/** Decremented each frame, triggers occlusion test for occludable {@link Marker}s when zero.\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis.occlusionTestCountdown = 0;\n\n\t\t/**\n The number of models currently loading.\n\n @property loading\n @final\n @type {Number}\n */\n\t\tthis.loading = 0;\n\n\t\t/**\n The epoch time (in milliseconds since 1970) when this Scene was instantiated.\n\n @property timeCreated\n @final\n @type {Number}\n */\n\t\tthis.startTime = new Date().getTime();\n\n\t\t/**\n\t\t * Map of {@link SceneModel}s that represent models.\n\t\t *\n\t\t * Each {@link SceneModel} is mapped here by {@link SceneModel#id} when {@link SceneModel#isModel} is ````true````.\n\t\t *\n\t\t * @property models\n\t\t * @final\n\t\t * @type {{String:SceneModel}}\n\t\t */\n\t\tthis.models = {};\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represents objects.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * @property objects\n\t\t * @final\n\t\t * @type {{String:Entity}}\n\t\t */\n\t\tthis.objects = {};\n\t\tthis._numObjects = 0;\n\n\t\t/**\n\t\t * Map of currently visible {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is visible when {@link Entity#visible} is true.\n\t\t *\n\t\t * @property visibleObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.visibleObjects = {};\n\t\tthis._numVisibleObjects = 0;\n\n\t\t/**\n\t\t * Map of currently xrayed {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is xrayed when {@link Entity#xrayed} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property xrayedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.xrayedObjects = {};\n\t\tthis._numXRayedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently highlighted {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true```` is true, and is highlighted when {@link Entity#highlighted} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property highlightedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.highlightedObjects = {};\n\t\tthis._numHighlightedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently selected {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is true, and is selected while {@link Entity#selected} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property selectedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.selectedObjects = {};\n\t\tthis._numSelectedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently colorized {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property colorizedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.colorizedObjects = {};\n\t\tthis._numColorizedObjects = 0;\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent objects whose opacity was updated.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property opacityObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.opacityObjects = {};\n\t\tthis._numOpacityObjects = 0;\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent objects whose {@link Entity#offset}s were updated.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property offsetObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.offsetObjects = {};\n\t\tthis._numOffsetObjects = 0;\n\n\t\t// Cached ID arrays, lazy-rebuilt as needed when stale after map updates\n\n\t\t/**\n Lazy-regenerated ID lists.\n */\n\t\tthis._modelIds = null;\n\t\tthis._objectIds = null;\n\t\tthis._visibleObjectIds = null;\n\t\tthis._xrayedObjectIds = null;\n\t\tthis._highlightedObjectIds = null;\n\t\tthis._selectedObjectIds = null;\n\t\tthis._colorizedObjectIds = null;\n\t\tthis._opacityObjectIds = null;\n\t\tthis._offsetObjectIds = null;\n\n\t\tthis._collidables = {}; // Components that contribute to the Scene AABB\n\t\tthis._compilables = {}; // Components that require shader compilation\n\n\t\tthis._needRecompile = false;\n\n\t\t/**\n\t\t * For each {@link Component} type, a map of IDs to {@link Component} instances of that type.\n\t\t *\n\t\t * @type {{String:{String:Component}}}\n\t\t */\n\t\tthis.types = {};\n\n\t\t/**\n\t\t * The {@link Component}s within this Scene, each mapped to its {@link Component#id}.\n\t\t *\n\t\t * *@type {{String:Component}}\n\t\t */\n\t\tthis.components = {};\n\n\t\t/**\n\t\t * The {@link SectionPlane}s in this Scene, each mapped to its {@link SectionPlane#id}.\n\t\t *\n\t\t * @type {{String:SectionPlane}}\n\t\t */\n\t\tthis.sectionPlanes = {};\n\n\t\t/**\n\t\t * The {@link Light}s in this Scene, each mapped to its {@link Light#id}.\n\t\t *\n\t\t * @type {{String:Light}}\n\t\t */\n\t\tthis.lights = {};\n\n\t\t/**\n\t\t * The {@link LightMap}s in this Scene, each mapped to its {@link LightMap#id}.\n\t\t *\n\t\t * @type {{String:LightMap}}\n\t\t */\n\t\tthis.lightMaps = {};\n\n\t\t/**\n\t\t * The {@link ReflectionMap}s in this Scene, each mapped to its {@link ReflectionMap#id}.\n\t\t *\n\t\t * @type {{String:ReflectionMap}}\n\t\t */\n\t\tthis.reflectionMaps = {};\n\n\t\t/**\n\t\t * The {@link Bitmap}s in this Scene, each mapped to its {@link Bitmap#id}.\n\t\t *\n\t\t * @type {{String:Bitmap}}\n\t\t */\n\t\tthis.bitmaps = {};\n\n\t\t/**\n\t\t * The {@link LineSet}s in this Scene, each mapped to its {@link LineSet#id}.\n\t\t *\n\t\t * @type {{String:LineSet}}\n\t\t */\n\t\tthis.lineSets = {};\n\n\t\t/**\n\t\t * The real world offset for this Scene\n\t\t *\n\t\t * @type {Number[]}\n\t\t */\n\t\tthis.realWorldOffset = cfg.realWorldOffset || new Float64Array([0, 0, 0]);\n\n\t\t/**\n\t\t * Manages the HTML5 canvas for this Scene.\n\t\t *\n\t\t * @type {Canvas}\n\t\t */\n\t\tthis.canvas = new _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__.Canvas(this, {\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\n\t\t\tcanvas: canvas,\n\t\t\tspinnerElementId: cfg.spinnerElementId,\n\t\t\ttransparent: this._transparent,\n\t\t\twebgl2: cfg.webgl2 !== false,\n\t\t\tcontextAttr: cfg.contextAttr || {},\n\t\t\tbackgroundColor: cfg.backgroundColor,\n\t\t\tbackgroundColorFromAmbientLight: cfg.backgroundColorFromAmbientLight,\n\t\t\tpremultipliedAlpha: cfg.premultipliedAlpha,\n\t\t\tresolutionScale: cfg.resolutionScale\n\t\t});\n\n\t\tthis.canvas.on(\"boundary\", () => {\n\t\t\tthis.glRedraw();\n\t\t});\n\n\t\tthis.canvas.on(\"webglContextFailed\", () => {\n\t\t\talert(\"tctwins failed to find WebGL!\");\n\t\t});\n\n\t\tthis._renderer = new _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__.Renderer(this, {\n\t\t\ttransparent: this._transparent,\n\t\t\talphaDepthMask: alphaDepthMask,\n\t\t\tedgesEnabled: this._edgesEnabled\n\t\t});\n\n\t\tthis._sectionPlanesState = new (function () {\n\t\t\tthis.sectionPlanes = [];\n\n\t\t\tthis.clippingCaps = false;\n\n\t\t\tthis._numCachedSectionPlanes = 0;\n\n\t\t\tlet hash = null;\n\n\t\t\tthis.getHash = function () {\n\t\t\t\tif (hash) {\n\t\t\t\t\treturn hash;\n\t\t\t\t}\n\t\t\t\tconst numAllocatedSectionPlanes = this.getNumAllocatedSectionPlanes();\n\t\t\t\tconst sectionPlanes = this.sectionPlanes;\n\t\t\t\tif (numAllocatedSectionPlanes === 0) {\n\t\t\t\t\treturn (this.hash = \";\");\n\t\t\t\t}\n\t\t\t\tlet sectionPlane;\n\n\t\t\t\tconst hashParts = [];\n\t\t\t\tfor (let i = 0, len = numAllocatedSectionPlanes; i < len; i++) {\n\t\t\t\t\tsectionPlane = sectionPlanes[i];\n\t\t\t\t\thashParts.push(\"cp\");\n\t\t\t\t}\n\t\t\t\thashParts.push(\";\");\n\t\t\t\thash = hashParts.join(\"\");\n\t\t\t\treturn hash;\n\t\t\t};\n\n\t\t\tthis.addSectionPlane = function (sectionPlane) {\n\t\t\t\tthis.sectionPlanes.push(sectionPlane);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeSectionPlane = function (sectionPlane) {\n\t\t\t\tfor (let i = 0, len = this.sectionPlanes.length; i < len; i++) {\n\t\t\t\t\tif (this.sectionPlanes[i].id === sectionPlane.id) {\n\t\t\t\t\t\tthis.sectionPlanes.splice(i, 1);\n\t\t\t\t\t\thash = null;\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.setNumCachedSectionPlanes = function (numCachedSectionPlanes) {\n\t\t\t\tthis._numCachedSectionPlanes = numCachedSectionPlanes;\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.getNumCachedSectionPlanes = function () {\n\t\t\t\treturn this._numCachedSectionPlanes;\n\t\t\t};\n\n\t\t\tthis.getNumAllocatedSectionPlanes = function () {\n\t\t\t\tconst num = this.sectionPlanes.length;\n\t\t\t\treturn num > this._numCachedSectionPlanes ? num : this._numCachedSectionPlanes;\n\t\t\t};\n\t\t})();\n\n\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(cfg.numCachedSectionPlanes || 0);\n\n\t\tthis._lightsState = new (function () {\n\t\t\tconst DEFAULT_AMBIENT = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 0]);\n\t\t\tconst ambientColorIntensity = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4();\n\n\t\t\tthis.lights = [];\n\t\t\tthis.reflectionMaps = [];\n\t\t\tthis.lightMaps = [];\n\n\t\t\tlet hash = null;\n\t\t\tlet ambientLight = null;\n\n\t\t\tthis.getHash = function () {\n\t\t\t\tif (hash) {\n\t\t\t\t\treturn hash;\n\t\t\t\t}\n\t\t\t\tconst hashParts = [];\n\t\t\t\tconst lights = this.lights;\n\t\t\t\tlet light;\n\t\t\t\tfor (let i = 0, len = lights.length; i < len; i++) {\n\t\t\t\t\tlight = lights[i];\n\t\t\t\t\thashParts.push(\"/\");\n\t\t\t\t\thashParts.push(light.type);\n\t\t\t\t\thashParts.push(light.space === \"world\" ? \"w\" : \"v\");\n\t\t\t\t\tif (light.castsShadow) {\n\t\t\t\t\t\thashParts.push(\"sh\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.lightMaps.length > 0) {\n\t\t\t\t\thashParts.push(\"/lm\");\n\t\t\t\t}\n\t\t\t\tif (this.reflectionMaps.length > 0) {\n\t\t\t\t\thashParts.push(\"/rm\");\n\t\t\t\t}\n\t\t\t\thashParts.push(\";\");\n\t\t\t\thash = hashParts.join(\"\");\n\t\t\t\treturn hash;\n\t\t\t};\n\n\t\t\tthis.addLight = function (state) {\n\t\t\t\tthis.lights.push(state);\n\t\t\t\tambientLight = null;\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeLight = function (state) {\n\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\n\t\t\t\t\tconst light = this.lights[i];\n\t\t\t\t\tif (light.id === state.id) {\n\t\t\t\t\t\tthis.lights.splice(i, 1);\n\t\t\t\t\t\tif (ambientLight && ambientLight.id === state.id) {\n\t\t\t\t\t\t\tambientLight = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\thash = null;\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.addReflectionMap = function (state) {\n\t\t\t\tthis.reflectionMaps.push(state);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeReflectionMap = function (state) {\n\t\t\t\tfor (let i = 0, len = this.reflectionMaps.length; i < len; i++) {\n\t\t\t\t\tif (this.reflectionMaps[i].id === state.id) {\n\t\t\t\t\t\tthis.reflectionMaps.splice(i, 1);\n\t\t\t\t\t\thash = null;\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.addLightMap = function (state) {\n\t\t\t\tthis.lightMaps.push(state);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeLightMap = function (state) {\n\t\t\t\tfor (let i = 0, len = this.lightMaps.length; i < len; i++) {\n\t\t\t\t\tif (this.lightMaps[i].id === state.id) {\n\t\t\t\t\t\tthis.lightMaps.splice(i, 1);\n\t\t\t\t\t\thash = null;\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.getAmbientColorAndIntensity = function () {\n\t\t\t\tif (!ambientLight) {\n\t\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\n\t\t\t\t\t\tconst light = this.lights[i];\n\t\t\t\t\t\tif (light.type === \"ambient\") {\n\t\t\t\t\t\t\tambientLight = light;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (ambientLight) {\n\t\t\t\t\tconst color = ambientLight.color;\n\t\t\t\t\tconst intensity = ambientLight.intensity;\n\t\t\t\t\tambientColorIntensity[0] = color[0];\n\t\t\t\t\tambientColorIntensity[1] = color[1];\n\t\t\t\t\tambientColorIntensity[2] = color[2];\n\t\t\t\t\tambientColorIntensity[3] = intensity;\n\t\t\t\t\treturn ambientColorIntensity;\n\t\t\t\t} else {\n\t\t\t\t\treturn DEFAULT_AMBIENT;\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\t/**\n\t\t * Publishes input events that occur on this Scene's canvas.\n\t\t * @property input\n\t\t * @type {Input}\n\t\t * @final\n\t\t */\n\t\tthis.input = new _input_Input_js__WEBPACK_IMPORTED_MODULE_7__.Input(this, {\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\n\t\t\telement: this.canvas.canvas,\n\t\t\tkeyboardEventsElement: cfg.keyboardEventsElement\n\t\t});\n\n\t\t/**\n\t\t * Configures this Scene's units of measurement and coordinate mapping between Real-space and World-space 3D coordinate systems.\n\t\t *\n\t\t * @property metrics\n\t\t * @type {Metrics}\n\t\t * @final\n\t\t */\n\t\tthis.metrics = new _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__.Metrics(this, {\n\t\t\tunits: cfg.units,\n\t\t\tscale: cfg.scale,\n\t\t\torigin: cfg.origin\n\t\t});\n\n\t\t/** Configures Scalable Ambient Obscurance (SAO) for this Scene.\n\t\t * @type {SAO}\n\t\t * @final\n\t\t */\n\t\tthis.sao = new _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__.SAO(this, {\n\t\t\tenabled: cfg.saoEnabled\n\t\t});\n\n\t\tthis.ticksPerRender = cfg.ticksPerRender;\n\t\tthis.ticksPerOcclusionTest = cfg.ticksPerOcclusionTest;\n\t\tthis.passes = cfg.passes;\n\t\tthis.clearEachPass = cfg.clearEachPass;\n\t\tthis.gammaInput = cfg.gammaInput;\n\t\tthis.gammaOutput = cfg.gammaOutput;\n\t\tthis.gammaFactor = cfg.gammaFactor;\n\n\t\tthis._entityOffsetsEnabled = !!cfg.entityOffsetsEnabled;\n\t\tthis._logarithmicDepthBufferEnabled = !!cfg.logarithmicDepthBufferEnabled;\n\n\t\tthis._dtxEnabled = cfg.dtxEnabled !== false;\n\t\tthis._pbrEnabled = !!cfg.pbrEnabled;\n\t\tthis._colorTextureEnabled = cfg.colorTextureEnabled !== false;\n\t\tthis._dtxEnabled = !!cfg.dtxEnabled;\n\t\tthis._lodEnabled = cfg.lodEnabled !== false;\n\n\t\t// Register Scene on xeokit\n\t\t// Do this BEFORE we add components below\n\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core._addScene(this);\n\n\t\tthis._initDefaults();\n\n\t\t// Global components\n\n\t\tthis._viewport = new _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__.Viewport(this, {\n\t\t\tid: \"default.viewport\",\n\t\t\tautoBoundary: true,\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\n\t\t});\n\n\t\tthis._camera = new _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__.Camera(this, {\n\t\t\tid: \"default.camera\",\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\n\t\t});\n\n\t\t// Default lights\n\n\t\tnew _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__.AmbientLight(this, {\n\t\t\tcolor: [1.0, 1.0, 1.0],\n\t\t\tintensity: 0.6\n\t\t});\n\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\n\t\t\tdir: [0.8, -0.5, -0.5],\n\t\t\tcolor: [0.67, 0.67, 1.0],\n\t\t\tintensity: 0.6,\n\t\t\tspace: \"world\"\n\t\t});\n\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\n\t\t\tdir: [-0.8, -1.0, 0.5],\n\t\t\tcolor: [1, 1, 0.9],\n\t\t\tintensity: 0.8,\n\t\t\tspace: \"world\"\n\t\t});\n\n\t\tthis._camera.on(\"dirty\", () => {\n\t\t\tthis._renderer.imageDirty();\n\t\t});\n\n\t\tthis._lod = new _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__.LOD(this, {\n\t\t\tenabled: this._lodEnabled,\n\t\t\ttargetFPS: 30\n\t\t});\n\t}\n\n\t_initDefaults() {\n\t\t// Call this Scene's property accessors to lazy-init their properties\n\n\t\tlet dummy; // Keeps Codacy happy\n\n\t\tdummy = this.geometry;\n\t\tdummy = this.material;\n\t\tdummy = this.xrayMaterial;\n\t\tdummy = this.edgeMaterial;\n\t\tdummy = this.selectedMaterial;\n\t\tdummy = this.highlightMaterial;\n\t}\n\n\t_addComponent(component) {\n\t\tif (component.id) {\n\t\t\t// Manual ID\n\t\t\tif (this.components[component.id]) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Component \" +\n\t\t\t\t\t\t_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.inQuotes(component.id) +\n\t\t\t\t\t\t\" already exists in Scene - ignoring ID, will randomly-generate instead\"\n\t\t\t\t);\n\t\t\t\tcomponent.id = null;\n\t\t\t}\n\t\t}\n\t\tif (!component.id) {\n\t\t\t// Auto ID\n\t\t\tif (window.nextID === undefined) {\n\t\t\t\twindow.nextID = 0;\n\t\t\t}\n\t\t\t//component.id = math.createUUID();\n\t\t\tcomponent.id = \"__\" + window.nextID++;\n\t\t\twhile (this.components[component.id]) {\n\t\t\t\tcomponent.id = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.createUUID();\n\t\t\t}\n\t\t}\n\t\tthis.components[component.id] = component;\n\n\t\t// Register for class type\n\t\tconst type = component.type;\n\t\tlet types = this.types[component.type];\n\t\tif (!types) {\n\t\t\ttypes = this.types[type] = {};\n\t\t}\n\t\ttypes[component.id] = component;\n\n\t\tif (component.compile) {\n\t\t\tthis._compilables[component.id] = component;\n\t\t}\n\t\tif (component.isDrawable) {\n\t\t\tthis._renderer.addDrawable(component.id, component);\n\t\t\tthis._collidables[component.id] = component;\n\t\t}\n\t}\n\n\t_removeComponent(component) {\n\t\tvar id = component.id;\n\t\tvar type = component.type;\n\t\tdelete this.components[id];\n\t\t// Unregister for types\n\t\tconst types = this.types[type];\n\t\tif (types) {\n\t\t\tdelete types[id];\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isEmptyObject(types)) {\n\t\t\t\tdelete this.types[type];\n\t\t\t}\n\t\t}\n\t\tif (component.compile) {\n\t\t\tdelete this._compilables[component.id];\n\t\t}\n\t\tif (component.isDrawable) {\n\t\t\tthis._renderer.removeDrawable(component.id);\n\t\t\tdelete this._collidables[component.id];\n\t\t}\n\t}\n\n\t// Methods below are called by various component types to register themselves on their\n\t// Scene. Violates Hollywood Principle, where we could just filter on type in _addComponent,\n\t// but this is faster than checking the type of each component in such a filter.\n\n\t_sectionPlaneCreated(sectionPlane) {\n\t\tthis.sectionPlanes[sectionPlane.id] = sectionPlane;\n\t\tthis.scene._sectionPlanesState.addSectionPlane(sectionPlane._state);\n\t\tthis.scene.fire(\"sectionPlaneCreated\", sectionPlane, true /* Don't retain event */);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_bitmapCreated(bitmap) {\n\t\tthis.bitmaps[bitmap.id] = bitmap;\n\t\tthis.scene.fire(\"bitmapCreated\", bitmap, true /* Don't retain event */);\n\t}\n\n\t_lineSetCreated(lineSet) {\n\t\tthis.lineSets[lineSet.id] = lineSet;\n\t\tthis.scene.fire(\"lineSetCreated\", lineSet, true /* Don't retain event */);\n\t}\n\n\t_lightCreated(light) {\n\t\tthis.lights[light.id] = light;\n\t\tthis.scene._lightsState.addLight(light._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_lightMapCreated(lightMap) {\n\t\tthis.lightMaps[lightMap.id] = lightMap;\n\t\tthis.scene._lightsState.addLightMap(lightMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_reflectionMapCreated(reflectionMap) {\n\t\tthis.reflectionMaps[reflectionMap.id] = reflectionMap;\n\t\tthis.scene._lightsState.addReflectionMap(reflectionMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_sectionPlaneDestroyed(sectionPlane) {\n\t\tdelete this.sectionPlanes[sectionPlane.id];\n\t\tthis.scene._sectionPlanesState.removeSectionPlane(sectionPlane._state);\n\t\tthis.scene.fire(\"sectionPlaneDestroyed\", sectionPlane, true /* Don't retain event */);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_bitmapDestroyed(bitmap) {\n\t\tdelete this.bitmaps[bitmap.id];\n\t\tthis.scene.fire(\"bitmapDestroyed\", bitmap, true /* Don't retain event */);\n\t}\n\n\t_lineSetDestroyed(lineSet) {\n\t\tdelete this.lineSets[lineSet.id];\n\t\tthis.scene.fire(\"lineSetDestroyed\", lineSet, true /* Don't retain event */);\n\t}\n\n\t_lightDestroyed(light) {\n\t\tdelete this.lights[light.id];\n\t\tthis.scene._lightsState.removeLight(light._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_lightMapDestroyed(lightMap) {\n\t\tdelete this.lightMaps[lightMap.id];\n\t\tthis.scene._lightsState.removeLightMap(lightMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_reflectionMapDestroyed(reflectionMap) {\n\t\tdelete this.reflectionMaps[reflectionMap.id];\n\t\tthis.scene._lightsState.removeReflectionMap(reflectionMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_registerModel(model) {\n\t\tthis.models[model.id] = model;\n\t\tthis._modelIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterModel(model) {\n\t\tconst modelId = model.id;\n\t\tdelete this.models[modelId];\n\t\tthis._modelIds = null; // Lazy regenerate\n\t\tthis.fire(\"modelUnloaded\", modelId);\n\t}\n\n\t_registerObject(entity) {\n\t\tthis.objects[entity.id] = entity;\n\t\tthis._numObjects++;\n\t\tthis._objectIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterObject(entity) {\n\t\tdelete this.objects[entity.id];\n\t\tthis._numObjects--;\n\t\tthis._objectIds = null; // Lazy regenerate\n\t}\n\n\t_objectVisibilityUpdated(entity, notify = true) {\n\t\tif (entity.visible) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.visibleObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.visibleObjects[entity.id] = entity;\n\t\t\tthis._numVisibleObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.visibleObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.visibleObjects[entity.id];\n\t\t\tthis._numVisibleObjects--;\n\t\t}\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectVisibility\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterVisibleObject(entity) {\n\t\tdelete this.visibleObjects[entity.id];\n\t\tthis._numVisibleObjects--;\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectXRayedUpdated(entity, notify = true) {\n\t\tif (entity.xrayed) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.xrayedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.xrayedObjects[entity.id] = entity;\n\t\t\tthis._numXRayedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.xrayedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.xrayedObjects[entity.id];\n\t\t\tthis._numXRayedObjects--;\n\t\t}\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectXRayed\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterXRayedObject(entity) {\n\t\tdelete this.xrayedObjects[entity.id];\n\t\tthis._numXRayedObjects--;\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectHighlightedUpdated(entity) {\n\t\tif (entity.highlighted) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.highlightedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.highlightedObjects[entity.id] = entity;\n\t\t\tthis._numHighlightedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.highlightedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.highlightedObjects[entity.id];\n\t\t\tthis._numHighlightedObjects--;\n\t\t}\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterHighlightedObject(entity) {\n\t\tdelete this.highlightedObjects[entity.id];\n\t\tthis._numHighlightedObjects--;\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectSelectedUpdated(entity, notify = true) {\n\t\tif (entity.selected) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.selectedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object select update (selected=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.selectedObjects[entity.id] = entity;\n\t\t\tthis._numSelectedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.selectedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object select update (selected=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.selectedObjects[entity.id];\n\t\t\tthis._numSelectedObjects--;\n\t\t}\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectSelected\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterSelectedObject(entity) {\n\t\tdelete this.selectedObjects[entity.id];\n\t\tthis._numSelectedObjects--;\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectColorizeUpdated(entity, colorized) {\n\t\tif (colorized) {\n\t\t\tthis.colorizedObjects[entity.id] = entity;\n\t\t\tthis._numColorizedObjects++;\n\t\t} else {\n\t\t\tdelete this.colorizedObjects[entity.id];\n\t\t\tthis._numColorizedObjects--;\n\t\t}\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterColorizedObject(entity) {\n\t\tdelete this.colorizedObjects[entity.id];\n\t\tthis._numColorizedObjects--;\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectOpacityUpdated(entity, opacityUpdated) {\n\t\tif (opacityUpdated) {\n\t\t\tthis.opacityObjects[entity.id] = entity;\n\t\t\tthis._numOpacityObjects++;\n\t\t} else {\n\t\t\tdelete this.opacityObjects[entity.id];\n\t\t\tthis._numOpacityObjects--;\n\t\t}\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterOpacityObject(entity) {\n\t\tdelete this.opacityObjects[entity.id];\n\t\tthis._numOpacityObjects--;\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectOffsetUpdated(entity, offset) {\n\t\tif (!offset || (offset[0] === 0 && offset[1] === 0 && offset[2] === 0)) {\n\t\t\tthis.offsetObjects[entity.id] = entity;\n\t\t\tthis._numOffsetObjects++;\n\t\t} else {\n\t\t\tdelete this.offsetObjects[entity.id];\n\t\t\tthis._numOffsetObjects--;\n\t\t}\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterOffsetObject(entity) {\n\t\tdelete this.offsetObjects[entity.id];\n\t\tthis._numOffsetObjects--;\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\n\t}\n\n\t_webglContextLost() {\n\t\t// this.loading++;\n\t\tthis.canvas.spinner.processes++;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tconst component = this.components[id];\n\t\t\t\tif (component._webglContextLost) {\n\t\t\t\t\tcomponent._webglContextLost();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._renderer.webglContextLost();\n\t}\n\n\t_webglContextRestored() {\n\t\tconst gl = this.canvas.gl;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tconst component = this.components[id];\n\t\t\t\tif (component._webglContextRestored) {\n\t\t\t\t\tcomponent._webglContextRestored(gl);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._renderer.webglContextRestored(gl);\n\t\t//this.loading--;\n\t\tthis.canvas.spinner.processes--;\n\t}\n\n\t/**\n\t * Returns the capabilities of this Scene.\n\t *\n\t * @private\n\t * @returns {{astcSupported: boolean, etc1Supported: boolean, pvrtcSupported: boolean, etc2Supported: boolean, dxtSupported: boolean, bptcSupported: boolean}}\n\t */\n\tget capabilities() {\n\t\treturn this._renderer.capabilities;\n\t}\n\n\t/**\n\t * Whether {@link Entity#offset} is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * @returns {Boolean} True if {@link Entity#offset} is enabled.\n\t */\n\tget entityOffsetsEnabled() {\n\t\treturn this._entityOffsetsEnabled;\n\t}\n\n\t/**\n\t * Whether precision surface picking is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.\n\t *\n\t * Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer.\n\t *\n\t * @returns {Boolean} True if precision picking is enabled.\n\t */\n\tget pickSurfacePrecisionEnabled() {\n\t\treturn false; // Removed\n\t}\n\n\t/**\n\t * Whether logarithmic depth buffer is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * @returns {Boolean} True if logarithmic depth buffer is enabled.\n\t */\n\tget logarithmicDepthBufferEnabled() {\n\t\treturn this._logarithmicDepthBufferEnabled;\n\t}\n\n\t/**\n\t * Sets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t *\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t *\n\t * Default is ````0````.\n\t */\n\tset numCachedSectionPlanes(numCachedSectionPlanes) {\n\t\tnumCachedSectionPlanes = numCachedSectionPlanes || 0;\n\t\tif (this._sectionPlanesState.getNumCachedSectionPlanes() !== numCachedSectionPlanes) {\n\t\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(numCachedSectionPlanes);\n\t\t\tthis._needRecompile = true;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t *\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @returns {number} The number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t */\n\tget numCachedSectionPlanes() {\n\t\treturn this._sectionPlanesState.getNumCachedSectionPlanes();\n\t}\n\n\t/**\n\t * Sets whether physically-based rendering is enabled.\n\t *\n\t * Default is ````false````.\n\t */\n\tset pbrEnabled(pbrEnabled) {\n\t\tthis._pbrEnabled = !!pbrEnabled;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether physically-based rendering is enabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} True if quality rendering is enabled.\n\t */\n\tget pbrEnabled() {\n\t\treturn this._pbrEnabled;\n\t}\n\n\t/**\n\t * Sets whether data texture scene representation (DTX) is enabled for the {@link Scene}.\n\t *\n\t * Even when enabled, DTX will only work if supported.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset dtxEnabled(value) {\n\t\tvalue = !!value;\n\t\tif (this._dtxEnabled === value) {\n\t\t\treturn;\n\t\t}\n\t\tthis._dtxEnabled = value;\n\t}\n\n\t/**\n\t * Gets whether data texture-based scene representation (DTX) is enabled for the {@link Scene}.\n\t *\n\t * Even when enabled, DTX will only apply if supported.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget dtxEnabled() {\n\t\treturn this._dtxEnabled;\n\t}\n\n\t/**\n\t * set showedges enable\n\t * @param {boolean} edgesEnabled\n\t */\n\tset edgesEnabled(edgesEnabled) {\n\t\tedgesEnabled = !!edgesEnabled;\n\t\tif (this._edgesEnabled === edgesEnabled) {\n\t\t\treturn;\n\t\t}\n\t\tthis._edgesEnabled = edgesEnabled;\n\t\tthis._renderer.setEdgesEnabled(edgesEnabled);\n\t}\n\n\t/**\n\t * @param {boolean} trans\n\t */\n\tget edgesEnabled() {\n\t\treturn this._edgesEnabled;\n\t}\n\n\t/**\n\t * set whether transparent of canvas background\n\t * @param {boolean} trans\n\t */\n\tset backgroundTransparent(trans) {\n\t\ttrans = !!trans;\n\t\t// if (this._transparent == trans) {\n\t\t// return;\n\t\t// }\n\t\tthis._transparent = trans;\n\t\tthis._renderer.setTransparentEnabled(trans);\n\t}\n\n\t/**\n\t * @returns {boolean} backgroundTransparent\n\t */\n\tget backgroundTransparent() {\n\t\treturn this._transparent;\n\t}\n\n\t/**\n\t * set background color\n\t * @param {[]} color\n\t */\n\tset backgroundColor(color) {\n\t\tthis.canvas.backgroundColor = color;\n\t\tthis._renderer.render({ force: true });\n\t}\n\n\t/**\n\t * return backgroundColor\n\t * @returns {boolean} backgroundColor\n\t */\n\tget backgroundColor() {\n\t\treturn this.canvas.backgroundColor();\n\t}\n\n\t/**\n\t * Sets whether basic color texture rendering is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\n\t */\n\tset colorTextureEnabled(colorTextureEnabled) {\n\t\tthis._colorTextureEnabled = !!colorTextureEnabled;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether basic color texture rendering is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\n\t */\n\tget colorTextureEnabled() {\n\t\treturn this._colorTextureEnabled;\n\t}\n\n\tget lightsObject() {\n\t\treturn this.lights;\n\t}\n\n\t/**\n\t * Performs an occlusion test on all {@link Marker}s in this {@link Scene}.\n\t *\n\t * Sets each {@link Marker#visible} ````true```` if the Marker is currently not occluded by any opaque {@link Entity}s\n\t * in the Scene, or ````false```` if an Entity is occluding it.\n\t */\n\tdoOcclusionTest() {\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\t\tthis._renderer.doOcclusionTest();\n\t}\n\n\t/**\n\t * Renders a single frame of this Scene.\n\t *\n\t * The Scene will periodically render itself after any updates, but you can call this method to force a render\n\t * if required.\n\t *\n\t * @param {Boolean} [forceRender=false] Forces a render when true, otherwise only renders if something has changed in this Scene\n\t * since the last render.\n\t */\n\trender(forceRender) {\n\t\tif (forceRender) {\n\t\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.runTasks();\n\t\t}\n\n\t\tconst renderEvent = {\n\t\t\tsceneId: null,\n\t\t\tpass: 0\n\t\t};\n\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\n\t\tif (!forceRender && !this._renderer.needsRender()) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderEvent.sceneId = this.id;\n\n\t\tconst passes = this._passes;\n\t\tconst clearEachPass = this._clearEachPass;\n\t\tlet pass;\n\t\tlet clear;\n\n\t\tfor (pass = 0; pass < passes; pass++) {\n\t\t\trenderEvent.pass = pass;\n\n\t\t\t/**\n\t\t\t * Fired when about to render a frame for a Scene.\n\t\t\t *\n\t\t\t * @event rendering\n\t\t\t * @param {String} sceneID The ID of this Scene.\n\t\t\t * @param {Number} pass Index of the pass we are about to render (see {@link Scene#passes}).\n\t\t\t */\n\t\t\tthis.fire(\"rendering\", renderEvent, true);\n\n\t\t\tclear = clearEachPass || pass === 0;\n\n\t\t\tthis._renderer.render({ pass: pass, clear: clear, force: forceRender });\n\n\t\t\t/**\n\t\t\t * Fired when we have just rendered a frame for a Scene.\n\t\t\t *\n\t\t\t * @event rendering\n\t\t\t * @param {String} sceneID The ID of this Scene.\n\t\t\t * @param {Number} pass Index of the pass we rendered (see {@link Scene#passes}).\n\t\t\t */\n\t\t\tthis.fire(\"rendered\", renderEvent, true);\n\t\t}\n\n\t\tthis._saveAmbientColor();\n\t}\n\n\t/**\n\t * @private\n\t */\n\tcompile() {\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\t}\n\n\t_recompile() {\n\t\tfor (const id in this._compilables) {\n\t\t\tif (this._compilables.hasOwnProperty(id)) {\n\t\t\t\tthis._compilables[id].compile();\n\t\t\t}\n\t\t}\n\t\tthis._renderer.shadowsDirty();\n\t\tthis.fire(\"compile\", this, true);\n\t}\n\n\t_saveAmbientColor() {\n\t\tconst canvas = this.canvas;\n\t\tif (!canvas.transparent && !canvas.backgroundImage && !canvas.backgroundColor) {\n\t\t\tconst ambientColorIntensity = this._lightsState.getAmbientColorAndIntensity();\n\t\t\tif (\n\t\t\t\t!this._lastAmbientColor ||\n\t\t\t\tthis._lastAmbientColor[0] !== ambientColorIntensity[0] ||\n\t\t\t\tthis._lastAmbientColor[1] !== ambientColorIntensity[1] ||\n\t\t\t\tthis._lastAmbientColor[2] !== ambientColorIntensity[2] ||\n\t\t\t\tthis._lastAmbientColor[3] !== ambientColorIntensity[3]\n\t\t\t) {\n\t\t\t\tcanvas.backgroundColor = ambientColorIntensity;\n\t\t\t\tif (!this._lastAmbientColor) {\n\t\t\t\t\tthis._lastAmbientColor = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 1]);\n\t\t\t\t}\n\t\t\t\tthis._lastAmbientColor.set(ambientColorIntensity);\n\t\t\t}\n\t\t} else {\n\t\t\tthis._lastAmbientColor = null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#models}.\n\t *\n\t * @type {String[]}\n\t */\n\tget modelIds() {\n\t\tif (!this._modelIds) {\n\t\t\tthis._modelIds = Object.keys(this.models);\n\t\t}\n\t\treturn this._modelIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#objects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numObjects() {\n\t\treturn this._numObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#objects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget objectIds() {\n\t\tif (!this._objectIds) {\n\t\t\tthis._objectIds = Object.keys(this.objects);\n\t\t}\n\t\treturn this._objectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#visibleObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numVisibleObjects() {\n\t\treturn this._numVisibleObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#visibleObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget visibleObjectIds() {\n\t\tif (!this._visibleObjectIds) {\n\t\t\tthis._visibleObjectIds = Object.keys(this.visibleObjects);\n\t\t}\n\t\treturn this._visibleObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#xrayedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numXRayedObjects() {\n\t\treturn this._numXRayedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#xrayedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget xrayedObjectIds() {\n\t\tif (!this._xrayedObjectIds) {\n\t\t\tthis._xrayedObjectIds = Object.keys(this.xrayedObjects);\n\t\t}\n\t\treturn this._xrayedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#highlightedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numHighlightedObjects() {\n\t\treturn this._numHighlightedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#highlightedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget highlightedObjectIds() {\n\t\tif (!this._highlightedObjectIds) {\n\t\t\tthis._highlightedObjectIds = Object.keys(this.highlightedObjects);\n\t\t}\n\t\treturn this._highlightedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#selectedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numSelectedObjects() {\n\t\treturn this._numSelectedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#selectedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget selectedObjectIds() {\n\t\tif (!this._selectedObjectIds) {\n\t\t\tthis._selectedObjectIds = Object.keys(this.selectedObjects);\n\t\t}\n\t\treturn this._selectedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#colorizedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numColorizedObjects() {\n\t\treturn this._numColorizedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#colorizedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget colorizedObjectIds() {\n\t\tif (!this._colorizedObjectIds) {\n\t\t\tthis._colorizedObjectIds = Object.keys(this.colorizedObjects);\n\t\t}\n\t\treturn this._colorizedObjectIds;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#opacityObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget opacityObjectIds() {\n\t\tif (!this._opacityObjectIds) {\n\t\t\tthis._opacityObjectIds = Object.keys(this.opacityObjects);\n\t\t}\n\t\treturn this._opacityObjectIds;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#offsetObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget offsetObjectIds() {\n\t\tif (!this._offsetObjectIds) {\n\t\t\tthis._offsetObjectIds = Object.keys(this.offsetObjects);\n\t\t}\n\t\treturn this._offsetObjectIds;\n\t}\n\n\t/**\n\t * Sets the number of \"ticks\" that happen between each render or this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tset ticksPerRender(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 1;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\"Unsupported value for 'ticksPerRender': '\" + value + \"' - should be an integer greater than zero.\");\n\t\t\tvalue = 1;\n\t\t}\n\t\tif (value === this._ticksPerRender) {\n\t\t\treturn;\n\t\t}\n\t\tthis._ticksPerRender = value;\n\t}\n\n\t/**\n\t * Gets the number of \"ticks\" that happen between each render or this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget ticksPerRender() {\n\t\treturn this._ticksPerRender;\n\t}\n\n\t/**\n\t * Sets the number of \"ticks\" that happen between occlusion testing for {@link Marker}s.\n\t *\n\t * Default value is ````20````.\n\t *\n\t * @type {Number}\n\t */\n\tset ticksPerOcclusionTest(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 20;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\n\t\t\t\t\"Unsupported value for 'ticksPerOcclusionTest': '\" + value + \"' - should be an integer greater than zero.\"\n\t\t\t);\n\t\t\tvalue = 20;\n\t\t}\n\t\tif (value === this._ticksPerOcclusionTest) {\n\t\t\treturn;\n\t\t}\n\t\tthis._ticksPerOcclusionTest = value;\n\t}\n\n\t/**\n\t * Gets the number of \"ticks\" that happen between each render of this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget ticksPerOcclusionTest() {\n\t\treturn this._ticksPerOcclusionTest;\n\t}\n\n\t/**\n\t * Sets the number of times this Scene renders per frame.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tset passes(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 1;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\"Unsupported value for 'passes': '\" + value + \"' - should be an integer greater than zero.\");\n\t\t\tvalue = 1;\n\t\t}\n\t\tif (value === this._passes) {\n\t\t\treturn;\n\t\t}\n\t\tthis._passes = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the number of times this Scene renders per frame.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget passes() {\n\t\treturn this._passes;\n\t}\n\n\t/**\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset clearEachPass(value) {\n\t\tvalue = !!value;\n\t\tif (value === this._clearEachPass) {\n\t\t\treturn;\n\t\t}\n\t\tthis._clearEachPass = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget clearEachPass() {\n\t\treturn this._clearEachPass;\n\t}\n\n\t/**\n\t * Sets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset gammaInput(value) {\n\t\tvalue = value !== false;\n\t\tif (value === this._renderer.gammaInput) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaInput = value;\n\t\tthis._needRecompile = true;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget gammaInput() {\n\t\treturn this._renderer.gammaInput;\n\t}\n\n\t/**\n\t * Sets whether or not to render pixels with pre-multiplied gama.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset gammaOutput(value) {\n\t\tvalue = !!value;\n\t\tif (value === this._renderer.gammaOutput) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaOutput = value;\n\t\tthis._needRecompile = true;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether or not to render pixels with pre-multiplied gama.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget gammaOutput() {\n\t\treturn this._renderer.gammaOutput;\n\t}\n\n\t/**\n\t * Sets the gamma factor to use when {@link Scene#gammaOutput} is set true.\n\t *\n\t * Default value is ````2.2````.\n\t *\n\t * @type {Number}\n\t */\n\tset gammaFactor(value) {\n\t\tvalue = value === undefined || value === null ? 2.2 : value;\n\t\tif (value === this._renderer.gammaFactor) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaFactor = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the gamma factor to use when {@link Scene#gammaOutput} is set true.\n\t *\n\t * Default value is ````2.2````.\n\t *\n\t * @type {Number}\n\t */\n\tget gammaFactor() {\n\t\treturn this._renderer.gammaFactor;\n\t}\n\n\t/**\n\t * Gets the default {@link Geometry} for this Scene, which is a {@link ReadableGeometry} with a unit-sized box shape.\n\t *\n\t * Has {@link ReadableGeometry#id} set to \"default.geometry\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#geometry} set to this {@link ReadableGeometry} by default.\n\t *\n\t * @type {ReadableGeometry}\n\t */\n\tget geometry() {\n\t\treturn (\n\t\t\tthis.components[\"default.geometry\"] ||\n\t\t\t(0,_geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__.buildBoxGeometry)(_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__.ReadableGeometry, this, {\n\t\t\t\tid: \"default.geometry\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default {@link Material} for this Scene, which is a {@link PhongMaterial}.\n\t *\n\t * Has {@link PhongMaterial#id} set to \"default.material\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#material} set to this {@link PhongMaterial} by default.\n\t *\n\t * @type {PhongMaterial}\n\t */\n\tget material() {\n\t\treturn (\n\t\t\tthis.components[\"default.material\"] ||\n\t\t\tnew _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__.PhongMaterial(this, {\n\t\t\t\tid: \"default.material\",\n\t\t\t\temissive: [0.4, 0.4, 0.4], // Visible by default on geometry without normals\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default xraying {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.xrayMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#xrayMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are xrayed while {@link Mesh#xrayed} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget xrayMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.xrayMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.xrayMaterial\",\n\t\t\t\tpreset: \"sepia\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default highlight {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.highlightMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget highlightMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.highlightMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.highlightMaterial\",\n\t\t\t\tpreset: \"yellowHighlight\",\n\t\t\t\tfillAlpha: 0.1,\n\t\t\t\tfillColor: [0.7, 0.9, 0.9],\n\t\t\t\tdontClear: false,\n\t\t\t\tedges: false,\n\t\t\t\tglowThrough: false\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default selection {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.selectedMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget selectedMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.selectedMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.selectedMaterial\",\n\t\t\t\tpreset: \"greenSelected\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default {@link EdgeMaterial} for this Scene.\n\t *\n\t * Has {@link EdgeMaterial#id} set to \"default.edgeMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#edgeMaterial} set to this {@link EdgeMaterial} by default.\n\t *\n\t * {@link Mesh}s have their edges emphasized while {@link Mesh#edges} is ````true````.\n\t *\n\t * @type {EdgeMaterial}\n\t */\n\tget edgeMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.edgeMaterial\"] ||\n\t\t\tnew _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__.EdgeMaterial(this, {\n\t\t\t\tid: \"default.edgeMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tedgeColor: [0.0, 0.0, 0.0],\n\t\t\t\tedgeAlpha: 1.0,\n\t\t\t\tedgeWidth: 1,\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link PointsMaterial} for this Scene.\n\t *\n\t * @type {PointsMaterial}\n\t */\n\tget pointsMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.pointsMaterial\"] ||\n\t\t\tnew _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__.PointsMaterial(this, {\n\t\t\t\tid: \"default.pointsMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link LinesMaterial} for this Scene.\n\t *\n\t * @type {LinesMaterial}\n\t */\n\tget linesMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.linesMaterial\"] ||\n\t\t\tnew _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__.LinesMaterial(this, {\n\t\t\t\tid: \"default.linesMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link Viewport} for this Scene.\n\t *\n\t * @type Viewport\n\t */\n\tget viewport() {\n\t\treturn this._viewport;\n\t}\n\n\t/**\n\t * Gets the {@link Camera} for this Scene.\n\t *\n\t * @type {Camera}\n\t */\n\tget camera() {\n\t\treturn this._camera;\n\t}\n\n\t/**\n\t * Gets the World-space 3D center of this Scene.\n\t *\n\t *@type {Number[]}\n\t */\n\tget center() {\n\t\tif (this._aabbDirty || !this._center) {\n\t\t\tif (!this._center || !this._center) {\n\t\t\t\tthis._center = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec3();\n\t\t\t}\n\t\t\tconst aabb = this.aabb;\n\t\t\tthis._center[0] = (aabb[0] + aabb[3]) / 2;\n\t\t\tthis._center[1] = (aabb[1] + aabb[4]) / 2;\n\t\t\tthis._center[2] = (aabb[2] + aabb[5]) / 2;\n\t\t}\n\t\treturn this._center;\n\t}\n\n\t/**\n\t * Gets the World-space axis-aligned 3D boundary (AABB) of this Scene.\n\t *\n\t * The AABB is represented by a six-element Float64Array containing the min/max extents of the axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\n\t *\n\t * When the Scene has no content, will be ````[-100,-100,-100,100,100,100]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget aabb() {\n\t\tif (this._aabbDirty) {\n\t\t\tif (this._aabbUpdate) {\n\t\t\t\treturn this._aabb;\n\t\t\t}\n\t\t\tif (!this._aabb) {\n\t\t\t\tthis._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\n\t\t\t}\n\t\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet aabb;\n\t\t\tconst collidables = this._collidables;\n\t\t\tlet collidable;\n\t\t\tlet valid = false;\n\t\t\tfor (const collidableId in collidables) {\n\t\t\t\tif (collidables.hasOwnProperty(collidableId)) {\n\t\t\t\t\tcollidable = collidables[collidableId];\n\t\t\t\t\tif (collidable.collidable === false) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\taabb = collidable.aabb;\n\t\t\t\t\tif (aabb[0] < xmin) {\n\t\t\t\t\t\txmin = aabb[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[1] < ymin) {\n\t\t\t\t\t\tymin = aabb[1];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[2] < zmin) {\n\t\t\t\t\t\tzmin = aabb[2];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[3] > xmax) {\n\t\t\t\t\t\txmax = aabb[3];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[4] > ymax) {\n\t\t\t\t\t\tymax = aabb[4];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[5] > zmax) {\n\t\t\t\t\t\tzmax = aabb[5];\n\t\t\t\t\t}\n\t\t\t\t\tvalid = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!valid) {\n\t\t\t\txmin = -100;\n\t\t\t\tymin = -100;\n\t\t\t\tzmin = -100;\n\t\t\t\txmax = 100;\n\t\t\t\tymax = 100;\n\t\t\t\tzmax = 100;\n\t\t\t}\n\t\t\tthis._aabb[0] = xmin;\n\t\t\tthis._aabb[1] = ymin;\n\t\t\tthis._aabb[2] = zmin;\n\t\t\tthis._aabb[3] = xmax;\n\t\t\tthis._aabb[4] = ymax;\n\t\t\tthis._aabb[5] = zmax;\n\t\t\tthis._aabbDirty = false;\n\t\t\tif (valid) this._aabbUpdate = true;\n\t\t}\n\t\treturn this._aabb;\n\t}\n\n\tget aabbs() {\n\t\tconst collidables = this._collidables;\n\t\tfor (const collidableId in collidables) {\n\t\t\treturn collidables[collidableId].aabbs;\n\t\t}\n\t}\n\n\tcalculateBoxCenter(boxs) {\n\t\tlet points = [];\n\t\tfor (let i = 0; i < boxs.length; i++) {\n\t\t\tlet box = boxs[i];\n\t\t\tlet center = [(box[0] + box[3]) / 2, (box[1] + box[4]) / 2, (box[2] + box[5]) / 2];\n\t\t\tpoints.push(_math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec3(center));\n\t\t}\n\t\treturn points;\n\t}\n\n\t_setAABBDirty() {\n\t\tthis._aabbDirty = true;\n\t\tthis._aabbUpdate = false;\n\t\tthis.center;\n\t\t// this.fire(\"boundary\");\n\t\tthis.fire(\"aabb\");\n\t}\n\n\t/**\n * Attempts to pick an {@link Entity} in this Scene.\n *\n * Ignores {@link Entity}s with {@link Entity#pickable} set ````false````.\n *\n * When an {@link Entity} is picked, fires a \"pick\" event on the {@link Entity} with the pick result as parameters.\n *\n * Picking the {@link Entity} at the given canvas coordinates:\n\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an Entity\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * Picking, with a ray cast through the canvas, hits an {@link Entity}:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true,\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an Entity\n *\n * var entity = pickResult.entity;\n *\n * if (pickResult.primitive === \"triangle\") {\n *\n * // Picked a triangle on the entity surface\n *\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n *\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\n *\n * // Picked a point and normal on the entity surface\n *\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\n * }\n * }\n * ````\n *\n * Picking the {@link Entity} that intersects an arbitrarily-aligned World-space ray:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true, // Picking with arbitrarily-positioned ray\n * origin: [0,0,-5], // Ray origin\n * direction: [0,0,1] // Ray direction\n * });\n *\n * if (pickResult) { // Picked an Entity with the ray\n *\n * var entity = pickResult.entity;\n *\n * if (pickResult.primitive == \"triangle\") {\n *\n * // Picked a triangle on the entity surface\n *\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n * var origin = pickResult.origin; // Float64Array containing the World-space ray origin\n * var direction = pickResult.direction; // Float64Array containing the World-space ray direction\n *\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\n *\n * // Picked a point and normal on the entity surface\n *\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\n * }\n * }\n * ````\n *\n * @param {*} params Picking parameters.\n * @param {Boolean} [params.pickSurface=false] Whether to find the picked position on the surface of the Entity.\n * @param {Boolean} [params.pickSurfacePrecision=false] When picking an Entity surface position, indicates whether or not we want full-precision {@link PickResult#worldPos}. Only works when {@link Scene#pickSurfacePrecisionEnabled} is ````true````. If pick succeeds, the returned {@link PickResult} will have {@link PickResult#precision} set ````true````, to indicate that it contains full-precision surface pick results.\n * @param {Boolean} [params.pickSurfaceNormal=false] Whether to find the picked normal on the surface of the Entity. Only works if ````pickSurface```` is given.\n * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\n * @param {Number[]} [params.origin] World-space ray origin when ray-picking. Ignored when canvasPos given.\n * @param {Number[]} [params.direction] World-space ray direction when ray-picking. Also indicates the length of the ray. Ignored when canvasPos given.\n * @param {Number[]} [params.matrix] 4x4 transformation matrix to define the World-space ray origin and direction, as an alternative to ````origin```` and ````direction````.\n * @param {String[]} [params.includeEntities] IDs of {@link Entity}s to restrict picking to. When given, ignores {@link Entity}s whose IDs are not in this list.\n * @param {String[]} [params.excludeEntities] IDs of {@link Entity}s to ignore. When given, will pick *through* these {@link Entity}s, as if they were not there.\n * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\n * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\n * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\n * @param {PickResult} [pickResult] Holds the results of the pick attempt. Will use the Scene's singleton PickResult if you don't supply your own.\n * @returns {PickResult} Holds results of the pick attempt, returned when an {@link Entity} is picked, else null. See method comments for description.\n */\n\tpick(params, pickResult) {\n\t\tif (this.canvas.boundary[2] === 0 || this.canvas.boundary[3] === 0) {\n\t\t\tthis.error(\"Picking not allowed while canvas has zero width or height\");\n\t\t\treturn null;\n\t\t}\n\n\t\tparams = params || {};\n\n\t\tparams.pickSurface = params.pickSurface || params.rayPick; // Backwards compatibility\n\n\t\tif (!params.canvasPos && !params.matrix && (!params.origin || !params.direction)) {\n\t\t\tthis.warn(\"picking without canvasPos, matrix, or ray origin and direction\");\n\t\t}\n\n\t\tconst includeEntities = params.includeEntities || params.include; // Backwards compat\n\t\tif (includeEntities) {\n\t\t\tparams.includeEntityIds = getEntityIDMap(this, includeEntities);\n\t\t}\n\n\t\tconst excludeEntities = params.excludeEntities || params.exclude; // Backwards compat\n\t\tif (excludeEntities) {\n\t\t\tparams.excludeEntityIds = getEntityIDMap(this, excludeEntities);\n\t\t}\n\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\n\t\tif (params.snapToEdge || params.snapToVertex) {\n\t\t\tpickResult = this._renderer.snapPick(\n\t\t\t\tparams.canvasPos,\n\t\t\t\tparams.snapRadius || 30,\n\t\t\t\tparams.snapToVertex,\n\t\t\t\tparams.snapToEdge,\n\t\t\t\tpickResult\n\t\t\t);\n\t\t} else {\n\t\t\tpickResult = this._renderer.pick(params, pickResult);\n\t\t}\n\n\t\tif (pickResult) {\n\t\t\tif (pickResult.entity && pickResult.entity.fire) {\n\t\t\t\tpickResult.entity.fire(\"picked\", pickResult); // TODO: SceneModelEntity doesn't fire events\n\t\t\t}\n\t\t}\n\n\t\treturn pickResult;\n\t}\n\n\t/**\n\t * @param {Object} params Picking parameters.\n\t * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\n\t * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\n\t * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\n\t * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\n\t * @deprecated\n\t */\n\tsnapPick(params) {\n\t\tif (undefined === this._warnSnapPickDeprecated) {\n\t\t\tthis._warnSnapPickDeprecated = true;\n\t\t\tthis.warn(\"Scene.snapPick() is deprecated since v2.4.2 - use Scene.pick() instead\");\n\t\t}\n\t\treturn this._renderer.snapPick(params.canvasPos, params.snapRadius || 30, params.snapToVertex, params.snapToEdge);\n\t}\n\n\t/**\n\t * Destroys all non-default {@link Component}s in this Scene.\n\t */\n\tclear() {\n\t\tvar component;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tcomponent = this.components[id];\n\t\t\t\tif (!component._dontClear) {\n\t\t\t\t\t// Don't destroy components like Camera, Input, Viewport etc.\n\t\t\t\t\tcomponent.destroy();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Light}s in this Scene..\n\t */\n\tclearLights() {\n\t\tconst ids = Object.keys(this.lights);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.lights[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link SectionPlane}s in this Scene.\n\t */\n\tclearSectionPlanes() {\n\t\tconst ids = Object.keys(this.sectionPlanes);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.sectionPlanes[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Line}s in this Scene.\n\t */\n\tclearBitmaps() {\n\t\tconst ids = Object.keys(this.bitmaps);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.bitmaps[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Line}s in this Scene.\n\t */\n\tclearLines() {\n\t\tconst ids = Object.keys(this.lineSets);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.lineSets[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the collective axis-aligned boundary (AABB) of a batch of {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which {@link Entity#isObject} is registered by {@link Entity#id} in {@link Scene#visibleObjects}.\n\t *\n\t * Each {@link Entity} is only included in the AABB when {@link Entity#collidable} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @returns {[Number, Number, Number, Number, Number, Number]} An axis-aligned World-space bounding box, given as elements ````[xmin, ymin, zmin, xmax, ymax, zmax]````.\n\t */\n\tgetAABB(ids) {\n\t\tif (ids === undefined) {\n\t\t\treturn this.aabb;\n\t\t}\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\n\t\t\tconst entity = this.objects[ids];\n\t\t\tif (entity && entity.aabb) {\n\t\t\t\t// A Component subclass with an AABB\n\t\t\t\treturn entity.aabb;\n\t\t\t}\n\t\t\tids = [ids]; // Must be an entity type\n\t\t}\n\t\tif (ids.length === 0) {\n\t\t\treturn this.aabb;\n\t\t}\n\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet valid;\n\t\tthis.withObjects(ids, (entity) => {\n\t\t\tif (entity.collidable) {\n\t\t\t\tconst aabb = entity.aabb;\n\t\t\t\tif (aabb[0] < xmin) {\n\t\t\t\t\txmin = aabb[0];\n\t\t\t\t}\n\t\t\t\tif (aabb[1] < ymin) {\n\t\t\t\t\tymin = aabb[1];\n\t\t\t\t}\n\t\t\t\tif (aabb[2] < zmin) {\n\t\t\t\t\tzmin = aabb[2];\n\t\t\t\t}\n\t\t\t\tif (aabb[3] > xmax) {\n\t\t\t\t\txmax = aabb[3];\n\t\t\t\t}\n\t\t\t\tif (aabb[4] > ymax) {\n\t\t\t\t\tymax = aabb[4];\n\t\t\t\t}\n\t\t\t\tif (aabb[5] > zmax) {\n\t\t\t\t\tzmax = aabb[5];\n\t\t\t\t}\n\t\t\t\tvalid = true;\n\t\t\t}\n\t\t});\n\t\tif (valid) {\n\t\t\tconst aabb2 = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\n\t\t\taabb2[0] = xmin;\n\t\t\taabb2[1] = ymin;\n\t\t\taabb2[2] = zmin;\n\t\t\taabb2[3] = xmax;\n\t\t\taabb2[4] = ymax;\n\t\t\taabb2[5] = zmax;\n\t\t\treturn aabb2;\n\t\t} else {\n\t\t\treturn this.aabb; // Scene AABB\n\t\t}\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#visible} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#visible} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#visibleObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} visible Whether or not to set visible.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsVisible(ids, visible) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.visible !== visible;\n\t\t\tentity.visible = visible;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#collidable} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} collidable Whether or not to set collidable.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsCollidable(ids, collidable) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.collidable !== collidable;\n\t\t\tentity.collidable = collidable;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#culled} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} culled Whether or not to cull.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsCulled(ids, culled) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.culled !== culled;\n\t\t\tentity.culled = culled;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#selected} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#selected} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#selectedObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} selected Whether or not to select.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsSelected(ids, selected) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.selected !== selected;\n\t\t\tentity.selected = selected;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#highlighted} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#highlighted} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#highlightedObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} highlighted Whether or not to highlight.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsHighlighted(ids, highlighted) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.highlighted !== highlighted;\n\t\t\tentity.highlighted = highlighted;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#xrayed} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} xrayed Whether or not to xray.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsXRayed(ids, xrayed) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.xrayed !== xrayed;\n\t\t\tentity.xrayed = xrayed;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#edges} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} edges Whether or not to show edges.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsEdges(ids, edges) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.edges !== edges;\n\t\t\tentity.edges = edges;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#colorize} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number[]} [colorize=(1,1,1)] RGB colorize factors, multiplied by the rendered pixel colors.\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsColorized(ids, colorize) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tentity.colorize = colorize;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#opacity} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number} [opacity=1.0] Opacity factor, multiplied by the rendered pixel alphas.\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsOpacity(ids, opacity) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.opacity !== opacity;\n\t\t\tentity.opacity = opacity;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#pickable} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} pickable Whether or not to set pickable.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsPickable(ids, pickable) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.pickable !== pickable;\n\t\t\tentity.pickable = pickable;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#offset} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number[]} [offset] 3D offset vector.\n\t */\n\tsetObjectsOffset(ids, offset) {\n\t\tthis.withObjects(ids, (entity) => {\n\t\t\tentity.offset = offset;\n\t\t});\n\t}\n\n\t/**\n\t * Iterates with a callback over {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Function} callback Callback to execute on eacn {@link Entity}.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\twithObjects(ids, callback) {\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\n\t\t\tids = [ids];\n\t\t}\n\t\tlet changed = false;\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tconst id = ids[i];\n\t\t\tlet entity = this.objects[id];\n\t\t\tif (entity) {\n\t\t\t\tchanged = callback(entity) || changed;\n\t\t\t} else {\n\t\t\t\tconst modelIds = this.modelIds;\n\t\t\t\tfor (let i = 0, len = modelIds.length; i < len; i++) {\n\t\t\t\t\tconst modelId = modelIds[i];\n\t\t\t\t\tconst globalObjectId = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.globalizeObjectId(modelId, id);\n\t\t\t\t\tentity = this.objects[globalObjectId];\n\t\t\t\t\tif (entity) {\n\t\t\t\t\t\tchanged = callback(entity) || changed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn changed;\n\t}\n\n\t/**\n\t * This method will \"tickify\" the provided `cb` function.\n\t *\n\t * This means, the function will be wrapped so:\n\t *\n\t * - it runs time-aligned to scene ticks\n\t * - it runs maximum once per scene-tick\n\t *\n\t * @param {Function} cb The function to tickify\n\t * @returns {Function}\n\t */\n\ttickify(cb) {\n\t\tconst cbString = cb.toString();\n\n\t\t/**\n\t\t * Check if the function is already tickified, and if so return the cached one.\n\t\t */\n\t\tif (cbString in this._tickifiedFunctions) {\n\t\t\treturn this._tickifiedFunctions[cbString].wrapperFunc;\n\t\t}\n\n\t\tlet alreadyRun = 0;\n\t\tlet needToRun = 0;\n\n\t\tlet lastArgs;\n\n\t\t/**\n\t\t * The provided `cb` function is replaced with a \"set-dirty\" function\n\t\t *\n\t\t * @type {Function}\n\t\t */\n\t\tconst wrapperFunc = function (...args) {\n\t\t\tlastArgs = args;\n\t\t\tneedToRun++;\n\t\t};\n\n\t\t/**\n\t\t * An each scene tick, if the \"dirty-flag\" is set, run the `cb` function.\n\t\t *\n\t\t * This will make it run time-aligned to the scene tick.\n\t\t */\n\t\tconst tickSubId = this.on(\"tick\", () => {\n\t\t\tconst tmp = needToRun;\n\t\t\tif (tmp > alreadyRun) {\n\t\t\t\talreadyRun = tmp;\n\t\t\t\tcb(...lastArgs);\n\t\t\t}\n\t\t});\n\n\t\t/**\n\t\t * And, store the list of subscribers.\n\t\t */\n\t\tthis._tickifiedFunctions[cbString] = { tickSubId, wrapperFunc };\n\n\t\treturn wrapperFunc;\n\t}\n\n\t/**\n\t * Destroys this Scene.\n\t */\n\tdestroy(callback) {\n\t\tsuper.destroy();\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tthis.components[id].destroy();\n\t\t\t}\n\t\t}\n\t\t// this.canvas.destroy(); // canvas是scene的其中一个component,所有以不必再destroy\n\n\t\t// Memory leak prevention\n\t\tthis.components = null;\n\t\tthis.models = null;\n\t\tthis.objects = null;\n\t\tthis.visibleObjects = null;\n\t\tthis.xrayedObjects = null;\n\t\tthis.highlightedObjects = null;\n\t\tthis.selectedObjects = null;\n\t\tthis.colorizedObjects = null;\n\t\tthis.opacityObjects = null;\n\t\tthis.sectionPlanes = null;\n\t\tthis.lights = null;\n\t\tthis.lightMaps = null;\n\t\tthis.reflectionMaps = null;\n\t\tthis._objectIds = null;\n\t\tthis._visibleObjectIds = null;\n\t\tthis._xrayedObjectIds = null;\n\t\tthis._highlightedObjectIds = null;\n\t\tthis._selectedObjectIds = null;\n\t\tthis._colorizedObjectIds = null;\n\t\tthis.types = null;\n\t\tthis._renderer = null;\n\t\tthis.input = null;\n\t\tthis._viewport = null;\n\t\tthis._camera = null;\n\t\tthis.canvas = null;\n\t\tif (typeof callback === \"function\") {\n\t\t\tcallback();\n\t\t}\n\t}\n}\n\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/scene/Scene.js?");
|
|
4828
4828
|
|
|
4829
4829
|
/***/ }),
|
|
4830
4830
|
|
|
@@ -5094,7 +5094,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
5094
5094
|
\*******************************************/
|
|
5095
5095
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5096
5096
|
|
|
5097
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Program: () => (/* binding */ Program)\n/* harmony export */ });\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n/* harmony import */ var _Shader_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Shader.js */ \"./src/viewer/scene/webgl/Shader.js\");\n/* harmony import */ var _Sampler_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Sampler.js */ \"./src/viewer/scene/webgl/Sampler.js\");\n/* harmony import */ var _Attribute_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Attribute.js */ \"./src/viewer/scene/webgl/Attribute.js\");\n\
|
|
5097
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Program: () => (/* binding */ Program)\n/* harmony export */ });\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n/* harmony import */ var _Shader_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Shader.js */ \"./src/viewer/scene/webgl/Shader.js\");\n/* harmony import */ var _Sampler_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Sampler.js */ \"./src/viewer/scene/webgl/Sampler.js\");\n/* harmony import */ var _Attribute_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Attribute.js */ \"./src/viewer/scene/webgl/Attribute.js\");\n\n\n\n\n\nconst ids = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_0__.Map({});\n\nfunction joinSansComments(srcLines) {\n const src = [];\n let line;\n let n;\n for (let i = 0, len = srcLines.length; i < len; i++) {\n line = srcLines[i];\n n = line.indexOf(\"/\");\n if (n > 0) {\n if (line.charAt(n + 1) === \"/\") {\n line = line.substring(0, n);\n }\n }\n src.push(line);\n }\n return src.join(\"\\n\");\n}\n\nfunction logErrors(errors) {\n console.error(errors.join(\"\\n\"));\n}\n\n/**\n * @desc Represents a WebGL program.\n * @private\n */\nclass Program {\n\n constructor(gl, shaderSource) {\n this.id = ids.addItem({});\n this.source = shaderSource;\n this.init(gl);\n }\n\n init(gl) {\n this.gl = gl;\n this.allocated = false;\n this.compiled = false;\n this.linked = false;\n this.validated = false;\n this.errors = null;\n this.uniforms = {};\n this.samplers = {};\n this.attributes = {};\n this._vertexShader = new _Shader_js__WEBPACK_IMPORTED_MODULE_1__.Shader(gl, gl.VERTEX_SHADER, joinSansComments(this.source.vertex));\n this._fragmentShader = new _Shader_js__WEBPACK_IMPORTED_MODULE_1__.Shader(gl, gl.FRAGMENT_SHADER, joinSansComments(this.source.fragment));\n if (!this._vertexShader.allocated) {\n this.errors = [\"Vertex shader failed to allocate\"].concat(this._vertexShader.errors);\n logErrors(this.errors);\n return;\n }\n if (!this._fragmentShader.allocated) {\n this.errors = [\"Fragment shader failed to allocate\"].concat(this._fragmentShader.errors);\n logErrors(this.errors);\n return;\n }\n this.allocated = true;\n if (!this._vertexShader.compiled) {\n this.errors = [\"Vertex shader failed to compile\"].concat(this._vertexShader.errors);\n logErrors(this.errors);\n return;\n }\n if (!this._fragmentShader.compiled) {\n this.errors = [\"Fragment shader failed to compile\"].concat(this._fragmentShader.errors);\n logErrors(this.errors);\n return;\n }\n this.compiled = true;\n let a;\n let i;\n let u;\n let uName;\n let location;\n this.handle = gl.createProgram();\n if (!this.handle) {\n this.errors = [\"Failed to allocate program\"];\n return;\n }\n gl.attachShader(this.handle, this._vertexShader.handle);\n gl.attachShader(this.handle, this._fragmentShader.handle);\n gl.linkProgram(this.handle);\n this.linked = gl.getProgramParameter(this.handle, gl.LINK_STATUS);\n // HACK: Disable validation temporarily\n // Perhaps we should defer validation until render-time, when the program has values set for all inputs?\n this.validated = true;\n if (!this.linked || !this.validated) {\n this.errors = [];\n this.errors.push(\"\");\n this.errors.push(gl.getProgramInfoLog(this.handle));\n this.errors.push(\"\\nVertex shader:\\n\");\n this.errors = this.errors.concat(this.source.vertex);\n this.errors.push(\"\\nFragment shader:\\n\");\n this.errors = this.errors.concat(this.source.fragment);\n logErrors(this.errors);\n return;\n }\n const numUniforms = gl.getProgramParameter(this.handle, gl.ACTIVE_UNIFORMS);\n for (i = 0; i < numUniforms; ++i) {\n u = gl.getActiveUniform(this.handle, i);\n if (u) {\n uName = u.name;\n if (uName[uName.length - 1] === \"\\u0000\") {\n uName = uName.substr(0, uName.length - 1);\n }\n location = gl.getUniformLocation(this.handle, uName);\n if ((u.type === gl.SAMPLER_2D) || (u.type === gl.SAMPLER_CUBE) || (u.type === 35682)) {\n this.samplers[uName] = new _Sampler_js__WEBPACK_IMPORTED_MODULE_2__.Sampler(gl, location);\n } else if (gl instanceof WebGL2RenderingContext && (u.type === gl.UNSIGNED_INT_SAMPLER_2D || u.type === gl.INT_SAMPLER_2D)) {\n this.samplers[uName] = new _Sampler_js__WEBPACK_IMPORTED_MODULE_2__.Sampler(gl, location);\n } else {\n this.uniforms[uName] = location;\n }\n }\n }\n const numAttribs = gl.getProgramParameter(this.handle, gl.ACTIVE_ATTRIBUTES);\n for (i = 0; i < numAttribs; i++) {\n a = gl.getActiveAttrib(this.handle, i);\n if (a) {\n location = gl.getAttribLocation(this.handle, a.name);\n this.attributes[a.name] = new _Attribute_js__WEBPACK_IMPORTED_MODULE_3__.Attribute(gl, location);\n }\n }\n this.allocated = true;\n }\n\n bind() {\n if (!this.allocated) {\n return;\n }\n this.gl.useProgram(this.handle);\n }\n\n getLocation(name) {\n if (!this.allocated) {\n return;\n }\n return this.uniforms[name];\n }\n\n getAttribute(name) {\n if (!this.allocated) {\n return;\n }\n return this.attributes[name];\n }\n\n bindTexture(name, texture, unit) {\n if (!this.allocated) {\n return false;\n }\n const sampler = this.samplers[name];\n if (sampler) {\n return sampler.bindTexture(texture, unit);\n } else {\n return false;\n }\n }\n\n destroy() {\n if (!this.allocated) {\n return;\n }\n ids.removeItem(this.id);\n this.gl.deleteProgram(this.handle);\n this.gl.deleteShader(this._vertexShader.handle);\n this.gl.deleteShader(this._fragmentShader.handle);\n this.handle = null;\n this.attributes = null;\n this.uniforms = null;\n this.samplers = null;\n this.allocated = false;\n }\n}\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/webgl/Program.js?");
|
|
5098
5098
|
|
|
5099
5099
|
/***/ }),
|
|
5100
5100
|
|