@xeokit/xeokit-sdk 2.6.96 → 2.6.97

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xeokit/xeokit-sdk",
3
- "version": "2.6.96",
3
+ "version": "2.6.97",
4
4
  "description": "3D BIM IFC Viewer SDK for AEC engineering applications. Open Source JavaScript Toolkit based on pure WebGL for top performance, real-world coordinates and full double precision",
5
5
  "module": "./dist/xeokit-sdk.es.js",
6
6
  "main": "./dist/xeokit-sdk.cjs.js",
@@ -3337,34 +3337,37 @@ export class SceneModel extends Component {
3337
3337
  /**
3338
3338
  * @private
3339
3339
  */
3340
- _withEachVisibleLayer(testNumVisibleLayerPortions, cb) {
3340
+ _withEachVisibleLayer(frameCtx, testNumVisibleLayerPortions, cb) {
3341
3341
  if (testNumVisibleLayerPortions && (this.numVisibleLayerPortions === 0)) {
3342
3342
  return;
3343
3343
  }
3344
+ const testLayerCull = frameCtx.testAABB;
3344
3345
  const renderFlags = this.renderFlags;
3345
3346
  for (let i = 0, len = renderFlags.visibleLayers.length; i < len; i++) {
3346
- const layerIndex = renderFlags.visibleLayers[i];
3347
- cb(this.layerList[layerIndex]);
3348
- }
3349
- }
3350
-
3351
- drawColorOpaque (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawColorOpaque (this.renderFlags, frameCtx)); }
3352
- drawColorTransparent (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawColorTransparent (this.renderFlags, frameCtx)); }
3353
- drawDepth (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawDepth (this.renderFlags, frameCtx)); } // Dedicated to SAO because it skips transparent objects
3354
- drawSilhouetteXRayed (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteXRayed (this.renderFlags, frameCtx)); }
3355
- drawSilhouetteHighlighted(frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteHighlighted(this.renderFlags, frameCtx)); }
3356
- drawSilhouetteSelected (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawSilhouetteSelected (this.renderFlags, frameCtx)); }
3357
- drawEdgesColorOpaque (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesColorOpaque (this.renderFlags, frameCtx)); }
3358
- drawEdgesColorTransparent(frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesColorTransparent(this.renderFlags, frameCtx)); }
3359
- drawEdgesXRayed (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesXRayed (this.renderFlags, frameCtx)); }
3360
- drawEdgesHighlighted (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesHighlighted (this.renderFlags, frameCtx)); }
3361
- drawEdgesSelected (frameCtx) { this._withEachVisibleLayer(false, layer => layer.drawEdgesSelected (this.renderFlags, frameCtx)); }
3362
- drawOcclusion (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawOcclusion (this.renderFlags, frameCtx)); }
3363
- drawShadow (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawShadow (this.renderFlags, frameCtx)); }
3364
- drawPickMesh (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickMesh (this.renderFlags, frameCtx)); }
3365
- drawPickDepths (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickDepths (this.renderFlags, frameCtx)); }
3366
- drawPickNormals (frameCtx) { this._withEachVisibleLayer(true, layer => layer.drawPickNormals (this.renderFlags, frameCtx)); }
3367
- _drawSnap (frameCtx, isSnapInit) { this._withEachVisibleLayer(true, layer => layer.drawSnap (this.renderFlags, frameCtx, isSnapInit)); }
3347
+ const layer = this.layerList[renderFlags.visibleLayers[i]];
3348
+ if ((! testLayerCull) || testLayerCull(layer.getAABB())) {
3349
+ cb(layer);
3350
+ }
3351
+ }
3352
+ }
3353
+
3354
+ drawColorOpaque (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawColorOpaque (this.renderFlags, frameCtx)); }
3355
+ drawColorTransparent (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawColorTransparent (this.renderFlags, frameCtx)); }
3356
+ drawDepth (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawDepth (this.renderFlags, frameCtx)); } // Dedicated to SAO because it skips transparent objects
3357
+ drawSilhouetteXRayed (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawSilhouetteXRayed (this.renderFlags, frameCtx)); }
3358
+ drawSilhouetteHighlighted(frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawSilhouetteHighlighted(this.renderFlags, frameCtx)); }
3359
+ drawSilhouetteSelected (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawSilhouetteSelected (this.renderFlags, frameCtx)); }
3360
+ drawEdgesColorOpaque (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawEdgesColorOpaque (this.renderFlags, frameCtx)); }
3361
+ drawEdgesColorTransparent(frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawEdgesColorTransparent(this.renderFlags, frameCtx)); }
3362
+ drawEdgesXRayed (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawEdgesXRayed (this.renderFlags, frameCtx)); }
3363
+ drawEdgesHighlighted (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawEdgesHighlighted (this.renderFlags, frameCtx)); }
3364
+ drawEdgesSelected (frameCtx) { this._withEachVisibleLayer(frameCtx, false, layer => layer.drawEdgesSelected (this.renderFlags, frameCtx)); }
3365
+ drawOcclusion (frameCtx) { this._withEachVisibleLayer(frameCtx, true, layer => layer.drawOcclusion (this.renderFlags, frameCtx)); }
3366
+ drawShadow (frameCtx) { this._withEachVisibleLayer(frameCtx, true, layer => layer.drawShadow (this.renderFlags, frameCtx)); }
3367
+ drawPickMesh (frameCtx) { this._withEachVisibleLayer(frameCtx, true, layer => layer.drawPickMesh (this.renderFlags, frameCtx)); }
3368
+ drawPickDepths (frameCtx) { this._withEachVisibleLayer(frameCtx, true, layer => layer.drawPickDepths (this.renderFlags, frameCtx)); }
3369
+ drawPickNormals (frameCtx) { this._withEachVisibleLayer(frameCtx, true, layer => layer.drawPickNormals (this.renderFlags, frameCtx)); }
3370
+ _drawSnap (frameCtx, isSnapInit) { this._withEachVisibleLayer(frameCtx, true, layer => layer.drawSnap (this.renderFlags, frameCtx, isSnapInit)); }
3368
3371
 
