@xtctwins/tctwins-core 1.0.33 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tctwins-core.es.js +354 -341
- package/dist/tctwins-core.min.es.js +5 -5
- package/package.json +2 -2
- package/types/viewer/Viewer.d.ts +2 -0
|
@@ -2154,7 +2154,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2154
2154
|
\********************************************************/
|
|
2155
2155
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2156
2156
|
|
|
2157
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XTCLoaderPlugin: () => (/* binding */ XTCLoaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/model/index.js */ \"./src/viewer/scene/model/index.js\");\n/* harmony import */ var _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/metadata/MetaModel.js */ \"./src/viewer/metadata/MetaModel.js\");\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./XTCDefaultDataSource.js */ \"./src/plugins/XTCLoaderPlugin/XTCDefaultDataSource.js\");\n/* harmony import */ var _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/metadata/IFCObjectDefaults.js */ \"./src/viewer/metadata/IFCObjectDefaults.js\");\n/* harmony import */ var _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./parsers/ParserV1.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV1.js\");\n/* harmony import */ var _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./parsers/ParserV2.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV2.js\");\n/* harmony import */ var _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./parsers/ParserV3.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV3.js\");\n/* harmony import */ var _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./parsers/ParserV4.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV4.js\");\n/* harmony import */ var _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./parsers/ParserV5.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV5.js\");\n/* harmony import */ var _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./parsers/ParserV6.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV6.js\");\n/* harmony import */ var _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./parsers/ParserV7.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV7.js\");\n/* harmony import */ var _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./parsers/ParserV8.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV8.js\");\n/* harmony import */ var _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./parsers/ParserV9.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV9.js\");\n/* harmony import */ var _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./parsers/ParserV10.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV10.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\nconst parsers = {};\r\n\r\nparsers[_parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1.version] = _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1;\r\nparsers[_parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2.version] = _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2;\r\nparsers[_parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3.version] = _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3;\r\nparsers[_parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4.version] = _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4;\r\nparsers[_parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5.version] = _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5;\r\nparsers[_parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6.version] = _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6;\r\nparsers[_parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7.version] = _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7;\r\nparsers[_parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8.version] = _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8;\r\nparsers[_parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9.version] = _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9;\r\nparsers[_parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10.version] = _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10;\r\n\r\n/**\r\n * {@link Viewer} plugin that loads models from xeokit's optimized *````.XTC````* format.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter\"><img src=\"http://xeokit.io/img/docs/XTCLoaderPlugin/XTCLoaderPlugin.png\"></a>\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter)]\r\n *\r\n * # Overview\r\n *\r\n * * XTCLoaderPlugin is the most efficient way to load high-detail models into xeokit.\r\n * * An *````.XTC````* file is a single BLOB containing a model, compressed using geometry quantization\r\n * and [pako](https://nodeca.github.io/pako/).\r\n * * Supports double-precision coordinates.\r\n * * Supports compressed textures.\r\n * * Set the position, scale and rotation of each model as you load it.\r\n * * Filter which IFC types get loaded.\r\n * * Configure initial default appearances for IFC types.\r\n * * Set a custom data source for *````.XTC````* and IFC metadata files.\r\n * * Option to load multiple copies of the same model, without object ID clashes.\r\n *\r\n * # Creating *````.XTC````* Files and Metadata\r\n *\r\n * We have several sways to convert your files into XTC. See these tutorials for more info:\r\n *\r\n * * [Converting Models to XTC with convert2xtc](https://www.notion.so/xeokit/Converting-Models-to-XTC-with-convert2xtc-fa567843313f4db8a7d6535e76da9380) - how to convert various file formats (glTF, IFC, CityJSON, LAS/LAZ...) to XTC using our nodejs-based converter.\r\n * * [Converting IFC Models to XTC using 3rd-Party Open Source Tools](https://www.notion.so/xeokit/Converting-IFC-Models-to-XTC-using-3rd-Party-Open-Source-Tools-c373e48bc4094ff5b6e5c5700ff580ee) - how to convert IFC files to XTC using 3rd-party open source CLI tools.\r\n *\r\n * # Scene representation\r\n *\r\n * When loading a model, XTCLoaderPlugin creates an {@link Entity} that represents the model, which\r\n * will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id}\r\n * in {@link Scene#models}. The XTCLoaderPlugin also creates an {@link Entity} for each object within the\r\n * model. Those Entities will have {@link Entity#isObject} set ````true```` and will be registered\r\n * by {@link Entity#id} in {@link Scene#objects}.\r\n *\r\n * # Metadata\r\n *\r\n * Since XTC V8, model metadata is included in the XTC file. If the XTC file has metadata, then loading it creates\r\n * model metadata components within the Viewer, namely a {@link MetaModel} corresponding to the model {@link Entity},\r\n * and a {@link MetaObject} for each object {@link Entity}.\r\n *\r\n * Each {@link MetaObject} has a {@link MetaObject#type}, which indicates the classification of its corresponding\r\n * {@link Entity}. When loading metadata, we can also configure XTCLoaderPlugin with a custom lookup table of initial\r\n * values to set on the properties of each type of {@link Entity}. By default, XTCLoaderPlugin uses its own map of\r\n * default colors and visibilities for IFC element types.\r\n *\r\n * For XTC versions prior to V8, we provided the metadata to XTCLoaderPlugin as an accompanying JSON file to load. We can\r\n * still do that for all XTC versions, and for XTC V8+ it will override any metadata provided within the XTC file.\r\n *\r\n * # Usage\r\n *\r\n * In the example below we'll load the Schependomlaan model from a [.XTC file](https://github.com/xeokit/xeokit-sdk/tree/master/examples/models/xtc/schependomlaan).\r\n *\r\n * This will create a bunch of {@link Entity}s that represents the model and its objects, along with a {@link MetaModel} and {@link MetaObject}s\r\n * that hold their metadata.\r\n *\r\n * Since this model contains IFC types, the XTCLoaderPlugin will set the initial appearance of each object\r\n * {@link Entity} according to its IFC type in {@link XTCLoaderPlugin#objectDefaults}.\r\n *\r\n * Read more about this example in the user guide on [Viewing BIM Models Offline](https://www.notion.so/xeokit/Viewing-an-IFC-Model-with-xeokit-c373e48bc4094ff5b6e5c5700ff580ee).\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_metadata_Schependomlaan)]\r\n *\r\n * ````javascript\r\n * import {Viewer, XTCLoaderPlugin} from \"tctwins-core.es.js\";\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a Viewer,\r\n * // 2. Arrange the camera\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * // 2\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a XTCLoaderPlugin,\r\n * // 2. Load a building model and JSON IFC metadata\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * // 2\r\n * const model = xtcLoader.load({ // Returns an Entity that represents the model\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n *\r\n * //--------------------------------------------------------------------------------------------------------------\r\n * // 1. Find metadata on the third storey\r\n * // 2. Select all the objects in the building's third storey\r\n * // 3. Fit the camera to all the objects on the third storey\r\n * //--------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const metaModel = viewer.metaScene.metaModels[\"myModel\"]; // MetaModel with ID \"myModel\"\r\n * const metaObject\r\n * = viewer.metaScene.metaObjects[\"0u4wgLe6n0ABVaiXyikbkA\"]; // MetaObject with ID \"0u4wgLe6n0ABVaiXyikbkA\"\r\n *\r\n * const name = metaObject.name; // \"01 eerste verdieping\"\r\n * const type = metaObject.type; // \"IfcBuildingStorey\"\r\n * const parent = metaObject.parent; // MetaObject with type \"IfcBuilding\"\r\n * const children = metaObject.children; // Array of child MetaObjects\r\n * const objectId = metaObject.id; // \"0u4wgLe6n0ABVaiXyikbkA\"\r\n * const objectIds = viewer.metaScene.getObjectIDsInSubtree(objectId); // IDs of leaf sub-objects\r\n * const aabb = viewer.scene.getAABB(objectIds); // Axis-aligned boundary of the leaf sub-objects\r\n *\r\n * // 2\r\n * viewer.scene.setObjectsSelected(objectIds, true);\r\n *\r\n * // 3\r\n * viewer.cameraFlight.flyTo(aabb);\r\n * });\r\n *\r\n * // Find the model Entity by ID\r\n * model = viewer.scene.models[\"myModel\"];\r\n *\r\n * // Destroy the model\r\n * model.destroy();\r\n * ````\r\n *\r\n * # Loading XTC files containing textures\r\n *\r\n * XTCLoaderPlugin uses a {@link KTX2TextureTranscoder} to load textures in XTC files (XTC v10+). An XTCLoaderPlugin has its own\r\n * default KTX2TextureTranscoder, configured to load the Basis Codec from the CDN. If we wish, we can override that with our own\r\n * KTX2TextureTranscoder instance that's configured to load the Codec locally.\r\n *\r\n * In the example below, we'll create a {@link Viewer} and add an XTCLoaderPlugin\r\n * configured with a KTX2TextureTranscoder that finds the Codec in our local file system. Then we'll use the\r\n * XTCLoaderPlugin to load an XTC file that contains KTX2 textures, which the plugin will transcode using\r\n * its KTX2TextureTranscoder.\r\n *\r\n * We'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory. If we were happy with loading the\r\n * Codec from our CDN (ie. our app will always have an Internet connection) then we could just leave out the\r\n * KTX2TextureTranscoder altogether, and let the XTCLoaderPlugin use its internal default KTX2TextureTranscoder, which is configured to\r\n * load the Codec from the CDN. We'll stick with loading our own Codec, in case we want to run our app without an Internet connection.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan\"><img src=\"https://xeokit.github.io/xeokit-sdk/assets/images/xtcWithTextures.png\"></a>\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan)]\r\n *\r\n * ````javascript\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const textureTranscoder = new KTX2TextureTranscoder({\r\n * viewer,\r\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to Basis Universal transcoder\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * textureTranscoder // <<------------- Transcodes KTX2 textures in XTC files\r\n * });\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./HousePlan.xtc\" // <<------ XTC file with KTX2 textures\r\n * });\r\n * ````\r\n *\r\n * # Transforming\r\n *\r\n * We have the option to rotate, scale and translate each *````.XTC````* model as we load it.\r\n *\r\n * This lets us load multiple models, or even multiple copies of the same model, and position them apart from each other.\r\n *\r\n * In the example below, we'll scale our model to half its size, rotate it 90 degrees about its local X-axis, then\r\n * translate it 100 units along its X axis.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Duplex_transform)]\r\n *\r\n * ````javascript\r\n * xtcLoader.load({\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * rotation: [90,0,0],\r\n * scale: [0.5, 0.5, 0.5],\r\n * position: [100, 0, 0]\r\n * });\r\n * ````\r\n *\r\n * # Including and excluding IFC types\r\n *\r\n * We can also load only those objects that have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that represent walls.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_includeTypes)]\r\n *\r\n * ````javascript\r\n * const model2 = xtcLoader.load({\r\n * id: \"myModel2\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * includeTypes: [\"IfcWallStandardCase\"]\r\n * });\r\n * ````\r\n *\r\n * We can also load only those objects that **don't** have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that do not represent empty space.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_excludeTypes)]\r\n *\r\n * ````javascript\r\n * const model3 = xtcLoader.load({\r\n * id: \"myModel3\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * excludeTypes: [\"IfcSpace\"]\r\n * });\r\n * ````\r\n *\r\n * # Configuring initial IFC object appearances\r\n *\r\n * We can specify the custom initial appearance of loaded objects according to their IFC types.\r\n *\r\n * This is useful for things like:\r\n *\r\n * * setting the colors to our objects according to their IFC types,\r\n * * automatically hiding ````IfcSpace```` objects, and\r\n * * ensuring that ````IfcWindow```` objects are always transparent.\r\n * <br>\r\n * In the example below, we'll load a model, while configuring ````IfcSpace```` elements to be always initially invisible,\r\n * and ````IfcWindow```` types to be always translucent blue.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_objectDefaults)]\r\n *\r\n * ````javascript\r\n * const myObjectDefaults = {\r\n *\r\n * IfcSpace: {\r\n * visible: false\r\n * },\r\n * IfcWindow: {\r\n * colorize: [0.337255, 0.303922, 0.870588], // Blue\r\n * opacity: 0.3\r\n * },\r\n *\r\n * //...\r\n *\r\n * DEFAULT: {\r\n * colorize: [0.5, 0.5, 0.5]\r\n * }\r\n * };\r\n *\r\n * const model4 = xtcLoader.load({\r\n * id: \"myModel4\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * objectDefaults: myObjectDefaults // Use our custom initial default states for object Entities\r\n * });\r\n * ````\r\n *\r\n * When we don't customize the appearance of IFC types, as just above, then IfcSpace elements tend to obscure other\r\n * elements, which can be confusing.\r\n *\r\n * It's often helpful to make IfcSpaces transparent and unpickable, like this:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * pickable: false,\r\n * opacity: 0.2\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * Alternatively, we could just make IfcSpaces invisible, which also makes them unpickable:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * visible: false\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * # Configuring a custom data source\r\n *\r\n * By default, XTCLoaderPlugin will load *````.XTC````* files and metadata JSON over HTTP.\r\n *\r\n * In the example below, we'll customize the way XTCLoaderPlugin loads the files by configuring it with our own data source\r\n * object. For simplicity, our custom data source example also uses HTTP, using a couple of xeokit utility functions.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_dataSource)]\r\n *\r\n * ````javascript\r\n * import {utils} from \"tctwins-core.es.js\";\r\n *\r\n * class MyDataSource {\r\n *\r\n * constructor() {\r\n * }\r\n *\r\n * // Gets metamodel JSON\r\n * getMetaModel(metaModelSrc, ok, error) {\r\n * console.log(\"MyDataSource#getMetaModel(\" + metaModelSrc + \", ... )\");\r\n * utils.loadJSON(metaModelSrc,\r\n * (json) => {\r\n * ok(json);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n *\r\n * // Gets the contents of the given .XTC file in an arraybuffer\r\n * getXTC(xTCSrc, ok, error) {\r\n * console.log(\"MyDataSource#getXTC(\" + xTCSrc + \", ... )\");\r\n * utils.loadArraybuffer(xTCSrc,\r\n * (arraybuffer) => {\r\n * ok(arraybuffer);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n * }\r\n *\r\n * const xtcLoader2 = new XTCLoaderPlugin(viewer, {\r\n * dataSource: new MyDataSource()\r\n * });\r\n *\r\n * const model5 = xtcLoader2.load({\r\n * id: \"myModel5\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\"\r\n * });\r\n * ````\r\n *\r\n * # Loading multiple copies of a model, without object ID clashes\r\n *\r\n * Sometimes we need to load two or more instances of the same model, without having clashes\r\n * between the IDs of the equivalent objects in the model instances.\r\n *\r\n * As shown in the example below, we do this by setting {@link XTCLoaderPlugin#globalizeObjectIds} ````true```` before we load our models.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#TreeViewPlugin_Containment_MultipleModels)]\r\n *\r\n * ````javascript\r\n * xtcLoader.globalizeObjectIds = true;\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"model1\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n *\r\n * const model2 = xtcLoader.load({\r\n * id: \"model2\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n * ````\r\n *\r\n * For each {@link Entity} loaded by these two calls, {@link Entity#id} and {@link MetaObject#id} will get prefixed by\r\n * the ID of their model, in order to avoid ID clashes between the two models.\r\n *\r\n * An Entity belonging to the first model will get an ID like this:\r\n *\r\n * ````\r\n * myModel1#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * The equivalent Entity in the second model will get an ID like this:\r\n *\r\n * ````\r\n * myModel2#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * Now, to update the visibility of both of those Entities collectively, using {@link Scene#setObjectsVisible}, we can\r\n * supply just the IFC product ID part to that method:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n * ````\r\n *\r\n * The method, along with {@link Scene#setObjectsXRayed}, {@link Scene#setObjectsHighlighted} etc, will internally expand\r\n * the given ID to refer to the instances of that Entity in both models.\r\n *\r\n * We can also, of course, reference each Entity directly, using its globalized ID:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"myModel1#0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n *````\r\n *\r\n * We can also provide an HTTP URL to the XTC file:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/models/xtc/Schependomlaan.xtc\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * # Loading a model from a manifest of XTC files\r\n *\r\n * The `ifc2gltf` tool from Creoox, which converts IFC files into glTF geometry and JSON metadata files, has the option to\r\n * split its output into multiple pairs of glTF and JSON files, accompanied by a JSON manifest that lists the files.\r\n *\r\n * To integrate with that option, the `convert2xtc` tool, which converts glTF geometry and JSON metadata files into XTC files,\r\n * also has the option to batch-convert the glTF+JSON files in the manifest, in one invocation.\r\n *\r\n * When we use this option, convert2xtc will output a bunch of XTC files, along with a JSON manifest file that lists those XTC files.\r\n *\r\n * Working down the pipeline, the XTCLoaderPlugin has the option batch-load all XTC files listed in that manifest\r\n * into a xeokit Viewer in one load operation, combining the XTC files into a single SceneModel and MetaModel.\r\n *\r\n * You can learn more about this conversion and loading process, with splitting, batch converting and batch loading,\r\n * in [this tutorial](https://www.notion.so/xeokit/Importing-Huge-IFC-Models-as-Multiple-XTC-Files-165fc022e94742cf966ee50003572259).\r\n *\r\n * To show how to use XTCLoaderPlugin to load a manifest of XTC files, let's imagine that we have a set of such XTC files. As\r\n * described in the tutorial, they were converted by `ifc2gltf` from an IFC file into a set of glTF+JSON files, that were\r\n * then converted by convert2xtc into this set of XTC files and a manifest, as shown below.\r\n *\r\n * ````bash\r\n * ./\r\n * ├── model_1.xtc\r\n * ├── model_2.xtc\r\n * ├── model_3.xtc\r\n * ├── model_4..xtc\r\n * └── model.xtc.manifest.json\r\n * ````\r\n *\r\n * The `model.xtc.manifest.json` XTC manifest would look something like this:\r\n *\r\n * ````json\r\n * {\r\n * \"inputFile\": null,\r\n * \"converterApplication\": \"convert2xtc\",\r\n * \"converterApplicationVersion\": \"v1.1.9\",\r\n * \"conversionDate\": \"10-08-2023- 02-05-01\",\r\n * \"outputDir\": null,\r\n * \"xtcFiles\": [\r\n * \"model_1.xtc\",\r\n * \"model_2.xtc\",\r\n * \"model_3.xtc\",\r\n * \"model_4.xtc\"\r\n * ]\r\n * }\r\n * ````\r\n *\r\n * Now, to load all those XTC files into a single SceneModel and MetaModel in one operation, we pass a path to the XTC\r\n * manifest to `XTCLoaderPlugin.load`, as shown in the example below:\r\n *\r\n * ````javascript\r\n * import {\r\n * Viewer,\r\n * XTCLoaderPlugin,\r\n * TreeViewPlugin,\r\n * } from \"tctwins-core.es.js\";\r\n *\r\n * constviewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [26.54, 29.29, 36.20,];\r\n * viewer.scene.camera.look = [-23.51, -8.26, -21.65,];\r\n * viewer.scene.camera.up = [-0.2, 0.89, -0.33,];\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n *\r\n * const metaModel = viewer.metaScene.metaModels[sceneModel.id];\r\n *\r\n * // Then when we need to, we can destroy the SceneModel\r\n * // and MetaModel in one shot, like so:\r\n *\r\n * sceneModel.destroy();\r\n * metaModel.destroy();\r\n * ````\r\n *\r\n * The main advantage here, of splitting IFC files like this within the conversion and import pipeline,\r\n * is to reduce the memory pressure on each of the `ifc2gltf`, `convert2xtc` and XTCLoaderPlugin components.\r\n * They work much reliably (and faster) when processing smaller files (eg. 20MB) than when processing large files (eg. 500MB), where\r\n * they have less trouble allocating the system memory they need for conversion and parsing.\r\n *\r\n * We can also provide an HTTP URL to the manifest:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * We can also provide the manifest as parameter object:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * We can also provide the paths to the XTC files as HTTP URLs:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * @class XTCLoaderPlugin\r\n */\r\nclass XTCLoaderPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t *\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {Object} cfg Plugin configuration.\r\n\t * @param {String} [cfg.id=\"XTCLoader\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {Object} [cfg.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {Object} [cfg.dataSource] A custom data source through which the XTCLoaderPlugin can load model and metadata files. Defaults to an instance of {@link XTCDefaultDataSource}, which loads uover HTTP.\r\n\t * @param {String[]} [cfg.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [cfg.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [cfg.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have a lot of geometry reuse, but may also increase the amount of\r\n\t * browser and GPU memory they require. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\r\n\t * to limit the size of the batched geometry arrays that {@link SceneModel} internally creates for batched geometries.\r\n\t * A low value means less heap allocation/de-allocation while loading batched geometries, but more draw calls and\r\n\t * slower rendering speed. A high value means larger heap allocation/de-allocation while loading, but less draw calls\r\n\t * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\r\n\t * @param {KTX2TextureTranscoder} [cfg.textureTranscoder] Transcoder used internally to transcode KTX2\r\n\t * textures within the XTC. Only required when the XTC is version 10 or later, and contains KTX2 textures.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"XTCLoader\", viewer, cfg);\r\n\r\n\t\tthis._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\r\n\r\n\t\tthis.textureTranscoder = cfg.textureTranscoder;\r\n\t\tthis.dataSource = cfg.dataSource;\r\n\t\tthis.objectDefaults = cfg.objectDefaults;\r\n\t\tthis.includeTypes = cfg.includeTypes;\r\n\t\tthis.excludeTypes = cfg.excludeTypes;\r\n\t\tthis.excludeUnclassifiedObjects = cfg.excludeUnclassifiedObjects;\r\n\t\tthis.reuseGeometries = cfg.reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the ````.xtc```` format versions supported by this XTCLoaderPlugin/\r\n\t * @returns {string[]}\r\n\t */\r\n\tget supportedVersions() {\r\n\t\treturn Object.keys(parsers);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tget textureTranscoder() {\r\n\t\treturn this._textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tset textureTranscoder(textureTranscoder) {\r\n\t\tthis._textureTranscoder = textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tget dataSource() {\r\n\t\treturn this._dataSource;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tset dataSource(value) {\r\n\t\tthis._dataSource = value || new _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__.XTCDefaultDataSource();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tget objectDefaults() {\r\n\t\treturn this._objectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tset objectDefaults(value) {\r\n\t\tthis._objectDefaults = value || _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__.IFCObjectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget includeTypes() {\r\n\t\treturn this._includeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset includeTypes(value) {\r\n\t\tthis._includeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget excludeTypes() {\r\n\t\treturn this._excludeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset excludeTypes(value) {\r\n\t\tthis._excludeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget excludeUnclassifiedObjects() {\r\n\t\treturn this._excludeUnclassifiedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset excludeUnclassifiedObjects(value) {\r\n\t\tthis._excludeUnclassifiedObjects = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget globalizeObjectIds() {\r\n\t\treturn this._globalizeObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Set this ````true```` when you need to load multiple instances of the same model, to avoid ID clashes\r\n\t * between the objects in the different instances.\r\n\t *\r\n\t * When we load a model with this set ````true````, then each {@link Entity#id} and {@link MetaObject#id} will be\r\n\t * prefixed by the ID of the model, ie. ````<modelId>#<objectId>````.\r\n\t *\r\n\t * {@link Entity#originalSystemId} and {@link MetaObject#originalSystemId} will always hold the original, un-prefixed, ID values.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * See the main {@link XTCLoaderPlugin} class documentation for usage info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset globalizeObjectIds(value) {\r\n\t\tthis._globalizeObjectIds = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget reuseGeometries() {\r\n\t\treturn this._reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * Geometry reuse saves memory, but can impact Viewer performance when there are many reused geometries. For\r\n\t * this reason, we can set this ````false```` to disable geometry reuse for models loaded by this XTCLoaderPlugin\r\n\t * (which will then \"expand\" the geometry instances into batches instead).\r\n\t *\r\n\t * The result will be be less WebGL draw calls (which are expensive), at the cost of increased memory footprint.\r\n\t *\r\n\t * See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset reuseGeometries(value) {\r\n\t\tthis._reuseGeometries = value !== false;\r\n\t}\r\n\r\n\t/**\r\n\t * Loads an ````.xtc```` model into this XTCLoaderPlugin's {@link Viewer}.\r\n\t *\r\n\t * Since xeokit/xeokit-sdk 1.9.0, XTCLoaderPlugin has supported XTC 8, which bundles the metamodel\r\n\t * data (eg. an IFC element hierarchy) in the XTC file itself. For XTC 8, we therefore no longer need to\r\n\t * load the metamodel data from a separate accompanying JSON file, as we did with previous XTC versions.\r\n\t * However, if we do choose to specify a separate metamodel JSON file to load (eg. for backward compatibility\r\n\t * in data pipelines), then that metamodel will be loaded and the metamodel in the XTC 8 file will be ignored.\r\n\t *\r\n\t * @param {*} params Loading parameters.\r\n\t * @param {String} [params.id] ID to assign to the root {@link Entity#id}, unique among all components in the Viewer's {@link Scene}, generated automatically by default.\r\n\t * @param {String} [params.src] Path or URL to an *````.xtc````* file, as an alternative to the ````xtc```` parameter.\r\n\t * @param {ArrayBuffer} [params.xtc] The *````.xtc````* file data, as an alternative to the ````src```` parameter.\r\n\t * @param {String} [params.metaModelSrc] Path or URL to an optional metadata file, as an alternative to the ````metaModelData```` parameter.\r\n\t * @param {*} [params.metaModelData] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.\r\n\t * @param {String} [params.manifestSrc] Path or URL to a JSON manifest file that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {Object} [params.manifest] A JSON manifest object (as an alternative to a path or URL) that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [params.edges=false] Whether or not xeokit renders the model with edges emphasized.\r\n\t * @param {Number[]} [params.origin=[0,0,0]] The model's World-space double-precision 3D origin. Use this to position the model within xeokit's World coordinate system, using double-precision coordinates.\r\n\t * @param {Number[]} [params.position=[0,0,0]] The model single-precision 3D position, relative to the ````origin```` parameter.\r\n\t * @param {Number[]} [params.scale=[1,1,1]] The model's scale.\r\n\t * @param {Number[]} [params.rotation=[0,0,0]] The model's orientation, given as Euler angles in degrees, for each of the X, Y and Z axis.\r\n\t * @param {Number[]} [params.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] The model's world transform matrix. Overrides the position, scale and rotation parameters. Relative to ````origin````.\r\n\t * @param {Boolean} [params.edges=false] Indicates if the model's edges are initially emphasized.\r\n\t * @param {Boolean} [params.saoEnabled=true] Indicates if Scalable Ambient Obscurance (SAO) is enabled for the model. SAO is configured by the Scene's {@link SAO} component. Only works when {@link SAO#enabled} is also ````true````\r\n\t * @param {Boolean} [params.pbrEnabled=true] Indicates if physically-based rendering (PBR) is enabled for the model. Overrides ````colorTextureEnabled````. Only works when {@link Scene#pbrEnabled} is also ````true````.\r\n\t * @param {Boolean} [params.colorTextureEnabled=true] Indicates if base color texture rendering is enabled for the model. Overridden by ````pbrEnabled````. Only works when {@link Scene#colorTextureEnabled} is also ````true````.\r\n\t * @param {Number} [params.backfaces=false] When we set this ````true````, then we force rendering of backfaces for the model. When\r\n\t * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\r\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.\r\n\t * @param {Boolean} [params.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [params.globalizeObjectIds=false] Indicates whether to globalize each {@link Entity#id} and {@link MetaObject#id}, in case you need to prevent ID clashes with other models. See {@link XTCLoaderPlugin#globalizeObjectIds} for more info.\r\n\t * @param {Boolean} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have excessive geometry reuse, but may also increases the amount of\r\n\t * browser and GPU memory used by the model. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\r\n\t * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\r\n\t * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\r\n\t * primitives. Only works while {@link DTX#enabled} is also ````true````.\r\n\t * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.\r\n\t */\r\n\tload(params = {}) {\r\n\t\tif (params.id && this.viewer.scene.components[params.id]) {\r\n\t\t\tthis.error(\"Component with this ID already exists in viewer: \" + params.id + \" - will autogenerate this ID\");\r\n\t\t\tdelete params.id;\r\n\t\t}\r\n\r\n\t\tif (!params.src && !params.xtc && !params.manifestSrc && !params.manifest) {\r\n\t\t\tthis.error(\"load() param expected: src, xtc, manifestSrc or manifestData\");\r\n\t\t\treturn sceneModel; // Return new empty model\r\n\t\t}\r\n\r\n\t\tconst options = {};\r\n\t\tconst includeTypes = params.includeTypes || this._includeTypes;\r\n\t\tconst excludeTypes = params.excludeTypes || this._excludeTypes;\r\n\t\tconst objectDefaults = params.objectDefaults || this._objectDefaults;\r\n\r\n\t\toptions.reuseGeometries =\r\n\t\t\tparams.reuseGeometries !== null && params.reuseGeometries !== undefined\r\n\t\t\t\t? params.reuseGeometries\r\n\t\t\t\t: this._reuseGeometries !== false;\r\n\r\n\t\tif (includeTypes) {\r\n\t\t\toptions.includeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = includeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.includeTypesMap[includeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (excludeTypes) {\r\n\t\t\toptions.excludeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = excludeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.excludeTypesMap[excludeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (objectDefaults) {\r\n\t\t\toptions.objectDefaults = objectDefaults;\r\n\t\t}\r\n\r\n\t\toptions.excludeUnclassifiedObjects =\r\n\t\t\tparams.excludeUnclassifiedObjects !== undefined\r\n\t\t\t\t? !!params.excludeUnclassifiedObjects\r\n\t\t\t\t: this._excludeUnclassifiedObjects;\r\n\t\toptions.globalizeObjectIds =\r\n\t\t\tparams.globalizeObjectIds !== undefined && params.globalizeObjectIds !== null\r\n\t\t\t\t? !!params.globalizeObjectIds\r\n\t\t\t\t: this._globalizeObjectIds;\r\n\r\n\t\tconst sceneModel = new _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__.SceneModel(\r\n\t\t\tthis.viewer.scene,\r\n\t\t\t_viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.apply(params, {\r\n\t\t\t\tisModel: true,\r\n\t\t\t\ttextureTranscoder: this._textureTranscoder,\r\n\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\r\n\t\t\t\torigin: params.origin,\r\n\t\t\t\tdisableVertexWelding: params.disableVertexWelding || false,\r\n\t\t\t\tdisableIndexRebucketing: params.disableIndexRebucketing || false,\r\n\t\t\t\tdtxEnabled: params.dtxEnabled\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst modelId = sceneModel.id; // In case ID was auto-generated\r\n\r\n\t\tconst metaModel = new _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__.MetaModel({\r\n\t\t\tmetaScene: this.viewer.metaScene,\r\n\t\t\tid: modelId\r\n\t\t});\r\n\r\n\t\tthis.viewer.scene.canvas.spinner.processes++;\r\n\r\n\t\tconst finish = () => {\r\n\t\t\t// this._createDefaultMetaModelIfNeeded(sceneModel, params, options);\r\n\t\t\tsceneModel.finalize();\r\n\t\t\tmetaModel.finalize();\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tsceneModel.once(\"destroyed\", () => {\r\n\t\t\t\tthis.viewer.metaScene.destroyMetaModel(metaModel.id);\r\n\t\t\t});\r\n\t\t\tthis.scheduleTask(() => {\r\n\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tsceneModel.scene.fire(\"modelLoaded\", sceneModel.id); // FIXME: Assumes listeners know order of these two events\r\n\t\t\t\tsceneModel.fire(\"loaded\", true, false); // Don't forget the event, for late subscribers\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\tconst error = (errMsg) => {\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tthis.error(errMsg);\r\n\t\t\tsceneModel.fire(\"error\", errMsg);\r\n\t\t};\r\n\r\n\t\tlet nextId = 0;\r\n\t\tconst manifestCtx = {\r\n\t\t\tgetNextId: () => {\r\n\t\t\t\treturn `${modelId}.${nextId++}`;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t//模型文件\r\n\t\tif (params.metaModelSrc || params.metaModelData) {\r\n\t\t\tif (params.metaModelSrc) {\r\n\t\t\t\tconst metaModelSrc = params.metaModelSrc;\r\n\r\n\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\tmetaModelSrc,\r\n\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tif (params.src) {\r\n\t\t\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\t\t\tfinish();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(errMsg) => {\r\n\t\t\t\t\t\terror(`load(): Failed to load model metadata for model '${modelId} from '${metaModelSrc}' - ${errMsg}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t} else if (params.metaModelData) {\r\n\t\t\t\tmetaModel.loadData(params.metaModelData, {\r\n\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t});\r\n\t\t\t\tif (params.src) {\r\n\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\tfinish();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (params.src) {\r\n\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, metaModel, manifestCtx, finish, error);\r\n\t\t\t} else if (params.xtc) {\r\n\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tfinish();\r\n\t\t\t} else if (params.manifestSrc || params.manifest) {\r\n\t\t\t\tconst baseDir = params.manifestSrc ? getBaseDirectory(params.manifestSrc) : \"\";\r\n\t\t\t\tconst loadJSONs = (metaDataFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= metaDataFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\t\t\t\t`${baseDir}${metaDataFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tconst loadXTCs = (xtcFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= xtcFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getXTC(\r\n\t\t\t\t\t\t\t\t`${baseDir}${xtcFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(arrayBuffer) => {\r\n\t\t\t\t\t\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tif (params.manifest) {\r\n\t\t\t\t\tconst manifestData = params.manifest;\r\n\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._dataSource.getManifest(\r\n\t\t\t\t\t\tparams.manifestSrc,\r\n\t\t\t\t\t\t(manifestData) => {\r\n\t\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\terror\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn sceneModel;\r\n\t}\r\n\r\n\t_loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {\r\n\t\tthis._dataSource.getXTC(\r\n\t\t\tparams.src,\r\n\t\t\t(arrayBuffer) => {\r\n\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tdone();\r\n\t\t\t},\r\n\t\t\terror\r\n\t\t);\r\n\t}\r\n\r\n\t_parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {\r\n\t\tif (sceneModel.destroyed) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst dataView = new DataView(arrayBuffer);\r\n\t\tconst dataArray = new Uint8Array(arrayBuffer);\r\n\t\tconst xtcVersion = dataView.getUint32(0, true);\r\n\t\tconst parser = parsers[xtcVersion];\r\n\t\tif (!parser) {\r\n\t\t\tthis.error(\r\n\t\t\t\t\"Unsupported .XTC file version: \" +\r\n\t\t\t\t\txtcVersion +\r\n\t\t\t\t\t\" - this XTCLoaderPlugin supports versions \" +\r\n\t\t\t\t\tObject.keys(parsers)\r\n\t\t\t);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.log(\"Loading .xtc V\" + xtcVersion);\r\n\t\tconst numElements = dataView.getUint32(4, true);\r\n\t\tconst elements = [];\r\n\t\tlet byteOffset = (numElements + 2) * 4;\r\n\t\tfor (let i = 0; i < numElements; i++) {\r\n\t\t\tconst elementSize = dataView.getUint32((i + 2) * 4, true);\r\n\t\t\telements.push(dataArray.subarray(byteOffset, byteOffset + elementSize));\r\n\t\t\tbyteOffset += elementSize;\r\n\t\t}\r\n\t\tparser.parse(this.viewer, options, elements, sceneModel, metaModel, manifestCtx);\r\n\t}\r\n\r\n\tloadMetadata(metaModel, deflatedMetadata, done) {\r\n\t\tmetaModel._finalized = false;\r\n\r\n\t\ttry {\r\n\t\t\t{\r\n\t\t\t\tthis._workerInflate(\r\n\t\t\t\t\tmetaModel,\r\n\t\t\t\t\tdeflatedMetadata,\r\n\t\t\t\t\t(worker) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaLoaded\", { result: \"success\", metaModel });\r\n\t\t\t\t\t\tif (typeof done === \"function\") done();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(worker, error) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaLoaded\", { result: \"failed\", message: error, metaModel });\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tthis.fire(\"metaloaded\", { result: error, metaModel });\r\n\t\t}\r\n\t}\r\n\r\n\t_workerInflate(metaModel, buffer, done, err) {\r\n\t\tconst plugin = this;\r\n\t\tconst worker = createInlineWorker();\r\n\t\tworker.postMessage({\r\n\t\t\tbuffer\r\n\t\t\t// executionTime: new Date().getTime()\r\n\t\t});\r\n\r\n\t\tworker.onmessage = function (e) {\r\n\t\t\tplugin.fire(\"metaLoading\", () => {\r\n\t\t\t\tmetaModel.loadData(\r\n\t\t\t\t\te.data.metaJson,\r\n\t\t\t\t\t() => {\r\n\t\t\t\t\t\tmetaModel.finalize();\r\n\t\t\t\t\t\tif (typeof done === \"function\") done(worker);\r\n\t\t\t\t\t\telse worker.terminate();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(e) => {\r\n\t\t\t\t\t\tif (typeof err === \"function\") err(worker, e);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t\t};\r\n\t\tworker.onerror = function (e) {\r\n\t\t\tif (typeof err === \"function\") err(worker, e.message);\r\n\t\t\tworker.terminate();\r\n\t\t};\r\n\t}\r\n\r\n\t// _createDefaultMetaModelIfNeeded(sceneModel, params, options) {\r\n\t//\r\n\t// const metaModelId = sceneModel.id;\r\n\t//\r\n\t// if (!this.viewer.metaScene.metaModels[metaModelId]) {\r\n\t//\r\n\t// const metaModelData = {\r\n\t// metaObjects: []\r\n\t// };\r\n\t//\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: metaModelId,\r\n\t// type: \"default\",\r\n\t// name: metaModelId,\r\n\t// parent: null\r\n\t// });\r\n\t//\r\n\t// const entityList = sceneModel.entityList;\r\n\t//\r\n\t// for (let i = 0, len = entityList.length; i < len; i++) {\r\n\t// const entity = entityList[i];\r\n\t// if (entity.isObject) {\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: entity.id,\r\n\t// type: \"default\",\r\n\t// name: entity.id,\r\n\t// parent: metaModelId\r\n\t// });\r\n\t// }\r\n\t// }\r\n\t//\r\n\t// const src = params.src;\r\n\t//\r\n\t// this.viewer.metaScene.createMetaModel(metaModelId, metaModelData, {\r\n\t//\r\n\t// includeTypes: options.includeTypes,\r\n\t// excludeTypes: options.excludeTypes,\r\n\t// globalizeObjectIds: options.globalizeObjectIds,\r\n\t//\r\n\t// getProperties: async (propertiesId) => {\r\n\t// return await this._dataSource.getProperties(src, propertiesId);\r\n\t// }\r\n\t// });\r\n\t//\r\n\t// sceneModel.once(\"destroyed\", () => {\r\n\t// this.viewer.metaScene.destroyMetaModel(metaModelId);\r\n\t// });\r\n\t// }\r\n\t// }\r\n}\r\n\r\nfunction getBaseDirectory(filePath) {\r\n\tconst pathArray = filePath.split(\"/\");\r\n\tpathArray.pop(); // Remove the file name or the last segment of the path\r\n\treturn pathArray.join(\"/\") + \"/\";\r\n}\r\nfunction createInlineWorker() {\r\n\tconst workerCode = `\r\n self.importScripts('https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako.min.js');\r\n \r\n function inflateMetadata(deflatedData) {\r\n return JSON.parse(self.pako.inflate(deflatedData, { to: \"string\" }));\r\n }\r\n \r\n self.onmessage = function (e) {\r\n console.log(\"start worker:\");\r\n const metaJson = inflateMetadata(e.data.buffer);\r\n\r\n self.postMessage({\r\n metaJson,\r\n time: new Date().getTime()\r\n });\r\n };\r\n `;\r\n\tconst blob = new Blob([workerCode], { type: \"application/javascript\" });\r\n\tconst workerUrl = URL.createObjectURL(blob);\r\n\treturn new Worker(workerUrl);\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XTCLoaderPlugin/XTCLoaderPlugin.js?");
|
|
2157
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XTCLoaderPlugin: () => (/* binding */ XTCLoaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/model/index.js */ \"./src/viewer/scene/model/index.js\");\n/* harmony import */ var _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/metadata/MetaModel.js */ \"./src/viewer/metadata/MetaModel.js\");\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./XTCDefaultDataSource.js */ \"./src/plugins/XTCLoaderPlugin/XTCDefaultDataSource.js\");\n/* harmony import */ var _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/metadata/IFCObjectDefaults.js */ \"./src/viewer/metadata/IFCObjectDefaults.js\");\n/* harmony import */ var _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./parsers/ParserV1.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV1.js\");\n/* harmony import */ var _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./parsers/ParserV2.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV2.js\");\n/* harmony import */ var _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./parsers/ParserV3.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV3.js\");\n/* harmony import */ var _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./parsers/ParserV4.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV4.js\");\n/* harmony import */ var _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./parsers/ParserV5.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV5.js\");\n/* harmony import */ var _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./parsers/ParserV6.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV6.js\");\n/* harmony import */ var _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./parsers/ParserV7.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV7.js\");\n/* harmony import */ var _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./parsers/ParserV8.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV8.js\");\n/* harmony import */ var _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./parsers/ParserV9.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV9.js\");\n/* harmony import */ var _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./parsers/ParserV10.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV10.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\nconst parsers = {};\r\n\r\nparsers[_parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1.version] = _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1;\r\nparsers[_parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2.version] = _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2;\r\nparsers[_parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3.version] = _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3;\r\nparsers[_parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4.version] = _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4;\r\nparsers[_parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5.version] = _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5;\r\nparsers[_parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6.version] = _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6;\r\nparsers[_parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7.version] = _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7;\r\nparsers[_parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8.version] = _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8;\r\nparsers[_parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9.version] = _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9;\r\nparsers[_parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10.version] = _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10;\r\n\r\n/**\r\n * {@link Viewer} plugin that loads models from xeokit's optimized *````.XTC````* format.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter\"><img src=\"http://xeokit.io/img/docs/XTCLoaderPlugin/XTCLoaderPlugin.png\"></a>\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter)]\r\n *\r\n * # Overview\r\n *\r\n * * XTCLoaderPlugin is the most efficient way to load high-detail models into xeokit.\r\n * * An *````.XTC````* file is a single BLOB containing a model, compressed using geometry quantization\r\n * and [pako](https://nodeca.github.io/pako/).\r\n * * Supports double-precision coordinates.\r\n * * Supports compressed textures.\r\n * * Set the position, scale and rotation of each model as you load it.\r\n * * Filter which IFC types get loaded.\r\n * * Configure initial default appearances for IFC types.\r\n * * Set a custom data source for *````.XTC````* and IFC metadata files.\r\n * * Option to load multiple copies of the same model, without object ID clashes.\r\n *\r\n * # Creating *````.XTC````* Files and Metadata\r\n *\r\n * We have several sways to convert your files into XTC. See these tutorials for more info:\r\n *\r\n * * [Converting Models to XTC with convert2xtc](https://www.notion.so/xeokit/Converting-Models-to-XTC-with-convert2xtc-fa567843313f4db8a7d6535e76da9380) - how to convert various file formats (glTF, IFC, CityJSON, LAS/LAZ...) to XTC using our nodejs-based converter.\r\n * * [Converting IFC Models to XTC using 3rd-Party Open Source Tools](https://www.notion.so/xeokit/Converting-IFC-Models-to-XTC-using-3rd-Party-Open-Source-Tools-c373e48bc4094ff5b6e5c5700ff580ee) - how to convert IFC files to XTC using 3rd-party open source CLI tools.\r\n *\r\n * # Scene representation\r\n *\r\n * When loading a model, XTCLoaderPlugin creates an {@link Entity} that represents the model, which\r\n * will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id}\r\n * in {@link Scene#models}. The XTCLoaderPlugin also creates an {@link Entity} for each object within the\r\n * model. Those Entities will have {@link Entity#isObject} set ````true```` and will be registered\r\n * by {@link Entity#id} in {@link Scene#objects}.\r\n *\r\n * # Metadata\r\n *\r\n * Since XTC V8, model metadata is included in the XTC file. If the XTC file has metadata, then loading it creates\r\n * model metadata components within the Viewer, namely a {@link MetaModel} corresponding to the model {@link Entity},\r\n * and a {@link MetaObject} for each object {@link Entity}.\r\n *\r\n * Each {@link MetaObject} has a {@link MetaObject#type}, which indicates the classification of its corresponding\r\n * {@link Entity}. When loading metadata, we can also configure XTCLoaderPlugin with a custom lookup table of initial\r\n * values to set on the properties of each type of {@link Entity}. By default, XTCLoaderPlugin uses its own map of\r\n * default colors and visibilities for IFC element types.\r\n *\r\n * For XTC versions prior to V8, we provided the metadata to XTCLoaderPlugin as an accompanying JSON file to load. We can\r\n * still do that for all XTC versions, and for XTC V8+ it will override any metadata provided within the XTC file.\r\n *\r\n * # Usage\r\n *\r\n * In the example below we'll load the Schependomlaan model from a [.XTC file](https://github.com/xeokit/xeokit-sdk/tree/master/examples/models/xtc/schependomlaan).\r\n *\r\n * This will create a bunch of {@link Entity}s that represents the model and its objects, along with a {@link MetaModel} and {@link MetaObject}s\r\n * that hold their metadata.\r\n *\r\n * Since this model contains IFC types, the XTCLoaderPlugin will set the initial appearance of each object\r\n * {@link Entity} according to its IFC type in {@link XTCLoaderPlugin#objectDefaults}.\r\n *\r\n * Read more about this example in the user guide on [Viewing BIM Models Offline](https://www.notion.so/xeokit/Viewing-an-IFC-Model-with-xeokit-c373e48bc4094ff5b6e5c5700ff580ee).\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_metadata_Schependomlaan)]\r\n *\r\n * ````javascript\r\n * import {Viewer, XTCLoaderPlugin} from \"tctwins-core.es.js\";\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a Viewer,\r\n * // 2. Arrange the camera\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * // 2\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a XTCLoaderPlugin,\r\n * // 2. Load a building model and JSON IFC metadata\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * // 2\r\n * const model = xtcLoader.load({ // Returns an Entity that represents the model\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n *\r\n * //--------------------------------------------------------------------------------------------------------------\r\n * // 1. Find metadata on the third storey\r\n * // 2. Select all the objects in the building's third storey\r\n * // 3. Fit the camera to all the objects on the third storey\r\n * //--------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const metaModel = viewer.metaScene.metaModels[\"myModel\"]; // MetaModel with ID \"myModel\"\r\n * const metaObject\r\n * = viewer.metaScene.metaObjects[\"0u4wgLe6n0ABVaiXyikbkA\"]; // MetaObject with ID \"0u4wgLe6n0ABVaiXyikbkA\"\r\n *\r\n * const name = metaObject.name; // \"01 eerste verdieping\"\r\n * const type = metaObject.type; // \"IfcBuildingStorey\"\r\n * const parent = metaObject.parent; // MetaObject with type \"IfcBuilding\"\r\n * const children = metaObject.children; // Array of child MetaObjects\r\n * const objectId = metaObject.id; // \"0u4wgLe6n0ABVaiXyikbkA\"\r\n * const objectIds = viewer.metaScene.getObjectIDsInSubtree(objectId); // IDs of leaf sub-objects\r\n * const aabb = viewer.scene.getAABB(objectIds); // Axis-aligned boundary of the leaf sub-objects\r\n *\r\n * // 2\r\n * viewer.scene.setObjectsSelected(objectIds, true);\r\n *\r\n * // 3\r\n * viewer.cameraFlight.flyTo(aabb);\r\n * });\r\n *\r\n * // Find the model Entity by ID\r\n * model = viewer.scene.models[\"myModel\"];\r\n *\r\n * // Destroy the model\r\n * model.destroy();\r\n * ````\r\n *\r\n * # Loading XTC files containing textures\r\n *\r\n * XTCLoaderPlugin uses a {@link KTX2TextureTranscoder} to load textures in XTC files (XTC v10+). An XTCLoaderPlugin has its own\r\n * default KTX2TextureTranscoder, configured to load the Basis Codec from the CDN. If we wish, we can override that with our own\r\n * KTX2TextureTranscoder instance that's configured to load the Codec locally.\r\n *\r\n * In the example below, we'll create a {@link Viewer} and add an XTCLoaderPlugin\r\n * configured with a KTX2TextureTranscoder that finds the Codec in our local file system. Then we'll use the\r\n * XTCLoaderPlugin to load an XTC file that contains KTX2 textures, which the plugin will transcode using\r\n * its KTX2TextureTranscoder.\r\n *\r\n * We'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory. If we were happy with loading the\r\n * Codec from our CDN (ie. our app will always have an Internet connection) then we could just leave out the\r\n * KTX2TextureTranscoder altogether, and let the XTCLoaderPlugin use its internal default KTX2TextureTranscoder, which is configured to\r\n * load the Codec from the CDN. We'll stick with loading our own Codec, in case we want to run our app without an Internet connection.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan\"><img src=\"https://xeokit.github.io/xeokit-sdk/assets/images/xtcWithTextures.png\"></a>\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan)]\r\n *\r\n * ````javascript\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const textureTranscoder = new KTX2TextureTranscoder({\r\n * viewer,\r\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to Basis Universal transcoder\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * textureTranscoder // <<------------- Transcodes KTX2 textures in XTC files\r\n * });\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./HousePlan.xtc\" // <<------ XTC file with KTX2 textures\r\n * });\r\n * ````\r\n *\r\n * # Transforming\r\n *\r\n * We have the option to rotate, scale and translate each *````.XTC````* model as we load it.\r\n *\r\n * This lets us load multiple models, or even multiple copies of the same model, and position them apart from each other.\r\n *\r\n * In the example below, we'll scale our model to half its size, rotate it 90 degrees about its local X-axis, then\r\n * translate it 100 units along its X axis.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Duplex_transform)]\r\n *\r\n * ````javascript\r\n * xtcLoader.load({\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * rotation: [90,0,0],\r\n * scale: [0.5, 0.5, 0.5],\r\n * position: [100, 0, 0]\r\n * });\r\n * ````\r\n *\r\n * # Including and excluding IFC types\r\n *\r\n * We can also load only those objects that have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that represent walls.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_includeTypes)]\r\n *\r\n * ````javascript\r\n * const model2 = xtcLoader.load({\r\n * id: \"myModel2\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * includeTypes: [\"IfcWallStandardCase\"]\r\n * });\r\n * ````\r\n *\r\n * We can also load only those objects that **don't** have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that do not represent empty space.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_excludeTypes)]\r\n *\r\n * ````javascript\r\n * const model3 = xtcLoader.load({\r\n * id: \"myModel3\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * excludeTypes: [\"IfcSpace\"]\r\n * });\r\n * ````\r\n *\r\n * # Configuring initial IFC object appearances\r\n *\r\n * We can specify the custom initial appearance of loaded objects according to their IFC types.\r\n *\r\n * This is useful for things like:\r\n *\r\n * * setting the colors to our objects according to their IFC types,\r\n * * automatically hiding ````IfcSpace```` objects, and\r\n * * ensuring that ````IfcWindow```` objects are always transparent.\r\n * <br>\r\n * In the example below, we'll load a model, while configuring ````IfcSpace```` elements to be always initially invisible,\r\n * and ````IfcWindow```` types to be always translucent blue.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_objectDefaults)]\r\n *\r\n * ````javascript\r\n * const myObjectDefaults = {\r\n *\r\n * IfcSpace: {\r\n * visible: false\r\n * },\r\n * IfcWindow: {\r\n * colorize: [0.337255, 0.303922, 0.870588], // Blue\r\n * opacity: 0.3\r\n * },\r\n *\r\n * //...\r\n *\r\n * DEFAULT: {\r\n * colorize: [0.5, 0.5, 0.5]\r\n * }\r\n * };\r\n *\r\n * const model4 = xtcLoader.load({\r\n * id: \"myModel4\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * objectDefaults: myObjectDefaults // Use our custom initial default states for object Entities\r\n * });\r\n * ````\r\n *\r\n * When we don't customize the appearance of IFC types, as just above, then IfcSpace elements tend to obscure other\r\n * elements, which can be confusing.\r\n *\r\n * It's often helpful to make IfcSpaces transparent and unpickable, like this:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * pickable: false,\r\n * opacity: 0.2\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * Alternatively, we could just make IfcSpaces invisible, which also makes them unpickable:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * visible: false\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * # Configuring a custom data source\r\n *\r\n * By default, XTCLoaderPlugin will load *````.XTC````* files and metadata JSON over HTTP.\r\n *\r\n * In the example below, we'll customize the way XTCLoaderPlugin loads the files by configuring it with our own data source\r\n * object. For simplicity, our custom data source example also uses HTTP, using a couple of xeokit utility functions.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_dataSource)]\r\n *\r\n * ````javascript\r\n * import {utils} from \"tctwins-core.es.js\";\r\n *\r\n * class MyDataSource {\r\n *\r\n * constructor() {\r\n * }\r\n *\r\n * // Gets metamodel JSON\r\n * getMetaModel(metaModelSrc, ok, error) {\r\n * console.log(\"MyDataSource#getMetaModel(\" + metaModelSrc + \", ... )\");\r\n * utils.loadJSON(metaModelSrc,\r\n * (json) => {\r\n * ok(json);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n *\r\n * // Gets the contents of the given .XTC file in an arraybuffer\r\n * getXTC(xTCSrc, ok, error) {\r\n * console.log(\"MyDataSource#getXTC(\" + xTCSrc + \", ... )\");\r\n * utils.loadArraybuffer(xTCSrc,\r\n * (arraybuffer) => {\r\n * ok(arraybuffer);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n * }\r\n *\r\n * const xtcLoader2 = new XTCLoaderPlugin(viewer, {\r\n * dataSource: new MyDataSource()\r\n * });\r\n *\r\n * const model5 = xtcLoader2.load({\r\n * id: \"myModel5\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\"\r\n * });\r\n * ````\r\n *\r\n * # Loading multiple copies of a model, without object ID clashes\r\n *\r\n * Sometimes we need to load two or more instances of the same model, without having clashes\r\n * between the IDs of the equivalent objects in the model instances.\r\n *\r\n * As shown in the example below, we do this by setting {@link XTCLoaderPlugin#globalizeObjectIds} ````true```` before we load our models.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#TreeViewPlugin_Containment_MultipleModels)]\r\n *\r\n * ````javascript\r\n * xtcLoader.globalizeObjectIds = true;\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"model1\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n *\r\n * const model2 = xtcLoader.load({\r\n * id: \"model2\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n * ````\r\n *\r\n * For each {@link Entity} loaded by these two calls, {@link Entity#id} and {@link MetaObject#id} will get prefixed by\r\n * the ID of their model, in order to avoid ID clashes between the two models.\r\n *\r\n * An Entity belonging to the first model will get an ID like this:\r\n *\r\n * ````\r\n * myModel1#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * The equivalent Entity in the second model will get an ID like this:\r\n *\r\n * ````\r\n * myModel2#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * Now, to update the visibility of both of those Entities collectively, using {@link Scene#setObjectsVisible}, we can\r\n * supply just the IFC product ID part to that method:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n * ````\r\n *\r\n * The method, along with {@link Scene#setObjectsXRayed}, {@link Scene#setObjectsHighlighted} etc, will internally expand\r\n * the given ID to refer to the instances of that Entity in both models.\r\n *\r\n * We can also, of course, reference each Entity directly, using its globalized ID:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"myModel1#0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n *````\r\n *\r\n * We can also provide an HTTP URL to the XTC file:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/models/xtc/Schependomlaan.xtc\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * # Loading a model from a manifest of XTC files\r\n *\r\n * The `ifc2gltf` tool from Creoox, which converts IFC files into glTF geometry and JSON metadata files, has the option to\r\n * split its output into multiple pairs of glTF and JSON files, accompanied by a JSON manifest that lists the files.\r\n *\r\n * To integrate with that option, the `convert2xtc` tool, which converts glTF geometry and JSON metadata files into XTC files,\r\n * also has the option to batch-convert the glTF+JSON files in the manifest, in one invocation.\r\n *\r\n * When we use this option, convert2xtc will output a bunch of XTC files, along with a JSON manifest file that lists those XTC files.\r\n *\r\n * Working down the pipeline, the XTCLoaderPlugin has the option batch-load all XTC files listed in that manifest\r\n * into a xeokit Viewer in one load operation, combining the XTC files into a single SceneModel and MetaModel.\r\n *\r\n * You can learn more about this conversion and loading process, with splitting, batch converting and batch loading,\r\n * in [this tutorial](https://www.notion.so/xeokit/Importing-Huge-IFC-Models-as-Multiple-XTC-Files-165fc022e94742cf966ee50003572259).\r\n *\r\n * To show how to use XTCLoaderPlugin to load a manifest of XTC files, let's imagine that we have a set of such XTC files. As\r\n * described in the tutorial, they were converted by `ifc2gltf` from an IFC file into a set of glTF+JSON files, that were\r\n * then converted by convert2xtc into this set of XTC files and a manifest, as shown below.\r\n *\r\n * ````bash\r\n * ./\r\n * ├── model_1.xtc\r\n * ├── model_2.xtc\r\n * ├── model_3.xtc\r\n * ├── model_4..xtc\r\n * └── model.xtc.manifest.json\r\n * ````\r\n *\r\n * The `model.xtc.manifest.json` XTC manifest would look something like this:\r\n *\r\n * ````json\r\n * {\r\n * \"inputFile\": null,\r\n * \"converterApplication\": \"convert2xtc\",\r\n * \"converterApplicationVersion\": \"v1.1.9\",\r\n * \"conversionDate\": \"10-08-2023- 02-05-01\",\r\n * \"outputDir\": null,\r\n * \"xtcFiles\": [\r\n * \"model_1.xtc\",\r\n * \"model_2.xtc\",\r\n * \"model_3.xtc\",\r\n * \"model_4.xtc\"\r\n * ]\r\n * }\r\n * ````\r\n *\r\n * Now, to load all those XTC files into a single SceneModel and MetaModel in one operation, we pass a path to the XTC\r\n * manifest to `XTCLoaderPlugin.load`, as shown in the example below:\r\n *\r\n * ````javascript\r\n * import {\r\n * Viewer,\r\n * XTCLoaderPlugin,\r\n * TreeViewPlugin,\r\n * } from \"tctwins-core.es.js\";\r\n *\r\n * constviewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [26.54, 29.29, 36.20,];\r\n * viewer.scene.camera.look = [-23.51, -8.26, -21.65,];\r\n * viewer.scene.camera.up = [-0.2, 0.89, -0.33,];\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n *\r\n * const metaModel = viewer.metaScene.metaModels[sceneModel.id];\r\n *\r\n * // Then when we need to, we can destroy the SceneModel\r\n * // and MetaModel in one shot, like so:\r\n *\r\n * sceneModel.destroy();\r\n * metaModel.destroy();\r\n * ````\r\n *\r\n * The main advantage here, of splitting IFC files like this within the conversion and import pipeline,\r\n * is to reduce the memory pressure on each of the `ifc2gltf`, `convert2xtc` and XTCLoaderPlugin components.\r\n * They work much reliably (and faster) when processing smaller files (eg. 20MB) than when processing large files (eg. 500MB), where\r\n * they have less trouble allocating the system memory they need for conversion and parsing.\r\n *\r\n * We can also provide an HTTP URL to the manifest:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * We can also provide the manifest as parameter object:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * We can also provide the paths to the XTC files as HTTP URLs:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * @class XTCLoaderPlugin\r\n */\r\nclass XTCLoaderPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t *\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {Object} cfg Plugin configuration.\r\n\t * @param {String} [cfg.id=\"XTCLoader\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {Object} [cfg.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {Object} [cfg.dataSource] A custom data source through which the XTCLoaderPlugin can load model and metadata files. Defaults to an instance of {@link XTCDefaultDataSource}, which loads uover HTTP.\r\n\t * @param {String[]} [cfg.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [cfg.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [cfg.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have a lot of geometry reuse, but may also increase the amount of\r\n\t * browser and GPU memory they require. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\r\n\t * to limit the size of the batched geometry arrays that {@link SceneModel} internally creates for batched geometries.\r\n\t * A low value means less heap allocation/de-allocation while loading batched geometries, but more draw calls and\r\n\t * slower rendering speed. A high value means larger heap allocation/de-allocation while loading, but less draw calls\r\n\t * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\r\n\t * @param {KTX2TextureTranscoder} [cfg.textureTranscoder] Transcoder used internally to transcode KTX2\r\n\t * textures within the XTC. Only required when the XTC is version 10 or later, and contains KTX2 textures.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"XTCLoader\", viewer, cfg);\r\n\r\n\t\tthis._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\r\n\r\n\t\tthis.textureTranscoder = cfg.textureTranscoder;\r\n\t\tthis.dataSource = cfg.dataSource;\r\n\t\tthis.objectDefaults = cfg.objectDefaults;\r\n\t\tthis.includeTypes = cfg.includeTypes;\r\n\t\tthis.excludeTypes = cfg.excludeTypes;\r\n\t\tthis.excludeUnclassifiedObjects = cfg.excludeUnclassifiedObjects;\r\n\t\tthis.reuseGeometries = cfg.reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the ````.xtc```` format versions supported by this XTCLoaderPlugin/\r\n\t * @returns {string[]}\r\n\t */\r\n\tget supportedVersions() {\r\n\t\treturn Object.keys(parsers);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tget textureTranscoder() {\r\n\t\treturn this._textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tset textureTranscoder(textureTranscoder) {\r\n\t\tthis._textureTranscoder = textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tget dataSource() {\r\n\t\treturn this._dataSource;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tset dataSource(value) {\r\n\t\tthis._dataSource = value || new _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__.XTCDefaultDataSource();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tget objectDefaults() {\r\n\t\treturn this._objectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tset objectDefaults(value) {\r\n\t\tthis._objectDefaults = value || _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__.IFCObjectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget includeTypes() {\r\n\t\treturn this._includeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset includeTypes(value) {\r\n\t\tthis._includeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget excludeTypes() {\r\n\t\treturn this._excludeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset excludeTypes(value) {\r\n\t\tthis._excludeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget excludeUnclassifiedObjects() {\r\n\t\treturn this._excludeUnclassifiedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset excludeUnclassifiedObjects(value) {\r\n\t\tthis._excludeUnclassifiedObjects = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget globalizeObjectIds() {\r\n\t\treturn this._globalizeObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Set this ````true```` when you need to load multiple instances of the same model, to avoid ID clashes\r\n\t * between the objects in the different instances.\r\n\t *\r\n\t * When we load a model with this set ````true````, then each {@link Entity#id} and {@link MetaObject#id} will be\r\n\t * prefixed by the ID of the model, ie. ````<modelId>#<objectId>````.\r\n\t *\r\n\t * {@link Entity#originalSystemId} and {@link MetaObject#originalSystemId} will always hold the original, un-prefixed, ID values.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * See the main {@link XTCLoaderPlugin} class documentation for usage info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset globalizeObjectIds(value) {\r\n\t\tthis._globalizeObjectIds = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget reuseGeometries() {\r\n\t\treturn this._reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * Geometry reuse saves memory, but can impact Viewer performance when there are many reused geometries. For\r\n\t * this reason, we can set this ````false```` to disable geometry reuse for models loaded by this XTCLoaderPlugin\r\n\t * (which will then \"expand\" the geometry instances into batches instead).\r\n\t *\r\n\t * The result will be be less WebGL draw calls (which are expensive), at the cost of increased memory footprint.\r\n\t *\r\n\t * See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset reuseGeometries(value) {\r\n\t\tthis._reuseGeometries = value !== false;\r\n\t}\r\n\r\n\t/**\r\n\t * Loads an ````.xtc```` model into this XTCLoaderPlugin's {@link Viewer}.\r\n\t *\r\n\t * Since xeokit/xeokit-sdk 1.9.0, XTCLoaderPlugin has supported XTC 8, which bundles the metamodel\r\n\t * data (eg. an IFC element hierarchy) in the XTC file itself. For XTC 8, we therefore no longer need to\r\n\t * load the metamodel data from a separate accompanying JSON file, as we did with previous XTC versions.\r\n\t * However, if we do choose to specify a separate metamodel JSON file to load (eg. for backward compatibility\r\n\t * in data pipelines), then that metamodel will be loaded and the metamodel in the XTC 8 file will be ignored.\r\n\t *\r\n\t * @param {*} params Loading parameters.\r\n\t * @param {String} [params.id] ID to assign to the root {@link Entity#id}, unique among all components in the Viewer's {@link Scene}, generated automatically by default.\r\n\t * @param {String} [params.src] Path or URL to an *````.xtc````* file, as an alternative to the ````xtc```` parameter.\r\n\t * @param {ArrayBuffer} [params.xtc] The *````.xtc````* file data, as an alternative to the ````src```` parameter.\r\n\t * @param {String} [params.metaModelSrc] Path or URL to an optional metadata file, as an alternative to the ````metaModelData```` parameter.\r\n\t * @param {*} [params.metaModelData] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.\r\n\t * @param {String} [params.manifestSrc] Path or URL to a JSON manifest file that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {Object} [params.manifest] A JSON manifest object (as an alternative to a path or URL) that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [params.edges=false] Whether or not xeokit renders the model with edges emphasized.\r\n\t * @param {Number[]} [params.origin=[0,0,0]] The model's World-space double-precision 3D origin. Use this to position the model within xeokit's World coordinate system, using double-precision coordinates.\r\n\t * @param {Number[]} [params.position=[0,0,0]] The model single-precision 3D position, relative to the ````origin```` parameter.\r\n\t * @param {Number[]} [params.scale=[1,1,1]] The model's scale.\r\n\t * @param {Number[]} [params.rotation=[0,0,0]] The model's orientation, given as Euler angles in degrees, for each of the X, Y and Z axis.\r\n\t * @param {Number[]} [params.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] The model's world transform matrix. Overrides the position, scale and rotation parameters. Relative to ````origin````.\r\n\t * @param {Boolean} [params.edges=false] Indicates if the model's edges are initially emphasized.\r\n\t * @param {Boolean} [params.saoEnabled=true] Indicates if Scalable Ambient Obscurance (SAO) is enabled for the model. SAO is configured by the Scene's {@link SAO} component. Only works when {@link SAO#enabled} is also ````true````\r\n\t * @param {Boolean} [params.pbrEnabled=true] Indicates if physically-based rendering (PBR) is enabled for the model. Overrides ````colorTextureEnabled````. Only works when {@link Scene#pbrEnabled} is also ````true````.\r\n\t * @param {Boolean} [params.colorTextureEnabled=true] Indicates if base color texture rendering is enabled for the model. Overridden by ````pbrEnabled````. Only works when {@link Scene#colorTextureEnabled} is also ````true````.\r\n\t * @param {Number} [params.backfaces=false] When we set this ````true````, then we force rendering of backfaces for the model. When\r\n\t * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\r\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.\r\n\t * @param {Boolean} [params.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [params.globalizeObjectIds=false] Indicates whether to globalize each {@link Entity#id} and {@link MetaObject#id}, in case you need to prevent ID clashes with other models. See {@link XTCLoaderPlugin#globalizeObjectIds} for more info.\r\n\t * @param {Boolean} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have excessive geometry reuse, but may also increases the amount of\r\n\t * browser and GPU memory used by the model. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\r\n\t * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\r\n\t * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\r\n\t * primitives. Only works while {@link DTX#enabled} is also ````true````.\r\n\t * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.\r\n\t */\r\n\tload(params = {}) {\r\n\t\tif (params.id && this.viewer.scene.components[params.id]) {\r\n\t\t\tthis.error(\"Component with this ID already exists in viewer: \" + params.id + \" - will autogenerate this ID\");\r\n\t\t\tdelete params.id;\r\n\t\t}\r\n\r\n\t\tif (!params.src && !params.xtc && !params.manifestSrc && !params.manifest) {\r\n\t\t\tthis.error(\"load() param expected: src, xtc, manifestSrc or manifestData\");\r\n\t\t\treturn sceneModel; // Return new empty model\r\n\t\t}\r\n\r\n\t\tconst options = {};\r\n\t\tconst includeTypes = params.includeTypes || this._includeTypes;\r\n\t\tconst excludeTypes = params.excludeTypes || this._excludeTypes;\r\n\t\tconst objectDefaults = params.objectDefaults || this._objectDefaults;\r\n\r\n\t\toptions.reuseGeometries =\r\n\t\t\tparams.reuseGeometries !== null && params.reuseGeometries !== undefined\r\n\t\t\t\t? params.reuseGeometries\r\n\t\t\t\t: this._reuseGeometries !== false;\r\n\r\n\t\tif (includeTypes) {\r\n\t\t\toptions.includeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = includeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.includeTypesMap[includeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (excludeTypes) {\r\n\t\t\toptions.excludeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = excludeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.excludeTypesMap[excludeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (objectDefaults) {\r\n\t\t\toptions.objectDefaults = objectDefaults;\r\n\t\t}\r\n\r\n\t\toptions.excludeUnclassifiedObjects =\r\n\t\t\tparams.excludeUnclassifiedObjects !== undefined\r\n\t\t\t\t? !!params.excludeUnclassifiedObjects\r\n\t\t\t\t: this._excludeUnclassifiedObjects;\r\n\t\toptions.globalizeObjectIds =\r\n\t\t\tparams.globalizeObjectIds !== undefined && params.globalizeObjectIds !== null\r\n\t\t\t\t? !!params.globalizeObjectIds\r\n\t\t\t\t: this._globalizeObjectIds;\r\n\r\n\t\tconst sceneModel = new _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__.SceneModel(\r\n\t\t\tthis.viewer.scene,\r\n\t\t\t_viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.apply(params, {\r\n\t\t\t\tisModel: true,\r\n\t\t\t\ttextureTranscoder: this._textureTranscoder,\r\n\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\r\n\t\t\t\torigin: params.origin,\r\n\t\t\t\tdisableVertexWelding: params.disableVertexWelding || false,\r\n\t\t\t\tdisableIndexRebucketing: params.disableIndexRebucketing || false,\r\n\t\t\t\tdtxEnabled: params.dtxEnabled\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst modelId = sceneModel.id; // In case ID was auto-generated\r\n\r\n\t\tconst metaModel = new _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__.MetaModel({\r\n\t\t\tmetaScene: this.viewer.metaScene,\r\n\t\t\tid: modelId\r\n\t\t});\r\n\r\n\t\tthis.viewer.scene.canvas.spinner.processes++;\r\n\r\n\t\tconst finish = () => {\r\n\t\t\t// this._createDefaultMetaModelIfNeeded(sceneModel, params, options);\r\n\t\t\tsceneModel.finalize();\r\n\t\t\tmetaModel.finalize();\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tsceneModel.once(\"destroyed\", () => {\r\n\t\t\t\tthis.viewer.metaScene.destroyMetaModel(metaModel.id);\r\n\t\t\t});\r\n\t\t\tthis.scheduleTask(() => {\r\n\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tsceneModel.scene.fire(\"modelLoaded\", sceneModel.id); // FIXME: Assumes listeners know order of these two events\r\n\t\t\t\tsceneModel.fire(\"loaded\", true, false); // Don't forget the event, for late subscribers\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\tconst error = (errMsg) => {\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tthis.error(errMsg);\r\n\t\t\tsceneModel.fire(\"error\", errMsg);\r\n\t\t};\r\n\r\n\t\tlet nextId = 0;\r\n\t\tconst manifestCtx = {\r\n\t\t\tgetNextId: () => {\r\n\t\t\t\treturn `${modelId}.${nextId++}`;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t//模型文件\r\n\t\tif (params.metaModelSrc || params.metaModelData) {\r\n\t\t\tif (params.metaModelSrc) {\r\n\t\t\t\tconst metaModelSrc = params.metaModelSrc;\r\n\r\n\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\tmetaModelSrc,\r\n\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tif (params.src) {\r\n\t\t\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\t\t\tfinish();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(errMsg) => {\r\n\t\t\t\t\t\terror(`load(): Failed to load model metadata for model '${modelId} from '${metaModelSrc}' - ${errMsg}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t} else if (params.metaModelData) {\r\n\t\t\t\tmetaModel.loadData(params.metaModelData, {\r\n\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t});\r\n\t\t\t\tif (params.src) {\r\n\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\tfinish();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (params.src) {\r\n\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, metaModel, manifestCtx, finish, error);\r\n\t\t\t} else if (params.xtc) {\r\n\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tfinish();\r\n\t\t\t} else if (params.manifestSrc || params.manifest) {\r\n\t\t\t\tconst baseDir = params.manifestSrc ? getBaseDirectory(params.manifestSrc) : \"\";\r\n\t\t\t\tconst loadJSONs = (metaDataFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= metaDataFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\t\t\t\t`${baseDir}${metaDataFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tconst loadXTCs = (xtcFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= xtcFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getXTC(\r\n\t\t\t\t\t\t\t\t`${baseDir}${xtcFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(arrayBuffer) => {\r\n\t\t\t\t\t\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tif (params.manifest) {\r\n\t\t\t\t\tconst manifestData = params.manifest;\r\n\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._dataSource.getManifest(\r\n\t\t\t\t\t\tparams.manifestSrc,\r\n\t\t\t\t\t\t(manifestData) => {\r\n\t\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\terror\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn sceneModel;\r\n\t}\r\n\r\n\t_loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {\r\n\t\tthis._dataSource.getXTC(\r\n\t\t\tparams.src,\r\n\t\t\t(arrayBuffer) => {\r\n\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tdone();\r\n\t\t\t},\r\n\t\t\terror\r\n\t\t);\r\n\t}\r\n\r\n\t_parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {\r\n\t\tif (sceneModel.destroyed) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst dataView = new DataView(arrayBuffer);\r\n\t\tconst dataArray = new Uint8Array(arrayBuffer);\r\n\t\tconst xtcVersion = dataView.getUint32(0, true);\r\n\t\tconst parser = parsers[xtcVersion];\r\n\t\tif (!parser) {\r\n\t\t\tthis.error(\r\n\t\t\t\t\"Unsupported .XTC file version: \" +\r\n\t\t\t\t\txtcVersion +\r\n\t\t\t\t\t\" - this XTCLoaderPlugin supports versions \" +\r\n\t\t\t\t\tObject.keys(parsers)\r\n\t\t\t);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.log(\"Loading .xtc V\" + xtcVersion);\r\n\t\tconst numElements = dataView.getUint32(4, true);\r\n\t\tconst elements = [];\r\n\t\tlet byteOffset = (numElements + 2) * 4;\r\n\t\tfor (let i = 0; i < numElements; i++) {\r\n\t\t\tconst elementSize = dataView.getUint32((i + 2) * 4, true);\r\n\t\t\telements.push(dataArray.subarray(byteOffset, byteOffset + elementSize));\r\n\t\t\tbyteOffset += elementSize;\r\n\t\t}\r\n\t\tparser.parse(this.viewer, options, elements, sceneModel, metaModel, manifestCtx);\r\n\t}\r\n\r\n\tloadMetadata(metaModel, deflatedMetadata, done) {\r\n\t\tmetaModel._finalized = false;\r\n\r\n\t\ttry {\r\n\t\t\t{\r\n\t\t\t\tthis._workerInflate(\r\n\t\t\t\t\tmetaModel,\r\n\t\t\t\t\tdeflatedMetadata,\r\n\t\t\t\t\t(worker) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaLoaded\", { result: \"success\", metaModel });\r\n\t\t\t\t\t\tif (typeof done === \"function\") done();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(worker, error) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaLoaded\", { result: \"failed\", message: error, metaModel });\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tthis.fire(\"metaloaded\", { result: error, metaModel });\r\n\t\t}\r\n\t}\r\n\r\n\t_workerInflate(metaModel, buffer, done, err) {\r\n\t\tconst plugin = this;\r\n\t\tconst worker = createInlineWorker();\r\n\t\tworker.postMessage({\r\n\t\t\tbuffer\r\n\t\t\t// executionTime: new Date().getTime()\r\n\t\t});\r\n\r\n\t\tworker.onmessage = function (e) {\r\n\t\t\tplugin.fire(\"metaLoading\", () => {\r\n\t\t\t\tmetaModel.loadData(\r\n\t\t\t\t\te.data.metaJson,\r\n\t\t\t\t\t() => {\r\n\t\t\t\t\t\tmetaModel.finalize();\r\n\t\t\t\t\t\tif (typeof done === \"function\") done(worker);\r\n\t\t\t\t\t\telse worker.terminate();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(e) => {\r\n\t\t\t\t\t\tif (typeof err === \"function\") err(worker, e);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t\t};\r\n\t\tworker.onerror = function (e) {\r\n\t\t\tif (typeof err === \"function\") err(worker, e.message);\r\n\t\t\tworker.terminate();\r\n\t\t};\r\n\t}\r\n\r\n\t// _createDefaultMetaModelIfNeeded(sceneModel, params, options) {\r\n\t//\r\n\t// const metaModelId = sceneModel.id;\r\n\t//\r\n\t// if (!this.viewer.metaScene.metaModels[metaModelId]) {\r\n\t//\r\n\t// const metaModelData = {\r\n\t// metaObjects: []\r\n\t// };\r\n\t//\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: metaModelId,\r\n\t// type: \"default\",\r\n\t// name: metaModelId,\r\n\t// parent: null\r\n\t// });\r\n\t//\r\n\t// const entityList = sceneModel.entityList;\r\n\t//\r\n\t// for (let i = 0, len = entityList.length; i < len; i++) {\r\n\t// const entity = entityList[i];\r\n\t// if (entity.isObject) {\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: entity.id,\r\n\t// type: \"default\",\r\n\t// name: entity.id,\r\n\t// parent: metaModelId\r\n\t// });\r\n\t// }\r\n\t// }\r\n\t//\r\n\t// const src = params.src;\r\n\t//\r\n\t// this.viewer.metaScene.createMetaModel(metaModelId, metaModelData, {\r\n\t//\r\n\t// includeTypes: options.includeTypes,\r\n\t// excludeTypes: options.excludeTypes,\r\n\t// globalizeObjectIds: options.globalizeObjectIds,\r\n\t//\r\n\t// getProperties: async (propertiesId) => {\r\n\t// return await this._dataSource.getProperties(src, propertiesId);\r\n\t// }\r\n\t// });\r\n\t//\r\n\t// sceneModel.once(\"destroyed\", () => {\r\n\t// this.viewer.metaScene.destroyMetaModel(metaModelId);\r\n\t// });\r\n\t// }\r\n\t// }\r\n}\r\n\r\nfunction createInlineWorker() {\r\n\tconst workerCode = `\r\n self.importScripts('https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako.min.js');\r\n \r\n function inflateMetadata(deflatedData) {\r\n\t\t\ttry {\r\n\t\t\t\treturn JSON.parse(self.pako.inflate(deflatedData, { to: \"string\" }));\r\n\t\t\t} catch (error) {\r\n\t\t\t\tconsole.error(\"Error inflating metadata:\", error);\r\n\t\t\t\tthrow error;\r\n\t\t\t} \r\n\t\t}\r\n \r\n self.onmessage = function (e) {\r\n console.log(\"start worker:\");\r\n const metaJson = inflateMetadata(e.data.buffer);\r\n\r\n self.postMessage({\r\n metaJson,\r\n time: new Date().getTime()\r\n });\r\n };\r\n `;\r\n\tconst blob = new Blob([workerCode], { type: \"application/javascript\" });\r\n\tconst workerUrl = URL.createObjectURL(blob);\r\n\treturn new Worker(workerUrl);\r\n}\r\nfunction getBaseDirectory(filePath) {\r\n\tconst pathArray = filePath.split(\"/\");\r\n\tpathArray.pop(); // Remove the file name or the last segment of the path\r\n\treturn pathArray.join(\"/\") + \"/\";\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XTCLoaderPlugin/XTCLoaderPlugin.js?");
|
|
2158
2158
|
|
|
2159
2159
|
/***/ }),
|
|
2160
2160
|
|
|
@@ -2364,7 +2364,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2364
2364
|
\******************************/
|
|
2365
2365
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2366
2366
|
|
|
2367
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Viewer: () => (/* binding */ Viewer)\n/* harmony export */ });\n/* harmony import */ var _scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _scene_camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scene/camera/CameraFlightAnimation.js */ \"./src/viewer/scene/camera/CameraFlightAnimation.js\");\n/* harmony import */ var _scene_CameraControl_CameraControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./scene/CameraControl/CameraControl.js */ \"./src/viewer/scene/CameraControl/CameraControl.js\");\n/* harmony import */ var _metadata_MetaScene_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./metadata/MetaScene.js */ \"./src/viewer/metadata/MetaScene.js\");\n/* harmony import */ var _localization_LocaleService_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./localization/LocaleService.js */ \"./src/viewer/localization/LocaleService.js\");\n/* harmony import */ var html2canvas_dist_html2canvas_esm_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! html2canvas/dist/html2canvas.esm.js */ \"./node_modules/html2canvas/dist/html2canvas.esm.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * The 3D Viewer at the heart of the xeokit SDK.\r\n *\r\n * * A Viewer wraps a single {@link Scene}\r\n * * Add {@link Plugin}s to a Viewer to extend its functionality.\r\n * * {@link Viewer#metaScene} holds metadata about models in the\r\n * Viewer's {@link MetaScene}.\r\n * * Use {@link Viewer#cameraFlight} to fly or jump the {@link Scene}'s\r\n * {@link Camera} to target positions, boundaries or {@link Entity}s.\r\n *\r\n * @public\r\n */\r\nclass Viewer {\r\n\t/**\r\n\t * @constructor\r\n\t * @param {Object} cfg Viewer configuration.\r\n\t * @param {String} [cfg.id] Optional ID for this Viewer, defaults to the ID of {@link Viewer#scene}, which xeokit automatically generates.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas for the {@link Viewer#scene} - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas for the {@link Viewer#scene} - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {div} [cfg.viewerElement] Reference of an existing div to contain the canvas\r\n\t * @param {HTMLElement} [cfg.keyboardEventsElement] Optional reference to HTML element on which key events should be handled. Defaults to the HTML Document.\r\n\t * @param {String} [cfg.spinnerElementId] ID of existing HTML element to show the {@link Spinner} - internally creates a default element automatically if this is omitted.\r\n\t * @param {Number} [cfg.passes=1] The number of times the {@link Viewer#scene} renders per frame.\r\n\t * @param {Boolean} [cfg.clearEachPass=false] When doing multiple passes per frame, specifies if to clear the canvas before each pass (true) or just before the first pass (false).\r\n\t * @param {Boolean} [cfg.preserveDrawingBuffer=true] Whether or not to preserve the WebGL drawing buffer. This needs to be ````true```` for {@link Viewer#getSnapshot} to work.\r\n\t * @param {Boolean} [cfg.transparent=true] Whether or not the canvas is transparent.\r\n\t * @param {Boolean} [cfg.premultipliedAlpha=false] Whether or not you want alpha composition with premultiplied alpha. Highlighting and selection works best when this is ````false````.\r\n\t * @param {Boolean} [cfg.gammaInput=true] When true, expects that all textures and colors are premultiplied gamma.\r\n\t * @param {Boolean} [cfg.gammaOutput=false] Whether or not to render with pre-multiplied gama.\r\n\t * @param {Number} [cfg.gammaFactor=2.2] The gamma factor to use when rendering with pre-multiplied gamma.\r\n\t * @param {Number[]} [cfg.backgroundColor=[1,1,1]] Sets the canvas background color to use when ````transparent```` is false.\r\n\t * @param {Boolean} [cfg.backgroundColorFromAmbientLight=true] When ````transparent```` is false, set this ````true````\r\n\t * to derive the canvas background color from {@link AmbientLight#color}, or ````false```` to set the canvas background to ````backgroundColor````.\r\n\t * @param {String} [cfg.units=\"meters\"] The measurement unit type. Accepted values are ````\"meters\"````, ````\"metres\"````, , ````\"centimeters\"````, ````\"centimetres\"````, ````\"millimeters\"````, ````\"millimetres\"````, ````\"yards\"````, ````\"feet\"```` and ````\"inches\"````.\r\n\t * @param {Number} [cfg.scale=1] The number of Real-space units in each World-space coordinate system unit.\r\n\t * @param {Number[]} [cfg.origin=[0,0,0]] The Real-space 3D origin, in current measurement units, at which the World-space coordinate origin ````[0,0,0]```` sits.\r\n\t * @param {Boolean} [cfg.saoEnabled=false] Whether to enable Scalable Ambient Obscurance (SAO) effect. See {@link SAO} for more info.\r\n\t * @param {Boolean} [cfg.antialias=true] Whether to enable anti-aliasing.\r\n\t * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.\r\n\t * @param {Boolean} [cfg.alphaDepthMask=true] Whether writing into the depth buffer is enabled or disabled when rendering transparent objects.\r\n\t * @param {Boolean} [cfg.entityOffsetsEnabled=false] Whether to enable {@link Entity#offset}. For best performance, only set this ````true```` when you need to use {@link Entity#offset}.\r\n\t * @param {Boolean} [cfg.pickSurfacePrecisionEnabled=false] Whether to enable full-precision accuracy when surface picking with {@link Scene#pick}. Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer. The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.\r\n\t * @param {Boolean} [cfg.logarithmicDepthBufferEnabled=false] Whether to enable logarithmic depth buffer. When this is true,\r\n\t * you can set huge values for {@link Perspective#far} and {@link Ortho#far}, to push the far clipping plane back so\r\n\t * that it does not clip huge models.\r\n\t * @param {Boolean} [cfg.colorTextureEnabled=true] Whether to enable base color texture rendering.\r\n\t * @param {Boolean} [cfg.pbrEnabled=false] Whether to enable physically-based rendering.\r\n\t * @param {Boolean} [cfg.edgesEnabled] Whether to show edges\r\n\t * @param {Boolean} [cfg.lodEnabled] Whether to use lod\r\n\t * @param {LocaleService} [cfg.localeService=null] Optional locale-based translation service.\r\n\t * @param {Boolean} [cfg.dtxEnabled=false] Whether to enable data texture-based (DTX) scene representation within the Viewer. When this is true, the Viewer will use data textures to\r\n\t * store geometry on the GPU for triangle meshes that don't have textures. This gives a much lower memory footprint for these types of model element. This mode may not perform well on low-end GPUs that are optimized\r\n\t * to use textures to hold geometry data. Works great on most medium/high-end GPUs found in desktop computers, including the nVIDIA and Intel HD chipsets. Set this false to use the default vertex buffer object (VBO)\r\n\t * mode for storing geometry, which is the standard technique used in most graphics engines, and will work adequately on most low-end GPUs.\r\n\t * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity\r\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\r\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\r\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\r\n\t * your expected usage.\r\n\t */\r\n\tconstructor(cfg) {\r\n\t\tthis.container = cfg.viewerElement;\r\n\t\t/**\r\n\t\t * The Viewer's current language setting.\r\n\t\t * @property language\r\n\t\t * @deprecated\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.language = \"en\";\r\n\r\n\t\t/**\r\n\t\t * The viewer's locale service.\r\n\t\t *\r\n\t\t * This is configured via the Viewer's constructor.\r\n\t\t *\r\n\t\t * By default, this service will be an instance of {@link LocaleService}, which will just return\r\n\t\t * null translations for all given strings and phrases.\r\n\t\t *\r\n\t\t * @property localeService\r\n\t\t * @type {LocaleService}\r\n\t\t * @since 2.0\r\n\t\t */\r\n\t\tthis.localeService = cfg.localeService || new _localization_LocaleService_js__WEBPACK_IMPORTED_MODULE_4__.LocaleService();\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link Scene}.\r\n\t\t * @property scene\r\n\t\t * @type {Scene}\r\n\t\t */\r\n\t\tthis.scene = new _scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_0__.Scene(this, {\r\n\t\t\tcanvasId: cfg.canvasId,\r\n\t\t\tcanvasElement: cfg.canvasElement,\r\n\t\t\tkeyboardEventsElement: cfg.keyboardEventsElement,\r\n\t\t\tcontextAttr: {\r\n\t\t\t\tpreserveDrawingBuffer: cfg.preserveDrawingBuffer !== false,\r\n\t\t\t\tpremultipliedAlpha: !!cfg.premultipliedAlpha,\r\n\t\t\t\tantialias: cfg.antialias !== false\r\n\t\t\t},\r\n\t\t\tspinnerElementId: cfg.spinnerElementId,\r\n\t\t\ttransparent: cfg.transparent !== false,\r\n\t\t\tgammaInput: true,\r\n\t\t\tgammaOutput: false,\r\n\t\t\tbackgroundColor: cfg.backgroundColor,\r\n\t\t\tbackgroundColorFromAmbientLight: cfg.backgroundColorFromAmbientLight,\r\n\t\t\tticksPerRender: 1,\r\n\t\t\tticksPerOcclusionTest: 20,\r\n\t\t\tunits: cfg.units,\r\n\t\t\tscale: cfg.scale,\r\n\t\t\torigin: cfg.origin,\r\n\t\t\tsaoEnabled: cfg.saoEnabled,\r\n\t\t\talphaDepthMask: cfg.alphaDepthMask !== false,\r\n\t\t\tentityOffsetsEnabled: !!cfg.entityOffsetsEnabled,\r\n\t\t\tpickSurfacePrecisionEnabled: !!cfg.pickSurfacePrecisionEnabled,\r\n\t\t\tlogarithmicDepthBufferEnabled: !!cfg.logarithmicDepthBufferEnabled,\r\n\t\t\tpbrEnabled: !!cfg.pbrEnabled,\r\n\t\t\tcolorTextureEnabled: cfg.colorTextureEnabled !== false,\r\n\t\t\tdtxEnabled: !!cfg.dtxEnabled,\r\n\t\t\tedgesEnabled: cfg.edgesEnabled,\r\n\t\t\tnumCachedSectionPlanes: cfg.numCachedSectionPlanes,\r\n\t\t\tlodEnabled: !!cfg.lodEnabled\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * Metadata about the {@link Scene} and the models and objects within it.\r\n\t\t * @property metaScene\r\n\t\t * @type {MetaScene}\r\n\t\t * @readonly\r\n\t\t */\r\n\t\tthis.metaScene = new _metadata_MetaScene_js__WEBPACK_IMPORTED_MODULE_3__.MetaScene(this, this.scene);\r\n\r\n\t\t/**\r\n\t\t * The Viewer's ID.\r\n\t\t * @property id\r\n\t\t *\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = cfg.id || this.scene.id;\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link Camera}. This is also found on {@link Scene#camera}.\r\n\t\t * @property camera\r\n\t\t * @type {Camera}\r\n\t\t */\r\n\t\tthis.camera = this.scene.camera;\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link CameraFlightAnimation}, which\r\n\t\t * is used to fly the {@link Scene}'s {@link Camera} to given targets.\r\n\t\t * @property cameraFlight\r\n\t\t * @type {CameraFlightAnimation}\r\n\t\t */\r\n\t\tthis.cameraFlight = new _scene_camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__.CameraFlightAnimation(this.scene, {\r\n\t\t\tduration: 0.5\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link CameraControl}, which\r\n\t\t * controls the {@link Scene}'s {@link Camera} with mouse, touch and keyboard input.\r\n\t\t * @property cameraControl\r\n\t\t * @type {CameraControl}\r\n\t\t */\r\n\t\tthis.cameraControl = new _scene_CameraControl_CameraControl_js__WEBPACK_IMPORTED_MODULE_2__.CameraControl(this.scene, {\r\n\t\t\t// panToPointer: true,\r\n\t\t\tsnapRadius: cfg.snapRadius,\r\n\t\t\tdoublePickFlyTo: true\r\n\t\t});\r\n\r\n\t\tthis.scene.canvas.on(\"boundary\", (event) => {\r\n\t\t\tthis.cameraControl.updatePivotElement();\r\n\t\t});\r\n\r\n\t\tthis._plugins = [];\r\n\r\n\t\t/**\r\n\t\t * Subscriptions to events sent with {@link fire}.\r\n\t\t * @private\r\n\t\t */\r\n\t\tthis._eventSubs = {};\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the capabilities of this Viewer.\r\n\t *\r\n\t * @returns {{astcSupported: boolean, etc1Supported: boolean, pvrtcSupported: boolean, etc2Supported: boolean, dxtSupported: boolean, bptcSupported: boolean}}\r\n\t */\r\n\tget capabilities() {\r\n\t\treturn this.scene.capabilities;\r\n\t}\r\n\r\n\t/**\r\n\t * Subscribes to an event fired at this Viewer.\r\n\t *\r\n\t * @param {String} event The event\r\n\t * @param {Function} callback Callback fired on the event\r\n\t */\r\n\ton(event, callback) {\r\n\t\tlet subs = this._eventSubs[event];\r\n\t\tif (!subs) {\r\n\t\t\tsubs = [];\r\n\t\t\tthis._eventSubs[event] = subs;\r\n\t\t}\r\n\t\tsubs.push(callback);\r\n\t}\r\n\r\n\t/**\r\n\t * Fires an event at this Viewer.\r\n\t *\r\n\t * @param {String} event Event name\r\n\t * @param {Object} value Event parameters\r\n\t */\r\n\tfire(event, value) {\r\n\t\tconst subs = this._eventSubs[event];\r\n\t\tif (subs) {\r\n\t\t\tfor (let i = 0, len = subs.length; i < len; i++) {\r\n\t\t\t\tsubs[i](value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Unsubscribes from an event fired at this Viewer.\r\n\t * @param event\r\n\t */\r\n\toff(event) {\r\n\t\t// TODO\r\n\t}\r\n\r\n\t/**\r\n\t * Logs a message to the JavaScript developer console, prefixed with the ID of this Viewer.\r\n\t *\r\n\t * @param {String} msg The message\r\n\t */\r\n\tlog(msg) {\r\n\t\tconsole.log(`[xtctwins viewer ${this.id}]: ${msg}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Logs an error message to the JavaScript developer console, prefixed with the ID of this Viewer.\r\n\t *\r\n\t * @param {String} msg The error message\r\n\t */\r\n\terror(msg) {\r\n\t\tconsole.error(`[xtctwins viewer ${this.id}]: ${msg}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Installs a Plugin.\r\n\t *\r\n\t * @private\r\n\t */\r\n\taddPlugin(plugin) {\r\n\t\tthis._plugins.push(plugin);\r\n\t}\r\n\r\n\t/**\r\n\t * Uninstalls a Plugin, clearing content from it first.\r\n\t *\r\n\t * @private\r\n\t */\r\n\tremovePlugin(plugin) {\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\tconst p = this._plugins[i];\r\n\t\t\tif (p === plugin) {\r\n\t\t\t\tif (p.clear) {\r\n\t\t\t\t\tp.clear();\r\n\t\t\t\t}\r\n\t\t\t\tthis._plugins.splice(i, 1);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sends a message to installed Plugins.\r\n\t *\r\n\t * The message can optionally be accompanied by a value.\r\n\t * @private\r\n\t */\r\n\tsendToPlugins(name, value) {\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\tconst p = this._plugins[i];\r\n\t\t\tif (p.send) {\r\n\t\t\t\tp.send(name, value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t * @deprecated\r\n\t */\r\n\tclear() {\r\n\t\tthrow 'Viewer#clear() no longer implemented - use \\'#sendToPlugins(\"clear\") instead';\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t * @deprecated\r\n\t */\r\n\tresetView() {\r\n\t\tthrow \"Viewer#resetView() no longer implemented - use CameraMemento & ObjectsMemento classes instead\";\r\n\t}\r\n\r\n\t/**\r\n\t * Enter snapshot mode.\r\n\t *\r\n\t * Switches rendering to a hidden snapshot canvas.\r\n\t *\r\n\t * Exit snapshot mode using {@link Viewer#endSnapshot}.\r\n\t */\r\n\tbeginSnapshot() {\r\n\t\tif (this._snapshotBegun) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.scene._renderer.beginSnapshot();\r\n\t\tthis._snapshotBegun = true;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets a snapshot of this Viewer's {@link Scene} as a Base64-encoded image.\r\n\t *\r\n\t * #### Usage:\r\n\t *\r\n\t * ````javascript\r\n\t * const imageData = viewer.getSnapshot({\r\n\t * width: 500,\r\n\t * height: 500,\r\n\t * format: \"png\"\r\n\t * });\r\n\t * ````\r\n\t * @param {*} [params] Capture options.\r\n\t * @param {Number} [params.width] Desired width of result in pixels - defaults to width of canvas.\r\n\t * @param {Number} [params.height] Desired height of result in pixels - defaults to height of canvas.\r\n\t * @param {String} [params.format=\"jpeg\"] Desired format; \"jpeg\", \"png\" or \"bmp\".\r\n\t * @param {Boolean} [params.includeGizmos=false] When true, will include gizmos like {@link SectionPlane} in the snapshot.\r\n\t * @returns {String} String-encoded image data URI.\r\n\t */\r\n\tgetSnapshot(params = {}) {\r\n\t\tconst needFinishSnapshot = !this._snapshotBegun;\r\n\t\tconst resize = params.width !== undefined && params.height !== undefined;\r\n\t\tconst canvas = this.scene.canvas.canvas;\r\n\t\tconst saveWidth = canvas.clientWidth;\r\n\t\tconst saveHeight = canvas.clientHeight;\r\n\t\tconst width = params.width ? Math.floor(params.width) : canvas.width;\r\n\t\tconst height = params.height ? Math.floor(params.height) : canvas.height;\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = width;\r\n\t\t\tcanvas.height = height;\r\n\t\t}\r\n\r\n\t\tif (!this._snapshotBegun) {\r\n\t\t\tthis.beginSnapshot({\r\n\t\t\t\twidth,\r\n\t\t\t\theight\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotStarting\"); // Tells plugins to hide things that shouldn't be in snapshot\r\n\t\t}\r\n\r\n\t\tconst captured = {};\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\tconst plugin = this._plugins[i];\r\n\t\t\tif (plugin.getContainerElement) {\r\n\t\t\t\tconst container = plugin.getContainerElement();\r\n\t\t\t\tif (container !== document.body) {\r\n\t\t\t\t\tif (!captured[container.id]) {\r\n\t\t\t\t\t\tcaptured[container.id] = true;\r\n\t\t\t\t\t\t(0,html2canvas_dist_html2canvas_esm_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(container).then(function (canvas) {\r\n\t\t\t\t\t\t\tdocument.body.appendChild(canvas);\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.scene._renderer.renderSnapshot();\r\n\r\n\t\tconst imageDataURI = this.scene._renderer.readSnapshot(params);\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = saveWidth;\r\n\t\t\tcanvas.height = saveHeight;\r\n\r\n\t\t\tthis.scene.glRedraw();\r\n\t\t}\r\n\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotFinished\");\r\n\t\t}\r\n\r\n\t\tif (needFinishSnapshot) {\r\n\t\t\tthis.endSnapshot();\r\n\t\t}\r\n\r\n\t\treturn imageDataURI;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets a snapshot of this Viewer's {@link Scene} as a Base64-encoded image which includes\r\n\t * the HTML elements created by various plugins.\r\n\t *\r\n\t * The snapshot image is composed of an image of the viewer canvas, overlaid with an image\r\n\t * of the HTML container element belonging to each installed Viewer plugin. Each container\r\n\t * element is only rendered once, so it's OK for plugins to share the same container.\r\n\t *\r\n\t * #### Usage:\r\n\t *\r\n\t * ````javascript\r\n\t * viewer.getSnapshotWithPlugins({\r\n\t * width: 500,\r\n\t * height: 500,\r\n\t * format: \"png\"\r\n\t * }).then((imageData)=>{\r\n\t *\r\n\t * });\r\n\t * ````\r\n\t * @param {*} [params] Capture options.\r\n\t * @param {Number} [params.width] Desired width of result in pixels - defaults to width of canvas.\r\n\t * @param {Number} [params.height] Desired height of result in pixels - defaults to height of canvas.\r\n\t * @param {String} [params.format=\"jpeg\"] Desired format; \"jpeg\", \"png\" or \"bmp\".\r\n\t * @param {Boolean} [params.includeGizmos=false] When true, will include gizmos like {@link SectionPlane} in the snapshot.\r\n\t * @returns {Promise} Promise which returns a string-encoded image data URI.\r\n\t */\r\n\tasync getSnapshotWithPlugins(params = {}) {\r\n\t\t// We use gl.readPixels to get the WebGL canvas snapshot in a new\r\n\t\t// HTMLCanvas element, scaled to the target snapshot size, then\r\n\t\t// use html2canvas to render each plugin's container element into\r\n\t\t// that HTMLCanvas. Finally, we save the HTMLCanvas to a bitmap.\r\n\r\n\t\t// We don't rely on html2canvas to up-scale our WebGL canvas\r\n\t\t// when we want a higher-resolution snapshot, which would cause\r\n\t\t// blurring. Instead, we manage the scale and redraw of the WebGL\r\n\t\t// canvas ourselves, in order to allow the Viewer to render the\r\n\t\t// right amount of pixels, for a sharper image.\r\n\r\n\t\tconst needFinishSnapshot = !this._snapshotBegun;\r\n\t\tconst resize = params.width !== undefined && params.height !== undefined;\r\n\t\tconst canvas = this.scene.canvas.canvas;\r\n\t\tconst saveWidth = canvas.clientWidth;\r\n\t\tconst saveHeight = canvas.clientHeight;\r\n\t\tconst snapshotWidth = params.width ? Math.floor(params.width) : canvas.width;\r\n\t\tconst snapshotHeight = params.height ? Math.floor(params.height) : canvas.height;\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = snapshotWidth;\r\n\t\t\tcanvas.height = snapshotHeight;\r\n\t\t}\r\n\r\n\t\tif (!this._snapshotBegun) {\r\n\t\t\tthis.beginSnapshot();\r\n\t\t}\r\n\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotStarting\"); // Tells plugins to hide things that shouldn't be in snapshot\r\n\t\t}\r\n\r\n\t\tthis.scene._renderer.renderSnapshot();\r\n\r\n\t\tconst snapshotCanvas = this.scene._renderer.readSnapshotAsCanvas();\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = saveWidth;\r\n\t\t\tcanvas.height = saveHeight;\r\n\t\t\tthis.scene.glRedraw();\r\n\t\t}\r\n\r\n\t\tconst pluginToCapture = {};\r\n\t\tconst pluginContainerElements = [];\r\n\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\t// Find plugin container elements\r\n\t\t\tconst plugin = this._plugins[i];\r\n\t\t\tif (plugin.getContainerElement) {\r\n\t\t\t\tconst containerElement = plugin.getContainerElement();\r\n\t\t\t\tif (containerElement !== document.body) {\r\n\t\t\t\t\tif (!pluginToCapture[containerElement.id]) {\r\n\t\t\t\t\t\tpluginToCapture[containerElement.id] = true;\r\n\t\t\t\t\t\tpluginContainerElements.push(containerElement);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (let i = 0, len = pluginContainerElements.length; i < len; i++) {\r\n\t\t\tconst containerElement = pluginContainerElements[i];\r\n\t\t\tawait (0,html2canvas_dist_html2canvas_esm_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(containerElement, {\r\n\t\t\t\tcanvas: snapshotCanvas,\r\n\t\t\t\tbackgroundColor: null,\r\n\t\t\t\tscale: snapshotCanvas.width / containerElement.clientWidth\r\n\t\t\t});\r\n\t\t}\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotFinished\");\r\n\t\t}\r\n\t\tif (needFinishSnapshot) {\r\n\t\t\tthis.endSnapshot();\r\n\t\t}\r\n\t\tlet format = params.format || \"png\";\r\n\t\tif (format !== \"jpeg\" && format !== \"png\" && format !== \"bmp\") {\r\n\t\t\tconsole.error(\r\n\t\t\t\t\"Unsupported image format: '\" + format + \"' - supported types are 'jpeg', 'bmp' and 'png' - defaulting to 'png'\"\r\n\t\t\t);\r\n\t\t\tformat = \"png\";\r\n\t\t}\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotFinished\");\r\n\t\t}\r\n\t\tif (needFinishSnapshot) {\r\n\t\t\tthis.endSnapshot();\r\n\t\t}\r\n\t\treturn snapshotCanvas.toDataURL(`image/${format}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Exits snapshot mode.\r\n\t *\r\n\t * Switches rendering back to the main canvas.\r\n\t *\r\n\t */\r\n\tendSnapshot() {\r\n\t\tif (!this._snapshotBegun) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.scene._renderer.endSnapshot();\r\n\t\tthis.scene._renderer.render({ force: true });\r\n\t\tthis._snapshotBegun = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this Viewer.\r\n\t */\r\n\tdestroy(callback) {\r\n\t\tconst plugins = this._plugins.slice(); // Array will modify as we delete plugins\r\n\t\tif (plugins.length > 0) {\r\n\t\t\tfor (let i = 0, len = plugins.length; i < len; i++) {\r\n\t\t\t\tconst plugin = plugins[i];\r\n\t\t\t\tplugin.destroy();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.cameraControl.destroy();\r\n\t\tthis.scene.destroy(callback);\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/Viewer.js?");
|
|
2367
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Viewer: () => (/* binding */ Viewer)\n/* harmony export */ });\n/* harmony import */ var _scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _scene_camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scene/camera/CameraFlightAnimation.js */ \"./src/viewer/scene/camera/CameraFlightAnimation.js\");\n/* harmony import */ var _scene_CameraControl_CameraControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./scene/CameraControl/CameraControl.js */ \"./src/viewer/scene/CameraControl/CameraControl.js\");\n/* harmony import */ var _metadata_MetaScene_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./metadata/MetaScene.js */ \"./src/viewer/metadata/MetaScene.js\");\n/* harmony import */ var _localization_LocaleService_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./localization/LocaleService.js */ \"./src/viewer/localization/LocaleService.js\");\n/* harmony import */ var html2canvas_dist_html2canvas_esm_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! html2canvas/dist/html2canvas.esm.js */ \"./node_modules/html2canvas/dist/html2canvas.esm.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * The 3D Viewer at the heart of the xeokit SDK.\r\n *\r\n * * A Viewer wraps a single {@link Scene}\r\n * * Add {@link Plugin}s to a Viewer to extend its functionality.\r\n * * {@link Viewer#metaScene} holds metadata about models in the\r\n * Viewer's {@link MetaScene}.\r\n * * Use {@link Viewer#cameraFlight} to fly or jump the {@link Scene}'s\r\n * {@link Camera} to target positions, boundaries or {@link Entity}s.\r\n *\r\n * @public\r\n */\r\nclass Viewer {\r\n\t/**\r\n\t * @constructor\r\n\t * @param {Object} cfg Viewer configuration.\r\n\t * @param {String} [cfg.id] Optional ID for this Viewer, defaults to the ID of {@link Viewer#scene}, which xeokit automatically generates.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas for the {@link Viewer#scene} - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas for the {@link Viewer#scene} - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {div} [cfg.viewerElement] Reference of an existing div to contain the canvas\r\n\t * @param {HTMLElement} [cfg.keyboardEventsElement] Optional reference to HTML element on which key events should be handled. Defaults to the HTML Document.\r\n\t * @param {String} [cfg.spinnerElementId] ID of existing HTML element to show the {@link Spinner} - internally creates a default element automatically if this is omitted.\r\n\t * @param {Number} [cfg.passes=1] The number of times the {@link Viewer#scene} renders per frame.\r\n\t * @param {Boolean} [cfg.clearEachPass=false] When doing multiple passes per frame, specifies if to clear the canvas before each pass (true) or just before the first pass (false).\r\n\t * @param {Boolean} [cfg.preserveDrawingBuffer=true] Whether or not to preserve the WebGL drawing buffer. This needs to be ````true```` for {@link Viewer#getSnapshot} to work.\r\n\t * @param {Boolean} [cfg.transparent=true] Whether or not the canvas is transparent.\r\n\t * @param {Boolean} [cfg.premultipliedAlpha=false] Whether or not you want alpha composition with premultiplied alpha. Highlighting and selection works best when this is ````false````.\r\n\t * @param {Boolean} [cfg.gammaInput=true] When true, expects that all textures and colors are premultiplied gamma.\r\n\t * @param {Boolean} [cfg.gammaOutput=false] Whether or not to render with pre-multiplied gama.\r\n\t * @param {Number} [cfg.gammaFactor=2.2] The gamma factor to use when rendering with pre-multiplied gamma.\r\n\t * @param {Number[]} [cfg.backgroundColor=[1,1,1]] Sets the canvas background color to use when ````transparent```` is false.\r\n\t * @param {Boolean} [cfg.backgroundColorFromAmbientLight=true] When ````transparent```` is false, set this ````true````\r\n\t * to derive the canvas background color from {@link AmbientLight#color}, or ````false```` to set the canvas background to ````backgroundColor````.\r\n\t * @param {String} [cfg.units=\"meters\"] The measurement unit type. Accepted values are ````\"meters\"````, ````\"metres\"````, , ````\"centimeters\"````, ````\"centimetres\"````, ````\"millimeters\"````, ````\"millimetres\"````, ````\"yards\"````, ````\"feet\"```` and ````\"inches\"````.\r\n\t * @param {Number} [cfg.scale=1] The number of Real-space units in each World-space coordinate system unit.\r\n\t * @param {Number[]} [cfg.origin=[0,0,0]] The Real-space 3D origin, in current measurement units, at which the World-space coordinate origin ````[0,0,0]```` sits.\r\n\t * @param {Boolean} [cfg.saoEnabled=false] Whether to enable Scalable Ambient Obscurance (SAO) effect. See {@link SAO} for more info.\r\n\t * @param {Boolean} [cfg.antialias=true] Whether to enable anti-aliasing.\r\n\t * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.\r\n\t * @param {Boolean} [cfg.alphaDepthMask=true] Whether writing into the depth buffer is enabled or disabled when rendering transparent objects.\r\n\t * @param {Boolean} [cfg.entityOffsetsEnabled=false] Whether to enable {@link Entity#offset}. For best performance, only set this ````true```` when you need to use {@link Entity#offset}.\r\n\t * @param {Boolean} [cfg.pickSurfacePrecisionEnabled=false] Whether to enable full-precision accuracy when surface picking with {@link Scene#pick}. Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer. The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.\r\n\t * @param {Boolean} [cfg.logarithmicDepthBufferEnabled=false] Whether to enable logarithmic depth buffer. When this is true,\r\n\t * you can set huge values for {@link Perspective#far} and {@link Ortho#far}, to push the far clipping plane back so\r\n\t * that it does not clip huge models.\r\n\t * @param {Boolean} [cfg.colorTextureEnabled=true] Whether to enable base color texture rendering.\r\n\t * @param {Boolean} [cfg.pbrEnabled=false] Whether to enable physically-based rendering.\r\n\t * @param {Boolean} [cfg.edgesEnabled] Whether to show edges\r\n\t * @param {Boolean} [cfg.lodEnabled] Whether to use lod\r\n\t * @param {LocaleService} [cfg.localeService=null] Optional locale-based translation service.\r\n\t * @param {Boolean} [cfg.dtxEnabled=false] Whether to enable data texture-based (DTX) scene representation within the Viewer. When this is true, the Viewer will use data textures to\r\n\t * store geometry on the GPU for triangle meshes that don't have textures. This gives a much lower memory footprint for these types of model element. This mode may not perform well on low-end GPUs that are optimized\r\n\t * to use textures to hold geometry data. Works great on most medium/high-end GPUs found in desktop computers, including the nVIDIA and Intel HD chipsets. Set this false to use the default vertex buffer object (VBO)\r\n\t * mode for storing geometry, which is the standard technique used in most graphics engines, and will work adequately on most low-end GPUs.\r\n\t * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity\r\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\r\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\r\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\r\n\t * your expected usage.\r\n\t */\r\n\tconstructor(cfg) {\r\n\t\tthis.container = cfg.viewerElement;\r\n\t\t/**\r\n\t\t * The Viewer's current language setting.\r\n\t\t * @property language\r\n\t\t * @deprecated\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.language = \"en\";\r\n\r\n\t\t/**\r\n\t\t * The viewer's locale service.\r\n\t\t *\r\n\t\t * This is configured via the Viewer's constructor.\r\n\t\t *\r\n\t\t * By default, this service will be an instance of {@link LocaleService}, which will just return\r\n\t\t * null translations for all given strings and phrases.\r\n\t\t *\r\n\t\t * @property localeService\r\n\t\t * @type {LocaleService}\r\n\t\t * @since 2.0\r\n\t\t */\r\n\t\tthis.localeService = cfg.localeService || new _localization_LocaleService_js__WEBPACK_IMPORTED_MODULE_4__.LocaleService();\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link Scene}.\r\n\t\t * @property scene\r\n\t\t * @type {Scene}\r\n\t\t */\r\n\t\tthis.scene = new _scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_0__.Scene(this, {\r\n\t\t\tcanvasId: cfg.canvasId,\r\n\t\t\tcanvasElement: cfg.canvasElement,\r\n\t\t\tkeyboardEventsElement: cfg.keyboardEventsElement,\r\n\t\t\tcontextAttr: {\r\n\t\t\t\tpreserveDrawingBuffer: cfg.preserveDrawingBuffer !== false,\r\n\t\t\t\tpremultipliedAlpha: !!cfg.premultipliedAlpha,\r\n\t\t\t\tantialias: cfg.antialias !== false\r\n\t\t\t},\r\n\t\t\tspinnerElementId: cfg.spinnerElementId,\r\n\t\t\ttransparent: cfg.transparent !== false,\r\n\t\t\tgammaInput: true,\r\n\t\t\tgammaOutput: false,\r\n\t\t\tbackgroundColor: cfg.backgroundColor,\r\n\t\t\tbackgroundColorFromAmbientLight: cfg.backgroundColorFromAmbientLight,\r\n\t\t\tticksPerRender: 1,\r\n\t\t\tticksPerOcclusionTest: 20,\r\n\t\t\tunits: cfg.units,\r\n\t\t\tscale: cfg.scale,\r\n\t\t\torigin: cfg.origin,\r\n\t\t\tsaoEnabled: cfg.saoEnabled,\r\n\t\t\talphaDepthMask: cfg.alphaDepthMask !== false,\r\n\t\t\tentityOffsetsEnabled: !!cfg.entityOffsetsEnabled,\r\n\t\t\tpickSurfacePrecisionEnabled: !!cfg.pickSurfacePrecisionEnabled,\r\n\t\t\tlogarithmicDepthBufferEnabled: !!cfg.logarithmicDepthBufferEnabled,\r\n\t\t\tpbrEnabled: !!cfg.pbrEnabled,\r\n\t\t\tcolorTextureEnabled: cfg.colorTextureEnabled !== false,\r\n\t\t\tdtxEnabled: !!cfg.dtxEnabled,\r\n\t\t\tedgesEnabled: cfg.edgesEnabled,\r\n\t\t\tnumCachedSectionPlanes: cfg.numCachedSectionPlanes,\r\n\t\t\tlodEnabled: !!cfg.lodEnabled,\r\n\t\t\tresolutionScale: cfg.resolutionScale\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * Metadata about the {@link Scene} and the models and objects within it.\r\n\t\t * @property metaScene\r\n\t\t * @type {MetaScene}\r\n\t\t * @readonly\r\n\t\t */\r\n\t\tthis.metaScene = new _metadata_MetaScene_js__WEBPACK_IMPORTED_MODULE_3__.MetaScene(this, this.scene);\r\n\r\n\t\t/**\r\n\t\t * The Viewer's ID.\r\n\t\t * @property id\r\n\t\t *\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = cfg.id || this.scene.id;\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link Camera}. This is also found on {@link Scene#camera}.\r\n\t\t * @property camera\r\n\t\t * @type {Camera}\r\n\t\t */\r\n\t\tthis.camera = this.scene.camera;\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link CameraFlightAnimation}, which\r\n\t\t * is used to fly the {@link Scene}'s {@link Camera} to given targets.\r\n\t\t * @property cameraFlight\r\n\t\t * @type {CameraFlightAnimation}\r\n\t\t */\r\n\t\tthis.cameraFlight = new _scene_camera_CameraFlightAnimation_js__WEBPACK_IMPORTED_MODULE_1__.CameraFlightAnimation(this.scene, {\r\n\t\t\tduration: 0.5\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * The Viewer's {@link CameraControl}, which\r\n\t\t * controls the {@link Scene}'s {@link Camera} with mouse, touch and keyboard input.\r\n\t\t * @property cameraControl\r\n\t\t * @type {CameraControl}\r\n\t\t */\r\n\t\tthis.cameraControl = new _scene_CameraControl_CameraControl_js__WEBPACK_IMPORTED_MODULE_2__.CameraControl(this.scene, {\r\n\t\t\t// panToPointer: true,\r\n\t\t\tsnapRadius: cfg.snapRadius,\r\n\t\t\tdoublePickFlyTo: true\r\n\t\t});\r\n\r\n\t\tthis.scene.canvas.on(\"boundary\", (event) => {\r\n\t\t\tthis.cameraControl.updatePivotElement();\r\n\t\t});\r\n\r\n\t\tthis._plugins = [];\r\n\r\n\t\t/**\r\n\t\t * Subscriptions to events sent with {@link fire}.\r\n\t\t * @private\r\n\t\t */\r\n\t\tthis._eventSubs = {};\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the capabilities of this Viewer.\r\n\t *\r\n\t * @returns {{astcSupported: boolean, etc1Supported: boolean, pvrtcSupported: boolean, etc2Supported: boolean, dxtSupported: boolean, bptcSupported: boolean}}\r\n\t */\r\n\tget capabilities() {\r\n\t\treturn this.scene.capabilities;\r\n\t}\r\n\r\n\t/**\r\n\t * Subscribes to an event fired at this Viewer.\r\n\t *\r\n\t * @param {String} event The event\r\n\t * @param {Function} callback Callback fired on the event\r\n\t */\r\n\ton(event, callback) {\r\n\t\tlet subs = this._eventSubs[event];\r\n\t\tif (!subs) {\r\n\t\t\tsubs = [];\r\n\t\t\tthis._eventSubs[event] = subs;\r\n\t\t}\r\n\t\tsubs.push(callback);\r\n\t}\r\n\r\n\t/**\r\n\t * Fires an event at this Viewer.\r\n\t *\r\n\t * @param {String} event Event name\r\n\t * @param {Object} value Event parameters\r\n\t */\r\n\tfire(event, value) {\r\n\t\tconst subs = this._eventSubs[event];\r\n\t\tif (subs) {\r\n\t\t\tfor (let i = 0, len = subs.length; i < len; i++) {\r\n\t\t\t\tsubs[i](value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Unsubscribes from an event fired at this Viewer.\r\n\t * @param event\r\n\t */\r\n\toff(event) {\r\n\t\t// TODO\r\n\t}\r\n\r\n\t/**\r\n\t * Logs a message to the JavaScript developer console, prefixed with the ID of this Viewer.\r\n\t *\r\n\t * @param {String} msg The message\r\n\t */\r\n\tlog(msg) {\r\n\t\tconsole.log(`[xtctwins viewer ${this.id}]: ${msg}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Logs an error message to the JavaScript developer console, prefixed with the ID of this Viewer.\r\n\t *\r\n\t * @param {String} msg The error message\r\n\t */\r\n\terror(msg) {\r\n\t\tconsole.error(`[xtctwins viewer ${this.id}]: ${msg}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Installs a Plugin.\r\n\t *\r\n\t * @private\r\n\t */\r\n\taddPlugin(plugin) {\r\n\t\tthis._plugins.push(plugin);\r\n\t}\r\n\r\n\t/**\r\n\t * Uninstalls a Plugin, clearing content from it first.\r\n\t *\r\n\t * @private\r\n\t */\r\n\tremovePlugin(plugin) {\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\tconst p = this._plugins[i];\r\n\t\t\tif (p === plugin) {\r\n\t\t\t\tif (p.clear) {\r\n\t\t\t\t\tp.clear();\r\n\t\t\t\t}\r\n\t\t\t\tthis._plugins.splice(i, 1);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sends a message to installed Plugins.\r\n\t *\r\n\t * The message can optionally be accompanied by a value.\r\n\t * @private\r\n\t */\r\n\tsendToPlugins(name, value) {\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\tconst p = this._plugins[i];\r\n\t\t\tif (p.send) {\r\n\t\t\t\tp.send(name, value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t * @deprecated\r\n\t */\r\n\tclear() {\r\n\t\tthrow 'Viewer#clear() no longer implemented - use \\'#sendToPlugins(\"clear\") instead';\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t * @deprecated\r\n\t */\r\n\tresetView() {\r\n\t\tthrow \"Viewer#resetView() no longer implemented - use CameraMemento & ObjectsMemento classes instead\";\r\n\t}\r\n\r\n\t/**\r\n\t * Enter snapshot mode.\r\n\t *\r\n\t * Switches rendering to a hidden snapshot canvas.\r\n\t *\r\n\t * Exit snapshot mode using {@link Viewer#endSnapshot}.\r\n\t */\r\n\tbeginSnapshot() {\r\n\t\tif (this._snapshotBegun) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.scene._renderer.beginSnapshot();\r\n\t\tthis._snapshotBegun = true;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets a snapshot of this Viewer's {@link Scene} as a Base64-encoded image.\r\n\t *\r\n\t * #### Usage:\r\n\t *\r\n\t * ````javascript\r\n\t * const imageData = viewer.getSnapshot({\r\n\t * width: 500,\r\n\t * height: 500,\r\n\t * format: \"png\"\r\n\t * });\r\n\t * ````\r\n\t * @param {*} [params] Capture options.\r\n\t * @param {Number} [params.width] Desired width of result in pixels - defaults to width of canvas.\r\n\t * @param {Number} [params.height] Desired height of result in pixels - defaults to height of canvas.\r\n\t * @param {String} [params.format=\"jpeg\"] Desired format; \"jpeg\", \"png\" or \"bmp\".\r\n\t * @param {Boolean} [params.includeGizmos=false] When true, will include gizmos like {@link SectionPlane} in the snapshot.\r\n\t * @returns {String} String-encoded image data URI.\r\n\t */\r\n\tgetSnapshot(params = {}) {\r\n\t\tconst needFinishSnapshot = !this._snapshotBegun;\r\n\t\tconst resize = params.width !== undefined && params.height !== undefined;\r\n\t\tconst canvas = this.scene.canvas.canvas;\r\n\t\tconst saveWidth = canvas.clientWidth;\r\n\t\tconst saveHeight = canvas.clientHeight;\r\n\t\tconst width = params.width ? Math.floor(params.width) : canvas.width;\r\n\t\tconst height = params.height ? Math.floor(params.height) : canvas.height;\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = width;\r\n\t\t\tcanvas.height = height;\r\n\t\t}\r\n\r\n\t\tif (!this._snapshotBegun) {\r\n\t\t\tthis.beginSnapshot({\r\n\t\t\t\twidth,\r\n\t\t\t\theight\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotStarting\"); // Tells plugins to hide things that shouldn't be in snapshot\r\n\t\t}\r\n\r\n\t\tconst captured = {};\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\tconst plugin = this._plugins[i];\r\n\t\t\tif (plugin.getContainerElement) {\r\n\t\t\t\tconst container = plugin.getContainerElement();\r\n\t\t\t\tif (container !== document.body) {\r\n\t\t\t\t\tif (!captured[container.id]) {\r\n\t\t\t\t\t\tcaptured[container.id] = true;\r\n\t\t\t\t\t\t(0,html2canvas_dist_html2canvas_esm_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(container).then(function (canvas) {\r\n\t\t\t\t\t\t\tdocument.body.appendChild(canvas);\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.scene._renderer.renderSnapshot();\r\n\r\n\t\tconst imageDataURI = this.scene._renderer.readSnapshot(params);\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = saveWidth;\r\n\t\t\tcanvas.height = saveHeight;\r\n\r\n\t\t\tthis.scene.glRedraw();\r\n\t\t}\r\n\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotFinished\");\r\n\t\t}\r\n\r\n\t\tif (needFinishSnapshot) {\r\n\t\t\tthis.endSnapshot();\r\n\t\t}\r\n\r\n\t\treturn imageDataURI;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets a snapshot of this Viewer's {@link Scene} as a Base64-encoded image which includes\r\n\t * the HTML elements created by various plugins.\r\n\t *\r\n\t * The snapshot image is composed of an image of the viewer canvas, overlaid with an image\r\n\t * of the HTML container element belonging to each installed Viewer plugin. Each container\r\n\t * element is only rendered once, so it's OK for plugins to share the same container.\r\n\t *\r\n\t * #### Usage:\r\n\t *\r\n\t * ````javascript\r\n\t * viewer.getSnapshotWithPlugins({\r\n\t * width: 500,\r\n\t * height: 500,\r\n\t * format: \"png\"\r\n\t * }).then((imageData)=>{\r\n\t *\r\n\t * });\r\n\t * ````\r\n\t * @param {*} [params] Capture options.\r\n\t * @param {Number} [params.width] Desired width of result in pixels - defaults to width of canvas.\r\n\t * @param {Number} [params.height] Desired height of result in pixels - defaults to height of canvas.\r\n\t * @param {String} [params.format=\"jpeg\"] Desired format; \"jpeg\", \"png\" or \"bmp\".\r\n\t * @param {Boolean} [params.includeGizmos=false] When true, will include gizmos like {@link SectionPlane} in the snapshot.\r\n\t * @returns {Promise} Promise which returns a string-encoded image data URI.\r\n\t */\r\n\tasync getSnapshotWithPlugins(params = {}) {\r\n\t\t// We use gl.readPixels to get the WebGL canvas snapshot in a new\r\n\t\t// HTMLCanvas element, scaled to the target snapshot size, then\r\n\t\t// use html2canvas to render each plugin's container element into\r\n\t\t// that HTMLCanvas. Finally, we save the HTMLCanvas to a bitmap.\r\n\r\n\t\t// We don't rely on html2canvas to up-scale our WebGL canvas\r\n\t\t// when we want a higher-resolution snapshot, which would cause\r\n\t\t// blurring. Instead, we manage the scale and redraw of the WebGL\r\n\t\t// canvas ourselves, in order to allow the Viewer to render the\r\n\t\t// right amount of pixels, for a sharper image.\r\n\r\n\t\tconst needFinishSnapshot = !this._snapshotBegun;\r\n\t\tconst resize = params.width !== undefined && params.height !== undefined;\r\n\t\tconst canvas = this.scene.canvas.canvas;\r\n\t\tconst saveWidth = canvas.clientWidth;\r\n\t\tconst saveHeight = canvas.clientHeight;\r\n\t\tconst snapshotWidth = params.width ? Math.floor(params.width) : canvas.width;\r\n\t\tconst snapshotHeight = params.height ? Math.floor(params.height) : canvas.height;\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = snapshotWidth;\r\n\t\t\tcanvas.height = snapshotHeight;\r\n\t\t}\r\n\r\n\t\tif (!this._snapshotBegun) {\r\n\t\t\tthis.beginSnapshot();\r\n\t\t}\r\n\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotStarting\"); // Tells plugins to hide things that shouldn't be in snapshot\r\n\t\t}\r\n\r\n\t\tthis.scene._renderer.renderSnapshot();\r\n\r\n\t\tconst snapshotCanvas = this.scene._renderer.readSnapshotAsCanvas();\r\n\r\n\t\tif (resize) {\r\n\t\t\tcanvas.width = saveWidth;\r\n\t\t\tcanvas.height = saveHeight;\r\n\t\t\tthis.scene.glRedraw();\r\n\t\t}\r\n\r\n\t\tconst pluginToCapture = {};\r\n\t\tconst pluginContainerElements = [];\r\n\r\n\t\tfor (let i = 0, len = this._plugins.length; i < len; i++) {\r\n\t\t\t// Find plugin container elements\r\n\t\t\tconst plugin = this._plugins[i];\r\n\t\t\tif (plugin.getContainerElement) {\r\n\t\t\t\tconst containerElement = plugin.getContainerElement();\r\n\t\t\t\tif (containerElement !== document.body) {\r\n\t\t\t\t\tif (!pluginToCapture[containerElement.id]) {\r\n\t\t\t\t\t\tpluginToCapture[containerElement.id] = true;\r\n\t\t\t\t\t\tpluginContainerElements.push(containerElement);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (let i = 0, len = pluginContainerElements.length; i < len; i++) {\r\n\t\t\tconst containerElement = pluginContainerElements[i];\r\n\t\t\tawait (0,html2canvas_dist_html2canvas_esm_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(containerElement, {\r\n\t\t\t\tcanvas: snapshotCanvas,\r\n\t\t\t\tbackgroundColor: null,\r\n\t\t\t\tscale: snapshotCanvas.width / containerElement.clientWidth\r\n\t\t\t});\r\n\t\t}\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotFinished\");\r\n\t\t}\r\n\t\tif (needFinishSnapshot) {\r\n\t\t\tthis.endSnapshot();\r\n\t\t}\r\n\t\tlet format = params.format || \"png\";\r\n\t\tif (format !== \"jpeg\" && format !== \"png\" && format !== \"bmp\") {\r\n\t\t\tconsole.error(\r\n\t\t\t\t\"Unsupported image format: '\" + format + \"' - supported types are 'jpeg', 'bmp' and 'png' - defaulting to 'png'\"\r\n\t\t\t);\r\n\t\t\tformat = \"png\";\r\n\t\t}\r\n\t\tif (!params.includeGizmos) {\r\n\t\t\tthis.sendToPlugins(\"snapshotFinished\");\r\n\t\t}\r\n\t\tif (needFinishSnapshot) {\r\n\t\t\tthis.endSnapshot();\r\n\t\t}\r\n\t\treturn snapshotCanvas.toDataURL(`image/${format}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Exits snapshot mode.\r\n\t *\r\n\t * Switches rendering back to the main canvas.\r\n\t *\r\n\t */\r\n\tendSnapshot() {\r\n\t\tif (!this._snapshotBegun) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.scene._renderer.endSnapshot();\r\n\t\tthis.scene._renderer.render({ force: true });\r\n\t\tthis._snapshotBegun = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this Viewer.\r\n\t */\r\n\tdestroy(callback) {\r\n\t\tconst plugins = this._plugins.slice(); // Array will modify as we delete plugins\r\n\t\tif (plugins.length > 0) {\r\n\t\t\tfor (let i = 0, len = plugins.length; i < len; i++) {\r\n\t\t\t\tconst plugin = plugins[i];\r\n\t\t\t\tplugin.destroy();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.cameraControl.destroy();\r\n\t\tthis.scene.destroy(callback);\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/Viewer.js?");
|
|
2368
2368
|
|
|
2369
2369
|
/***/ }),
|
|
2370
2370
|
|
|
@@ -2764,7 +2764,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2764
2764
|
\**********************************/
|
|
2765
2765
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2766
2766
|
|
|
2767
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ core: () => (/* binding */ core)\n/* harmony export */ });\n/* harmony import */ var _utils_Queue_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils/Queue.js */ \"./src/viewer/scene/utils/Queue.js\");\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n/* harmony import */ var _stats_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stats.js */ \"./src/viewer/scene/stats.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils.js */ \"./src/viewer/scene/utils.js\");\n\r\n\r\n\r\n\r\n\r\nconst scenesRenderInfo = {}; // Used for throttling FPS for each Scene\r\nconst sceneIDMap = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_1__.Map(); // Ensures unique scene IDs\r\nconst taskQueue = new _utils_Queue_js__WEBPACK_IMPORTED_MODULE_0__.Queue(); // Task queue, which is pumped on each frame; tasks are pushed to it with calls to xeokit.schedule\r\nconst tickEvent = {sceneId: null, time: null, startTime: null, prevTime: null, deltaTime: null};\r\nconst taskBudget = 10; // Millisecs we're allowed to spend on tasks in each frame\r\nconst fpsSamples = [];\r\nconst numFPSSamples = 30;\r\n\r\nlet lastTime = 0;\r\nlet elapsedTime;\r\nlet totalFPS = 0;\r\n\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Core() {\r\n\r\n /**\r\n Semantic version number. The value for this is set by an expression that's concatenated to\r\n the end of the built binary by the xeokit build script.\r\n @property version\r\n @namespace xeokit\r\n @type {String}\r\n */\r\n this.version = \"1.0.0\";\r\n\r\n /**\r\n Existing {@link Scene}s , mapped to their IDs\r\n @property scenes\r\n @namespace xeokit\r\n @type {Scene}\r\n */\r\n this.scenes = {};\r\n\r\n this._superTypes = {}; // For each component type, a list of its supertypes, ordered upwards in the hierarchy.\r\n\r\n /**\r\n * Registers a scene on xeokit.\r\n * This is called within the xeokit.Scene constructor.\r\n * @private\r\n */\r\n this._addScene = function (scene) {\r\n if (scene.id) { // User-supplied ID\r\n if (core.scenes[scene.id]) {\r\n console.error(`[ERROR] Scene ${_utils_js__WEBPACK_IMPORTED_MODULE_3__.utils.inQuotes(scene.id)} already exists`);\r\n return;\r\n }\r\n } else { // Auto-generated ID\r\n scene.id = sceneIDMap.addItem({});\r\n }\r\n core.scenes[scene.id] = scene;\r\n const ticksPerOcclusionTest = scene.ticksPerOcclusionTest;\r\n const ticksPerRender = scene.ticksPerRender;\r\n scenesRenderInfo[scene.id] = {\r\n ticksPerOcclusionTest: ticksPerOcclusionTest,\r\n ticksPerRender: ticksPerRender,\r\n renderCountdown: ticksPerRender\r\n };\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.components.scenes++;\r\n scene.once(\"destroyed\", () => { // Unregister destroyed scenes\r\n sceneIDMap.removeItem(scene.id);\r\n delete core.scenes[scene.id];\r\n delete scenesRenderInfo[scene.id];\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.components.scenes--;\r\n });\r\n };\r\n\r\n /**\r\n * @private\r\n */\r\n this.clear = function () {\r\n let scene;\r\n for (const id in core.scenes) {\r\n if (core.scenes.hasOwnProperty(id)) {\r\n scene = core.scenes[id];\r\n // Only clear the default Scene\r\n // but destroy all the others\r\n if (id === \"default.scene\") {\r\n scene.clear();\r\n } else {\r\n scene.destroy();\r\n delete core.scenes[scene.id];\r\n }\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Schedule a task to run at the next frame.\r\n *\r\n * Internally, this pushes the task to a FIFO queue. Within each frame interval, xeokit processes the queue\r\n * for a certain period of time, popping tasks and running them. After each frame interval, tasks that did not\r\n * get a chance to run during the task are left in the queue to be run next time.\r\n *\r\n * @param {Function} callback Callback that runs the task.\r\n * @param {Object} [scope] Scope for the callback.\r\n */\r\n this.scheduleTask = function (callback, scope = null) {\r\n taskQueue.push(callback);\r\n taskQueue.push(scope);\r\n };\r\n\r\n this.runTasks = function (until = -1) { // Pops and processes tasks in the queue, until the given number of milliseconds has elapsed.\r\n let time = (new Date()).getTime();\r\n let callback;\r\n let scope;\r\n let tasksRun = 0;\r\n while (taskQueue.length > 0 && (until < 0 || time < until)) {\r\n callback = taskQueue.shift();\r\n scope = taskQueue.shift();\r\n if (scope) {\r\n callback.call(scope);\r\n } else {\r\n callback();\r\n }\r\n time = (new Date()).getTime();\r\n tasksRun++;\r\n }\r\n return tasksRun;\r\n };\r\n\r\n this.getNumTasks = function () {\r\n return taskQueue.length;\r\n };\r\n}\r\n\r\n/**\r\n * @private\r\n * @type {Core}\r\n */\r\nconst core = new Core();\r\n\r\nconst frame = function () {\r\n let time = Date.now();\r\n elapsedTime = time - lastTime;\r\n if (lastTime > 0 && elapsedTime > 0) { // Log FPS stats\r\n var newFPS = 1000 / elapsedTime; // Moving average of FPS\r\n totalFPS += newFPS;\r\n fpsSamples.push(newFPS);\r\n if (fpsSamples.length >= numFPSSamples) {\r\n totalFPS -= fpsSamples.shift();\r\n }\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.fps = Math.round(totalFPS / fpsSamples.length);\r\n }\r\n for (let id in core.scenes) {\r\n core.scenes[id].compile();\r\n }\r\n runTasks(time);\r\n lastTime = time;\r\n};\r\n\r\nclass WorkerInterval {\r\n worker = null;\r\n\r\n constructor(callback, interval) {\r\n const blob = new Blob([`setInterval(() => postMessage(0), ${interval});`]);\r\n const workerScript = URL.createObjectURL(blob);\r\n this.worker = new Worker(workerScript);\r\n this.worker.onmessage = callback;\r\n }\r\n\r\n stop() {\r\n this.worker.terminate();\r\n }\r\n}\r\n\r\nconst interval = new WorkerInterval(frame, 100);\r\n\r\nconst renderFrame = function () {\r\n let time = Date.now();\r\n elapsedTime = time - lastTime;\r\n if (lastTime > 0 && elapsedTime > 0) { // Log FPS stats\r\n var newFPS = 1000 / elapsedTime; // Moving average of FPS\r\n totalFPS += newFPS;\r\n fpsSamples.push(newFPS);\r\n if (fpsSamples.length >= numFPSSamples) {\r\n totalFPS -= fpsSamples.shift();\r\n }\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.fps = Math.round(totalFPS / fpsSamples.length);\r\n }\r\n runTasks(time);\r\n fireTickEvents(time);\r\n renderScenes();\r\n (window.requestPostAnimationFrame !== undefined) ? window.requestPostAnimationFrame(frame) : requestAnimationFrame(renderFrame);\r\n};\r\n\r\nrenderFrame();\r\n\r\nfunction runTasks(time) { // Process as many enqueued tasks as we can within the per-frame task budget\r\n const tasksRun = core.runTasks(time + taskBudget);\r\n const tasksScheduled = core.getNumTasks();\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.tasksRun = tasksRun;\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.tasksScheduled = tasksScheduled;\r\n _stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.tasksBudget = taskBudget;\r\n}\r\n\r\nfunction fireTickEvents(time) { // Fire tick event on each Scene\r\n tickEvent.time = time;\r\n for (var id in core.scenes) {\r\n if (core.scenes.hasOwnProperty(id)) {\r\n var scene = core.scenes[id];\r\n tickEvent.sceneId = id;\r\n tickEvent.startTime = scene.startTime;\r\n tickEvent.deltaTime = tickEvent.prevTime != null ? tickEvent.time - tickEvent.prevTime : 0;\r\n /**\r\n * Fired on each game loop iteration.\r\n *\r\n * @event tick\r\n * @param {String} sceneID The ID of this Scene.\r\n * @param {Number} startTime The time in seconds since 1970 that this Scene was instantiated.\r\n * @param {Number} time The time in seconds since 1970 of this \"tick\" event.\r\n * @param {Number} prevTime The time of the previous \"tick\" event from this Scene.\r\n * @param {Number} deltaTime The time in seconds since the previous \"tick\" event from this Scene.\r\n */\r\n scene.fire(\"tick\", tickEvent, true);\r\n }\r\n }\r\n tickEvent.prevTime = time;\r\n}\r\n\r\nfunction renderScenes() {\r\n const scenes = core.scenes;\r\n const forceRender = false;\r\n let scene;\r\n let renderInfo;\r\n let ticksPerOcclusionTest;\r\n let ticksPerRender;\r\n let id;\r\n for (id in scenes) {\r\n if (scenes.hasOwnProperty(id)) {\r\n\r\n scene = scenes[id];\r\n renderInfo = scenesRenderInfo[id];\r\n\r\n if (!renderInfo) {\r\n renderInfo = scenesRenderInfo[id] = {}; // FIXME\r\n }\r\n\r\n ticksPerOcclusionTest = scene.ticksPerOcclusionTest;\r\n if (renderInfo.ticksPerOcclusionTest !== ticksPerOcclusionTest) {\r\n renderInfo.ticksPerOcclusionTest = ticksPerOcclusionTest;\r\n renderInfo.renderCountdown = ticksPerOcclusionTest;\r\n }\r\n if (--scene.occlusionTestCountdown <= 0) {\r\n scene.doOcclusionTest();\r\n scene.occlusionTestCountdown = ticksPerOcclusionTest;\r\n }\r\n\r\n ticksPerRender = scene.ticksPerRender;\r\n if (renderInfo.ticksPerRender !== ticksPerRender) {\r\n renderInfo.ticksPerRender = ticksPerRender;\r\n renderInfo.renderCountdown = ticksPerRender;\r\n }\r\n if (--renderInfo.renderCountdown === 0) {\r\n scene.render(forceRender);\r\n renderInfo.renderCountdown = ticksPerRender;\r\n }\r\n }\r\n }\r\n}\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/core.js?");
|
|
2767
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ core: () => (/* binding */ core)\n/* harmony export */ });\n/* harmony import */ var _utils_Queue_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils/Queue.js */ \"./src/viewer/scene/utils/Queue.js\");\n/* harmony import */ var _utils_Map_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils/Map.js */ \"./src/viewer/scene/utils/Map.js\");\n/* harmony import */ var _stats_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stats.js */ \"./src/viewer/scene/stats.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils.js */ \"./src/viewer/scene/utils.js\");\n\r\n\r\n\r\n\r\n\r\nconst scenesRenderInfo = {}; // Used for throttling FPS for each Scene\r\nconst sceneIDMap = new _utils_Map_js__WEBPACK_IMPORTED_MODULE_1__.Map(); // Ensures unique scene IDs\r\nconst taskQueue = new _utils_Queue_js__WEBPACK_IMPORTED_MODULE_0__.Queue(); // Task queue, which is pumped on each frame; tasks are pushed to it with calls to tctwins.schedule\r\nconst tickEvent = { sceneId: null, time: null, startTime: null, prevTime: null, deltaTime: null };\r\nconst taskBudget = 10; // Millisecs we're allowed to spend on tasks in each frame\r\nconst fpsSamples = [];\r\nconst numFPSSamples = 30;\r\n\r\nlet lastTime = 0;\r\nlet elapsedTime;\r\nlet totalFPS = 0;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Core() {\r\n\t/**\r\n Semantic version number. The value for this is set by an expression that's concatenated to\r\n the end of the built binary by the tctwins build script.\r\n @property version\r\n @namespace tctwins\r\n @type {String}\r\n */\r\n\tthis.version = \"1.0.0\";\r\n\r\n\t/**\r\n Existing {@link Scene}s , mapped to their IDs\r\n @property scenes\r\n @namespace tctwins\r\n @type {Scene}\r\n */\r\n\tthis.scenes = {};\r\n\r\n\tthis._superTypes = {}; // For each component type, a list of its supertypes, ordered upwards in the hierarchy.\r\n\r\n\t/**\r\n\t * Registers a scene on tctwins.\r\n\t * This is called within the tctwins.Scene constructor.\r\n\t * @private\r\n\t */\r\n\tthis._addScene = function (scene) {\r\n\t\tif (scene.id) {\r\n\t\t\t// User-supplied ID\r\n\t\t\tif (core.scenes[scene.id]) {\r\n\t\t\t\tconsole.error(`[ERROR] Scene ${_utils_js__WEBPACK_IMPORTED_MODULE_3__.utils.inQuotes(scene.id)} already exists`);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// Auto-generated ID\r\n\t\t\tscene.id = sceneIDMap.addItem({});\r\n\t\t}\r\n\t\tcore.scenes[scene.id] = scene;\r\n\t\tconst ticksPerOcclusionTest = scene.ticksPerOcclusionTest;\r\n\t\tconst ticksPerRender = scene.ticksPerRender;\r\n\t\tscenesRenderInfo[scene.id] = {\r\n\t\t\tticksPerOcclusionTest: ticksPerOcclusionTest,\r\n\t\t\tticksPerRender: ticksPerRender,\r\n\t\t\trenderCountdown: ticksPerRender\r\n\t\t};\r\n\t\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.components.scenes++;\r\n\t\tscene.once(\"destroyed\", () => {\r\n\t\t\t// Unregister destroyed scenes\r\n\t\t\tsceneIDMap.removeItem(scene.id);\r\n\t\t\tdelete core.scenes[scene.id];\r\n\t\t\tdelete scenesRenderInfo[scene.id];\r\n\t\t\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.components.scenes--;\r\n\t\t});\r\n\t};\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tthis.clear = function () {\r\n\t\tlet scene;\r\n\t\tfor (const id in core.scenes) {\r\n\t\t\tif (core.scenes.hasOwnProperty(id)) {\r\n\t\t\t\tscene = core.scenes[id];\r\n\t\t\t\t// Only clear the default Scene\r\n\t\t\t\t// but destroy all the others\r\n\t\t\t\tif (id === \"default.scene\") {\r\n\t\t\t\t\tscene.clear();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tscene.destroy();\r\n\t\t\t\t\tdelete core.scenes[scene.id];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n\r\n\t/**\r\n\t * Schedule a task to run at the next frame.\r\n\t *\r\n\t * Internally, this pushes the task to a FIFO queue. Within each frame interval, tctwins processes the queue\r\n\t * for a certain period of time, popping tasks and running them. After each frame interval, tasks that did not\r\n\t * get a chance to run during the task are left in the queue to be run next time.\r\n\t *\r\n\t * @param {Function} callback Callback that runs the task.\r\n\t * @param {Object} [scope] Scope for the callback.\r\n\t */\r\n\tthis.scheduleTask = function (callback, scope = null) {\r\n\t\ttaskQueue.push(callback);\r\n\t\ttaskQueue.push(scope);\r\n\t};\r\n\r\n\tthis.runTasks = function (until = -1) {\r\n\t\t// Pops and processes tasks in the queue, until the given number of milliseconds has elapsed.\r\n\t\tlet time = new Date().getTime();\r\n\t\tlet callback;\r\n\t\tlet scope;\r\n\t\tlet tasksRun = 0;\r\n\t\twhile (taskQueue.length > 0 && (until < 0 || time < until)) {\r\n\t\t\tcallback = taskQueue.shift();\r\n\t\t\tscope = taskQueue.shift();\r\n\t\t\tif (scope) {\r\n\t\t\t\tcallback.call(scope);\r\n\t\t\t} else {\r\n\t\t\t\tcallback();\r\n\t\t\t}\r\n\t\t\ttime = new Date().getTime();\r\n\t\t\ttasksRun++;\r\n\t\t}\r\n\t\treturn tasksRun;\r\n\t};\r\n\r\n\tthis.getNumTasks = function () {\r\n\t\treturn taskQueue.length;\r\n\t};\r\n}\r\n\r\n/**\r\n * @private\r\n * @type {Core}\r\n */\r\nconst core = new Core();\r\n\r\nconst frame = function () {\r\n\tlet time = Date.now();\r\n\telapsedTime = time - lastTime;\r\n\tif (lastTime > 0 && elapsedTime > 0) {\r\n\t\t// Log FPS stats\r\n\t\tvar newFPS = 1000 / elapsedTime; // Moving average of FPS\r\n\t\ttotalFPS += newFPS;\r\n\t\tfpsSamples.push(newFPS);\r\n\t\tif (fpsSamples.length >= numFPSSamples) {\r\n\t\t\ttotalFPS -= fpsSamples.shift();\r\n\t\t}\r\n\t\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.fps = Math.round(totalFPS / fpsSamples.length);\r\n\t}\r\n\tfor (let id in core.scenes) {\r\n\t\tcore.scenes[id].compile();\r\n\t}\r\n\trunTasks(time);\r\n\tlastTime = time;\r\n};\r\n\r\nclass WorkerInterval {\r\n\tworker = null;\r\n\r\n\tconstructor(callback, interval) {\r\n\t\tconst blob = new Blob([`setInterval(() => postMessage(0), ${interval});`]);\r\n\t\tconst workerScript = URL.createObjectURL(blob);\r\n\t\tthis.worker = new Worker(workerScript);\r\n\t\tthis.worker.onmessage = callback;\r\n\t}\r\n\r\n\tstop() {\r\n\t\tthis.worker.terminate();\r\n\t}\r\n}\r\n\r\nconst interval = new WorkerInterval(frame, 100);\r\n\r\nconst renderFrame = function () {\r\n\tlet time = Date.now();\r\n\telapsedTime = time - lastTime;\r\n\tif (lastTime > 0 && elapsedTime > 0) {\r\n\t\t// Log FPS stats\r\n\t\tvar newFPS = 1000 / elapsedTime; // Moving average of FPS\r\n\t\ttotalFPS += newFPS;\r\n\t\tfpsSamples.push(newFPS);\r\n\t\tif (fpsSamples.length >= numFPSSamples) {\r\n\t\t\ttotalFPS -= fpsSamples.shift();\r\n\t\t}\r\n\t\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.fps = Math.round(totalFPS / fpsSamples.length);\r\n\t}\r\n\trunTasks(time);\r\n\tfireTickEvents(time);\r\n\trenderScenes();\r\n\twindow.requestPostAnimationFrame !== undefined\r\n\t\t? window.requestPostAnimationFrame(frame)\r\n\t\t: requestAnimationFrame(renderFrame);\r\n};\r\n\r\nrenderFrame();\r\n\r\nfunction runTasks(time) {\r\n\t// Process as many enqueued tasks as we can within the per-frame task budget\r\n\tconst tasksRun = core.runTasks(time + taskBudget);\r\n\tconst tasksScheduled = core.getNumTasks();\r\n\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.tasksRun = tasksRun;\r\n\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.tasksScheduled = tasksScheduled;\r\n\t_stats_js__WEBPACK_IMPORTED_MODULE_2__.stats.frame.tasksBudget = taskBudget;\r\n}\r\n\r\nfunction fireTickEvents(time) {\r\n\t// Fire tick event on each Scene\r\n\ttickEvent.time = time;\r\n\tfor (var id in core.scenes) {\r\n\t\tif (core.scenes.hasOwnProperty(id)) {\r\n\t\t\tvar scene = core.scenes[id];\r\n\t\t\ttickEvent.sceneId = id;\r\n\t\t\ttickEvent.startTime = scene.startTime;\r\n\t\t\ttickEvent.deltaTime = tickEvent.prevTime != null ? tickEvent.time - tickEvent.prevTime : 0;\r\n\t\t\t/**\r\n\t\t\t * Fired on each game loop iteration.\r\n\t\t\t *\r\n\t\t\t * @event tick\r\n\t\t\t * @param {String} sceneID The ID of this Scene.\r\n\t\t\t * @param {Number} startTime The time in seconds since 1970 that this Scene was instantiated.\r\n\t\t\t * @param {Number} time The time in seconds since 1970 of this \"tick\" event.\r\n\t\t\t * @param {Number} prevTime The time of the previous \"tick\" event from this Scene.\r\n\t\t\t * @param {Number} deltaTime The time in seconds since the previous \"tick\" event from this Scene.\r\n\t\t\t */\r\n\t\t\tscene.fire(\"tick\", tickEvent, true);\r\n\t\t}\r\n\t}\r\n\ttickEvent.prevTime = time;\r\n}\r\n\r\nfunction renderScenes() {\r\n\tconst scenes = core.scenes;\r\n\tconst forceRender = false;\r\n\tlet scene;\r\n\tlet renderInfo;\r\n\tlet ticksPerOcclusionTest;\r\n\tlet ticksPerRender;\r\n\tlet id;\r\n\tfor (id in scenes) {\r\n\t\tif (scenes.hasOwnProperty(id)) {\r\n\t\t\tscene = scenes[id];\r\n\t\t\trenderInfo = scenesRenderInfo[id];\r\n\r\n\t\t\tif (!renderInfo) {\r\n\t\t\t\trenderInfo = scenesRenderInfo[id] = {}; // FIXME\r\n\t\t\t}\r\n\r\n\t\t\tticksPerOcclusionTest = scene.ticksPerOcclusionTest;\r\n\t\t\tif (renderInfo.ticksPerOcclusionTest !== ticksPerOcclusionTest) {\r\n\t\t\t\trenderInfo.ticksPerOcclusionTest = ticksPerOcclusionTest;\r\n\t\t\t\trenderInfo.renderCountdown = ticksPerOcclusionTest;\r\n\t\t\t}\r\n\t\t\tif (--scene.occlusionTestCountdown <= 0) {\r\n\t\t\t\tscene.doOcclusionTest();\r\n\t\t\t\tscene.occlusionTestCountdown = ticksPerOcclusionTest;\r\n\t\t\t}\r\n\r\n\t\t\tticksPerRender = scene.ticksPerRender;\r\n\t\t\tif (renderInfo.ticksPerRender !== ticksPerRender) {\r\n\t\t\t\trenderInfo.ticksPerRender = ticksPerRender;\r\n\t\t\t\trenderInfo.renderCountdown = ticksPerRender;\r\n\t\t\t}\r\n\t\t\tif (--renderInfo.renderCountdown === 0) {\r\n\t\t\t\tscene.render(forceRender);\r\n\t\t\t\trenderInfo.renderCountdown = ticksPerRender;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/core.js?");
|
|
2768
2768
|
|
|
2769
2769
|
/***/ }),
|
|
2770
2770
|
|
|
@@ -4804,7 +4804,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4804
4804
|
\*****************************************/
|
|
4805
4805
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4806
4806
|
|
|
4807
|
-
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\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 Entity}s that represent models.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isModel} is ````true````.\n\t\t *\n\t\t * @property models\n\t\t * @final\n\t\t * @type {{String:Entity}}\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});\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(\"xeokit 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.7\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.7,\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.9,\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(entity) {\n\t\tthis.models[entity.id] = entity;\n\t\tthis._modelIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterModel(entity) {\n\t\tconst modelId = entity.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._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\t_setAABBDirty() {\n\t\t//if (!this._aabbDirty) {\n\t\tthis._aabbDirty = true;\n\t\tthis.fire(\"boundary\");\n\t\t// }\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?");
|
|
4807
|
+
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\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 Entity}s that represent models.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isModel} is ````true````.\n\t\t *\n\t\t * @property models\n\t\t * @final\n\t\t * @type {{String:Entity}}\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.7\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.7,\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.9,\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(entity) {\n\t\tthis.models[entity.id] = entity;\n\t\tthis._modelIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterModel(entity) {\n\t\tconst modelId = entity.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._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\t_setAABBDirty() {\n\t\t//if (!this._aabbDirty) {\n\t\tthis._aabbDirty = true;\n\t\tthis.fire(\"boundary\");\n\t\t// }\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?");
|
|
4808
4808
|
|
|
4809
4809
|
/***/ }),
|
|
4810
4810
|
|
|
@@ -5204,7 +5204,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
5204
5204
|
\*******************************************************************/
|
|
5205
5205
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5206
5206
|
|
|
5207
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SAODepthLimitedBlurRenderer: () => (/* binding */ SAODepthLimitedBlurRenderer)\n/* harmony export */ });\n/* harmony import */ var _Program_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n\r\n\r\n\r\n\r\n\r\nconst blurStdDev = 4;\r\nconst blurDepthCutoff = 0.01;\r\nconst KERNEL_RADIUS = 16;\r\n\r\nconst sampleOffsetsVert = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [0, 1]));\r\nconst sampleOffsetsHor = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [1, 0]));\r\nconst sampleWeights = new Float32Array(createSampleWeights(KERNEL_RADIUS + 1, blurStdDev));\r\n\r\nconst tempVec2a = new Float32Array(2);\r\n\r\n/**\r\n * SAO implementation inspired from previous SAO work in THREE.js by ludobaka / ludobaka.github.io and bhouston\r\n * @private\r\n */\r\nclass SAODepthLimitedBlurRenderer {\r\n\r\n constructor(scene) {\r\n\r\n this._scene = scene;\r\n\r\n // The program\r\n\r\n this._program = null;\r\n this._programError = false;\r\n\r\n // Variable locations\r\n\r\n this._aPosition = null;\r\n this._aUV = null;\r\n\r\n this._uDepthTexture = \"uDepthTexture\";\r\n this._uOcclusionTexture = \"uOcclusionTexture\";\r\n\r\n this._uViewport = null;\r\n this._uCameraNear = null;\r\n this._uCameraFar = null;\r\n this._uCameraProjectionMatrix = null;\r\n this._uCameraInverseProjectionMatrix = null;\r\n\r\n // VBOs\r\n\r\n this._uvBuf = null;\r\n this._positionsBuf = null;\r\n this._indicesBuf = null;\r\n\r\n this.init();\r\n }\r\n\r\n init() {\r\n\r\n // Create program & VBOs, locate attributes and uniforms\r\n\r\n const gl = this._scene.canvas.gl;\r\n\r\n this._program = new _Program_js__WEBPACK_IMPORTED_MODULE_0__.Program(gl, {\r\n\r\n vertex: [\r\n `#version 300 es\r\n precision highp float;\r\n precision highp int;\r\n \r\n in vec3 aPosition;\r\n in vec2 aUV;\r\n uniform vec2 uViewport;\r\n out vec2 vUV;\r\n out vec2 vInvSize;\r\n void main () {\r\n vUV = aUV;\r\n vInvSize = 1.0 / uViewport;\r\n gl_Position = vec4(aPosition, 1.0);\r\n }`],\r\n\r\n fragment: [\r\n `#version 300 es\r\n precision highp float;\r\n precision highp int;\r\n \r\n #define PI 3.14159265359\r\n #define PI2 6.28318530718\r\n #define EPSILON 1e-6\r\n\r\n #define KERNEL_RADIUS ${KERNEL_RADIUS}\r\n\r\n in vec2 vUV;\r\n in vec2 vInvSize;\r\n \r\n uniform sampler2D uDepthTexture;\r\n uniform sampler2D uOcclusionTexture; \r\n \r\n uniform float uCameraNear;\r\n uniform float uCameraFar; \r\n uniform float uDepthCutoff;\r\n\r\n uniform vec2 uSampleOffsets[ KERNEL_RADIUS + 1 ];\r\n uniform float uSampleWeights[ KERNEL_RADIUS + 1 ];\r\n\r\n const float unpackDownscale = 255. / 256.; \r\n\r\n const vec3 packFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\r\n const vec4 unpackFactors = unpackDownscale / vec4( packFactors, 1. ); \r\n\r\n const float packUpscale = 256. / 255.;\r\n \r\n const float shiftRights = 1. / 256.;\r\n \r\n float unpackRGBAToFloat( const in vec4 v ) {\r\n return dot( floor( v * 255.0 + 0.5 ) / 255.0, unpackFactors );\r\n } \r\n\r\n vec4 packFloatToRGBA( const in float v ) {\r\n vec4 r = vec4( fract( v * packFactors ), v );\r\n r.yzw -= r.xyz * shiftRights; \r\n return r * packUpscale;\r\n }\r\n\r\n float viewZToOrthographicDepth( const in float viewZ) {\r\n return ( viewZ + uCameraNear ) / ( uCameraNear - uCameraFar );\r\n }\r\n \r\n float orthographicDepthToViewZ( const in float linearClipZ) {\r\n return linearClipZ * ( uCameraNear - uCameraFar ) - uCameraNear;\r\n }\r\n\r\n float viewZToPerspectiveDepth( const in float viewZ) {\r\n return (( uCameraNear + viewZ ) * uCameraFar ) / (( uCameraFar - uCameraNear ) * viewZ );\r\n }\r\n \r\n float perspectiveDepthToViewZ( const in float invClipZ) {\r\n return ( uCameraNear * uCameraFar ) / ( ( uCameraFar - uCameraNear ) * invClipZ - uCameraFar );\r\n }\r\n\r\n float getDepth( const in vec2 screenPosition ) {\r\n return vec4(texture(uDepthTexture, screenPosition)).r;\r\n }\r\n\r\n float getViewZ( const in float depth ) {\r\n return perspectiveDepthToViewZ( depth );\r\n }\r\n\r\n out vec4 outColor;\r\n \r\n void main() {\r\n \r\n float depth = getDepth( vUV );\r\n if( depth >= ( 1.0 - EPSILON ) ) {\r\n discard;\r\n }\r\n\r\n float centerViewZ = -getViewZ( depth );\r\n bool rBreak = false;\r\n bool lBreak = false;\r\n\r\n float weightSum = uSampleWeights[0];\r\n float occlusionSum = unpackRGBAToFloat(texture( uOcclusionTexture, vUV )) * weightSum;\r\n\r\n for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {\r\n\r\n float sampleWeight = uSampleWeights[i];\r\n vec2 sampleUVOffset = uSampleOffsets[i] * vInvSize;\r\n\r\n vec2 sampleUV = vUV + sampleUVOffset;\r\n float viewZ = -getViewZ( getDepth( sampleUV ) );\r\n\r\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\r\n rBreak = true;\r\n }\r\n\r\n if( ! rBreak ) {\r\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\r\n weightSum += sampleWeight;\r\n }\r\n\r\n sampleUV = vUV - sampleUVOffset;\r\n viewZ = -getViewZ( getDepth( sampleUV ) );\r\n\r\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\r\n lBreak = true;\r\n }\r\n\r\n if( ! lBreak ) {\r\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\r\n weightSum += sampleWeight;\r\n }\r\n }\r\n\r\n outColor = packFloatToRGBA(occlusionSum / weightSum);\r\n }`\r\n ]\r\n });\r\n\r\n if (this._program.errors) {\r\n console.error(this._program.errors.join(\"\\n\"));\r\n this._programError = true;\r\n return;\r\n }\r\n\r\n const uv = new Float32Array([1, 1, 0, 1, 0, 0, 1, 0]);\r\n const positions = new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]);\r\n\r\n // Mitigation: if Uint8Array is used, the geometry is corrupted on OSX when using Chrome with data-textures\r\n const indices = new Uint32Array([0, 1, 2, 0, 2, 3]);\r\n\r\n this._positionsBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, positions, positions.length, 3, gl.STATIC_DRAW);\r\n this._uvBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, uv, uv.length, 2, gl.STATIC_DRAW);\r\n this._indicesBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, indices.length, 1, gl.STATIC_DRAW);\r\n\r\n this._program.bind();\r\n\r\n this._uViewport = this._program.getLocation(\"uViewport\");\r\n\r\n this._uCameraNear = this._program.getLocation(\"uCameraNear\");\r\n this._uCameraFar = this._program.getLocation(\"uCameraFar\");\r\n\r\n this._uDepthCutoff = this._program.getLocation(\"uDepthCutoff\");\r\n\r\n this._uSampleOffsets = gl.getUniformLocation(this._program.handle, \"uSampleOffsets\");\r\n this._uSampleWeights = gl.getUniformLocation(this._program.handle, \"uSampleWeights\");\r\n\r\n this._aPosition = this._program.getAttribute(\"aPosition\");\r\n this._aUV = this._program.getAttribute(\"aUV\");\r\n }\r\n\r\n render(depthRenderBuffer, occlusionRenderBuffer, direction) {\r\n\r\n if (this._programError) {\r\n return;\r\n }\r\n\r\n if (!this._getInverseProjectMat) { // HACK: scene.camera not defined until render time\r\n this._getInverseProjectMat = (() => {\r\n let projMatDirty = true;\r\n this._scene.camera.on(\"projMatrix\", function () {\r\n projMatDirty = true;\r\n });\r\n const inverseProjectMat = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\r\n return () => {\r\n if (projMatDirty) {\r\n _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(scene.camera.projMatrix, inverseProjectMat);\r\n }\r\n return inverseProjectMat;\r\n }\r\n })();\r\n }\r\n\r\n const gl = this._scene.canvas.gl;\r\n const program = this._program;\r\n const scene = this._scene;\r\n const viewportWidth = gl.drawingBufferWidth;\r\n const viewportHeight = gl.drawingBufferHeight;\r\n const projectState = scene.camera.project._state;\r\n const near = projectState.near;\r\n const far = projectState.far;\r\n\r\n gl.viewport(0, 0, viewportWidth, viewportHeight);\r\n gl.clearColor(0, 0, 0, 1);\r\n gl.enable(gl.DEPTH_TEST);\r\n gl.disable(gl.BLEND);\r\n gl.frontFace(gl.CCW);\r\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\r\n\r\n program.bind();\r\n\r\n tempVec2a[0] = viewportWidth;\r\n tempVec2a[1] = viewportHeight;\r\n\r\n gl.uniform2fv(this._uViewport, tempVec2a);\r\n gl.uniform1f(this._uCameraNear, near);\r\n gl.uniform1f(this._uCameraFar, far);\r\n\r\n gl.uniform1f(this._uDepthCutoff, blurDepthCutoff);\r\n\r\n if (direction === 0) {// Horizontal\r\n gl.uniform2fv(this._uSampleOffsets, sampleOffsetsHor);\r\n } else { // Vertical\r\n gl.uniform2fv(this._uSampleOffsets, sampleOffsetsVert);\r\n }\r\n\r\n gl.uniform1fv(this._uSampleWeights, sampleWeights);\r\n\r\n const depthTexture = depthRenderBuffer.getDepthTexture();\r\n const occlusionTexture = occlusionRenderBuffer.getTexture();\r\n\r\n program.bindTexture(this._uDepthTexture, depthTexture, 0); // TODO: use FrameCtx.textureUnit\r\n program.bindTexture(this._uOcclusionTexture, occlusionTexture, 1);\r\n\r\n this._aUV.bindArrayBuffer(this._uvBuf);\r\n this._aPosition.bindArrayBuffer(this._positionsBuf);\r\n this._indicesBuf.bind();\r\n\r\n gl.drawElements(gl.TRIANGLES, this._indicesBuf.numItems, this._indicesBuf.itemType, 0);\r\n }\r\n\r\n destroy() {\r\n this._program.destroy();\r\n }\r\n}\r\n\r\nfunction createSampleWeights(kernelRadius, stdDev) {\r\n const weights = [];\r\n for (let i = 0; i <= kernelRadius; i++) {\r\n weights.push(gaussian(i, stdDev));\r\n }\r\n return weights; // TODO: Optimize\r\n}\r\n\r\nfunction gaussian(x, stdDev) {\r\n return Math.exp(-(x * x) / (2.0 * (stdDev * stdDev))) / (Math.sqrt(2.0 * Math.PI) * stdDev);\r\n}\r\n\r\nfunction createSampleOffsets(kernelRadius, uvIncrement) {\r\n const offsets = [];\r\n for (let i = 0; i <= kernelRadius; i++) {\r\n offsets.push(uvIncrement[0] * i);\r\n offsets.push(uvIncrement[1] * i);\r\n }\r\n return offsets;\r\n}\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js?");
|
|
5207
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SAODepthLimitedBlurRenderer: () => (/* binding */ SAODepthLimitedBlurRenderer)\n/* harmony export */ });\n/* harmony import */ var _Program_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../Program.js */ \"./src/viewer/scene/webgl/Program.js\");\n/* harmony import */ var _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../ArrayBuf.js */ \"./src/viewer/scene/webgl/ArrayBuf.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _webglInfo_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../webglInfo.js */ \"./src/viewer/scene/webglInfo.js\");\n\r\n\r\n\r\n\r\n\r\nconst blurStdDev = 4;\r\nconst blurDepthCutoff = 0.01;\r\nconst KERNEL_RADIUS = 100;\r\n\r\nconst sampleOffsetsVert = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [0, 1]));\r\nconst sampleOffsetsHor = new Float32Array(createSampleOffsets(KERNEL_RADIUS + 1, [1, 0]));\r\nconst sampleWeights = new Float32Array(createSampleWeights(KERNEL_RADIUS + 1, blurStdDev));\r\n\r\nconst tempVec2a = new Float32Array(2);\r\n\r\n/**\r\n * SAO implementation inspired from previous SAO work in THREE.js by ludobaka / ludobaka.github.io and bhouston\r\n * @private\r\n */\r\nclass SAODepthLimitedBlurRenderer {\r\n\tconstructor(scene) {\r\n\t\tthis._scene = scene;\r\n\r\n\t\t// The program\r\n\r\n\t\tthis._program = null;\r\n\t\tthis._programError = false;\r\n\r\n\t\t// Variable locations\r\n\r\n\t\tthis._aPosition = null;\r\n\t\tthis._aUV = null;\r\n\r\n\t\tthis._uDepthTexture = \"uDepthTexture\";\r\n\t\tthis._uOcclusionTexture = \"uOcclusionTexture\";\r\n\r\n\t\tthis._uViewport = null;\r\n\t\tthis._uCameraNear = null;\r\n\t\tthis._uCameraFar = null;\r\n\t\tthis._uCameraProjectionMatrix = null;\r\n\t\tthis._uCameraInverseProjectionMatrix = null;\r\n\r\n\t\t// VBOs\r\n\r\n\t\tthis._uvBuf = null;\r\n\t\tthis._positionsBuf = null;\r\n\t\tthis._indicesBuf = null;\r\n\r\n\t\tthis.init();\r\n\t}\r\n\r\n\tinit() {\r\n\t\t// Create program & VBOs, locate attributes and uniforms\r\n\r\n\t\tconst gl = this._scene.canvas.gl;\r\n\r\n\t\tthis._program = new _Program_js__WEBPACK_IMPORTED_MODULE_0__.Program(gl, {\r\n\t\t\tvertex: [\r\n\t\t\t\t`#version 300 es\r\n precision highp float;\r\n precision highp int;\r\n \r\n in vec3 aPosition;\r\n in vec2 aUV;\r\n uniform vec2 uViewport;\r\n out vec2 vUV;\r\n out vec2 vInvSize;\r\n void main () {\r\n vUV = aUV;\r\n vInvSize = 1.0 / uViewport;\r\n gl_Position = vec4(aPosition, 1.0);\r\n }`\r\n\t\t\t],\r\n\r\n\t\t\tfragment: [\r\n\t\t\t\t`#version 300 es\r\n precision highp float;\r\n precision highp int;\r\n \r\n #define PI 3.14159265359\r\n #define PI2 6.28318530718\r\n #define EPSILON 1e-6\r\n\r\n #define KERNEL_RADIUS ${KERNEL_RADIUS}\r\n\r\n in vec2 vUV;\r\n in vec2 vInvSize;\r\n \r\n uniform sampler2D uDepthTexture;\r\n uniform sampler2D uOcclusionTexture; \r\n \r\n uniform float uCameraNear;\r\n uniform float uCameraFar; \r\n uniform float uDepthCutoff;\r\n\r\n uniform vec2 uSampleOffsets[ KERNEL_RADIUS + 1 ];\r\n uniform float uSampleWeights[ KERNEL_RADIUS + 1 ];\r\n\r\n const float unpackDownscale = 255. / 256.; \r\n\r\n const vec3 packFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\r\n const vec4 unpackFactors = unpackDownscale / vec4( packFactors, 1. ); \r\n\r\n const float packUpscale = 256. / 255.;\r\n \r\n const float shiftRights = 1. / 256.;\r\n \r\n float unpackRGBAToFloat( const in vec4 v ) {\r\n return dot( floor( v * 255.0 + 0.5 ) / 255.0, unpackFactors );\r\n } \r\n\r\n vec4 packFloatToRGBA( const in float v ) {\r\n vec4 r = vec4( fract( v * packFactors ), v );\r\n r.yzw -= r.xyz * shiftRights; \r\n return r * packUpscale;\r\n }\r\n\r\n float viewZToOrthographicDepth( const in float viewZ) {\r\n return ( viewZ + uCameraNear ) / ( uCameraNear - uCameraFar );\r\n }\r\n \r\n float orthographicDepthToViewZ( const in float linearClipZ) {\r\n return linearClipZ * ( uCameraNear - uCameraFar ) - uCameraNear;\r\n }\r\n\r\n float viewZToPerspectiveDepth( const in float viewZ) {\r\n return (( uCameraNear + viewZ ) * uCameraFar ) / (( uCameraFar - uCameraNear ) * viewZ );\r\n }\r\n \r\n float perspectiveDepthToViewZ( const in float invClipZ) {\r\n return ( uCameraNear * uCameraFar ) / ( ( uCameraFar - uCameraNear ) * invClipZ - uCameraFar );\r\n }\r\n\r\n float getDepth( const in vec2 screenPosition ) {\r\n return vec4(texture(uDepthTexture, screenPosition)).r;\r\n }\r\n\r\n float getViewZ( const in float depth ) {\r\n return perspectiveDepthToViewZ( depth );\r\n }\r\n\r\n out vec4 outColor;\r\n \r\n void main() {\r\n \r\n float depth = getDepth( vUV );\r\n if( depth >= ( 1.0 - EPSILON ) ) {\r\n discard;\r\n }\r\n\r\n float centerViewZ = -getViewZ( depth );\r\n bool rBreak = false;\r\n bool lBreak = false;\r\n\r\n float weightSum = uSampleWeights[0];\r\n float occlusionSum = unpackRGBAToFloat(texture( uOcclusionTexture, vUV )) * weightSum;\r\n\r\n for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {\r\n\r\n float sampleWeight = uSampleWeights[i];\r\n vec2 sampleUVOffset = uSampleOffsets[i] * vInvSize;\r\n\r\n vec2 sampleUV = vUV + sampleUVOffset;\r\n float viewZ = -getViewZ( getDepth( sampleUV ) );\r\n\r\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\r\n rBreak = true;\r\n }\r\n\r\n if( ! rBreak ) {\r\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\r\n weightSum += sampleWeight;\r\n }\r\n\r\n sampleUV = vUV - sampleUVOffset;\r\n viewZ = -getViewZ( getDepth( sampleUV ) );\r\n\r\n if( abs( viewZ - centerViewZ ) > uDepthCutoff ) {\r\n lBreak = true;\r\n }\r\n\r\n if( ! lBreak ) {\r\n occlusionSum += unpackRGBAToFloat(texture( uOcclusionTexture, sampleUV )) * sampleWeight;\r\n weightSum += sampleWeight;\r\n }\r\n }\r\n\r\n outColor = packFloatToRGBA(occlusionSum / weightSum);\r\n }`\r\n\t\t\t]\r\n\t\t});\r\n\r\n\t\tif (this._program.errors) {\r\n\t\t\tconsole.error(this._program.errors.join(\"\\n\"));\r\n\t\t\tthis._programError = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst uv = new Float32Array([1, 1, 0, 1, 0, 0, 1, 0]);\r\n\t\tconst positions = new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]);\r\n\r\n\t\t// Mitigation: if Uint8Array is used, the geometry is corrupted on OSX when using Chrome with data-textures\r\n\t\tconst indices = new Uint32Array([0, 1, 2, 0, 2, 3]);\r\n\r\n\t\tthis._positionsBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, positions, positions.length, 3, gl.STATIC_DRAW);\r\n\t\tthis._uvBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ARRAY_BUFFER, uv, uv.length, 2, gl.STATIC_DRAW);\r\n\t\tthis._indicesBuf = new _ArrayBuf_js__WEBPACK_IMPORTED_MODULE_1__.ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, indices, indices.length, 1, gl.STATIC_DRAW);\r\n\r\n\t\tthis._program.bind();\r\n\r\n\t\tthis._uViewport = this._program.getLocation(\"uViewport\");\r\n\r\n\t\tthis._uCameraNear = this._program.getLocation(\"uCameraNear\");\r\n\t\tthis._uCameraFar = this._program.getLocation(\"uCameraFar\");\r\n\r\n\t\tthis._uDepthCutoff = this._program.getLocation(\"uDepthCutoff\");\r\n\r\n\t\tthis._uSampleOffsets = gl.getUniformLocation(this._program.handle, \"uSampleOffsets\");\r\n\t\tthis._uSampleWeights = gl.getUniformLocation(this._program.handle, \"uSampleWeights\");\r\n\r\n\t\tthis._aPosition = this._program.getAttribute(\"aPosition\");\r\n\t\tthis._aUV = this._program.getAttribute(\"aUV\");\r\n\t}\r\n\r\n\trender(depthRenderBuffer, occlusionRenderBuffer, direction) {\r\n\t\tif (this._programError) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!this._getInverseProjectMat) {\r\n\t\t\t// HACK: scene.camera not defined until render time\r\n\t\t\tthis._getInverseProjectMat = (() => {\r\n\t\t\t\tlet projMatDirty = true;\r\n\t\t\t\tthis._scene.camera.on(\"projMatrix\", function () {\r\n\t\t\t\t\tprojMatDirty = true;\r\n\t\t\t\t});\r\n\t\t\t\tconst inverseProjectMat = _math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.mat4();\r\n\t\t\t\treturn () => {\r\n\t\t\t\t\tif (projMatDirty) {\r\n\t\t\t\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.inverseMat4(scene.camera.projMatrix, inverseProjectMat);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn inverseProjectMat;\r\n\t\t\t\t};\r\n\t\t\t})();\r\n\t\t}\r\n\r\n\t\tconst gl = this._scene.canvas.gl;\r\n\t\tconst program = this._program;\r\n\t\tconst scene = this._scene;\r\n\t\tconst viewportWidth = gl.drawingBufferWidth;\r\n\t\tconst viewportHeight = gl.drawingBufferHeight;\r\n\t\tconst projectState = scene.camera.project._state;\r\n\t\tconst near = projectState.near;\r\n\t\tconst far = projectState.far;\r\n\r\n\t\tgl.viewport(0, 0, viewportWidth, viewportHeight);\r\n\t\tgl.clearColor(0, 0, 0, 1);\r\n\t\tgl.enable(gl.DEPTH_TEST);\r\n\t\tgl.disable(gl.BLEND);\r\n\t\tgl.frontFace(gl.CCW);\r\n\t\tgl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\r\n\r\n\t\tprogram.bind();\r\n\r\n\t\ttempVec2a[0] = viewportWidth;\r\n\t\ttempVec2a[1] = viewportHeight;\r\n\r\n\t\tgl.uniform2fv(this._uViewport, tempVec2a);\r\n\t\tgl.uniform1f(this._uCameraNear, near);\r\n\t\tgl.uniform1f(this._uCameraFar, far);\r\n\r\n\t\tgl.uniform1f(this._uDepthCutoff, blurDepthCutoff);\r\n\r\n\t\tif (direction === 0) {\r\n\t\t\t// Horizontal\r\n\t\t\tgl.uniform2fv(this._uSampleOffsets, sampleOffsetsHor);\r\n\t\t} else {\r\n\t\t\t// Vertical\r\n\t\t\tgl.uniform2fv(this._uSampleOffsets, sampleOffsetsVert);\r\n\t\t}\r\n\r\n\t\tgl.uniform1fv(this._uSampleWeights, sampleWeights);\r\n\r\n\t\tconst depthTexture = depthRenderBuffer.getDepthTexture();\r\n\t\tconst occlusionTexture = occlusionRenderBuffer.getTexture();\r\n\r\n\t\tprogram.bindTexture(this._uDepthTexture, depthTexture, 0); // TODO: use FrameCtx.textureUnit\r\n\t\tprogram.bindTexture(this._uOcclusionTexture, occlusionTexture, 1);\r\n\r\n\t\tthis._aUV.bindArrayBuffer(this._uvBuf);\r\n\t\tthis._aPosition.bindArrayBuffer(this._positionsBuf);\r\n\t\tthis._indicesBuf.bind();\r\n\r\n\t\tgl.drawElements(gl.TRIANGLES, this._indicesBuf.numItems, this._indicesBuf.itemType, 0);\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tthis._program.destroy();\r\n\t}\r\n}\r\n\r\nfunction createSampleWeights(kernelRadius, stdDev) {\r\n\tconst weights = [];\r\n\tfor (let i = 0; i <= kernelRadius; i++) {\r\n\t\tweights.push(gaussian(i, stdDev));\r\n\t}\r\n\treturn weights; // TODO: Optimize\r\n}\r\n\r\nfunction gaussian(x, stdDev) {\r\n\treturn Math.exp(-(x * x) / (2.0 * (stdDev * stdDev))) / (Math.sqrt(2.0 * Math.PI) * stdDev);\r\n}\r\n\r\nfunction createSampleOffsets(kernelRadius, uvIncrement) {\r\n\tconst offsets = [];\r\n\tfor (let i = 0; i <= kernelRadius; i++) {\r\n\t\toffsets.push(uvIncrement[0] * i);\r\n\t\toffsets.push(uvIncrement[1] * i);\r\n\t}\r\n\treturn offsets;\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/webgl/sao/SAODepthLimitedBlurRenderer.js?");
|
|
5208
5208
|
|
|
5209
5209
|
/***/ }),
|
|
5210
5210
|
|