@xeokit/xeokit-sdk 2.6.109 → 2.6.112

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.
@@ -1,11 +1,11 @@
1
1
  /**
2
- * xeokit-sdk v2.6.109
3
- * Commit: 3796b67f0bbcca7382160e5030522506fb49a54e
4
- * Built: 2026-05-08T06:25:43.604Z
2
+ * xeokit-sdk v2.6.112
3
+ * Commit: 2ce58020bcf3e4af1f68e47009f413c448a8a2a4
4
+ * Built: 2026-06-25T15:09:42.607Z
5
5
  */
6
6
 
7
7
  if (typeof window !== 'undefined') {
8
- window.__XEOKIT__ = { version: '2.6.109', commit: '3796b67f0bbcca7382160e5030522506fb49a54e', built: '2026-05-08T06:25:43.604Z' };
8
+ window.__XEOKIT__ = { version: '2.6.112', commit: '2ce58020bcf3e4af1f68e47009f413c448a8a2a4', built: '2026-06-25T15:09:42.607Z' };
9
9
  }
10
10
 
11
11
  'use strict';
@@ -59077,26 +59077,18 @@ class CameraUpdater {
59077
59077
 
59078
59078
  if (updates.rotateDeltaY !== 0 || updates.rotateDeltaX !== 0) {
59079
59079
 
59080
- if ((!configs.firstPerson) && configs.followPointer && pivotController.getPivoting()) {
59081
- pivotController.continuePivot(updates.rotateDeltaY, updates.rotateDeltaX);
59082
- pivotController.showPivot();
59083
-
59084
- } else {
59085
-
59080
+ if (configs.firstPerson) {
59086
59081
  if (updates.rotateDeltaX !== 0) {
59087
- if (configs.firstPerson) {
59088
- camera.pitch(-updates.rotateDeltaX);
59089
- } else {
59090
- camera.orbitPitch(updates.rotateDeltaX);
59091
- }
59082
+ camera.pitch(-updates.rotateDeltaX);
59092
59083
  }
59093
-
59094
59084
  if (updates.rotateDeltaY !== 0) {
59095
- if (configs.firstPerson) {
59096
- camera.yaw(updates.rotateDeltaY);
59097
- } else {
59098
- camera.orbitYaw(updates.rotateDeltaY);
59099
- }
59085
+ camera.yaw(updates.rotateDeltaY);
59086
+ }
59087
+ }
59088
+ else {
59089
+ if (configs.followPointer && pivotController.getPivoting()){
59090
+ pivotController.continuePivot(updates.rotateDeltaY, updates.rotateDeltaX);
59091
+ pivotController.showPivot();
59100
59092
  }
59101
59093
  }
59102
59094
 
@@ -111599,11 +111591,12 @@ function getBasePath(src) {
111599
111591
  function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok, error) {
111600
111592
  const spinner = plugin.viewer.scene.canvas.spinner;
111601
111593
  spinner.processes++;
111602
- parse$4(gltf, GLTFLoader, {
111594
+ const loadersGl = options.loadersGl;
111595
+ (loadersGl ? loadersGl.core.parse : parse$4)(gltf, loadersGl ? loadersGl.gltf.GLTFLoader : GLTFLoader, {
111603
111596
  ...(options.parseOptions || { }),
111604
111597
  baseUri: options.basePath
111605
111598
  }).then((gltfData) => {
111606
- const processedGLTF = postProcessGLTF(gltfData);
111599
+ const processedGLTF = (loadersGl ? loadersGl.gltf.postProcessGLTF : postProcessGLTF)(gltfData);
111607
111600
  const ctx = {
111608
111601
  src: src,
111609
111602
  entityId: options.entityId,
@@ -112505,6 +112498,9 @@ class GLTFLoaderPlugin extends Plugin {
112505
112498
  * @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.
112506
112499
  * @param {*} [params.parseOptions={}] Options to pass to loaders.gl parse method, eg. ````{ gltf: { excludeExtensions: { "KHR_texture_transform": false } } }````.
112507
112500
  * @param {Boolean} [params.entityPerMesh=false] Create an entity for each mesh, instead of grouping leaf meshes under their common entity.
112501
+ * @param {*} [params.loadersGl={core,gltf}] Alternative user-provided loaders.gl library.
112502
+ * This feature has been tested with loaders.gl 4.3.4 version.
112503
+ * Because loaders.gl is supplied externally, xeokit cannot guarantee compatibility with all loaders.gl versions.
112508
112504
  * @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}
112509
112505
  */
112510
112506
  load(params = {}) {
@@ -121090,6 +121086,9 @@ class ViewCullPlugin extends Plugin {
121090
121086
  if (cullDirty) {
121091
121087
  const kdNode = this._kdRoot;
121092
121088
  if (kdNode) {
121089
+ for (let objectIdx = 0, len = this._objectCullStates.numObjects; objectIdx < len; objectIdx++) {
121090
+ this._objectCullStates.setObjectViewCulled(objectIdx, false);
121091
+ }
121093
121092
  this._visitKDNode(kdNode);
121094
121093
  }
121095
121094
  }
@@ -123551,7 +123550,7 @@ function load$4(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
123551
123550
  if (!geometryArrays) {
123552
123551
 
123553
123552
  geometryArrays = {
123554
- batchThisMesh: (!options.reuseGeometries)
123553
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
123555
123554
  };
123556
123555
 
123557
123556
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
@@ -124065,7 +124064,7 @@ function load$3(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
124065
124064
 
124066
124065
  if (!geometryArrays) {
124067
124066
  geometryArrays = {
124068
- batchThisMesh: (!options.reuseGeometries)
124067
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
124069
124068
  };
124070
124069
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
124071
124070
  let geometryValid = false;
@@ -124671,7 +124670,7 @@ function load$2(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
124671
124670
 
124672
124671
  if (!geometryArrays) {
124673
124672
  geometryArrays = {
124674
- batchThisMesh: (!options.reuseGeometries)
124673
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
124675
124674
  };
124676
124675
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
124677
124676
  let geometryValid = false;
@@ -125319,7 +125318,7 @@ function load$1(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
125319
125318
 
125320
125319
  if (!geometryArrays) {
125321
125320
  geometryArrays = {
125322
- batchThisMesh: (!options.reuseGeometries)
125321
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
125323
125322
  };
125324
125323
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
125325
125324
  let geometryValid = false;
@@ -126054,7 +126053,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx)
126054
126053
 
126055
126054
  if (!geometryArrays) {
126056
126055
  geometryArrays = {
126057
- batchThisMesh: (!options.reuseGeometries)
126056
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
126058
126057
  };
126059
126058
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
126060
126059
  const axisLabel = eachGeometryAxisLabel[geometryIndex];
@@ -126990,7 +126989,7 @@ class XKTLoaderPlugin extends Plugin {
126990
126989
  * @param {String[]} [cfg.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
126991
126990
  * @param {String[]} [cfg.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
126992
126991
  * @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}.
126993
- * @param {Boolean} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand
126992
+ * @param {Boolean|Function} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand, a function will be called with a `{ instanceCount: <number> }` argument.
126994
126993
  * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly
126995
126994
  * improve Viewer performance for models that have a lot of geometry reuse, but may also increase the amount of
126996
126995
  * browser and GPU memory they require. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.
@@ -127258,7 +127257,7 @@ class XKTLoaderPlugin extends Plugin {
127258
127257
  * @type {Boolean}
127259
127258
  */
127260
127259
  set reuseGeometries(value) {
127261
- this._reuseGeometries = value !== false;
127260
+ this._reuseGeometries = value;
127262
127261
  }
127263
127262
 
127264
127263
  /**
@@ -127276,6 +127275,7 @@ class XKTLoaderPlugin extends Plugin {
127276
127275
  * @param {ArrayBuffer} [params.xkt] The *````.xkt````* file data, as an alternative to the ````src```` parameter.
127277
127276
  * @param {String} [params.metaModelSrc] Path or URL to an optional metadata file, as an alternative to the ````metaModelData```` parameter.
127278
127277
  * @param {*} [params.metaModelData] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.
127278
+ * @param {Boolean} [params.loadIntoMetaScene=true] Whether to load metadata into MetaScene, otherwise expose as SceneModel::metadata.
127279
127279
  * @param {String} [params.manifestSrc] Path or URL to a JSON manifest file that provides paths to ````.xkt```` files to load as parts of the model. Use this option to load models that have been split into
127280
127280
  * multiple XKT files. See [tutorial](https://xeokit.io/blog/automatically-splitting-large-models-for-better-performance) for more info.
127281
127281
  * @param {Object} [params.manifest] A JSON manifest object (as an alternative to a path or URL) that provides paths to ````.xkt```` files to load as parts of the model. Use this option to load models that have been split into
@@ -127299,9 +127299,9 @@ class XKTLoaderPlugin extends Plugin {
127299
127299
  * 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.
127300
127300
  * @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}.
127301
127301
  * @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 XKTLoaderPlugin#globalizeObjectIds} for more info.
127302
- * @param {Boolean} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand
127303
- * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly
127304
- * improve Viewer performance for models that have excessive geometry reuse, but may also increases the amount of
127302
+ * @param {Boolean|Function} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand
127303
+ * all geometry instances into batches (````false````), and not use instancing to render them. A function will be called with a `{ instanceCount: <number> }` argument. Setting this ````false```` can significantly
127304
+ * improve Viewer performance for models that have excessive geometry reuse, but may also increase the amount of
127305
127305
  * browser and GPU memory used by the model. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.
127306
127306
  * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to
127307
127307
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
@@ -127328,7 +127328,8 @@ class XKTLoaderPlugin extends Plugin {
127328
127328
  const includeIds = params.includeIds || this._includeIds;
127329
127329
  const objectDefaults = params.objectDefaults || this._objectDefaults;
127330
127330
 
127331
- options.reuseGeometries = (params.reuseGeometries !== null && params.reuseGeometries !== undefined) ? params.reuseGeometries : (this._reuseGeometries !== false);
127331
+ const reuseGeometries = params.reuseGeometries ?? this._reuseGeometries;
127332
+ options.reuseGeometries = (typeof reuseGeometries !== "function") ? (() => reuseGeometries) : reuseGeometries;
127332
127333
 
127333
127334
  if (includeTypes) {
127334
127335
  options.includeTypesMap = {};
@@ -127371,10 +127372,30 @@ class XKTLoaderPlugin extends Plugin {
127371
127372
 
127372
127373
  const modelId = sceneModel.id; // In case ID was auto-generated
127373
127374
 
127374
- const metaModel = new MetaModel({
127375
- metaScene: this.viewer.metaScene,
127376
- id: modelId
127377
- });
127375
+ const loadIntoMetaScene = (! ("loadIntoMetaScene" in params)) || params.loadIntoMetaScene;
127376
+ const metaModel = (loadIntoMetaScene
127377
+ ? new MetaModel({
127378
+ id: modelId,
127379
+ metaScene: this.viewer.metaScene
127380
+ })
127381
+ : (function() {
127382
+ let firstMetadata = null;
127383
+ let modelMetadata = null;
127384
+ return {
127385
+ loadData: metadata => {
127386
+ if (! firstMetadata) {
127387
+ firstMetadata = metadata;
127388
+ } else {
127389
+ if (! modelMetadata) {
127390
+ modelMetadata = { };
127391
+ Object.entries(firstMetadata).forEach(([ k, v ]) => modelMetadata[k] = Array.isArray(v) ? v.slice(0) : v);
127392
+ }
127393
+ Object.entries(metadata).forEach(([ k, v ]) => { if (Array.isArray(v)) { v.forEach(e => modelMetadata[k].push(e)); } });
127394
+ }
127395
+ },
127396
+ finalize: () => sceneModel.metadata = modelMetadata || firstMetadata
127397
+ };
127398
+ })());
127378
127399
 
127379
127400
  this.viewer.scene.canvas.spinner.processes++;
127380
127401
 
@@ -127387,7 +127408,7 @@ class XKTLoaderPlugin extends Plugin {
127387
127408
  metaModel.finalize();
127388
127409
  this.viewer.scene.canvas.spinner.processes--;
127389
127410
  sceneModel.once("destroyed", () => {
127390
- this.viewer.metaScene.destroyMetaModel(metaModel.id);
127411
+ loadIntoMetaScene && this.viewer.metaScene.destroyMetaModel(metaModel.id);
127391
127412
  });
127392
127413
  this.scheduleTask(() => {
127393
127414
  if (sceneModel.destroyed) {
@@ -1,11 +1,11 @@
1
1
  /**
2
- * xeokit-sdk v2.6.109
3
- * Commit: 3796b67f0bbcca7382160e5030522506fb49a54e
4
- * Built: 2026-05-08T06:25:43.604Z
2
+ * xeokit-sdk v2.6.112
3
+ * Commit: 2ce58020bcf3e4af1f68e47009f413c448a8a2a4
4
+ * Built: 2026-06-25T15:09:42.607Z
5
5
  */
6
6
 
7
7
  if (typeof window !== 'undefined') {
8
- window.__XEOKIT__ = { version: '2.6.109', commit: '3796b67f0bbcca7382160e5030522506fb49a54e', built: '2026-05-08T06:25:43.604Z' };
8
+ window.__XEOKIT__ = { version: '2.6.112', commit: '2ce58020bcf3e4af1f68e47009f413c448a8a2a4', built: '2026-06-25T15:09:42.607Z' };
9
9
  }
10
10
 
11
11
  /** @private */
@@ -59073,26 +59073,18 @@ class CameraUpdater {
59073
59073
 
59074
59074
  if (updates.rotateDeltaY !== 0 || updates.rotateDeltaX !== 0) {
59075
59075
 
59076
- if ((!configs.firstPerson) && configs.followPointer && pivotController.getPivoting()) {
59077
- pivotController.continuePivot(updates.rotateDeltaY, updates.rotateDeltaX);
59078
- pivotController.showPivot();
59079
-
59080
- } else {
59081
-
59076
+ if (configs.firstPerson) {
59082
59077
  if (updates.rotateDeltaX !== 0) {
59083
- if (configs.firstPerson) {
59084
- camera.pitch(-updates.rotateDeltaX);
59085
- } else {
59086
- camera.orbitPitch(updates.rotateDeltaX);
59087
- }
59078
+ camera.pitch(-updates.rotateDeltaX);
59088
59079
  }
59089
-
59090
59080
  if (updates.rotateDeltaY !== 0) {
59091
- if (configs.firstPerson) {
59092
- camera.yaw(updates.rotateDeltaY);
59093
- } else {
59094
- camera.orbitYaw(updates.rotateDeltaY);
59095
- }
59081
+ camera.yaw(updates.rotateDeltaY);
59082
+ }
59083
+ }
59084
+ else {
59085
+ if (configs.followPointer && pivotController.getPivoting()){
59086
+ pivotController.continuePivot(updates.rotateDeltaY, updates.rotateDeltaX);
59087
+ pivotController.showPivot();
59096
59088
  }
59097
59089
  }
59098
59090
 
@@ -111595,11 +111587,12 @@ function getBasePath(src) {
111595
111587
  function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok, error) {
111596
111588
  const spinner = plugin.viewer.scene.canvas.spinner;
111597
111589
  spinner.processes++;
111598
- parse$4(gltf, GLTFLoader, {
111590
+ const loadersGl = options.loadersGl;
111591
+ (loadersGl ? loadersGl.core.parse : parse$4)(gltf, loadersGl ? loadersGl.gltf.GLTFLoader : GLTFLoader, {
111599
111592
  ...(options.parseOptions || { }),
111600
111593
  baseUri: options.basePath
111601
111594
  }).then((gltfData) => {
111602
- const processedGLTF = postProcessGLTF(gltfData);
111595
+ const processedGLTF = (loadersGl ? loadersGl.gltf.postProcessGLTF : postProcessGLTF)(gltfData);
111603
111596
  const ctx = {
111604
111597
  src: src,
111605
111598
  entityId: options.entityId,
@@ -112501,6 +112494,9 @@ class GLTFLoaderPlugin extends Plugin {
112501
112494
  * @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.
112502
112495
  * @param {*} [params.parseOptions={}] Options to pass to loaders.gl parse method, eg. ````{ gltf: { excludeExtensions: { "KHR_texture_transform": false } } }````.
112503
112496
  * @param {Boolean} [params.entityPerMesh=false] Create an entity for each mesh, instead of grouping leaf meshes under their common entity.
112497
+ * @param {*} [params.loadersGl={core,gltf}] Alternative user-provided loaders.gl library.
112498
+ * This feature has been tested with loaders.gl 4.3.4 version.
112499
+ * Because loaders.gl is supplied externally, xeokit cannot guarantee compatibility with all loaders.gl versions.
112504
112500
  * @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}
112505
112501
  */
112506
112502
  load(params = {}) {
@@ -121086,6 +121082,9 @@ class ViewCullPlugin extends Plugin {
121086
121082
  if (cullDirty) {
121087
121083
  const kdNode = this._kdRoot;
121088
121084
  if (kdNode) {
121085
+ for (let objectIdx = 0, len = this._objectCullStates.numObjects; objectIdx < len; objectIdx++) {
121086
+ this._objectCullStates.setObjectViewCulled(objectIdx, false);
121087
+ }
121089
121088
  this._visitKDNode(kdNode);
121090
121089
  }
121091
121090
  }
@@ -123547,7 +123546,7 @@ function load$4(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
123547
123546
  if (!geometryArrays) {
123548
123547
 
123549
123548
  geometryArrays = {
123550
- batchThisMesh: (!options.reuseGeometries)
123549
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
123551
123550
  };
123552
123551
 
123553
123552
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
@@ -124061,7 +124060,7 @@ function load$3(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
124061
124060
 
124062
124061
  if (!geometryArrays) {
124063
124062
  geometryArrays = {
124064
- batchThisMesh: (!options.reuseGeometries)
124063
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
124065
124064
  };
124066
124065
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
124067
124066
  let geometryValid = false;
@@ -124667,7 +124666,7 @@ function load$2(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
124667
124666
 
124668
124667
  if (!geometryArrays) {
124669
124668
  geometryArrays = {
124670
- batchThisMesh: (!options.reuseGeometries)
124669
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
124671
124670
  };
124672
124671
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
124673
124672
  let geometryValid = false;
@@ -125315,7 +125314,7 @@ function load$1(viewer, options, inflatedData, sceneModel, metaModel, manifestCt
125315
125314
 
125316
125315
  if (!geometryArrays) {
125317
125316
  geometryArrays = {
125318
- batchThisMesh: (!options.reuseGeometries)
125317
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
125319
125318
  };
125320
125319
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
125321
125320
  let geometryValid = false;
@@ -126050,7 +126049,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx)
126050
126049
 
126051
126050
  if (!geometryArrays) {
126052
126051
  geometryArrays = {
126053
- batchThisMesh: (!options.reuseGeometries)
126052
+ batchThisMesh: (!options.reuseGeometries({ instanceCount: geometryReuseCount }))
126054
126053
  };
126055
126054
  const primitiveType = eachGeometryPrimitiveType[geometryIndex];
126056
126055
  const axisLabel = eachGeometryAxisLabel[geometryIndex];
@@ -126986,7 +126985,7 @@ class XKTLoaderPlugin extends Plugin {
126986
126985
  * @param {String[]} [cfg.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
126987
126986
  * @param {String[]} [cfg.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
126988
126987
  * @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}.
126989
- * @param {Boolean} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand
126988
+ * @param {Boolean|Function} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand, a function will be called with a `{ instanceCount: <number> }` argument.
126990
126989
  * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly
126991
126990
  * improve Viewer performance for models that have a lot of geometry reuse, but may also increase the amount of
126992
126991
  * browser and GPU memory they require. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.
@@ -127254,7 +127253,7 @@ class XKTLoaderPlugin extends Plugin {
127254
127253
  * @type {Boolean}
127255
127254
  */
127256
127255
  set reuseGeometries(value) {
127257
- this._reuseGeometries = value !== false;
127256
+ this._reuseGeometries = value;
127258
127257
  }
127259
127258
 
127260
127259
  /**
@@ -127272,6 +127271,7 @@ class XKTLoaderPlugin extends Plugin {
127272
127271
  * @param {ArrayBuffer} [params.xkt] The *````.xkt````* file data, as an alternative to the ````src```` parameter.
127273
127272
  * @param {String} [params.metaModelSrc] Path or URL to an optional metadata file, as an alternative to the ````metaModelData```` parameter.
127274
127273
  * @param {*} [params.metaModelData] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.
127274
+ * @param {Boolean} [params.loadIntoMetaScene=true] Whether to load metadata into MetaScene, otherwise expose as SceneModel::metadata.
127275
127275
  * @param {String} [params.manifestSrc] Path or URL to a JSON manifest file that provides paths to ````.xkt```` files to load as parts of the model. Use this option to load models that have been split into
127276
127276
  * multiple XKT files. See [tutorial](https://xeokit.io/blog/automatically-splitting-large-models-for-better-performance) for more info.
127277
127277
  * @param {Object} [params.manifest] A JSON manifest object (as an alternative to a path or URL) that provides paths to ````.xkt```` files to load as parts of the model. Use this option to load models that have been split into
@@ -127295,9 +127295,9 @@ class XKTLoaderPlugin extends Plugin {
127295
127295
  * 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.
127296
127296
  * @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}.
127297
127297
  * @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 XKTLoaderPlugin#globalizeObjectIds} for more info.
127298
- * @param {Boolean} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand
127299
- * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly
127300
- * improve Viewer performance for models that have excessive geometry reuse, but may also increases the amount of
127298
+ * @param {Boolean|Function} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand
127299
+ * all geometry instances into batches (````false````), and not use instancing to render them. A function will be called with a `{ instanceCount: <number> }` argument. Setting this ````false```` can significantly
127300
+ * improve Viewer performance for models that have excessive geometry reuse, but may also increase the amount of
127301
127301
  * browser and GPU memory used by the model. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.
127302
127302
  * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to
127303
127303
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
@@ -127324,7 +127324,8 @@ class XKTLoaderPlugin extends Plugin {
127324
127324
  const includeIds = params.includeIds || this._includeIds;
127325
127325
  const objectDefaults = params.objectDefaults || this._objectDefaults;
127326
127326
 
127327
- options.reuseGeometries = (params.reuseGeometries !== null && params.reuseGeometries !== undefined) ? params.reuseGeometries : (this._reuseGeometries !== false);
127327
+ const reuseGeometries = params.reuseGeometries ?? this._reuseGeometries;
127328
+ options.reuseGeometries = (typeof reuseGeometries !== "function") ? (() => reuseGeometries) : reuseGeometries;
127328
127329
 
127329
127330
  if (includeTypes) {
127330
127331
  options.includeTypesMap = {};
@@ -127367,10 +127368,30 @@ class XKTLoaderPlugin extends Plugin {
127367
127368
 
127368
127369
  const modelId = sceneModel.id; // In case ID was auto-generated
127369
127370
 
127370
- const metaModel = new MetaModel({
127371
- metaScene: this.viewer.metaScene,
127372
- id: modelId
127373
- });
127371
+ const loadIntoMetaScene = (! ("loadIntoMetaScene" in params)) || params.loadIntoMetaScene;
127372
+ const metaModel = (loadIntoMetaScene
127373
+ ? new MetaModel({
127374
+ id: modelId,
127375
+ metaScene: this.viewer.metaScene
127376
+ })
127377
+ : (function() {
127378
+ let firstMetadata = null;
127379
+ let modelMetadata = null;
127380
+ return {
127381
+ loadData: metadata => {
127382
+ if (! firstMetadata) {
127383
+ firstMetadata = metadata;
127384
+ } else {
127385
+ if (! modelMetadata) {
127386
+ modelMetadata = { };
127387
+ Object.entries(firstMetadata).forEach(([ k, v ]) => modelMetadata[k] = Array.isArray(v) ? v.slice(0) : v);
127388
+ }
127389
+ Object.entries(metadata).forEach(([ k, v ]) => { if (Array.isArray(v)) { v.forEach(e => modelMetadata[k].push(e)); } });
127390
+ }
127391
+ },
127392
+ finalize: () => sceneModel.metadata = modelMetadata || firstMetadata
127393
+ };
127394
+ })());
127374
127395
 
127375
127396
  this.viewer.scene.canvas.spinner.processes++;
127376
127397
 
@@ -127383,7 +127404,7 @@ class XKTLoaderPlugin extends Plugin {
127383
127404
  metaModel.finalize();
127384
127405
  this.viewer.scene.canvas.spinner.processes--;
127385
127406
  sceneModel.once("destroyed", () => {
127386
- this.viewer.metaScene.destroyMetaModel(metaModel.id);
127407
+ loadIntoMetaScene && this.viewer.metaScene.destroyMetaModel(metaModel.id);
127387
127408
  });
127388
127409
  this.scheduleTask(() => {
127389
127410
  if (sceneModel.destroyed) {