@xeokit/xeokit-sdk 2.6.28 → 2.6.30
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/README.md +1 -0
- package/dist/xeokit-sdk.cjs.js +1425 -649
- package/dist/xeokit-sdk.es.js +1420 -650
- package/dist/xeokit-sdk.es5.js +629 -552
- package/dist/xeokit-sdk.min.cjs.js +5 -5
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +4 -4
- package/package.json +1 -1
- package/src/extras/PointerCircle/PointerCircle.js +1 -1
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +22 -41
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +3 -18
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +20 -41
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +4 -20
- package/src/plugins/DistanceMeasurementsPlugin/index.js +1 -1
- package/src/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js +2 -110
- package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +252 -222
- package/src/plugins/StoreyViewsPlugin/StoreyViewsPlugin.js +31 -1
- package/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js +20 -8
- package/src/plugins/ZonesPlugin/ZonesPlugin.js +1939 -0
- package/src/plugins/ZonesPlugin/index.js +1 -1875
- package/src/viewer/Viewer.js +2 -2
- package/src/viewer/metadata/MetaScene.js +0 -2
- package/src/viewer/scene/math/MeshSurfaceArea.js +90 -0
- package/src/viewer/scene/math/MeshVolume.js +102 -0
- package/src/viewer/scene/math/index.js +3 -0
- package/src/viewer/scene/math/isTriangleMeshSolid.js +162 -0
- package/src/viewer/scene/math/math.js +8 -0
- package/src/viewer/scene/model/SceneModel.js +73 -34
- package/src/viewer/scene/model/SceneModelEntity.js +46 -1
- package/src/viewer/scene/model/SceneModelMesh.js +74 -1
- package/src/viewer/scene/model/SceneModelTextureSet.js +5 -0
- package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +7 -1
- package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +77 -1
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +8 -0
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +8 -0
- package/src/viewer/scene/model/vbo/VBORenderer.js +10 -1
- package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +6 -1
- package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +1 -1
- package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +6 -1
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +59 -18
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +40 -12
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +2 -3
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +25 -7
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +1 -1
- package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +6 -1
- package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +1 -1
- package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +6 -1
- package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +48 -14
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +74 -47
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +29 -14
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +5 -4
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +1 -1
- package/src/viewer/scene/scene/Scene.js +16 -5
- package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +1 -1
- package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +1 -5
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +7 -0
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.d.ts +26 -1
- package/types/plugins/DistanceMeasurementsPlugin/index.d.ts +3 -1
|
@@ -65,42 +65,6 @@ class GLTFSceneModelLoader {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
function getMetaModelCorrections(metaModelJSON) {
|
|
69
|
-
const eachRootStats = {};
|
|
70
|
-
const eachChildRoot = {};
|
|
71
|
-
const metaObjects = metaModelJSON.metaObjects || [];
|
|
72
|
-
const metaObjectsMap = {};
|
|
73
|
-
for (let i = 0, len = metaObjects.length; i < len; i++) {
|
|
74
|
-
const metaObject = metaObjects[i];
|
|
75
|
-
metaObjectsMap[metaObject.id] = metaObject;
|
|
76
|
-
}
|
|
77
|
-
for (let i = 0, len = metaObjects.length; i < len; i++) {
|
|
78
|
-
const metaObject = metaObjects[i];
|
|
79
|
-
if (metaObject.parent !== undefined && metaObject.parent !== null) {
|
|
80
|
-
const metaObjectParent = metaObjectsMap[metaObject.parent];
|
|
81
|
-
if (metaObject.type === metaObjectParent.type) {
|
|
82
|
-
let rootMetaObject = metaObjectParent;
|
|
83
|
-
while (rootMetaObject.parent && metaObjectsMap[rootMetaObject.parent].type === rootMetaObject.type) {
|
|
84
|
-
rootMetaObject = metaObjectsMap[rootMetaObject.parent];
|
|
85
|
-
}
|
|
86
|
-
const rootStats = eachRootStats[rootMetaObject.id] || (eachRootStats[rootMetaObject.id] = {
|
|
87
|
-
numChildren: 0,
|
|
88
|
-
countChildren: 0
|
|
89
|
-
});
|
|
90
|
-
rootStats.numChildren++;
|
|
91
|
-
eachChildRoot[metaObject.id] = rootMetaObject;
|
|
92
|
-
} else {
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
metaObjectsMap,
|
|
99
|
-
eachRootStats,
|
|
100
|
-
eachChildRoot
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
68
|
function loadGLTF(plugin, src, metaModelJSON, options, sceneModel, ok, error) {
|
|
105
69
|
const spinner = plugin.viewer.scene.canvas.spinner;
|
|
106
70
|
spinner.processes++;
|
|
@@ -142,7 +106,9 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
|
|
|
142
106
|
const ctx = {
|
|
143
107
|
src: src,
|
|
144
108
|
entityId: options.entityId,
|
|
145
|
-
|
|
109
|
+
metaModelJSON,
|
|
110
|
+
autoMetaModel: options.autoMetaModel,
|
|
111
|
+
metaObjects: [],
|
|
146
112
|
loadBuffer: options.loadBuffer,
|
|
147
113
|
basePath: options.basePath,
|
|
148
114
|
handlenode: options.handlenode,
|
|
@@ -161,8 +127,20 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
|
|
|
161
127
|
};
|
|
162
128
|
loadTextures(ctx);
|
|
163
129
|
loadMaterials(ctx);
|
|
130
|
+
if (options.autoMetaModel) {
|
|
131
|
+
ctx.metaObjects.push({
|
|
132
|
+
id: sceneModel.id,
|
|
133
|
+
type: "Default",
|
|
134
|
+
name: sceneModel.id
|
|
135
|
+
});
|
|
136
|
+
}
|
|
164
137
|
loadDefaultScene(ctx);
|
|
165
138
|
sceneModel.finalize();
|
|
139
|
+
if (options.autoMetaModel) {
|
|
140
|
+
plugin.viewer.metaScene.createMetaModel(sceneModel.id, {
|
|
141
|
+
metaObjects: ctx.metaObjects
|
|
142
|
+
});
|
|
143
|
+
}
|
|
166
144
|
spinner.processes--;
|
|
167
145
|
ok();
|
|
168
146
|
});
|
|
@@ -291,23 +269,21 @@ function loadTextureSet(ctx, material) {
|
|
|
291
269
|
if (material.emissiveTexture) {
|
|
292
270
|
textureSetCfg.emissiveTextureId = material.emissiveTexture.texture._textureId;
|
|
293
271
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
// materialCfg.alphaCutoff = alphaCutoff;
|
|
310
|
-
// }
|
|
272
|
+
|
|
273
|
+
switch (material.alphaMode) {
|
|
274
|
+
case "OPAQUE":
|
|
275
|
+
break;
|
|
276
|
+
case "MASK":
|
|
277
|
+
const alphaCutoff = material.alphaCutoff;
|
|
278
|
+
// Default from the spec https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-material
|
|
279
|
+
textureSetCfg.alphaCutoff = (alphaCutoff !== undefined) ? alphaCutoff : 0.5;
|
|
280
|
+
break;
|
|
281
|
+
case "BLEND":
|
|
282
|
+
break;
|
|
283
|
+
default:
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
|
|
311
287
|
const metallicPBR = material.pbrMetallicRoughness;
|
|
312
288
|
if (material.pbrMetallicRoughness) {
|
|
313
289
|
const pbrMetallicRoughness = material.pbrMetallicRoughness;
|
|
@@ -356,7 +332,7 @@ function loadMaterialAttributes(ctx, material) { // Substitute RGBA for material
|
|
|
356
332
|
opacity: 1,
|
|
357
333
|
metallic: 0,
|
|
358
334
|
roughness: 1,
|
|
359
|
-
doubleSided
|
|
335
|
+
doubleSided: true
|
|
360
336
|
};
|
|
361
337
|
if (extensions) {
|
|
362
338
|
const specularPBR = extensions["KHR_materials_pbrSpecularGlossiness"];
|
|
@@ -430,9 +406,22 @@ function loadScene(ctx, scene) {
|
|
|
430
406
|
const node = nodes[i];
|
|
431
407
|
countMeshUsage(ctx, node);
|
|
432
408
|
}
|
|
433
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
409
|
+
for (let i = 0, len = nodes.length; i < len && !ctx.nodesHaveNames; i++) {
|
|
434
410
|
const node = nodes[i];
|
|
435
|
-
|
|
411
|
+
if (testIfNodesHaveNames(node)) {
|
|
412
|
+
ctx.nodesHaveNames = true;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (!ctx.nodesHaveNames) {
|
|
416
|
+
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
417
|
+
const node = nodes[i];
|
|
418
|
+
parseNodesWithoutNames(ctx, node, 0, null);
|
|
419
|
+
}
|
|
420
|
+
} else {
|
|
421
|
+
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
422
|
+
const node = nodes[i];
|
|
423
|
+
parseNodesWithNames(ctx, node, 0, null);
|
|
424
|
+
}
|
|
436
425
|
}
|
|
437
426
|
}
|
|
438
427
|
|
|
@@ -454,10 +443,133 @@ function countMeshUsage(ctx, node) {
|
|
|
454
443
|
}
|
|
455
444
|
}
|
|
456
445
|
|
|
457
|
-
|
|
446
|
+
function testIfNodesHaveNames(node) {
|
|
447
|
+
if (node.name) {
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
if (node.children) {
|
|
451
|
+
const children = node.children;
|
|
452
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
453
|
+
const childNode = children[i];
|
|
454
|
+
if (testIfNodesHaveNames(childNode)) {
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
458
461
|
|
|
459
|
-
|
|
460
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Parses a glTF node hierarchy that is known to NOT contain "name" attributes on the nodes.
|
|
464
|
+
* Create a SceneMesh for each mesh primitive, and a single SceneObject.
|
|
465
|
+
*/
|
|
466
|
+
const parseNodesWithoutNames = (function () {
|
|
467
|
+
const meshIds = [];
|
|
468
|
+
return function (ctx, node, depth, matrix, parentNode) {
|
|
469
|
+
matrix = parseNodeMatrix(node, matrix);
|
|
470
|
+
if (node.mesh) {
|
|
471
|
+
parseNodeMesh(node, ctx, matrix, meshIds);
|
|
472
|
+
}
|
|
473
|
+
if (node.children) {
|
|
474
|
+
const children = node.children;
|
|
475
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
476
|
+
const childNode = children[i];
|
|
477
|
+
parseNodesWithoutNames(ctx, childNode, depth + 1, matrix, node);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (depth === 0) {
|
|
481
|
+
let entityId = "entity-" + ctx.nextId++;
|
|
482
|
+
if (meshIds && meshIds.length > 0) {
|
|
483
|
+
ctx.sceneModel.createEntity({
|
|
484
|
+
id: entityId,
|
|
485
|
+
meshIds,
|
|
486
|
+
isObject: true
|
|
487
|
+
});
|
|
488
|
+
if (ctx.autoMetaModel) {
|
|
489
|
+
ctx.metaObjects.push({
|
|
490
|
+
id: entityId,
|
|
491
|
+
type: "Default",
|
|
492
|
+
name: entityId,
|
|
493
|
+
parent: ctx.sceneModel.id
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
meshIds.length = 0;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
})();
|
|
501
|
+
|
|
502
|
+
const parseNodesWithNames = (function () {
|
|
503
|
+
|
|
504
|
+
const objectIdStack = [];
|
|
505
|
+
const meshIdsStack = [];
|
|
506
|
+
let meshIds = null;
|
|
507
|
+
|
|
508
|
+
return function (ctx, node, depth, matrix) {
|
|
509
|
+
matrix = parseNodeMatrix(node, matrix);
|
|
510
|
+
if (meshIds && node.mesh) {
|
|
511
|
+
parseNodeMesh(node, ctx, matrix, meshIds);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (node.name) {
|
|
515
|
+
meshIds = [];
|
|
516
|
+
let entityId = node.name;
|
|
517
|
+
if (!!entityId && ctx.sceneModel.objects[entityId]) {
|
|
518
|
+
// ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${entityId} - will randomly-generating an object ID in XKT`);
|
|
519
|
+
}
|
|
520
|
+
while (!entityId || ctx.sceneModel.objects[entityId]) {
|
|
521
|
+
entityId = "entity-" + ctx.nextId++;
|
|
522
|
+
}
|
|
523
|
+
objectIdStack.push(entityId);
|
|
524
|
+
meshIdsStack.push(meshIds);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (node.children) {
|
|
528
|
+
const children = node.children;
|
|
529
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
530
|
+
const childNode = children[i];
|
|
531
|
+
parseNodesWithNames(ctx, childNode, depth + 1, matrix);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Post-order visit scene node
|
|
536
|
+
|
|
537
|
+
const nodeName = node.name;
|
|
538
|
+
if ((nodeName !== undefined && nodeName !== null) || depth === 0) {
|
|
539
|
+
let entityId = objectIdStack.pop();
|
|
540
|
+
if (!entityId) { // For when there are no nodes with names
|
|
541
|
+
entityId = "entity-" + ctx.nextId++;
|
|
542
|
+
}
|
|
543
|
+
let entityMeshIds = meshIdsStack.pop();
|
|
544
|
+
if (meshIds && meshIds.length > 0) {
|
|
545
|
+
ctx.sceneModel.createEntity({
|
|
546
|
+
id: entityId,
|
|
547
|
+
meshIds: entityMeshIds,
|
|
548
|
+
isObject: true
|
|
549
|
+
});
|
|
550
|
+
if (ctx.autoMetaModel) {
|
|
551
|
+
ctx.metaObjects.push({
|
|
552
|
+
id: entityId,
|
|
553
|
+
type: "Default",
|
|
554
|
+
name: entityId,
|
|
555
|
+
parent: ctx.sceneModel.id
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
meshIds = meshIdsStack.length > 0 ? meshIdsStack[meshIdsStack.length - 1] : null;
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
})();
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Parses transform at the given glTF node.
|
|
567
|
+
*
|
|
568
|
+
* @param node the glTF node
|
|
569
|
+
* @param matrix Transfor matrix from parent nodes
|
|
570
|
+
* @returns {*} Transform matrix for the node
|
|
571
|
+
*/
|
|
572
|
+
function parseNodeMatrix(node, matrix) {
|
|
461
573
|
let localMatrix;
|
|
462
574
|
if (node.matrix) {
|
|
463
575
|
localMatrix = node.matrix;
|
|
@@ -491,174 +603,92 @@ function loadNode(ctx, node, depth, matrix) {
|
|
|
491
603
|
matrix = localMatrix;
|
|
492
604
|
}
|
|
493
605
|
}
|
|
606
|
+
return matrix;
|
|
607
|
+
}
|
|
494
608
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
609
|
+
/**
|
|
610
|
+
* Parses primitives referenced by the mesh belonging to the given node, creating XKTMeshes in the XKTModel.
|
|
611
|
+
*
|
|
612
|
+
* @param node glTF node
|
|
613
|
+
* @param ctx Parsing context
|
|
614
|
+
* @param matrix Matrix for the XKTMeshes
|
|
615
|
+
* @param meshIds returns IDs of the new XKTMeshes
|
|
616
|
+
*/
|
|
617
|
+
function parseNodeMesh(node, ctx, matrix, meshIds) {
|
|
618
|
+
const mesh = node.mesh;
|
|
619
|
+
if (!mesh) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
const numPrimitives = mesh.primitives.length;
|
|
623
|
+
if (numPrimitives > 0) {
|
|
624
|
+
for (let i = 0; i < numPrimitives; i++) {
|
|
625
|
+
const primitive = mesh.primitives[i];
|
|
626
|
+
if (primitive.mode < 4) {
|
|
627
|
+
continue;
|
|
503
628
|
}
|
|
504
|
-
|
|
505
|
-
|
|
629
|
+
const meshCfg = {
|
|
630
|
+
id: ctx.sceneModel.id + "." + ctx.numObjects++
|
|
631
|
+
};
|
|
632
|
+
const material = primitive.material;
|
|
633
|
+
if (material) {
|
|
634
|
+
meshCfg.textureSetId = material._textureSetId;
|
|
635
|
+
meshCfg.color = material._attributes.color;
|
|
636
|
+
meshCfg.opacity = material._attributes.opacity;
|
|
637
|
+
meshCfg.metallic = material._attributes.metallic;
|
|
638
|
+
meshCfg.roughness = material._attributes.roughness;
|
|
639
|
+
} else {
|
|
640
|
+
meshCfg.color = new Float32Array([1.0, 1.0, 1.0]);
|
|
641
|
+
meshCfg.opacity = 1.0;
|
|
506
642
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
meshCfg.
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
meshCfg.color = new Float32Array([1.0, 1.0, 1.0]);
|
|
533
|
-
meshCfg.opacity = 1.0;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
const backfaces = ((ctx.backfaces !== false) || (material && material.doubleSided !== false));
|
|
537
|
-
|
|
538
|
-
switch (primitive.mode) {
|
|
539
|
-
case 0: // POINTS
|
|
540
|
-
meshCfg.primitive = "points";
|
|
541
|
-
break;
|
|
542
|
-
case 1: // LINES
|
|
543
|
-
meshCfg.primitive = "lines";
|
|
544
|
-
break;
|
|
545
|
-
case 2: // LINE_LOOP
|
|
546
|
-
meshCfg.primitive = "lines";
|
|
547
|
-
break;
|
|
548
|
-
case 3: // LINE_STRIP
|
|
549
|
-
meshCfg.primitive = "lines";
|
|
550
|
-
break;
|
|
551
|
-
case 4: // TRIANGLES
|
|
552
|
-
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
553
|
-
break;
|
|
554
|
-
case 5: // TRIANGLE_STRIP
|
|
555
|
-
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
556
|
-
break;
|
|
557
|
-
case 6: // TRIANGLE_FAN
|
|
558
|
-
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
559
|
-
break;
|
|
560
|
-
default:
|
|
561
|
-
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
const POSITION = primitive.attributes.POSITION;
|
|
565
|
-
if (!POSITION) {
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
meshCfg.localPositions = POSITION.value;
|
|
569
|
-
meshCfg.positions = new Float64Array(meshCfg.localPositions.length);
|
|
570
|
-
|
|
571
|
-
if (primitive.attributes.NORMAL) {
|
|
572
|
-
meshCfg.normals = primitive.attributes.NORMAL.value;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (primitive.attributes.TEXCOORD_0) {
|
|
576
|
-
meshCfg.uv = primitive.attributes.TEXCOORD_0.value;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (primitive.indices) {
|
|
580
|
-
meshCfg.indices = primitive.indices.value;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
math.transformPositions3(worldMatrix, meshCfg.localPositions, meshCfg.positions);
|
|
584
|
-
const origin = math.vec3();
|
|
585
|
-
const rtcNeeded = worldToRTCPositions(meshCfg.positions, meshCfg.positions, origin); // Small cellsize guarantees better accuracy
|
|
586
|
-
if (rtcNeeded) {
|
|
587
|
-
meshCfg.origin = origin;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
sceneModel.createMesh(meshCfg);
|
|
591
|
-
deferredMeshIds.push(meshCfg.id);
|
|
643
|
+
const backfaces = ((ctx.backfaces !== false) || (material && material.doubleSided !== false));
|
|
644
|
+
switch (primitive.mode) {
|
|
645
|
+
case 0: // POINTS
|
|
646
|
+
meshCfg.primitive = "points";
|
|
647
|
+
break;
|
|
648
|
+
case 1: // LINES
|
|
649
|
+
meshCfg.primitive = "lines";
|
|
650
|
+
break;
|
|
651
|
+
case 2: // LINE_LOOP
|
|
652
|
+
meshCfg.primitive = "lines";
|
|
653
|
+
break;
|
|
654
|
+
case 3: // LINE_STRIP
|
|
655
|
+
meshCfg.primitive = "lines";
|
|
656
|
+
break;
|
|
657
|
+
case 4: // TRIANGLES
|
|
658
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
659
|
+
break;
|
|
660
|
+
case 5: // TRIANGLE_STRIP
|
|
661
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
662
|
+
break;
|
|
663
|
+
case 6: // TRIANGLE_FAN
|
|
664
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
665
|
+
break;
|
|
666
|
+
default:
|
|
667
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
592
668
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
if (node.children) {
|
|
597
|
-
const children = node.children;
|
|
598
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
599
|
-
const childNode = children[i];
|
|
600
|
-
loadNode(ctx, childNode, depth + 1, matrix);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// Post-order visit scene node
|
|
605
|
-
|
|
606
|
-
if (ctx.entityId) {
|
|
607
|
-
if (depth ===0) {
|
|
608
|
-
sceneModel.createEntity({
|
|
609
|
-
id: ctx.entityId,
|
|
610
|
-
meshIds: deferredMeshIds,
|
|
611
|
-
isObject: true
|
|
612
|
-
});
|
|
613
|
-
deferredMeshIds.length = 0;
|
|
614
|
-
}
|
|
615
|
-
} else {
|
|
616
|
-
const nodeName = node.name;
|
|
617
|
-
if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
|
|
618
|
-
if (nodeName === undefined || nodeName === null) {
|
|
619
|
-
ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
|
|
669
|
+
const POSITION = primitive.attributes.POSITION;
|
|
670
|
+
if (!POSITION) {
|
|
671
|
+
continue;
|
|
620
672
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
meshIds: deferredMeshIds,
|
|
638
|
-
isObject: true
|
|
639
|
-
});
|
|
640
|
-
deferredMeshIds.length = 0;
|
|
641
|
-
}
|
|
642
|
-
} else {
|
|
643
|
-
const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
|
|
644
|
-
if (metaObject) {
|
|
645
|
-
sceneModel.createEntity({
|
|
646
|
-
id: entityId,
|
|
647
|
-
meshIds: deferredMeshIds,
|
|
648
|
-
isObject: true
|
|
649
|
-
});
|
|
650
|
-
deferredMeshIds.length = 0;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
} else {
|
|
654
|
-
// Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
|
|
655
|
-
sceneModel.createEntity({
|
|
656
|
-
id: entityId,
|
|
657
|
-
meshIds: deferredMeshIds,
|
|
658
|
-
isObject: true
|
|
659
|
-
});
|
|
660
|
-
deferredMeshIds.length = 0;
|
|
673
|
+
meshCfg.localPositions = POSITION.value;
|
|
674
|
+
meshCfg.positions = new Float64Array(meshCfg.localPositions.length);
|
|
675
|
+
if (primitive.attributes.NORMAL) {
|
|
676
|
+
meshCfg.normals = primitive.attributes.NORMAL.value;
|
|
677
|
+
}
|
|
678
|
+
if (primitive.attributes.TEXCOORD_0) {
|
|
679
|
+
meshCfg.uv = primitive.attributes.TEXCOORD_0.value;
|
|
680
|
+
}
|
|
681
|
+
if (primitive.indices) {
|
|
682
|
+
meshCfg.indices = primitive.indices.value;
|
|
683
|
+
}
|
|
684
|
+
math.transformPositions3(matrix, meshCfg.localPositions, meshCfg.positions);
|
|
685
|
+
const origin = math.vec3();
|
|
686
|
+
const rtcNeeded = worldToRTCPositions(meshCfg.positions, meshCfg.positions, origin); // Small cellsize guarantees better accuracy
|
|
687
|
+
if (rtcNeeded) {
|
|
688
|
+
meshCfg.origin = origin;
|
|
661
689
|
}
|
|
690
|
+
ctx.sceneModel.createMesh(meshCfg);
|
|
691
|
+
meshIds.push(meshCfg.id);
|
|
662
692
|
}
|
|
663
693
|
}
|
|
664
694
|
}
|
|
@@ -675,13 +675,43 @@ class StoreyViewsPlugin extends Plugin {
|
|
|
675
675
|
getStoreyContainingWorldPos(worldPos) {
|
|
676
676
|
for (var storeyId in this.storeys) {
|
|
677
677
|
const storey = this.storeys[storeyId];
|
|
678
|
-
if (math.
|
|
678
|
+
if (math.point3AABB3AbsoluteIntersect(storey.storeyAABB, worldPos)) {
|
|
679
679
|
return storeyId;
|
|
680
680
|
}
|
|
681
681
|
}
|
|
682
682
|
return null;
|
|
683
683
|
}
|
|
684
684
|
|
|
685
|
+
/**
|
|
686
|
+
* Gets the ID of the storey which's bounding box contains the y point of the world position
|
|
687
|
+
*
|
|
688
|
+
* @param {Number[]} worldPos 3D World-space position.
|
|
689
|
+
* @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
|
|
690
|
+
*/
|
|
691
|
+
getStoreyInVerticalRange(worldPos) {
|
|
692
|
+
for(let storeyId in this.storeys) {
|
|
693
|
+
const storey = this.storeys[storeyId];
|
|
694
|
+
const aabb = [0,0,0,0,0,0], pos = [0,0,0];
|
|
695
|
+
aabb[1] = storey.storeyAABB[1];
|
|
696
|
+
aabb[4] = storey.storeyAABB[4];
|
|
697
|
+
pos[1] = worldPos[1];
|
|
698
|
+
if (math.point3AABB3AbsoluteIntersect(aabb, pos)) {
|
|
699
|
+
return storeyId;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return null;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
isPositionAboveOrBelowBuilding(worldPos){
|
|
706
|
+
const keys = Object.keys(this.storeys);
|
|
707
|
+
const ids = [keys[0], keys[keys.length-1]];
|
|
708
|
+
if(worldPos[1] < this.storeys[ids[0]].storeyAABB[1])
|
|
709
|
+
return ids[0];
|
|
710
|
+
else if (worldPos[1] > this.storeys[ids[1]].storeyAABB[4])
|
|
711
|
+
return ids[1];
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
|
|
685
715
|
/**
|
|
686
716
|
* Converts a 3D World-space position to a 2D position within a StoreyMap image.
|
|
687
717
|
*
|
|
@@ -942,6 +942,9 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
942
942
|
this.viewer.scene.canvas.spinner.processes++;
|
|
943
943
|
|
|
944
944
|
const finish = () => {
|
|
945
|
+
if (sceneModel.destroyed) {
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
945
948
|
// this._createDefaultMetaModelIfNeeded(sceneModel, params, options);
|
|
946
949
|
sceneModel.finalize();
|
|
947
950
|
metaModel.finalize();
|
|
@@ -1023,7 +1026,9 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
1023
1026
|
const loadJSONs = (metaDataFiles, done, error) => {
|
|
1024
1027
|
let i = 0;
|
|
1025
1028
|
const loadNext = () => {
|
|
1026
|
-
if (
|
|
1029
|
+
if (sceneModel.destroyed) {
|
|
1030
|
+
done();
|
|
1031
|
+
} else if (i >= metaDataFiles.length) {
|
|
1027
1032
|
done();
|
|
1028
1033
|
} else {
|
|
1029
1034
|
this._dataSource.getMetaModel(`${baseDir}${metaDataFiles[i]}`, (metaModelData) => {
|
|
@@ -1033,7 +1038,7 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
1033
1038
|
globalizeObjectIds: options.globalizeObjectIds
|
|
1034
1039
|
});
|
|
1035
1040
|
i++;
|
|
1036
|
-
this.scheduleTask(loadNext,
|
|
1041
|
+
this.scheduleTask(loadNext, 200);
|
|
1037
1042
|
}, error);
|
|
1038
1043
|
}
|
|
1039
1044
|
}
|
|
@@ -1042,13 +1047,16 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
1042
1047
|
const loadXKTs_excludeTheirMetaModels = (xktFiles, done, error) => { // Load XKTs, ignore metamodels in the XKT
|
|
1043
1048
|
let i = 0;
|
|
1044
1049
|
const loadNext = () => {
|
|
1045
|
-
if (
|
|
1050
|
+
if (sceneModel.destroyed) {
|
|
1051
|
+
done();
|
|
1052
|
+
} else if (i >= xktFiles.length) {
|
|
1046
1053
|
done();
|
|
1047
1054
|
} else {
|
|
1048
1055
|
this._dataSource.getXKT(`${baseDir}${xktFiles[i]}`, (arrayBuffer) => {
|
|
1049
1056
|
this._parseModel(arrayBuffer, params, options, sceneModel, null /* Ignore metamodel in XKT */, manifestCtx);
|
|
1057
|
+
sceneModel.preFinalize();
|
|
1050
1058
|
i++;
|
|
1051
|
-
this.scheduleTask(loadNext,
|
|
1059
|
+
this.scheduleTask(loadNext, 200);
|
|
1052
1060
|
}, error);
|
|
1053
1061
|
}
|
|
1054
1062
|
}
|
|
@@ -1057,13 +1065,16 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
1057
1065
|
const loadXKTs_includeTheirMetaModels = (xktFiles, done, error) => { // Load XKTs, parse metamodels from the XKT
|
|
1058
1066
|
let i = 0;
|
|
1059
1067
|
const loadNext = () => {
|
|
1060
|
-
if (
|
|
1068
|
+
if (sceneModel.destroyed) {
|
|
1069
|
+
done();
|
|
1070
|
+
} else if (i >= xktFiles.length) {
|
|
1061
1071
|
done();
|
|
1062
1072
|
} else {
|
|
1063
1073
|
this._dataSource.getXKT(`${baseDir}${xktFiles[i]}`, (arrayBuffer) => {
|
|
1064
1074
|
this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);
|
|
1075
|
+
sceneModel.preFinalize();
|
|
1065
1076
|
i++;
|
|
1066
|
-
this.scheduleTask(loadNext,
|
|
1077
|
+
this.scheduleTask(loadNext, 200);
|
|
1067
1078
|
}, error);
|
|
1068
1079
|
}
|
|
1069
1080
|
}
|
|
@@ -1113,11 +1124,12 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
1113
1124
|
_loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {
|
|
1114
1125
|
this._dataSource.getXKT(params.src, (arrayBuffer) => {
|
|
1115
1126
|
this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);
|
|
1127
|
+
sceneModel.preFinalize();
|
|
1116
1128
|
done();
|
|
1117
1129
|
}, error);
|
|
1118
1130
|
}
|
|
1119
1131
|
|
|
1120
|
-
_parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {
|
|
1132
|
+
async _parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {
|
|
1121
1133
|
if (sceneModel.destroyed) {
|
|
1122
1134
|
return;
|
|
1123
1135
|
}
|
|
@@ -1129,7 +1141,7 @@ class XKTLoaderPlugin extends Plugin {
|
|
|
1129
1141
|
this.error("Unsupported .XKT file version: " + xktVersion + " - this XKTLoaderPlugin supports versions " + Object.keys(parsers));
|
|
1130
1142
|
return;
|
|
1131
1143
|
}
|
|
1132
|
-
this.log("Loading .xkt V" + xktVersion);
|
|
1144
|
+
// this.log("Loading .xkt V" + xktVersion);
|
|
1133
1145
|
const numElements = dataView.getUint32(4, true);
|
|
1134
1146
|
const elements = [];
|
|
1135
1147
|
let byteOffset = (numElements + 2) * 4;
|