From ff1b90c960020389b6638050ae43e0eb7e9ccf72 Mon Sep 17 00:00:00 2001 From: lindsay Date: Fri, 8 Sep 2023 02:28:15 +0200 Subject: [PATCH] Fix ID uniqueness for multi-XKT models --- .../XKTLoaderPlugin/XKTLoaderPlugin.js | 12 ++++---- .../XKTLoaderPlugin/parsers/ParserV1.js | 2 ++ .../XKTLoaderPlugin/parsers/ParserV10.js | 30 ++++++++++--------- .../XKTLoaderPlugin/parsers/ParserV2.js | 8 +++-- .../XKTLoaderPlugin/parsers/ParserV3.js | 9 ++++-- .../XKTLoaderPlugin/parsers/ParserV4.js | 12 +++++--- .../XKTLoaderPlugin/parsers/ParserV5.js | 4 ++- .../XKTLoaderPlugin/parsers/ParserV6.js | 6 ++-- .../XKTLoaderPlugin/parsers/ParserV7.js | 6 ++-- .../XKTLoaderPlugin/parsers/ParserV8.js | 6 ++-- .../XKTLoaderPlugin/parsers/ParserV9.js | 6 ++-- 11 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js b/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js index 8b0d75951..96e904daa 100644 --- a/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js +++ b/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js @@ -900,8 +900,11 @@ class XKTLoaderPlugin extends Plugin { sceneModel.fire("error", errMsg); } + let nextId = 0; const manifestCtx = { - nextMeshId: 0 + getNextId: () => { + return `${modelId}.${nextId++}`; + } }; if (params.metaModelSrc || params.metaModelData) { @@ -944,7 +947,6 @@ class XKTLoaderPlugin extends Plugin { } - } else { if (params.src) { @@ -1016,9 +1018,9 @@ class XKTLoaderPlugin extends Plugin { _loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) { this._dataSource.getXKT(params.src, (arrayBuffer) => { - this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx); - done(); - }, error); + this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx); + done(); + }, error); } _parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) { diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV1.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV1.js index 7b1a52437..3056b4ef7 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV1.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV1.js @@ -63,6 +63,8 @@ function inflate(deflatedData) { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + sceneModel.positionsCompression = "precompressed"; sceneModel.normalsCompression = "precompressed"; diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV10.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV10.js index 460f1cefa..bba2be8b1 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV10.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV10.js @@ -115,6 +115,8 @@ const imagDataToImage = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + const metadata = inflatedData.metadata; const textureData = inflatedData.textureData; const eachTextureDataPortion = inflatedData.eachTextureDataPortion; @@ -181,7 +183,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const imageDataSubarray = new Uint8Array(textureData.subarray(textureDataPortionStart, textureDataPortionEnd)); const arrayBuffer = imageDataSubarray.buffer; - const textureId = `texture-${textureIndex}`; + const textureId = `${modelPartId}-texture-${textureIndex}`; if (compressed) { @@ -222,7 +224,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) for (let textureSetIndex = 0; textureSetIndex < numTextureSets; textureSetIndex++) { const eachTextureSetTexturesIndex = textureSetIndex * 5; - const textureSetId = `textureSet-${textureSetIndex}`; + const textureSetId = `${modelPartId}-textureSet-${textureSetIndex}`; const colorTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 0]; const metallicRoughnessTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 1]; const normalsTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 2]; @@ -230,11 +232,11 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const occlusionTextureIndex = eachTextureSetTextures[eachTextureSetTexturesIndex + 4]; sceneModel.createTextureSet({ id: textureSetId, - colorTextureId: colorTextureIndex >= 0 ? `texture-${colorTextureIndex}` : null, - normalsTextureId: normalsTextureIndex >= 0 ? `texture-${normalsTextureIndex}` : null, - metallicRoughnessTextureId: metallicRoughnessTextureIndex >= 0 ? `texture-${metallicRoughnessTextureIndex}` : null, - emissiveTextureId: emissiveTextureIndex >= 0 ? `texture-${emissiveTextureIndex}` : null, - occlusionTextureId: occlusionTextureIndex >= 0 ? `texture-${occlusionTextureIndex}` : null + colorTextureId: colorTextureIndex >= 0 ? `${modelPartId}-texture-${colorTextureIndex}` : null, + normalsTextureId: normalsTextureIndex >= 0 ? `${modelPartId}-texture-${normalsTextureIndex}` : null, + metallicRoughnessTextureId: metallicRoughnessTextureIndex >= 0 ? `${modelPartId}-texture-${metallicRoughnessTextureIndex}` : null, + emissiveTextureId: emissiveTextureIndex >= 0 ? `${modelPartId}-texture-${emissiveTextureIndex}` : null, + occlusionTextureId: occlusionTextureIndex >= 0 ? `${modelPartId}-texture-${occlusionTextureIndex}` : null }); } @@ -357,14 +359,14 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const textureSetIndex = eachMeshTextureSet[meshIndex]; - const textureSetId = (textureSetIndex >= 0) ? `textureSet-${textureSetIndex}` : null; + const textureSetId = (textureSetIndex >= 0) ? `${modelPartId}-textureSet-${textureSetIndex}` : null; const meshColor = decompressColor(eachMeshMaterialAttributes.subarray((meshIndex * 6), (meshIndex * 6) + 3)); const meshOpacity = eachMeshMaterialAttributes[(meshIndex * 6) + 3] / 255.0; const meshMetallic = eachMeshMaterialAttributes[(meshIndex * 6) + 4] / 255.0; const meshRoughness = eachMeshMaterialAttributes[(meshIndex * 6) + 5] / 255.0; - const meshId = manifestCtx.nextMeshId++; + const meshId = manifestCtx.getNextId(); if (isReusedGeometry) { @@ -373,7 +375,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMatrixIndex = eachMeshMatricesPortion[meshIndex]; const meshMatrix = matrices.slice(meshMatrixIndex, meshMatrixIndex + 16); - const geometryId = "geometry." + tileIndex + "." + geometryIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${tileIndex}.${geometryIndex}`; // These IDs are local to the SceneModel let geometryArrays = geometryArraysCache[geometryId]; @@ -477,7 +479,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) sceneModel.createMesh(utils.apply(meshDefaults, { id: meshId, - textureSetId: textureSetId, + textureSetId, origin: tileCenter, primitive: geometryArrays.primitiveName, positionsCompressed: transformedAndRecompressedPositions, @@ -516,8 +518,8 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) sceneModel.createMesh(utils.apply(meshDefaults, { id: meshId, - geometryId: geometryId, - textureSetId: textureSetId, + geometryId, + textureSetId, matrix: meshMatrix, color: meshColor, metallic: meshMetallic, @@ -592,7 +594,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) sceneModel.createMesh(utils.apply(meshDefaults, { id: meshId, - textureSetId: textureSetId, + textureSetId, origin: tileCenter, primitive: primitiveName, positionsCompressed: geometryPositions, diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV2.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV2.js index 8295401b2..d5ff711f3 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV2.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV2.js @@ -78,6 +78,8 @@ const decompressColor = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + sceneModel.positionsCompression = "precompressed"; sceneModel.normalsCompression = "precompressed"; @@ -147,7 +149,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const jj = entityMeshIds [j]; const lastMesh = (jj === (numMeshes - 1)); - const meshId = manifestCtx.nextMeshId++; + const meshId = manifestCtx.getNextId(); const color = decompressColor(meshColors.subarray((jj * 4), (jj * 4) + 3)); const opacity = meshColors[(jj * 4) + 3] / 255.0; @@ -159,7 +161,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) if (entityUsesInstancing [i] === 1) { - const geometryId = "geometry." + jj; + const geometryId = `${modelPartId}.geometry.${meshId}.${jj}`; if (!(geometryId in alreadyCreatedGeometries)) { @@ -181,7 +183,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) color: color, opacity: opacity, matrix: entityMatrix, - geometryId: geometryId, + geometryId, })); meshIds.push(meshId); diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV3.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV3.js index 9a4ae4117..602a64ce5 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV3.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV3.js @@ -69,6 +69,8 @@ const decompressColor = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + sceneModel.positionsCompression = "precompressed"; sceneModel.normalsCompression = "precompressed"; @@ -141,7 +143,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) var jj = entityMeshIds [j]; const lastMesh = (jj === (numMeshes - 1)); - const meshId = entityId + ".mesh." + jj; + const meshId = `${modelPartId}.${entityId}.mesh.${jj}`; const color = decompressColor(meshColors.subarray((jj * 4), (jj * 4) + 3)); const opacity = meshColors[(jj * 4) + 3] / 255.0; @@ -152,7 +154,8 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) var tmpEdgeIndices = edgeIndices.subarray(meshEdgesIndices [jj], lastMesh ? edgeIndices.length : meshEdgesIndices [jj + 1]); if (entityUsesInstancing [i] === 1) { - var geometryId = "geometry." + jj; + + const geometryId = `${modelPartId}.geometry.${meshId}.${jj}`; if (!(geometryId in _alreadyCreatedGeometries)) { @@ -174,7 +177,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) color: color, opacity: opacity, matrix: entityMatrix, - geometryId: geometryId, + geometryId, })); meshIds.push(meshId); diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV4.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV4.js index cf1776e59..5cf2a4402 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV4.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV4.js @@ -67,6 +67,8 @@ const decompressColor = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + sceneModel.positionsCompression = "precompressed"; sceneModel.normalsCompression = "precompressed"; @@ -174,7 +176,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) // Primitive instanced by more than one entity, and has positions in Model-space - var geometryId = "geometry" + orderedPrimitiveIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${orderedPrimitiveIndex}`; // These IDs are local to the SceneModel sceneModel.createGeometry({ id: geometryId, @@ -192,7 +194,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) // Primitive is used only by one entity, and has positions pre-transformed into World-space - const meshId = orderedPrimitiveIndex; // These IDs are local to the SceneModel + const meshId = `${modelPartId}-${orderedPrimitiveIndex}`; const entityIndex = batchedPrimitiveEntityIndexes[orderedPrimitiveIndex]; const entityId = eachEntityId[entityIndex]; @@ -235,8 +237,9 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshDefaults = {}; // TODO: get from lookup from entity IDs - const meshId = "instance." + countInstances++; - const geometryId = "geometry" + primitiveIndex; + const meshId = `${modelPartId}-instance.${countInstances++}`; + const geometryId = `${modelPartId}-geometry.${primitiveIndex}`; // These IDs are local to the SceneModel + const matricesIndex = (eachEntityMatricesPortion [entityIndex]) * 16; const matrix = matrices.subarray(matricesIndex, matricesIndex + 16); @@ -249,6 +252,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) meshIds.push(meshId); } else { + const meshId = `${modelPartId}-${primitiveIndex}`; meshIds.push(primitiveIndex); } } diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV5.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV5.js index b15728241..b253b210a 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV5.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV5.js @@ -62,6 +62,8 @@ const decompressColor = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + sceneModel.positionsCompression = "disabled"; // Positions in XKT V4 are floats, which we never quantize, for precision with big models sceneModel.normalsCompression = "precompressed"; // Normals are oct-encoded though @@ -141,7 +143,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) // Primitive instanced by more than one entity, and has positions in Model-space - var geometryId = "geometry" + primitiveIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${primitiveIndex}`; // These IDs are local to the SceneModel sceneModel.createGeometry({ id: geometryId, diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV6.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV6.js index 7c2b59e30..c3fdea694 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV6.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV6.js @@ -74,6 +74,8 @@ const decompressColor = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + const positions = inflatedData.positions; const normals = inflatedData.normals; const indices = inflatedData.indices; @@ -221,13 +223,13 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const color = decompressColor(eachPrimitiveColorAndOpacity.subarray((primitiveIndex * 4), (primitiveIndex * 4) + 3)); const opacity = eachPrimitiveColorAndOpacity[(primitiveIndex * 4) + 3] / 255.0; - const meshId = manifestCtx.nextMeshId++; + const meshId = manifestCtx.getNextId(); if (isReusedPrimitive) { // Create mesh for multi-use primitive - create (or reuse) geometry, create mesh using that geometry - const geometryId = "geometry." + tileIndex + "." + primitiveIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${tileIndex}.${primitiveIndex}`; // These IDs are local to the SceneModel if (!geometryCreated[geometryId]) { diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV7.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV7.js index b75ec893a..6ae1df5ac 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV7.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV7.js @@ -120,6 +120,8 @@ function convertColorsRGBToRGBA(colorsRGB) { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + const positions = inflatedData.positions; const normals = inflatedData.normals; const colors = inflatedData.colors; @@ -274,7 +276,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMetallic = eachMeshMaterial[(meshIndex * 6) + 4] / 255.0; const meshRoughness = eachMeshMaterial[(meshIndex * 6) + 5] / 255.0; - const meshId = manifestCtx.nextMeshId++; + const meshId = manifestCtx.getNextId(); if (isReusedGeometry) { @@ -283,7 +285,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMatrixIndex = eachMeshMatricesPortion[meshIndex]; const meshMatrix = matrices.slice(meshMatrixIndex, meshMatrixIndex + 16); - const geometryId = "geometry." + tileIndex + "." + geometryIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${tileIndex}.${geometryIndex}`; // These IDs are local to the SceneModel if (!geometryCreated[geometryId]) { diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV8.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV8.js index e9a9543a5..412c33c15 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV8.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV8.js @@ -130,6 +130,8 @@ function convertColorsRGBToRGBA(colorsRGB) { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + const types = JSON.parse(inflatedData.types); const eachMetaObjectId = JSON.parse(inflatedData.eachMetaObjectId); const eachMetaObjectType = inflatedData.eachMetaObjectType; @@ -317,7 +319,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMetallic = eachMeshMaterial[(meshIndex * 6) + 4] / 255.0; const meshRoughness = eachMeshMaterial[(meshIndex * 6) + 5] / 255.0; - const meshId = manifestCtx.nextMeshId++; + const meshId = manifestCtx.getNextId(); if (isReusedGeometry) { @@ -326,7 +328,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMatrixIndex = eachMeshMatricesPortion[meshIndex]; const meshMatrix = matrices.slice(meshMatrixIndex, meshMatrixIndex + 16); - const geometryId = "geometry." + tileIndex + "." + geometryIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${tileIndex}.${geometryIndex}`; // These IDs are local to the SceneModel let geometryArrays = geometryArraysCache[geometryId]; diff --git a/src/plugins/XKTLoaderPlugin/parsers/ParserV9.js b/src/plugins/XKTLoaderPlugin/parsers/ParserV9.js index 3bff41707..ff4f77bb7 100644 --- a/src/plugins/XKTLoaderPlugin/parsers/ParserV9.js +++ b/src/plugins/XKTLoaderPlugin/parsers/ParserV9.js @@ -111,6 +111,8 @@ const decompressColor = (function () { function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) { + const modelPartId = manifestCtx.getNextId(); + const metadata = inflatedData.metadata; const positions = inflatedData.positions; @@ -270,7 +272,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMetallic = eachMeshMaterial[(meshIndex * 6) + 4] / 255.0; const meshRoughness = eachMeshMaterial[(meshIndex * 6) + 5] / 255.0; - const meshId = manifestCtx.nextMeshId++; + const meshId = manifestCtx.getNextId(); if (isReusedGeometry) { @@ -279,7 +281,7 @@ function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) const meshMatrixIndex = eachMeshMatricesPortion[meshIndex]; const meshMatrix = matrices.slice(meshMatrixIndex, meshMatrixIndex + 16); - const geometryId = "geometry." + tileIndex + "." + geometryIndex; // These IDs are local to the SceneModel + const geometryId = `${modelPartId}-geometry.${tileIndex}.${geometryIndex}`; // These IDs are local to the SceneModel let geometryArrays = geometryArraysCache[geometryId];