@xeokit/xeokit-sdk 2.6.29 → 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/dist/xeokit-sdk.cjs.js +510 -429
- package/dist/xeokit-sdk.es.js +510 -429
- package/dist/xeokit-sdk.es5.js +315 -328
- package/dist/xeokit-sdk.min.cjs.js +4 -4
- package/dist/xeokit-sdk.min.es.js +4 -4
- package/dist/xeokit-sdk.min.es5.js +3 -3
- package/package.json +1 -1
- package/src/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js +2 -110
- package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +252 -222
- 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/occlusion/OcclusionLayer.js +1 -1
- package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +1 -4
|
@@ -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
|
}
|
|
@@ -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";
|
|
@@ -215,7 +215,7 @@ export class VBOBatchingLinesSnapRenderer extends VBORenderer{
|
|
|
215
215
|
|
|
216
216
|
src.push(`int pickFlag = int(flags) >> 12 & 0xF;`);
|
|
217
217
|
src.push(`if (pickFlag != renderPass) {`);
|
|
218
|
-
src.push(" gl_Position = vec4(
|
|
218
|
+
src.push(" gl_Position = vec4(2.0, 0.0, 0.0, 0.0);"); // Cull vertex
|
|
219
219
|
src.push(" } else {");
|
|
220
220
|
src.push(" vec4 worldPosition = worldMatrix * (positionsDecodeMatrix * vec4(position, 1.0)); ");
|
|
221
221
|
if (scene.entityOffsetsEnabled) {
|