@xeokit/xeokit-sdk 2.6.17 → 2.6.19

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.
Files changed (37) hide show
  1. package/dist/xeokit-sdk.cjs.js +2345 -117
  2. package/dist/xeokit-sdk.es.js +2335 -118
  3. package/dist/xeokit-sdk.es5.js +558 -418
  4. package/dist/xeokit-sdk.min.cjs.js +4 -4
  5. package/dist/xeokit-sdk.min.es.js +5 -5
  6. package/dist/xeokit-sdk.min.es5.js +4 -4
  7. package/package.json +2 -2
  8. package/src/extras/PointerLens/PointerLens.js +2 -2
  9. package/src/plugins/AnnotationsPlugin/Annotation.js +1 -0
  10. package/src/plugins/CityJSONLoaderPlugin/CityJSONDefaultDataSource.js +15 -2
  11. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.js +1 -1
  12. package/src/plugins/DotBIMLoaderPlugin/DotBIMDefaultDataSource.js +15 -2
  13. package/src/plugins/GLTFLoaderPlugin/GLTFDefaultDataSource.js +18 -5
  14. package/src/plugins/LASLoaderPlugin/LASDefaultDataSource.js +15 -1
  15. package/src/plugins/STLLoaderPlugin/STLDefaultDataSource.js +17 -0
  16. package/src/plugins/WebIFCLoaderPlugin/WebIFCDefaultDataSource.js +16 -1
  17. package/src/plugins/XKTLoaderPlugin/XKTDefaultDataSource.js +18 -4
  18. package/src/plugins/ZonesPlugin/index.js +2046 -0
  19. package/src/plugins/index.js +2 -1
  20. package/src/plugins/lib/html/Dot.js +19 -1
  21. package/src/viewer/Viewer.js +3 -1
  22. package/src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js +9 -0
  23. package/src/viewer/scene/geometry/builders/buildLineGeometry.js +267 -0
  24. package/src/viewer/scene/input/Input.js +41 -0
  25. package/src/viewer/scene/marker/Marker.js +1 -1
  26. package/src/viewer/scene/mesh/Mesh.js +5 -0
  27. package/src/viewer/scene/model/SceneModel.js +7 -1
  28. package/src/viewer/scene/scene/Scene.js +30 -4
  29. package/src/viewer/scene/sectionPlane/SectionPlane.js +3 -7
  30. package/src/viewer/scene/webgl/Renderer.js +84 -79
  31. package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +1 -1
  32. package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +8 -4
  33. package/types/viewer/Viewer.d.ts +2 -0
  34. package/types/viewer/scene/geometry/builders/buildLineGeometry.d.ts +22 -0
  35. package/types/viewer/scene/geometry/builders/buildPolylineGeometry.d.ts +2 -2
  36. package/types/viewer/scene/scene/Scene.d.ts +11 -0
  37. package/dist/web-ifc.wasm +0 -0
@@ -19,4 +19,5 @@ export * from "./XML3DLoaderPlugin/index.js";
19
19
  export * from "./WebIFCLoaderPlugin/index.js";
20
20
  export * from "./LASLoaderPlugin/index.js";
21
21
  export * from "./CityJSONLoaderPlugin/index.js";
22
- export * from "./DotBIMLoaderPlugin/index.js";
22
+ export * from "./DotBIMLoaderPlugin/index.js";
23
+ export * from "./ZonesPlugin/index.js";
@@ -135,7 +135,25 @@ class Dot {
135
135
  }
136
136
 
137
137
  }
138
-
138
+
139
+ if (cfg.onTouchstart) {
140
+ dotClickable.addEventListener('touchstart', (event) => {
141
+ cfg.onTouchstart(event, this);
142
+ });
143
+ }
144
+
145
+ if (cfg.onTouchmove) {
146
+ dotClickable.addEventListener('touchmove', (event) => {
147
+ cfg.onTouchmove(event, this);
148
+ });
149
+ }
150
+
151
+ if (cfg.onTouchend) {
152
+ dotClickable.addEventListener('touchend', (event) => {
153
+ cfg.onTouchend(event, this);
154
+ });
155
+ }
156
+
139
157
  this.setPos(cfg.x || 0, cfg.y || 0);
140
158
  this.setFillColor(cfg.fillColor);
141
159
  this.setBorderColor(cfg.borderColor);