3369
3372
  drawSnapInit(frameCtx) { this._drawSnap(frameCtx, true ); }
3370
3373
  drawSnap (frameCtx) { this._drawSnap(frameCtx, false); }
@@ -502,6 +502,15 @@ export class Layer {
502
502
 
503
503
  aabbChanged() { this._aabbDirty = true; }
504
504
 
505
+ getAABB() {
506
+ if (this._aabbDirty) { // Per-layer AABB for best RTC accuracy
507
+ math.collapseAABB3(this._aabb);
508
+ this._meshes.forEach(m => math.expandAABB3(this._aabb, m.aabb));
509
+ this._aabbDirty = false;
510
+ }
511
+ return this._aabb;
512
+ }
513
+
505
514
  __drawLayer(renderFlags, frameCtx, renderer, pass) {
506
515
  if ((this._countsByFlag[ENTITY_FLAGS.CULLED].count < this._portions.length) && (this._countsByFlag[ENTITY_FLAGS.VISIBLE].count > 0)) {
507
516
  const backfacePasses = (this.primitive !== "points") && (this.primitive !== "lines") && [
@@ -671,13 +680,7 @@ export class Layer {
671
680
  drawSnap(renderFlags, frameCtx, isSnapInit) {
672
681
  frameCtx.snapPickOrigin = [0, 0, 0];
673
682
 
674
- if (this._aabbDirty) { // Per-layer AABB for best RTC accuracy
675
- math.collapseAABB3(this._aabb);
676
- this._meshes.forEach(m => math.expandAABB3(this._aabb, m.aabb));
677
- this._aabbDirty = false;
678
- }
679
-
680
- const aabb = this._aabb;
683
+ const aabb = this.getAABB();
681
684
  frameCtx.snapPickCoordinateScale = math.mulVec3Scalar(
682
685
  safeInvVec3([ aabb[3] - aabb[0], aabb[4] - aabb[1], aabb[5] - aabb[2] ]),
683
686
  math.MAX_INT);
@@ -17,6 +17,9 @@ const vec3_0 = math.vec3([0,0,0]);
17
17
 
18
18
  const iota = (n) => { const ret = [ ]; for (let i = 0; i < n; ++i) ret.push(i); return ret; };
19
19
 
20
+ const tempPlanes = iota(6).map(() => math.vec4());
21
+ const tempVec4 = math.vec4();
22
+
20
23
  const bitShiftScreenZ = math.vec4([1.0 / (256.0 * 256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0]);
21
24
 
22
25
  const pixelToInt = pix => pix[0] + (pix[1] << 8) + (pix[2] << 16) + (pix[3] << 24);
@@ -26,6 +29,66 @@ const toWorldPos = (p, origin, scale) => math.vec3([ p[0] * scale[0] + origin
26
29
  p[1] * scale[1] + origin[1],
27
30
  p[2] * scale[2] + origin[2] ]);
28
31
 
32
+ const makeFrustumAABBIntersectionTest = function(camera) {
33
+ const m = math.mat4();
34
+ math.mulMat4(camera.projMatrix, camera.viewMatrix, m);
35
+
36
+ for (let i = 0; i < 3; ++i) {
37
+ tempPlanes[i * 2 + 0][0] = m[ 3] + m[i];
38
+ tempPlanes[i * 2 + 0][1] = m[ 7] + m[i + 4];
39
+ tempPlanes[i * 2 + 0][2] = m[11] + m[i + 8];
40
+ tempPlanes[i * 2 + 0][3] = m[15] + m[i + 12];
41
+
42
+ tempPlanes[i * 2 + 1][0] = m[ 3] - m[i];
43
+ tempPlanes[i * 2 + 1][1] = m[ 7] - m[i + 4];
44
+ tempPlanes[i * 2 + 1][2] = m[11] - m[i + 8];
45
+ tempPlanes[i * 2 + 1][3] = m[15] - m[i + 12];
46
+ }
47
+
48
+ // Normalize each plane
49
+ tempPlanes.forEach(p => math.divVec4Scalar(p, math.lenVec3(p), p));
50
+
51
+ return aabb => tempPlanes.every(p => {
52
+ // Compute the positive vertex (farthest in direction of normal)
53
+ tempVec4[0] = aabb[(p[0] >= 0) ? 3 : 0];
54
+ tempVec4[1] = aabb[(p[1] >= 0) ? 4 : 1];
55
+ tempVec4[2] = aabb[(p[2] >= 0) ? 5 : 2];
56
+ tempVec4[3] = 1;
57
+ return math.dotVec4(p, tempVec4) >= 0;
58
+ });
59
+ };
60
+
61
+ const makeRayAABBIntersectionTest = (O, D) => aabb => {
62
+ let tmin = -Infinity;
63
+ let tmax = Infinity;
64
+
65
+ for (let i = 0; i < 3; i++) {
66
+ const origin = O[i];
67
+ const direction = D[i];
68
+ const minBound = aabb[i];
69
+ const maxBound = aabb[i + 3];
70
+
71
+ if (Math.abs(direction) < 1e-8) {
72
+ // Ray is parallel to plane
73
+ if ((origin < minBound) || (origin > maxBound)) {
74
+ return false; // No intersection
75
+ }
76
+ } else {
77
+ const t1 = (minBound - origin) / direction;
78
+ const t2 = (maxBound - origin) / direction;
79
+
80
+ tmin = Math.max(tmin, Math.min(t1, t2)); // near
81
+ tmax = Math.min(tmax, Math.max(t1, t2)); // far
82
+
83
+ if (tmin > tmax) {
84
+ return false; // No intersection
85
+ }
86
+ }
87
+ }
88
+
89
+ return tmax >= 0; // Check if intersection is in front of ray
90
+ };
91
+
29
92
  /**
30
93
  * @private
31
94
  */
@@ -789,6 +852,8 @@ const Renderer = function (scene, options) {
789
852
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
790
853
  }
791
854
 
855
+ frameCtx.testAABB = makeFrustumAABBIntersectionTest(scene.camera);
856
+
792
857
  const renderDrawables = function(drawables) {
793
858
 
794
859
  let normalDrawSAOBinLen = 0;
@@ -1123,6 +1188,8 @@ const Renderer = function (scene, options) {
1123
1188
  renderDrawables(uiDrawableList);
1124
1189
  }
1125
1190
 
1191
+ frameCtx.testAABB = null;
1192
+
1126
1193
  const endTime = Date.now();
1127
1194
  const frameStats = stats.frame;
1128
1195
 
@@ -1231,11 +1298,16 @@ const Renderer = function (scene, options) {
1231
1298
 
1232
1299
  pickResult.canvasPos = params.canvasPos;
1233
1300
 
1301
+ math.canvasPosToWorldRay(canvas, pickViewMatrix, pickProjMatrix, projection, canvasPos, tempVec3a, tempVec3b);
1302
+ frameCtx.testAABB = makeRayAABBIntersectionTest(tempVec3a, tempVec3b);
1234
1303
  } else {
1235
1304
 
1236
1305
  // Picking with arbitrary World-space ray
1237
1306
  // Align camera along ray and fire ray through center of canvas
1238
1307
 
1308
+ canvasPos[0] = canvas.clientWidth * 0.5;
1309
+ canvasPos[1] = canvas.clientHeight * 0.5;
1310
+
1239
1311
  if (params.matrix) {
1240
1312
 
1241
1313
  pickViewMatrix = params.matrix;
@@ -1245,6 +1317,8 @@ const Renderer = function (scene, options) {
1245
1317
  nearAndFar[0] = camera.project.near;
1246
1318
  nearAndFar[1] = camera.project.far;
1247
1319
 
1320
+ math.canvasPosToWorldRay(canvas, pickViewMatrix, pickProjMatrix, projection, canvasPos, tempVec3a, tempVec3b);
1321
+ frameCtx.testAABB = makeRayAABBIntersectionTest(tempVec3a, tempVec3b);
1248
1322
  } else {
1249
1323
 
1250
1324
  worldRayOrigin.set(params.origin || [0, 0, 0]);
@@ -1273,10 +1347,9 @@ const Renderer = function (scene, options) {
1273
1347
 
1274
1348
  pickResult.origin = worldRayOrigin;
1275
1349
  pickResult.direction = worldRayDir;
1276
- }
1277
1350
 
1278
- canvasPos[0] = canvas.clientWidth * 0.5;
1279
- canvasPos[1] = canvas.clientHeight * 0.5;
1351
+ frameCtx.testAABB = makeRayAABBIntersectionTest(pickResult.origin, pickResult.direction);
1352
+ }
1280
1353
  }
1281
1354
 
1282
1355
  pickBuffer.bind();
@@ -1313,6 +1386,8 @@ const Renderer = function (scene, options) {
1313
1386
  renderDrawables(uiDrawableList);
1314
1387
  }
1315
1388
 
1389
+ frameCtx.testAABB = null;
1390
+
1316
1391
  const pickID = pixelToInt(pickBuffer.read(0, 0));
1317
1392
  const pickable = (pickID >= 0) && pickIDs.items[pickID];
1318
1393
 
@@ -1844,4 +1919,4 @@ const Renderer = function (scene, options) {
1844
1919
  };
1845
1920
  };
1846
1921
 
1847
- export {Renderer};
1922
+ export {Renderer};