@xeokit/xeokit-sdk 2.6.29 → 2.6.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/xeokit-sdk.cjs.js +635 -468
- package/dist/xeokit-sdk.es.js +635 -468
- package/dist/xeokit-sdk.es5.js +318 -330
- package/dist/xeokit-sdk.min.cjs.js +4 -4
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +3 -3
- package/package.json +1 -1
- package/src/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.js +110 -33
- package/src/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js +2 -110
- package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +257 -222
- package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +1 -1
- package/src/viewer/metadata/MetaScene.js +0 -2
- package/src/viewer/scene/model/SceneModel.js +9 -0
- package/src/viewer/scene/model/SceneModelTextureSet.js +5 -0
- 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/renderers/VBOBatchingLinesSnapRenderer.js +1 -1
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +26 -6
- 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/renderers/VBOInstancingLinesSnapRenderer.js +1 -1
- package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +17 -4
- 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/webgl/Renderer.js +6 -3
- package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +1 -1
- package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +1 -4
- package/types/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.d.ts +5 -3
- package/types/plugins/LASLoaderPlugin/LASLoaderPlugin.d.ts +2 -2
- package/types/plugins/OBJLoaderPlugin/OBJLoaderPlugin.d.ts +3 -3
|
@@ -5,6 +5,7 @@ import {sRGBEncoding} from "../../viewer/scene/constants/constants.js";
|
|
|
5
5
|
import {worldToRTCPositions} from "../../viewer/scene/math/rtcCoords.js";
|
|
6
6
|
import {parse} from '@loaders.gl/core';
|
|
7
7
|
import {GLTFLoader} from '@loaders.gl/gltf/dist/esm/gltf-loader.js';
|
|
8
|
+
|
|
8
9
|
import {
|
|
9
10
|
ClampToEdgeWrapping,
|
|
10
11
|
LinearFilter,
|
|
@@ -65,42 +66,6 @@ class GLTFSceneModelLoader {
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
|
|
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
69
|
function loadGLTF(plugin, src, metaModelJSON, options, sceneModel, ok, error) {
|
|
105
70
|
const spinner = plugin.viewer.scene.canvas.spinner;
|
|
106
71
|
spinner.processes++;
|
|
@@ -142,7 +107,9 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
|
|
|
142
107
|
const ctx = {
|
|
143
108
|
src: src,
|
|
144
109
|
entityId: options.entityId,
|
|
145
|
-
|
|
110
|
+
metaModelJSON,
|
|
111
|
+
autoMetaModel: options.autoMetaModel,
|
|
112
|
+
metaObjects: [],
|
|
146
113
|
loadBuffer: options.loadBuffer,
|
|
147
114
|
basePath: options.basePath,
|
|
148
115
|
handlenode: options.handlenode,
|
|
@@ -161,8 +128,20 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
|
|
|
161
128
|
};
|
|
162
129
|
loadTextures(ctx);
|
|
163
130
|
loadMaterials(ctx);
|
|
131
|
+
if (options.autoMetaModel) {
|
|
132
|
+
ctx.metaObjects.push({
|
|
133
|
+
id: sceneModel.id,
|
|
134
|
+
type: "Default",
|
|
135
|
+
name: sceneModel.id
|
|
136
|
+
});
|
|
137
|
+
}
|
|
164
138
|
loadDefaultScene(ctx);
|
|
165
139
|
sceneModel.finalize();
|
|
140
|
+
if (options.autoMetaModel) {
|
|
141
|
+
plugin.viewer.metaScene.createMetaModel(sceneModel.id, {
|
|
142
|
+
metaObjects: ctx.metaObjects
|
|
143
|
+
});
|
|
144
|
+
}
|
|
166
145
|
spinner.processes--;
|
|
167
146
|
ok();
|
|
168
147
|
});
|
|
@@ -291,23 +270,21 @@ function loadTextureSet(ctx, material) {
|
|
|
291
270
|
if (material.emissiveTexture) {
|
|
292
271
|
textureSetCfg.emissiveTextureId = material.emissiveTexture.texture._textureId;
|
|
293
272
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
// materialCfg.alphaCutoff = alphaCutoff;
|
|
310
|
-
// }
|
|
273
|
+
|
|
274
|
+
switch (material.alphaMode) {
|
|
275
|
+
case "OPAQUE":
|
|
276
|
+
break;
|
|
277
|
+
case "MASK":
|
|
278
|
+
const alphaCutoff = material.alphaCutoff;
|
|
279
|
+
// Default from the spec https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-material
|
|
280
|
+
textureSetCfg.alphaCutoff = (alphaCutoff !== undefined) ? alphaCutoff : 0.5;
|
|
281
|
+
break;
|
|
282
|
+
case "BLEND":
|
|
283
|
+
break;
|
|
284
|
+
default:
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
|
|
311
288
|
const metallicPBR = material.pbrMetallicRoughness;
|
|
312
289
|
if (material.pbrMetallicRoughness) {
|
|
313
290
|
const pbrMetallicRoughness = material.pbrMetallicRoughness;
|
|
@@ -356,7 +333,7 @@ function loadMaterialAttributes(ctx, material) { // Substitute RGBA for material
|
|
|
356
333
|
opacity: 1,
|
|
357
334
|
metallic: 0,
|
|
358
335
|
roughness: 1,
|
|
359
|
-
doubleSided
|
|
336
|
+
doubleSided: true
|
|
360
337
|
};
|
|
361
338
|
if (extensions) {
|
|
362
339
|
const specularPBR = extensions["KHR_materials_pbrSpecularGlossiness"];
|
|
@@ -430,9 +407,22 @@ function loadScene(ctx, scene) {
|
|
|
430
407
|
const node = nodes[i];
|
|
431
408
|
countMeshUsage(ctx, node);
|
|
432
409
|
}
|
|
433
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
410
|
+
for (let i = 0, len = nodes.length; i < len && !ctx.nodesHaveNames; i++) {
|
|
434
411
|
const node = nodes[i];
|
|
435
|
-
|
|
412
|
+
if (testIfNodesHaveNames(node)) {
|
|
413
|
+
ctx.nodesHaveNames = true;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (!ctx.nodesHaveNames) {
|
|
417
|
+
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
418
|
+
const node = nodes[i];
|
|
419
|
+
parseNodesWithoutNames(ctx, node, 0, null);
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
423
|
+
const node = nodes[i];
|
|
424
|
+
parseNodesWithNames(ctx, node, 0, null);
|
|
425
|
+
}
|
|
436
426
|
}
|
|
437
427
|
}
|
|
438
428
|
|
|
@@ -454,10 +444,133 @@ function countMeshUsage(ctx, node) {
|
|
|
454
444
|
}
|
|
455
445
|
}
|
|
456
446
|
|
|
457
|
-
|
|
447
|
+
function testIfNodesHaveNames(node) {
|
|
448
|
+
if (node.name) {
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
if (node.children) {
|
|
452
|
+
const children = node.children;
|
|
453
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
454
|
+
const childNode = children[i];
|
|
455
|
+
if (testIfNodesHaveNames(childNode)) {
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Parses a glTF node hierarchy that is known to NOT contain "name" attributes on the nodes.
|
|
465
|
+
* Create a SceneMesh for each mesh primitive, and a single SceneObject.
|
|
466
|
+
*/
|
|
467
|
+
const parseNodesWithoutNames = (function () {
|
|
468
|
+
const meshIds = [];
|
|
469
|
+
return function (ctx, node, depth, matrix, parentNode) {
|
|
470
|
+
matrix = parseNodeMatrix(node, matrix);
|
|
471
|
+
if (node.mesh) {
|
|
472
|
+
parseNodeMesh(node, ctx, matrix, meshIds);
|
|
473
|
+
}
|
|
474
|
+
if (node.children) {
|
|
475
|
+
const children = node.children;
|
|
476
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
477
|
+
const childNode = children[i];
|
|
478
|
+
parseNodesWithoutNames(ctx, childNode, depth + 1, matrix, node);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (depth === 0) {
|
|
482
|
+
let entityId = "entity-" + ctx.nextId++;
|
|
483
|
+
if (meshIds && meshIds.length > 0) {
|
|
484
|
+
ctx.sceneModel.createEntity({
|
|
485
|
+
id: entityId,
|
|
486
|
+
meshIds,
|
|
487
|
+
isObject: true
|
|
488
|
+
});
|
|
489
|
+
if (ctx.autoMetaModel) {
|
|
490
|
+
ctx.metaObjects.push({
|
|
491
|
+
id: entityId,
|
|
492
|
+
type: "Default",
|
|
493
|
+
name: entityId,
|
|
494
|
+
parent: ctx.sceneModel.id
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
meshIds.length = 0;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
})();
|
|
502
|
+
|
|
503
|
+
const parseNodesWithNames = (function () {
|
|
458
504
|
|
|
459
|
-
|
|
460
|
-
const
|
|
505
|
+
const objectIdStack = [];
|
|
506
|
+
const meshIdsStack = [];
|
|
507
|
+
let meshIds = [];
|
|
508
|
+
|
|
509
|
+
return function (ctx, node, depth, matrix) {
|
|
510
|
+
matrix = parseNodeMatrix(node, matrix);
|
|
511
|
+
if (meshIds && node.mesh) {
|
|
512
|
+
parseNodeMesh(node, ctx, matrix, meshIds);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (node.name) {
|
|
516
|
+
meshIds = [];
|
|
517
|
+
let entityId = node.name;
|
|
518
|
+
if (!!entityId && ctx.sceneModel.objects[entityId]) {
|
|
519
|
+
// ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${entityId} - will randomly-generating an object ID in XKT`);
|
|
520
|
+
}
|
|
521
|
+
while (!entityId || ctx.sceneModel.objects[entityId]) {
|
|
522
|
+
entityId = "entity-" + ctx.nextId++;
|
|
523
|
+
}
|
|
524
|
+
objectIdStack.push(entityId);
|
|
525
|
+
meshIdsStack.push(meshIds);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (node.children) {
|
|
529
|
+
const children = node.children;
|
|
530
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
531
|
+
const childNode = children[i];
|
|
532
|
+
parseNodesWithNames(ctx, childNode, depth + 1, matrix);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Post-order visit scene node
|
|
537
|
+
|
|
538
|
+
const nodeName = node.name;
|
|
539
|
+
if ((nodeName !== undefined && nodeName !== null) || depth === 0) {
|
|
540
|
+
let entityId = objectIdStack.pop();
|
|
541
|
+
if (!entityId) { // For when there are no nodes with names
|
|
542
|
+
entityId = "entity-" + ctx.nextId++;
|
|
543
|
+
}
|
|
544
|
+
let entityMeshIds = meshIdsStack.pop();
|
|
545
|
+
if (meshIds && meshIds.length > 0) {
|
|
546
|
+
ctx.sceneModel.createEntity({
|
|
547
|
+
id: entityId,
|
|
548
|
+
meshIds: entityMeshIds,
|
|
549
|
+
isObject: true
|
|
550
|
+
});
|
|
551
|
+
if (ctx.autoMetaModel) {
|
|
552
|
+
ctx.metaObjects.push({
|
|
553
|
+
id: entityId,
|
|
554
|
+
type: "Default",
|
|
555
|
+
name: entityId,
|
|
556
|
+
parent: ctx.sceneModel.id
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
meshIds = meshIdsStack.length > 0 ? meshIdsStack[meshIdsStack.length - 1] : null;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
})();
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Parses transform at the given glTF node.
|
|
568
|
+
*
|
|
569
|
+
* @param node the glTF node
|
|
570
|
+
* @param matrix Transfor matrix from parent nodes
|
|
571
|
+
* @returns {*} Transform matrix for the node
|
|
572
|
+
*/
|
|
573
|
+
function parseNodeMatrix(node, matrix) {
|
|
461
574
|
let localMatrix;
|
|
462
575
|
if (node.matrix) {
|
|
463
576
|
localMatrix = node.matrix;
|
|
@@ -491,174 +604,96 @@ function loadNode(ctx, node, depth, matrix) {
|
|
|
491
604
|
matrix = localMatrix;
|
|
492
605
|
}
|
|
493
606
|
}
|
|
607
|
+
return matrix;
|
|
608
|
+
}
|
|
494
609
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
610
|
+
/**
|
|
611
|
+
* Parses primitives referenced by the mesh belonging to the given node, creating XKTMeshes in the XKTModel.
|
|
612
|
+
*
|
|
613
|
+
* @param node glTF node
|
|
614
|
+
* @param ctx Parsing context
|
|
615
|
+
* @param matrix Matrix for the XKTMeshes
|
|
616
|
+
* @param meshIds returns IDs of the new XKTMeshes
|
|
617
|
+
*/
|
|
618
|
+
function parseNodeMesh(node, ctx, matrix, meshIds) {
|
|
619
|
+
const mesh = node.mesh;
|
|
620
|
+
if (!mesh) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
const numPrimitives = mesh.primitives.length;
|
|
624
|
+
if (numPrimitives > 0) {
|
|
625
|
+
for (let i = 0; i < numPrimitives; i++) {
|
|
626
|
+
const primitive = mesh.primitives[i];
|
|
627
|
+
if (primitive.mode < 4) {
|
|
628
|
+
continue;
|
|
503
629
|
}
|
|
504
|
-
|
|
505
|
-
|
|
630
|
+
const meshCfg = {
|
|
631
|
+
id: ctx.sceneModel.id + "." + ctx.numObjects++
|
|
632
|
+
};
|
|
633
|
+
const material = primitive.material;
|
|
634
|
+
if (material) {
|
|
635
|
+
meshCfg.textureSetId = material._textureSetId;
|
|
636
|
+
meshCfg.color = material._attributes.color;
|
|
637
|
+
meshCfg.opacity = material._attributes.opacity;
|
|
638
|
+
meshCfg.metallic = material._attributes.metallic;
|
|
639
|
+
meshCfg.roughness = material._attributes.roughness;
|
|
640
|
+
} else {
|
|
641
|
+
meshCfg.color = new Float32Array([1.0, 1.0, 1.0]);
|
|
642
|
+
meshCfg.opacity = 1.0;
|
|
506
643
|
}
|
|
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);
|
|
644
|
+
const backfaces = ((ctx.backfaces !== false) || (material && material.doubleSided !== false));
|
|
645
|
+
switch (primitive.mode) {
|
|
646
|
+
case 0: // POINTS
|
|
647
|
+
meshCfg.primitive = "points";
|
|
648
|
+
break;
|
|
649
|
+
case 1: // LINES
|
|
650
|
+
meshCfg.primitive = "lines";
|
|
651
|
+
break;
|
|
652
|
+
case 2: // LINE_LOOP
|
|
653
|
+
meshCfg.primitive = "lines";
|
|
654
|
+
break;
|
|
655
|
+
case 3: // LINE_STRIP
|
|
656
|
+
meshCfg.primitive = "lines";
|
|
657
|
+
break;
|
|
658
|
+
case 4: // TRIANGLES
|
|
659
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
660
|
+
break;
|
|
661
|
+
case 5: // TRIANGLE_STRIP
|
|
662
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
663
|
+
break;
|
|
664
|
+
case 6: // TRIANGLE_FAN
|
|
665
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
666
|
+
break;
|
|
667
|
+
default:
|
|
668
|
+
meshCfg.primitive = backfaces ? "triangles" : "solid";
|
|
592
669
|
}
|
|
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`);
|
|
670
|
+
const POSITION = primitive.attributes.POSITION;
|
|
671
|
+
if (!POSITION) {
|
|
672
|
+
continue;
|
|
620
673
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
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;
|
|
674
|
+
meshCfg.localPositions = POSITION.value;
|
|
675
|
+
meshCfg.positions = new Float64Array(meshCfg.localPositions.length);
|
|
676
|
+
if (primitive.attributes.NORMAL) {
|
|
677
|
+
meshCfg.normals = primitive.attributes.NORMAL.value;
|
|
678
|
+
}
|
|
679
|
+
if (primitive.attributes.TEXCOORD_0) {
|
|
680
|
+
meshCfg.uv = primitive.attributes.TEXCOORD_0.value;
|
|
681
|
+
}
|
|
682
|
+
if (primitive.indices) {
|
|
683
|
+
meshCfg.indices = primitive.indices.value;
|
|
684
|
+
}
|
|
685
|
+
if (matrix) {
|
|
686
|
+
math.transformPositions3(matrix, meshCfg.localPositions, meshCfg.positions);
|
|
687
|
+
} else { // eqiv to math.transformPositions3(math.identityMat4(), meshCfg.localPositions, meshCfg.positions);
|
|
688
|
+
meshCfg.positions.set(meshCfg.localPositions);
|
|
689
|
+
}
|
|
690
|
+
const origin = math.vec3();
|
|
691
|
+
const rtcNeeded = worldToRTCPositions(meshCfg.positions, meshCfg.positions, origin); // Small cellsize guarantees better accuracy
|
|
692
|
+
if (rtcNeeded) {
|
|
693
|
+
meshCfg.origin = origin;
|
|
661
694
|
}
|
|
695
|
+
ctx.sceneModel.createMesh(meshCfg);
|
|
696
|
+
meshIds.push(meshCfg.id);
|
|
662
697
|
}
|
|
663
698
|
}
|
|
664
699
|
}
|
|
@@ -990,7 +990,7 @@ export class TreeViewPlugin extends Plugin {
|
|
|
990
990
|
this._nodeNodes[buildingNode.nodeId] = buildingNode;
|
|
991
991
|
} else if (metaObjectType === "IfcBuildingStorey") {
|
|
992
992
|
if (!buildingNode) {
|
|
993
|
-
this.error("Failed to build storeys hierarchy for model
|
|
993
|
+
this.error("Failed to build storeys hierarchy for model - model does not have an IfcBuilding object, or is not an IFC model");
|
|
994
994
|
return;
|
|
995
995
|
}
|
|
996
996
|
storeyNode = {
|
|
@@ -126,8 +126,6 @@ class MetaScene {
|
|
|
126
126
|
* @param {String} modelId ID for the new {@link MetaModel}, which will have {@link MetaModel#id} set to this value.
|
|
127
127
|
* @param {Object} metaModelData Data for the {@link MetaModel}.
|
|
128
128
|
* @param {Object} [options] Options for creating the {@link MetaModel}.
|
|
129
|
-
* @param {Object} [options.includeTypes] When provided, only create {@link MetaObject}s with types in this list.
|
|
130
|
-
* @param {Object} [options.excludeTypes] When provided, never create {@link MetaObject}s with types in this list.
|
|
131
129
|
* @param {Boolean} [options.globalizeObjectIds=false] Whether to globalize each {@link MetaObject#id}. Set this ````true```` when you need to load multiple instances of the same meta model, to avoid ID clashes between the meta objects in the different instances.
|
|
132
130
|
* @returns {MetaModel} The new MetaModel.
|
|
133
131
|
*/
|
|
@@ -2644,6 +2644,7 @@ export class SceneModel extends Component {
|
|
|
2644
2644
|
id: textureSetId,
|
|
2645
2645
|
model: this,
|
|
2646
2646
|
colorTexture,
|
|
2647
|
+
alphaCutoff: cfg.alphaCutoff,
|
|
2647
2648
|
metallicRoughnessTexture,
|
|
2648
2649
|
normalsTexture,
|
|
2649
2650
|
emissiveTexture,
|
|
@@ -3077,6 +3078,14 @@ export class SceneModel extends Component {
|
|
|
3077
3078
|
return this._createMesh(cfg);
|
|
3078
3079
|
}
|
|
3079
3080
|
|
|
3081
|
+
_createDefaultIndices(numIndices) {
|
|
3082
|
+
const indices = [];
|
|
3083
|
+
for (let i = 0; i < numIndices; i++) {
|
|
3084
|
+
indices.push(i);
|
|
3085
|
+
}
|
|
3086
|
+
return indices;
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3080
3089
|
_createMesh(cfg) {
|
|
3081
3090
|
const mesh = new SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);
|
|
3082
3091
|
mesh.pickId = this.scene._renderer.getPickID(mesh);
|
|
@@ -304,6 +304,14 @@ export class DTXTrianglesSnapInitRenderer {
|
|
|
304
304
|
src.push("uvec4 flags = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+2, objectIndexCoords.y), 0);");
|
|
305
305
|
src.push("uvec4 flags2 = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+3, objectIndexCoords.y), 0);");
|
|
306
306
|
|
|
307
|
+
// flags.w = NOT_RENDERED | PICK
|
|
308
|
+
// renderPass = PICK
|
|
309
|
+
|
|
310
|
+
src.push(`if (int(flags.w) != renderPass) {`);
|
|
311
|
+
src.push(" gl_Position = vec4(3.0, 3.0, 3.0, 1.0);"); // Cull vertex
|
|
312
|
+
src.push(" return;"); // Cull vertex
|
|
313
|
+
src.push("}");
|
|
314
|
+
|
|
307
315
|
src.push("{");
|
|
308
316
|
|
|
309
317
|
// get color
|
|
@@ -311,6 +311,14 @@ export class DTXTrianglesSnapRenderer {
|
|
|
311
311
|
src.push("uvec4 flags = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+2, objectIndexCoords.y), 0);");
|
|
312
312
|
src.push("uvec4 flags2 = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+3, objectIndexCoords.y), 0);");
|
|
313
313
|
|
|
314
|
+
// flags.w = NOT_RENDERED | PICK
|
|
315
|
+
// renderPass = PICK
|
|
316
|
+
|
|
317
|
+
src.push(`if (int(flags.w) != renderPass) {`);
|
|
318
|
+
src.push(" gl_Position = vec4(3.0, 3.0, 3.0, 1.0);"); // Cull vertex
|
|
319
|
+
src.push(" return;"); // Cull vertex
|
|
320
|
+
src.push("}");
|
|
321
|
+
|
|
314
322
|
src.push("{");
|
|
315
323
|
|
|
316
324
|
// get vertex base
|
|
@@ -17,11 +17,12 @@ const tempMat4a = math.mat4();
|
|
|
17
17
|
* @private
|
|
18
18
|
*/
|
|
19
19
|
export class VBORenderer {
|
|
20
|
-
constructor(scene, withSAO = false, {instancing = false, edges = false} = {}) {
|
|
20
|
+
constructor(scene, withSAO = false, {instancing = false, edges = false, useAlphaCutoff = false} = {}) {
|
|
21
21
|
this._scene = scene;
|
|
22
22
|
this._withSAO = withSAO;
|
|
23
23
|
this._instancing = instancing;
|
|
24
24
|
this._edges = edges;
|
|
25
|
+
this._useAlphaCutoff = useAlphaCutoff;
|
|
25
26
|
this._hash = this._getHash();
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -272,6 +273,10 @@ export class VBORenderer {
|
|
|
272
273
|
this._uSAOParams = program.getLocation("uSAOParams");
|
|
273
274
|
}
|
|
274
275
|
|
|
276
|
+
if (this._useAlphaCutoff) {
|
|
277
|
+
this._alphaCutoffLocation = program.getLocation("materialAlphaCutoff");
|
|
278
|
+
}
|
|
279
|
+
|
|
275
280
|
if (scene.logarithmicDepthBufferEnabled) {
|
|
276
281
|
this._uLogDepthBufFC = program.getLocation("logDepthBufFC");
|
|
277
282
|
}
|
|
@@ -609,6 +614,10 @@ export class VBORenderer {
|
|
|
609
614
|
}
|
|
610
615
|
}
|
|
611
616
|
|
|
617
|
+
if (this._useAlphaCutoff) {
|
|
618
|
+
gl.uniform1f(this._alphaCutoffLocation, textureSet.alphaCutoff);
|
|
619
|
+
}
|
|
620
|
+
|
|
612
621
|
if (colorUniform) {
|
|
613
622
|
const colorKey = this._edges ? "edgeColor" : "fillColor";
|
|
614
623
|
const alphaKey = this._edges ? "edgeAlpha" : "fillAlpha";
|