@@ -3,7 +3,7 @@ import {CameraFlightAnimation} from "./scene/camera/CameraFlightAnimation.js";
3
3
  import {CameraControl} from "./scene/CameraControl/CameraControl.js";
4
4
  import {MetaScene} from "./metadata/MetaScene.js";
5
5
  import {LocaleService} from "./localization/LocaleService.js";
6
- import html2canvas from '../../node_modules/html2canvas/dist/html2canvas.esm.js';
6
+ import html2canvas from 'html2canvas/dist/html2canvas.esm.js';
7
7
 
8
8
  /**
9
9
  * The 3D Viewer at the heart of the xeokit SDK.
@@ -57,6 +57,7 @@ class Viewer {
57
57
  * 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
58
58
  * 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)
59
59
  * mode for storing geometry, which is the standard technique used in most graphics engines, and will work adequately on most low-end GPUs.
60
+ * @param {Number} [cfg.markerZOffset=-0.001] The Z value of offset for Marker's OcclusionTester. The closest the value is to 0.000 the more precise OcclusionTester will be, but at the same time the less precise it will behave for Markers that are located exactly on the Surface.
60
61
  * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity
61
62
  * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally
62
63
  * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing
@@ -120,6 +121,7 @@ class Viewer {
120
121
  pbrEnabled: (!!cfg.pbrEnabled),
121
122
  colorTextureEnabled: (cfg.colorTextureEnabled !== false),
122
123
  dtxEnabled: (!!cfg.dtxEnabled),
124
+ markerZOffset: cfg.markerZOffset,
123
125
  numCachedSectionPlanes: cfg.numCachedSectionPlanes
124
126
  });
125
127
 
@@ -55,6 +55,15 @@ class MousePickHandler {
55
55
  return;
56
56
  }
57
57
 
58
+ if (cameraControl.hasSubs("rayMove"))
59
+ {
60
+ const origin = math.vec3();
61
+ const direction = math.vec3();
62
+ // The origin from math.canvasPosToWorldRay is incorrect for a perspective camera, should be the same as scene.camera.eye
63
+ math.canvasPosToWorldRay(scene.canvas.canvas, scene.camera.viewMatrix, scene.camera.projMatrix, states.pointerCanvasPos, origin, direction);
64
+ cameraControl.fire("rayMove", { canvasPos: states.pointerCanvasPos, ray: { origin: origin, direction: direction, canvasPos: states.pointerCanvasPos } }, true);
65
+ }
66
+
58
67
  const hoverSubs = cameraControl.hasSubs("hover");
59
68
  const hoverEnterSubs = cameraControl.hasSubs("hoverEnter");
60
69
  const hoverOutSubs = cameraControl.hasSubs("hoverOut");
@@ -0,0 +1,267 @@
1
+ import {utils} from '../../utils.js';
2
+
3
+ /**
4
+ * @desc Creates a 3D line {@link Geometry}.
5
+ *
6
+ * ## Usage
7
+ *
8
+ * In the example below we'll create a {@link Mesh} with a line {@link ReadableGeometry}.
9
+ *
10
+ * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/scenegraph/#buildLineGeometry)]
11
+ *
12
+ * ````javascript
13
+ * //------------------------------------------------------------------------------------------------------------------
14
+ * // Import the modules we need for this example
15
+ * //------------------------------------------------------------------------------------------------------------------
16
+ *
17
+ * import {buildLineGeometry, Viewer, Mesh, ReadableGeometry, PhongMaterial} from "../../dist/xeokit-sdk.min.es.js";
18
+ *
19
+ * //------------------------------------------------------------------------------------------------------------------
20
+ * // Create a Viewer and arrange the camera
21
+ * //------------------------------------------------------------------------------------------------------------------
22
+ *
23
+ * const viewer = new Viewer({
24
+ * canvasId: "myCanvas"
25
+ * });
26
+ *
27
+ * viewer.camera.eye = [0, 0, 8];
28
+ * viewer.camera.look = [0, 0, 0];
29
+ * viewer.camera.up = [0, 1, 0];
30
+ *
31
+ * //------------------------------------------------------------------------------------------------------------------
32
+ * // Create a mesh with simple 2d line shape
33
+ * //------------------------------------------------------------------------------------------------------------------
34
+ *
35
+ * new Mesh(viewer.scene, {
36
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
37
+ * startPoint: [-5,-2,0],
38
+ * endPoint: [-5,2,0],
39
+ * })),
40
+ * material: new PhongMaterial(viewer.scene, {
41
+ * emissive: [0, 1,]
42
+ * })
43
+ * });
44
+ *
45
+ * //------------------------------------------------------------------------------------------------------------------
46
+ * // Create a mesh with simple 2d line shape with black color
47
+ * //------------------------------------------------------------------------------------------------------------------
48
+ *
49
+ * new Mesh(viewer.scene, {
50
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
51
+ * startPoint: [-4,-2,0],
52
+ * endPoint: [-4,2,0],
53
+ * })),
54
+ * material: new PhongMaterial(viewer.scene, {
55
+ * emissive: [0, 0, 0]
56
+ * })
57
+ * });
58
+ *
59
+ * //------------------------------------------------------------------------------------------------------------------
60
+ * // Create a mesh with simple 2d line shape with black color and simple pattern
61
+ * //------------------------------------------------------------------------------------------------------------------
62
+ *
63
+ * new Mesh(viewer.scene, {
64
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
65
+ * startPoint: [-3,-2,0],
66
+ * endPoint: [-3,2,0],
67
+ * pattern: [0.10],
68
+ * })),
69
+ * material: new PhongMaterial(viewer.scene, {
70
+ * emissive: [0, 0, 0]
71
+ * })
72
+ * });
73
+ *
74
+ * //------------------------------------------------------------------------------------------------------------------
75
+ * // Create a mesh with simple 2d line shape with blue color and simple pattern extended to end
76
+ * //------------------------------------------------------------------------------------------------------------------
77
+ *
78
+ * new Mesh(viewer.scene, {
79
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
80
+ * startPoint: [-2,-2,0],
81
+ * endPoint: [-2,2,0],
82
+ * pattern: [0.10],
83
+ * extendToEnd: true,
84
+ * })),
85
+ * material: new PhongMaterial(viewer.scene, {
86
+ * emissive: [0, 0, 1]
87
+ * })
88
+ * });
89
+ *
90
+ * //------------------------------------------------------------------------------------------------------------------
91
+ * // Create a mesh with simple 2d line shape with black color and more complex pattern
92
+ * //------------------------------------------------------------------------------------------------------------------
93
+ *
94
+ * new Mesh(viewer.scene, {
95
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
96
+ * startPoint: [-1,-2,0],
97
+ * endPoint: [-1,2,0],
98
+ * pattern: [0.15, 0.05],
99
+ * })),
100
+ * material: new PhongMaterial(viewer.scene, {
101
+ * emissive: [0, 0, 0]
102
+ * })
103
+ * });
104
+ *
105
+ * //------------------------------------------------------------------------------------------------------------------
106
+ * // Create a mesh with simple 2d line shape with blue color and more complex pattern extended to end
107
+ * //------------------------------------------------------------------------------------------------------------------
108
+ *
109
+ * new Mesh(viewer.scene, {
110
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
111
+ * startPoint: [0,-2,0],
112
+ * endPoint: [0,2,0],
113
+ * pattern: [0.15, 0.05],
114
+ * extendToEnd: true,
115
+ * })),
116
+ * material: new PhongMaterial(viewer.scene, {
117
+ * emissive: [0, 0, 1]
118
+ * })
119
+ * });
120
+ *
121
+ * //------------------------------------------------------------------------------------------------------------------
122
+ * // Create a mesh with simple 2d line shape with black color and complex pattern
123
+ * //------------------------------------------------------------------------------------------------------------------
124
+ *
125
+ * new Mesh(viewer.scene, {
126
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
127
+ * startPoint: [1,-2,0],
128
+ * endPoint: [1,2,0],
129
+ * pattern: [0.15, 0.05, 0.50],
130
+ * })),
131
+ * material: new PhongMaterial(viewer.scene, {
132
+ * emissive: [0, 0, 0]
133
+ * })
134
+ * });
135
+ *
136
+ * //------------------------------------------------------------------------------------------------------------------
137
+ * // Create a mesh with simple 2d line shape with blue color and complex pattern extended to end
138
+ * //------------------------------------------------------------------------------------------------------------------
139
+ *
140
+ * new Mesh(viewer.scene, {
141
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
142
+ * startPoint: [2,-2,0],
143
+ * endPoint: [2,2,0],
144
+ * pattern: [0.15, 0.05, 0.50],
145
+ * extendToEnd: true,
146
+ * })),
147
+ * material: new PhongMaterial(viewer.scene, {
148
+ * emissive: [0, 0, 1]
149
+ * })
150
+ * });
151
+ *
152
+ * //------------------------------------------------------------------------------------------------------------------
153
+ * // Create a mesh with simple 3d line shape with white color and simple pattern
154
+ * //------------------------------------------------------------------------------------------------------------------
155
+ *
156
+ * new Mesh(viewer.scene, {
157
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
158
+ * startPoint: [3,-2,-1],
159
+ * endPoint: [5,2,1],
160
+ * pattern: [0.10],
161
+ * })),
162
+ * material: new PhongMaterial(viewer.scene, {
163
+ * emissive: [1, 1, 1]
164
+ * })
165
+ * });
166
+ *
167
+ * //------------------------------------------------------------------------------------------------------------------
168
+ * // Create a mesh with simple 3d line shape with black color and simple dot pattern
169
+ * //------------------------------------------------------------------------------------------------------------------
170
+ *
171
+ * new Mesh(viewer.scene, {
172
+ * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({
173
+ * startPoint: [5,-2,-1],
174
+ * endPoint: [7,2,1],
175
+ * pattern: [0.03],
176
+ * })),
177
+ * material: new PhongMaterial(viewer.scene, {
178
+ * emissive: [0, 0, 0]
179
+ * })
180
+ * });
181
+ * ````
182
+ *
183
+ * @function buildLineGeometry
184
+ * @param {*} [cfg] Configs
185
+ * @param {String} [cfg.id] Optional ID, unique among all components in the parent {@link Scene}, generated automatically when omitted.
186
+ * @param {Number[]} [cfg.startPoint] 3D start point (x0, y0, z0).
187
+ * @param {Number[]} [cfg.endPoint] 3D end point (x1, y1, z1).
188
+ * @param {Number[]} [cfg.pattern] Lengths of segments that describe a pattern.
189
+ * @param {Bool} [cfg.extendToEnd] If true: it will try to make sure the line doesn't end up with a gap, as it will
190
+ * extend the last segment.
191
+ * @returns {Object} Configuration for a {@link Geometry} subtype.
192
+ */
193
+ function buildLineGeometry(cfg = {}) {
194
+
195
+ if (cfg.startPoint.length !== 3) {
196
+ throw "Start point should contain 3 elements in array: x, y and z";
197
+ }
198
+ if (cfg.endPoint.length !== 3) {
199
+ throw "End point should contain 3 elements in array: x, y and z";
200
+ }
201
+ let indices = [];
202
+ let points = [];
203
+ let x0 = cfg.startPoint[0]; let y0 = cfg.startPoint[1]; let z0 = cfg.startPoint[2];
204
+ let x1 = cfg.endPoint[0]; let y1 = cfg.endPoint[1]; let z1 = cfg.endPoint[2];
205
+ let lineLength = Math.sqrt((x1- x0)**2 + (y1 - y0)**2 + (z1 - z0)**2);
206
+ let normalizedDirectionVectorOfLine = [(x1-x0)/lineLength, (y1-y0)/lineLength, (z1-z0)/lineLength];
207
+
208
+ if (!cfg.pattern) {
209
+ indices.push(0);
210
+ indices.push(1);
211
+ points.push(x0, y0, z0, x1, y1, z1);
212
+ }
213
+ else {
214
+ let patternsNumber = cfg.pattern.length;
215
+ let gap = false;
216
+ let segmentFilled = 0.0;
217
+ let idOfCurrentPatternLength = 0;
218
+ let pointIndicesCounter = 0;
219
+ let currentStartPoint = [x0, y0, z0];
220
+ let currentPatternLength = cfg.pattern[idOfCurrentPatternLength];
221
+ points.push(currentStartPoint[0], currentStartPoint[1], currentStartPoint[2]);
222
+
223
+ while (currentPatternLength <= (lineLength - segmentFilled)) {
224
+ let vectorFromCurrentStartPointToCurrentEndPoint = [
225
+ normalizedDirectionVectorOfLine[0] * currentPatternLength,
226
+ normalizedDirectionVectorOfLine[1] * currentPatternLength,
227
+ normalizedDirectionVectorOfLine[2] * currentPatternLength,
228
+ ];
229
+ let currentEndPoint = [
230
+ currentStartPoint[0] + vectorFromCurrentStartPointToCurrentEndPoint[0],
231
+ currentStartPoint[1] + vectorFromCurrentStartPointToCurrentEndPoint[1],
232
+ currentStartPoint[2] + vectorFromCurrentStartPointToCurrentEndPoint[2],
233
+ ];
234
+
235
+ points.push(currentEndPoint[0], currentEndPoint[1], currentEndPoint[2]);
236
+
237
+ if (!gap) {
238
+ indices.push(pointIndicesCounter);
239
+ indices.push(pointIndicesCounter + 1);
240
+ }
241
+ gap = !gap;
242
+
243
+ pointIndicesCounter += 1;
244
+ currentStartPoint = currentEndPoint;
245
+ idOfCurrentPatternLength += 1;
246
+ if (idOfCurrentPatternLength >= patternsNumber) {
247
+ idOfCurrentPatternLength = 0;
248
+ }
249
+ segmentFilled += currentPatternLength;
250
+ currentPatternLength = cfg.pattern[idOfCurrentPatternLength];
251
+ }
252
+
253
+ if (cfg.extendToEnd) {
254
+ points.push(x1, y1, z1);
255
+ indices.push(indices.length - 2);
256
+ indices.push(indices.length - 1);
257
+ }
258
+ }
259
+
260
+ return utils.apply(cfg, {
261
+ primitive: "lines",
262
+ positions: points,
263
+ indices: indices,
264
+ });
265
+ }
266
+
267
+ export {buildLineGeometry};
@@ -1190,6 +1190,14 @@ class Input extends Component {
1190
1190
  }
1191
1191
  });
1192
1192
 
1193
+ this.element.addEventListener("contextmenu", this._contextmenuListener = (e) => {
1194
+ if (!this.enabled) {
1195
+ return;
1196
+ }
1197
+ this._getMouseCanvasPos(e);
1198
+ this.fire("contextmenu", this.mouseCanvasPos, true);
1199
+ });
1200
+
1193
1201
  const tickifiedMouseWheelFn = this.scene.tickify(
1194
1202
  (delta) => { this.fire("mousewheel", delta, true); }
1195
1203
  );
@@ -1223,6 +1231,24 @@ class Input extends Component {
1223
1231
  });
1224
1232
  }
1225
1233
 
1234
+ this.element.addEventListener("touchstart", this._touchstartListener = (e) => {
1235
+ if (!this.enabled) {
1236
+ return;
1237
+ }
1238
+ [...e.changedTouches].forEach(e => {
1239
+ this.fire("touchstart", [ e.identifier, this._getTouchCanvasPos(e) ], true);
1240
+ });
1241
+ });
1242
+
1243
+ this.element.addEventListener("touchend", this._touchendListener = (e) => {
1244
+ if (!this.enabled) {
1245
+ return;
1246
+ }
1247
+ [...e.changedTouches].forEach(e => {
1248
+ this.fire("touchend", [ e.identifier, this._getTouchCanvasPos(e) ], true);
1249
+ });
1250
+ });
1251
+
1226
1252
  this._eventsBound = true;
1227
1253
  }
1228
1254
 
@@ -1239,7 +1265,10 @@ class Input extends Component {
1239
1265
  document.removeEventListener("click", this._clickListener);
1240
1266
  document.removeEventListener("dblclick", this._dblClickListener);
1241
1267
  this.element.removeEventListener("mousemove", this._mouseMoveListener);
1268
+ this.element.removeEventListener("contextmenu", this._contextmenuListener);
1242
1269
  this.element.removeEventListener("wheel", this._mouseWheelListener);
1270
+ this.element.removeEventListener("touchstart", this._touchstartListener);
1271
+ this.element.removeEventListener("touchend", this._touchendListener);
1243
1272
  if (window.OrientationChangeEvent) {
1244
1273
  window.removeEventListener('orientationchange', this._orientationchangedListener);
1245
1274
  }
@@ -1252,6 +1281,18 @@ class Input extends Component {
1252
1281
  this._eventsBound = false;
1253
1282
  }
1254
1283
 
1284
+ _getTouchCanvasPos(event) {
1285
+ let element = event.target;
1286
+ let totalOffsetLeft = 0;
1287
+ let totalOffsetTop = 0;
1288
+ while (element.offsetParent) {
1289
+ totalOffsetLeft += element.offsetLeft;
1290
+ totalOffsetTop += element.offsetTop;
1291
+ element = element.offsetParent;
1292
+ }
1293
+ return [ event.pageX - totalOffsetLeft, event.pageY - totalOffsetTop ];
1294
+ }
1295
+
1255
1296
  _getMouseCanvasPos(event) {
1256
1297
  if (!event) {
1257
1298
  event = window.event;
@@ -370,7 +370,7 @@ class Marker extends Component {
370
370
  this.scene.camera.off(this._onCameraProjMatrix);
371
371
  if (this._entity) {
372
372
  if (this._onEntityDestroyed !== null) {
373
- this._entity.off(this._onEntityDestroyed);
373
+ this._entity.model.off(this._onEntityDestroyed);
374
374
  }
375
375
  if (this._onEntityModelDestroyed !== null) {
376
376
  this._entity.model.off(this._onEntityModelDestroyed);
@@ -216,11 +216,16 @@ class Mesh extends Component {
216
216
  * @param {EmphasisMaterial} [cfg.highlightMaterial] {@link EmphasisMaterial} to define the xrayed appearance for this Mesh. Inherits {@link Scene#highlightMaterial} by default.
217
217
  * @param {EmphasisMaterial} [cfg.selectedMaterial] {@link EmphasisMaterial} to define the selected appearance for this Mesh. Inherits {@link Scene#selectedMaterial} by default.
218
218
  * @param {EmphasisMaterial} [cfg.edgeMaterial] {@link EdgeMaterial} to define the appearance of enhanced edges for this Mesh. Inherits {@link Scene#edgeMaterial} by default.
219
+ * @param {Number} [cfg.renderOrder=0] Specifies the rendering order for this mESH. This is used to control the order in which
220
+ * mESHES are drawn when they have transparent objects, to give control over the order in which those objects are blended within the transparent
221
+ * render pass.
219
222
  */
220
223
  constructor(owner, cfg = {}) {
221
224
 
222
225
  super(owner, cfg);
223
226
 
227
+ this.renderOrder = cfg.renderOrder || 0;
228
+
224
229
  /**
225
230
  * ID of the corresponding object within the originating system, if any.
226
231
  *
@@ -1123,11 +1123,16 @@ export class SceneModel extends Component {
1123
1123
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
1124
1124
  * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
1125
1125
  * primitives. Only works while {@link DTX#enabled} is also ````true````.
1126
+ * @param {Number} [cfg.renderOrder=0] Specifies the rendering order for this SceneModel. This is used to control the order in which
1127
+ * SceneModels are drawn when they have transparent objects, to give control over the order in which those objects are blended within the transparent
1128
+ * render pass.
1126
1129
  */
1127
1130
  constructor(owner, cfg = {}) {
1128
1131
 
1129
1132
  super(owner, cfg);
1130
1133
 
1134
+ this.renderOrder = cfg.renderOrder || 0;
1135
+
1131
1136
  this._dtxEnabled = this.scene.dtxEnabled && (cfg.dtxEnabled !== false);
1132
1137
 
1133
1138
  this._enableVertexWelding = false; // Not needed for most objects, and very expensive, so disabled
@@ -3194,6 +3199,7 @@ export class SceneModel extends Component {
3194
3199
  _getVBOBatchingLayer(cfg) {
3195
3200
  const model = this;
3196
3201
  const origin = cfg.origin;
3202
+ const renderLayer = cfg.renderLayer || 0;
3197
3203
  const positionsDecodeHash = cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary ?
3198
3204
  this._createHashStringFromMatrix(cfg.positionsDecodeMatrix || cfg.positionsDecodeBoundary)
3199
3205
  : "-";
@@ -3680,7 +3686,7 @@ export class SceneModel extends Component {
3680
3686
  // -------------- RENDERING ---------------------------------------------------------------------------------------
3681
3687
 
3682
3688
  /** @private */
3683
- drawColorOpaque(frameCtx) {
3689
+ drawColorOpaque(frameCtx, layerList) {
3684
3690
  const renderFlags = this.renderFlags;
3685
3691
  for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3686
3692
  const layerIndex = renderFlags.visibleLayers[i];
@@ -864,6 +864,7 @@ class Scene extends Component {
864
864
  this._pbrEnabled = !!cfg.pbrEnabled;
865
865
  this._colorTextureEnabled = (cfg.colorTextureEnabled !== false);
866
866
  this._dtxEnabled = !!cfg.dtxEnabled;
867
+ this._markerZOffset = cfg.markerZOffset;
867
868
 
868
869
  // Register Scene on xeokit
869
870
  // Do this BEFORE we add components below
@@ -1427,6 +1428,22 @@ class Scene extends Component {
1427
1428
  return this._colorTextureEnabled;
1428
1429
  }
1429
1430
 
1431
+ /**
1432
+ * Gets the Z value of offset for Marker's OcclusionTester.
1433
+ * The closest the value is to 0.000 the more precise OcclusionTester will be, but at the same time the less
1434
+ * precise it will behave for Markers that are located exactly on the Surface.
1435
+ *
1436
+ * Default is ````-0.001````.
1437
+ *
1438
+ * @returns {Number} Z offset for Marker
1439
+ */
1440
+ get markerZOffset() {
1441
+ if (this._markerZOffset == null) {
1442
+ return -0.001;
1443
+ }
1444
+ return this._markerZOffset;
1445
+ }
1446
+
1430
1447
  /**
1431
1448
  * Performs an occlusion test on all {@link Marker}s in this {@link Scene}.
1432
1449
  *
@@ -2274,9 +2291,9 @@ class Scene extends Component {
2274
2291
  * @param {Number[]} [params.matrix] 4x4 transformation matrix to define the World-space ray origin and direction, as an alternative to ````origin```` and ````direction````.
2275
2292
  * @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.
2276
2293
  * @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.
2277
- * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels
2278
- * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.
2279
- * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.
2294
+ * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels.
2295
+ * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex. Only works when `canvasPos` given.
2296
+ * @param {boolean} [params.snapToEdge=true] Whether to snap to edge. Only works when `canvasPos` given.
2280
2297
  * @param {PickResult} [pickResult] Holds the results of the pick attempt. Will use the Scene's singleton PickResult if you don't supply your own.
2281
2298
  * @returns {PickResult} Holds results of the pick attempt, returned when an {@link Entity} is picked, else null. See method comments for description.
2282
2299
  */
@@ -2287,6 +2304,11 @@ class Scene extends Component {
2287
2304
  return null;
2288
2305
  }
2289
2306
 
2307
+ if ((params.snapToVertex || params.snapToEdge) && !params.canvasPos) {
2308
+ this.error("Scene.snapPick() `canvasPos` parameter expected for `snapToVertex:true` or `snapToEdge:true`");
2309
+ return;
2310
+ }
2311
+
2290
2312
  params = params || {};
2291
2313
 
2292
2314
  params.pickSurface = params.pickSurface || params.rayPick; // Backwards compatibility
@@ -2334,7 +2356,7 @@ class Scene extends Component {
2334
2356
 
2335
2357
  /**
2336
2358
  * @param {Object} params Picking parameters.
2337
- * @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.
2359
+ * @param {Number[]} params.canvasPos Canvas-space coordinates.
2338
2360
  * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels
2339
2361
  * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.
2340
2362
  * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.
@@ -2345,6 +2367,10 @@ class Scene extends Component {
2345
2367
  this._warnSnapPickDeprecated = true;
2346
2368
  this.warn("Scene.snapPick() is deprecated since v2.4.2 - use Scene.pick() instead")
2347
2369
  }
2370
+ if (!params.canvasPos) {
2371
+ this.error("Scene.snapPick() canvasPos parameter expected");
2372
+ return;
2373
+ }
2348
2374
  return this._renderer.snapPick(
2349
2375
  params.canvasPos,
2350
2376
  params.snapRadius || 30,
@@ -96,6 +96,7 @@ class SectionPlane extends Component {
96
96
  this._state.active = value !== false;
97
97
  this.glRedraw();
98
98
  this.fire("active", this._state.active);
99
+ this.scene.fire("sectionPlaneUpdated", this);
99
100
  }
100
101
 
101
102
  /**
@@ -176,13 +177,8 @@ class SectionPlane extends Component {
176
177
  * Inverts the direction of {@link SectionPlane#dir}.
177
178
  */
178
179
  flipDir() {
179
- const dir = this._state.dir;
180
- dir[0] *= -1.0;
181
- dir[1] *= -1.0;
182
- dir[2] *= -1.0;
183
- this._state.dist = (-math.dotVec3(this._state.pos, this._state.dir));
184
- this.fire("dir", this._state.dir);
185
- this.glRedraw();
180
+ math.mulVec3Scalar(this._state.dir, -1.0, this._state.dir);
181
+ this.dir = this._state.dir;
186
182
  }
187
183
 
188
184
  /**