/** * @license * Cesium - https://github.com/CesiumGS/cesium * Version 1.117 * * Copyright 2011-2022 Cesium Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Columbus View (Pat. Pend.) * * Portions licensed separately. * See https://github.com/CesiumGS/cesium/blob/main/LICENSE.md for full licensing details. */ import { require_draco_decoder_nodejs } from "./chunk-ZDP32RQI.js"; import { Color_default } from "./chunk-KPY4F4BW.js"; import { createTaskProcessorWorker_default } from "./chunk-IBXGK4WV.js"; import { WebMercatorProjection_default } from "./chunk-WEGCQ5DY.js"; import { Cartesian3_default, Cartographic_default, Ellipsoid_default, Matrix3_default } from "./chunk-C5CE4OG6.js"; import { Math_default } from "./chunk-4PHPQRSH.js"; import { defaultValue_default } from "./chunk-UCPPWV64.js"; import { Check_default } from "./chunk-U4IMCOF5.js"; import { __toESM, defined_default } from "./chunk-BDUJXBVF.js"; // packages/engine/Source/Workers/decodeI3S.js var import_draco_decoder_nodejs = __toESM(require_draco_decoder_nodejs(), 1); // packages/engine/Source/Core/srgbToLinear.js function srgbToLinear(value) { Check_default.defined("value", value); if (value <= 0.04045) { return value * 0.07739938080495357; } return Math.pow( // eslint-disable-next-line no-loss-of-precision (value + 0.055) * 0.9478672985781991, 2.4 ); } var srgbToLinear_default = srgbToLinear; // packages/engine/Source/Workers/decodeI3S.js var draco; function bilinearInterpolate(tx, ty, h00, h10, h01, h11) { const a = h00 * (1 - tx) + h10 * tx; const b = h01 * (1 - tx) + h11 * tx; return a * (1 - ty) + b * ty; } function sampleMap(u, v, width, data) { const address = u + v * width; return data[address]; } function sampleGeoid(sampleX, sampleY, geoidData) { const extent = geoidData.nativeExtent; let x = (sampleX - extent.west) / (extent.east - extent.west) * (geoidData.width - 1); let y = (sampleY - extent.south) / (extent.north - extent.south) * (geoidData.height - 1); const xi = Math.floor(x); let yi = Math.floor(y); x -= xi; y -= yi; const xNext = xi < geoidData.width ? xi + 1 : xi; let yNext = yi < geoidData.height ? yi + 1 : yi; yi = geoidData.height - 1 - yi; yNext = geoidData.height - 1 - yNext; const h00 = sampleMap(xi, yi, geoidData.width, geoidData.buffer); const h10 = sampleMap(xNext, yi, geoidData.width, geoidData.buffer); const h01 = sampleMap(xi, yNext, geoidData.width, geoidData.buffer); const h11 = sampleMap(xNext, yNext, geoidData.width, geoidData.buffer); let finalHeight = bilinearInterpolate(x, y, h00, h10, h01, h11); finalHeight = finalHeight * geoidData.scale + geoidData.offset; return finalHeight; } function sampleGeoidFromList(lon, lat, geoidDataList) { for (let i = 0; i < geoidDataList.length; i++) { const localExtent = geoidDataList[i].nativeExtent; let localPt = new Cartesian3_default(); if (geoidDataList[i].projectionType === "WebMercator") { const radii = geoidDataList[i].projection._ellipsoid._radii; const webMercatorProj = new WebMercatorProjection_default( new Ellipsoid_default(radii.x, radii.y, radii.z) ); localPt = webMercatorProj.project(new Cartographic_default(lon, lat, 0)); } else { localPt.x = lon; localPt.y = lat; } if (localPt.x > localExtent.west && localPt.x < localExtent.east && localPt.y > localExtent.south && localPt.y < localExtent.north) { return sampleGeoid(localPt.x, localPt.y, geoidDataList[i]); } } return 0; } function orthometricToEllipsoidal(vertexCount, position, scale_x, scale_y, center, geoidDataList, fast) { if (fast) { return; } const centerHeight = sampleGeoidFromList( center.longitude, center.latitude, geoidDataList ); for (let i = 0; i < vertexCount; ++i) { const height = sampleGeoidFromList( center.longitude + Math_default.toRadians(scale_x * position[i * 3]), center.latitude + Math_default.toRadians(scale_y * position[i * 3 + 1]), geoidDataList ); position[i * 3 + 2] += height - centerHeight; } } function transformToLocal(vertexCount, positions, normals, cartographicCenter, cartesianCenter, parentRotation, ellipsoidRadiiSquare, scale_x, scale_y) { if (vertexCount === 0 || !defined_default(positions) || positions.length === 0) { return; } const ellipsoid = new Ellipsoid_default( Math.sqrt(ellipsoidRadiiSquare.x), Math.sqrt(ellipsoidRadiiSquare.y), Math.sqrt(ellipsoidRadiiSquare.z) ); for (let i = 0; i < vertexCount; ++i) { const indexOffset = i * 3; const indexOffset1 = indexOffset + 1; const indexOffset2 = indexOffset + 2; const cartographic = new Cartographic_default(); cartographic.longitude = cartographicCenter.longitude + Math_default.toRadians(scale_x * positions[indexOffset]); cartographic.latitude = cartographicCenter.latitude + Math_default.toRadians(scale_y * positions[indexOffset1]); cartographic.height = cartographicCenter.height + positions[indexOffset2]; const position = {}; ellipsoid.cartographicToCartesian(cartographic, position); position.x -= cartesianCenter.x; position.y -= cartesianCenter.y; position.z -= cartesianCenter.z; const rotatedPosition = {}; Matrix3_default.multiplyByVector(parentRotation, position, rotatedPosition); positions[indexOffset] = rotatedPosition.x; positions[indexOffset1] = rotatedPosition.y; positions[indexOffset2] = rotatedPosition.z; if (defined_default(normals)) { const normal = new Cartesian3_default( normals[indexOffset], normals[indexOffset1], normals[indexOffset2] ); const rotatedNormal = {}; Matrix3_default.multiplyByVector(parentRotation, normal, rotatedNormal); normals[indexOffset] = rotatedNormal.x; normals[indexOffset1] = rotatedNormal.y; normals[indexOffset2] = rotatedNormal.z; } } } function cropUVs(vertexCount, uv0s, uvRegions) { for (let vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { const minU = uvRegions[vertexIndex * 4] / 65535; const minV = uvRegions[vertexIndex * 4 + 1] / 65535; const scaleU = (uvRegions[vertexIndex * 4 + 2] - uvRegions[vertexIndex * 4]) / 65535; const scaleV = (uvRegions[vertexIndex * 4 + 3] - uvRegions[vertexIndex * 4 + 1]) / 65535; uv0s[vertexIndex * 2] *= scaleU; uv0s[vertexIndex * 2] += minU; uv0s[vertexIndex * 2 + 1] *= scaleV; uv0s[vertexIndex * 2 + 1] += minV; } } function generateIndexArray(vertexCount, indices, colors, splitGeometryByColorTransparency) { const indexArray = new Uint32Array(vertexCount); const vertexIndexFn = defined_default(indices) ? (vertexIndex) => indices[vertexIndex] : (vertexIndex) => vertexIndex; let transparentVertexOffset = 0; if (splitGeometryByColorTransparency && defined_default(colors)) { const isVertexTransparentFn = (vertexIndex) => colors[vertexIndexFn(vertexIndex) * 4 + 3] < 255; for (let vertexIndex = 0; vertexIndex < vertexCount; vertexIndex += 3) { if (!isVertexTransparentFn(vertexIndex) && !isVertexTransparentFn(vertexIndex + 1) && !isVertexTransparentFn(vertexIndex + 2)) { indexArray[transparentVertexOffset++] = vertexIndexFn(vertexIndex); indexArray[transparentVertexOffset++] = vertexIndexFn(vertexIndex + 1); indexArray[transparentVertexOffset++] = vertexIndexFn(vertexIndex + 2); } } if (transparentVertexOffset > 0) { let offset = transparentVertexOffset; for (let vertexIndex = 0; vertexIndex < vertexCount; vertexIndex += 3) { if (isVertexTransparentFn(vertexIndex) || isVertexTransparentFn(vertexIndex + 1) || isVertexTransparentFn(vertexIndex + 2)) { indexArray[offset++] = vertexIndexFn(vertexIndex); indexArray[offset++] = vertexIndexFn(vertexIndex + 1); indexArray[offset++] = vertexIndexFn(vertexIndex + 2); } } } else { for (let vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { indexArray[vertexIndex] = vertexIndexFn(vertexIndex); } } } else { transparentVertexOffset = vertexCount; for (let vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { indexArray[vertexIndex] = vertexIndexFn(vertexIndex); } } return { indexArray, transparentVertexOffset }; } function getFeatureHash(symbologyData, outlinesHash, featureIndex) { const featureHash = outlinesHash[featureIndex]; if (defined_default(featureHash)) { return featureHash; } const newFeatureHash = outlinesHash[featureIndex] = { positions: {}, indices: {}, edges: {} }; const featureSymbology = defaultValue_default( symbologyData[featureIndex], symbologyData.default ); newFeatureHash.hasOutline = defined_default(featureSymbology?.edges); return newFeatureHash; } function addVertexToHash(indexHash, positionHash, vertexIndex, positions) { if (!defined_default(indexHash[vertexIndex])) { const startPositionIndex = vertexIndex * 3; let coordinateHash = positionHash; for (let index = 0; index < 3; index++) { const coordinate = positions[startPositionIndex + index]; if (!defined_default(coordinateHash[coordinate])) { coordinateHash[coordinate] = {}; } coordinateHash = coordinateHash[coordinate]; } if (!defined_default(coordinateHash.index)) { coordinateHash.index = vertexIndex; } indexHash[vertexIndex] = coordinateHash.index; } } function addEdgeToHash(edgeHash, vertexAIndex, vertexBIndex, vertexAIndexUnique, vertexBIndexUnique, normalIndex) { let startVertexIndex; let endVertexIndex; if (vertexAIndexUnique < vertexBIndexUnique) { startVertexIndex = vertexAIndexUnique; endVertexIndex = vertexBIndexUnique; } else { startVertexIndex = vertexBIndexUnique; endVertexIndex = vertexAIndexUnique; } let edgeStart = edgeHash[startVertexIndex]; if (!defined_default(edgeStart)) { edgeStart = edgeHash[startVertexIndex] = {}; } let edgeEnd = edgeStart[endVertexIndex]; if (!defined_default(edgeEnd)) { edgeEnd = edgeStart[endVertexIndex] = { normalsIndex: [], outlines: [] }; } edgeEnd.normalsIndex.push(normalIndex); if (edgeEnd.outlines.length === 0 || vertexAIndex !== vertexAIndexUnique || vertexBIndex !== vertexBIndexUnique) { edgeEnd.outlines.push(vertexAIndex, vertexBIndex); } } function generateOutlinesHash(symbologyData, featureIndexArray, indexArray, positions) { const outlinesHash = []; for (let i = 0; i < indexArray.length; i += 3) { const featureIndex = defined_default(featureIndexArray) ? featureIndexArray[indexArray[i]] : "default"; const featureHash = getFeatureHash( symbologyData, outlinesHash, featureIndex ); if (!featureHash.hasOutline) { continue; } const indexHash = featureHash.indices; const positionHash = featureHash.positions; for (let vertex = 0; vertex < 3; vertex++) { const vertexIndex = indexArray[i + vertex]; addVertexToHash(indexHash, positionHash, vertexIndex, positions); } const edgeHash = featureHash.edges; for (let vertex = 0; vertex < 3; vertex++) { const vertexIndex = indexArray[i + vertex]; const nextVertexIndex = indexArray[i + (vertex + 1) % 3]; const uniqueVertexIndex = indexHash[vertexIndex]; const uniqueNextVertexIndex = indexHash[nextVertexIndex]; addEdgeToHash( edgeHash, vertexIndex, nextVertexIndex, uniqueVertexIndex, uniqueNextVertexIndex, i ); } } return outlinesHash; } var calculateFaceNormalA = new Cartesian3_default(); var calculateFaceNormalB = new Cartesian3_default(); var calculateFaceNormalC = new Cartesian3_default(); function calculateFaceNormal(normals, vertexAIndex, indexArray, positions) { const positionAIndex = indexArray[vertexAIndex] * 3; const positionBIndex = indexArray[vertexAIndex + 1] * 3; const positionCIndex = indexArray[vertexAIndex + 2] * 3; Cartesian3_default.fromArray(positions, positionAIndex, calculateFaceNormalA); Cartesian3_default.fromArray(positions, positionBIndex, calculateFaceNormalB); Cartesian3_default.fromArray(positions, positionCIndex, calculateFaceNormalC); Cartesian3_default.subtract( calculateFaceNormalB, calculateFaceNormalA, calculateFaceNormalB ); Cartesian3_default.subtract( calculateFaceNormalC, calculateFaceNormalA, calculateFaceNormalC ); Cartesian3_default.cross( calculateFaceNormalB, calculateFaceNormalC, calculateFaceNormalA ); const magnitude = Cartesian3_default.magnitude(calculateFaceNormalA); if (magnitude !== 0) { Cartesian3_default.divideByScalar( calculateFaceNormalA, magnitude, calculateFaceNormalA ); } const normalAIndex = vertexAIndex * 3; const normalBIndex = (vertexAIndex + 1) * 3; const normalCIndex = (vertexAIndex + 2) * 3; Cartesian3_default.pack(calculateFaceNormalA, normals, normalAIndex); Cartesian3_default.pack(calculateFaceNormalA, normals, normalBIndex); Cartesian3_default.pack(calculateFaceNormalA, normals, normalCIndex); } var isEdgeSmoothA = new Cartesian3_default(); var isEdgeSmoothB = new Cartesian3_default(); function isEdgeSmooth(normals, normalAIndex, normalBIndex) { Cartesian3_default.fromArray(normals, normalAIndex, isEdgeSmoothA); Cartesian3_default.fromArray(normals, normalBIndex, isEdgeSmoothB); const cosine = Cartesian3_default.dot(isEdgeSmoothA, isEdgeSmoothB); const sine = Cartesian3_default.magnitude( Cartesian3_default.cross(isEdgeSmoothA, isEdgeSmoothB, isEdgeSmoothA) ); return Math.atan2(sine, cosine) < 0.25; } function addOutlinesForEdge(outlines, edgeData, indexArray, positions, normals) { if (edgeData.normalsIndex.length > 1) { const normalsByIndex = positions.length === normals.length; for (let indexA = 0; indexA < edgeData.normalsIndex.length; indexA++) { const vertexAIndex = edgeData.normalsIndex[indexA]; if (!defined_default(normals[vertexAIndex * 3])) { calculateFaceNormal(normals, vertexAIndex, indexArray, positions); } if (indexA === 0) { continue; } for (let indexB = 0; indexB < indexA; indexB++) { const vertexBIndex = edgeData.normalsIndex[indexB]; const normalAIndex = normalsByIndex ? indexArray[vertexAIndex] * 3 : vertexAIndex * 3; const normalBIndex = normalsByIndex ? indexArray[vertexBIndex] * 3 : vertexBIndex * 3; if (isEdgeSmooth(normals, normalAIndex, normalBIndex)) { return; } } } } outlines.push(...edgeData.outlines); } function addOutlinesForFeature(outlines, edgeHash, indexArray, positions, normals) { const edgeStartKeys = Object.keys(edgeHash); for (let startIndex = 0; startIndex < edgeStartKeys.length; startIndex++) { const edgeEnds = edgeHash[edgeStartKeys[startIndex]]; const edgeEndKeys = Object.keys(edgeEnds); for (let endIndex = 0; endIndex < edgeEndKeys.length; endIndex++) { const edgeData = edgeEnds[edgeEndKeys[endIndex]]; addOutlinesForEdge(outlines, edgeData, indexArray, positions, normals); } } } function generateOutlinesFromHash(outlinesHash, indexArray, positions, normals) { const outlines = []; const features = Object.keys(outlinesHash); for (let featureIndex = 0; featureIndex < features.length; featureIndex++) { const edgeHash = outlinesHash[features[featureIndex]].edges; addOutlinesForFeature(outlines, edgeHash, indexArray, positions, normals); } return outlines; } function generateOutlinesIndexArray(symbologyData, featureIndexArray, indexArray, positions, normals) { if (!defined_default(symbologyData) || Object.keys(symbologyData).length === 0) { return void 0; } const outlinesHash = generateOutlinesHash( symbologyData, featureIndexArray, indexArray, positions ); if (!defined_default(normals) || indexArray.length * 3 !== normals.length) { normals = []; } const outlines = generateOutlinesFromHash( outlinesHash, indexArray, positions, normals ); const outlinesIndexArray = outlines.length > 0 ? new Uint32Array(outlines) : void 0; return outlinesIndexArray; } function convertColorsArray(colors) { const colorsArray = new Float32Array(colors.length); for (let index = 0; index < colors.length; index += 4) { colorsArray[index] = srgbToLinear_default(Color_default.byteToFloat(colors[index])); colorsArray[index + 1] = srgbToLinear_default(Color_default.byteToFloat(colors[index + 1])); colorsArray[index + 2] = srgbToLinear_default(Color_default.byteToFloat(colors[index + 2])); colorsArray[index + 3] = Color_default.byteToFloat(colors[index + 3]); } return colorsArray; } function generateNormals(vertexCount, indices, positions, normals, uv0s, colors, featureIndex) { const result = { normals: void 0, positions: void 0, uv0s: void 0, colors: void 0, featureIndex: void 0, vertexCount: void 0 }; if (vertexCount === 0 || !defined_default(positions) || positions.length === 0 || defined_default(normals)) { return result; } if (defined_default(indices)) { result.vertexCount = indices.length; result.positions = new Float32Array(indices.length * 3); result.uv0s = defined_default(uv0s) ? new Float32Array(indices.length * 2) : void 0; result.colors = defined_default(colors) ? new Uint8Array(indices.length * 4) : void 0; result.featureIndex = defined_default(featureIndex) ? new Array(indices.length) : void 0; for (let i = 0; i < indices.length; i++) { const index = indices[i]; result.positions[i * 3] = positions[index * 3]; result.positions[i * 3 + 1] = positions[index * 3 + 1]; result.positions[i * 3 + 2] = positions[index * 3 + 2]; if (defined_default(result.uv0s)) { result.uv0s[i * 2] = uv0s[index * 2]; result.uv0s[i * 2 + 1] = uv0s[index * 2 + 1]; } if (defined_default(result.colors)) { result.colors[i * 4] = colors[index * 4]; result.colors[i * 4 + 1] = colors[index * 4 + 1]; result.colors[i * 4 + 2] = colors[index * 4 + 2]; result.colors[i * 4 + 3] = colors[index * 4 + 3]; } if (defined_default(result.featureIndex)) { result.featureIndex[i] = featureIndex[index]; } } vertexCount = indices.length; positions = result.positions; } indices = new Array(vertexCount); for (let i = 0; i < vertexCount; i++) { indices[i] = i; } result.normals = new Float32Array(indices.length * 3); for (let i = 0; i < indices.length; i += 3) { calculateFaceNormal(result.normals, i, indices, positions); } return result; } function generateGltfBuffer(vertexCount, indices, positions, normals, uv0s, colors, featureIndex, parameters) { if (vertexCount === 0 || !defined_default(positions) || positions.length === 0) { return { buffers: [], bufferViews: [], accessors: [], meshes: [], nodes: [], nodesInScene: [] }; } const buffers = []; const bufferViews = []; const accessors = []; const meshes = []; const nodes = []; const nodesInScene = []; const rootExtensions = {}; const extensionsUsed = []; if (defined_default(indices)) { vertexCount = indices.length; } const { indexArray, transparentVertexOffset } = generateIndexArray( vertexCount, indices, colors, parameters.splitGeometryByColorTransparency ); const indicesBlob = new Blob([indexArray], { type: "application/binary" }); const indicesURL = URL.createObjectURL(indicesBlob); const endIndex = vertexCount; const featureIndexArray = parameters.enableFeatures && defined_default(featureIndex) ? new Float32Array(featureIndex.length) : void 0; let featureCount = 0; if (defined_default(featureIndexArray)) { for (let index = 0; index < featureIndex.length; ++index) { featureIndexArray[index] = featureIndex[index]; const countByIndex = featureIndex[index] + 1; if (featureCount < countByIndex) { featureCount = countByIndex; } } } let outlinesIndicesURL; const outlinesIndexArray = generateOutlinesIndexArray( parameters.symbologyData, featureIndex, indexArray, positions, normals ); if (defined_default(outlinesIndexArray)) { const outlinesIndicesBlob = new Blob([outlinesIndexArray], { type: "application/binary" }); outlinesIndicesURL = URL.createObjectURL(outlinesIndicesBlob); } const meshPositions = positions.subarray(0, endIndex * 3); const positionsBlob = new Blob([meshPositions], { type: "application/binary" }); const positionsURL = URL.createObjectURL(positionsBlob); let minX = Number.POSITIVE_INFINITY; let maxX = Number.NEGATIVE_INFINITY; let minY = Number.POSITIVE_INFINITY; let maxY = Number.NEGATIVE_INFINITY; let minZ = Number.POSITIVE_INFINITY; let maxZ = Number.NEGATIVE_INFINITY; for (let i = 0; i < meshPositions.length / 3; i++) { minX = Math.min(minX, meshPositions[i * 3 + 0]); maxX = Math.max(maxX, meshPositions[i * 3 + 0]); minY = Math.min(minY, meshPositions[i * 3 + 1]); maxY = Math.max(maxY, meshPositions[i * 3 + 1]); minZ = Math.min(minZ, meshPositions[i * 3 + 2]); maxZ = Math.max(maxZ, meshPositions[i * 3 + 2]); } const meshNormals = normals ? normals.subarray(0, endIndex * 3) : void 0; let normalsURL; if (defined_default(meshNormals)) { const normalsBlob = new Blob([meshNormals], { type: "application/binary" }); normalsURL = URL.createObjectURL(normalsBlob); } const meshUv0s = uv0s ? uv0s.subarray(0, endIndex * 2) : void 0; let uv0URL; if (defined_default(meshUv0s)) { const uv0Blob = new Blob([meshUv0s], { type: "application/binary" }); uv0URL = URL.createObjectURL(uv0Blob); } const meshColorsInBytes = defined_default(colors) ? convertColorsArray(colors.subarray(0, endIndex * 4)) : void 0; let colorsURL; if (defined_default(meshColorsInBytes)) { const colorsBlob = new Blob([meshColorsInBytes], { type: "application/binary" }); colorsURL = URL.createObjectURL(colorsBlob); } const meshFeatureId0 = defined_default(featureIndexArray) ? featureIndexArray.subarray(0, endIndex) : void 0; let featureId0URL; if (defined_default(meshFeatureId0)) { const featureId0Blob = new Blob([meshFeatureId0], { type: "application/binary" }); featureId0URL = URL.createObjectURL(featureId0Blob); } const meshPropertyTable0 = defined_default(featureIndexArray) ? new Float32Array(featureCount) : void 0; let propertyTable0URL; if (defined_default(meshPropertyTable0)) { for (let index = 0; index < meshPropertyTable0.length; ++index) { meshPropertyTable0[index] = index; } const propertyTable0Blob = new Blob([meshPropertyTable0], { type: "application/binary" }); propertyTable0URL = URL.createObjectURL(propertyTable0Blob); } const attributes = {}; const extensions = {}; attributes.POSITION = accessors.length; buffers.push({ uri: positionsURL, byteLength: meshPositions.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: meshPositions.byteLength, target: 34962 }); accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5126, count: meshPositions.length / 3, type: "VEC3", max: [minX, minY, minZ], min: [maxX, maxY, maxZ] }); if (defined_default(normalsURL)) { attributes.NORMAL = accessors.length; buffers.push({ uri: normalsURL, byteLength: meshNormals.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: meshNormals.byteLength, target: 34962 }); accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5126, count: meshNormals.length / 3, type: "VEC3" }); } if (defined_default(uv0URL)) { attributes.TEXCOORD_0 = accessors.length; buffers.push({ uri: uv0URL, byteLength: meshUv0s.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: meshUv0s.byteLength, target: 34962 }); accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5126, count: meshUv0s.length / 2, type: "VEC2" }); } if (defined_default(colorsURL)) { attributes.COLOR_0 = accessors.length; buffers.push({ uri: colorsURL, byteLength: meshColorsInBytes.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: meshColorsInBytes.byteLength, target: 34962 }); accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5126, count: meshColorsInBytes.length / 4, type: "VEC4" }); } if (defined_default(featureId0URL)) { attributes._FEATURE_ID_0 = accessors.length; buffers.push({ uri: featureId0URL, byteLength: meshFeatureId0.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: meshFeatureId0.byteLength, target: 34963 }); accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5126, count: meshFeatureId0.length, type: "SCALAR" }); extensions.EXT_mesh_features = { featureIds: [ { attribute: 0, propertyTable: 0, featureCount } ] }; extensionsUsed.push("EXT_mesh_features"); } if (defined_default(propertyTable0URL)) { buffers.push({ uri: propertyTable0URL, byteLength: meshPropertyTable0.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: meshPropertyTable0.byteLength, target: 34963 }); rootExtensions.EXT_structural_metadata = { schema: { id: "i3s-metadata-schema-001", name: "I3S metadata schema 001", description: "The schema for I3S metadata", version: "1.0", classes: { feature: { name: "feature", description: "Feature metadata", properties: { index: { description: "The feature index", type: "SCALAR", componentType: "FLOAT32", required: true } } } } }, propertyTables: [ { name: "feature-indices-mapping", class: "feature", count: featureCount, properties: { index: { values: bufferViews.length - 1 } } } ] }; extensionsUsed.push("EXT_structural_metadata"); } if (defined_default(outlinesIndicesURL)) { buffers.push({ uri: outlinesIndicesURL, byteLength: outlinesIndexArray.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: outlinesIndexArray.byteLength, target: 34963 }); accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5125, count: outlinesIndexArray.length, type: "SCALAR" }); extensions.CESIUM_primitive_outline = { indices: accessors.length - 1 }; extensionsUsed.push("CESIUM_primitive_outline"); } buffers.push({ uri: indicesURL, byteLength: indexArray.byteLength }); bufferViews.push({ buffer: buffers.length - 1, byteOffset: 0, byteLength: indexArray.byteLength, target: 34963 }); const meshPrimitives = []; if (transparentVertexOffset > 0) { accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 0, componentType: 5125, count: transparentVertexOffset, type: "SCALAR" }); meshPrimitives.push({ attributes, indices: accessors.length - 1, material: meshPrimitives.length, extensions }); } if (transparentVertexOffset < vertexCount) { accessors.push({ bufferView: bufferViews.length - 1, byteOffset: 4 * transparentVertexOffset, // skip 4 bytes for each opaque vertex componentType: 5125, count: vertexCount - transparentVertexOffset, type: "SCALAR" }); meshPrimitives.push({ attributes, indices: accessors.length - 1, material: meshPrimitives.length, extensions, extra: { isTransparent: true } }); } meshes.push({ primitives: meshPrimitives }); nodesInScene.push(0); nodes.push({ mesh: 0 }); return { buffers, bufferViews, accessors, meshes, nodes, nodesInScene, rootExtensions, extensionsUsed }; } function decode(data, schema, bufferInfo, featureData) { const magicNumber = new Uint8Array(data, 0, 5); if (magicNumber[0] === "D".charCodeAt() && magicNumber[1] === "R".charCodeAt() && magicNumber[2] === "A".charCodeAt() && magicNumber[3] === "C".charCodeAt() && magicNumber[4] === "O".charCodeAt()) { return decodeDracoEncodedGeometry(data, bufferInfo); } return decodeBinaryGeometry(data, schema, bufferInfo, featureData); } function decodeDracoEncodedGeometry(data) { const dracoDecoderModule = draco; const buffer = new dracoDecoderModule.DecoderBuffer(); const byteArray = new Uint8Array(data); buffer.Init(byteArray, byteArray.length); const dracoDecoder = new dracoDecoderModule.Decoder(); const geometryType = dracoDecoder.GetEncodedGeometryType(buffer); const metadataQuerier = new dracoDecoderModule.MetadataQuerier(); let dracoGeometry; let status; if (geometryType === dracoDecoderModule.TRIANGULAR_MESH) { dracoGeometry = new dracoDecoderModule.Mesh(); status = dracoDecoder.DecodeBufferToMesh(buffer, dracoGeometry); } const decodedGeometry = { vertexCount: [0], featureCount: 0 }; if (defined_default(status) && status.ok() && dracoGeometry.ptr !== 0) { const faceCount = dracoGeometry.num_faces(); const attributesCount = dracoGeometry.num_attributes(); const vertexCount = dracoGeometry.num_points(); decodedGeometry.indices = new Uint32Array(faceCount * 3); const faces = decodedGeometry.indices; decodedGeometry.vertexCount[0] = vertexCount; decodedGeometry.scale_x = 1; decodedGeometry.scale_y = 1; const face = new dracoDecoderModule.DracoInt32Array(3); for (let faceIndex = 0; faceIndex < faceCount; ++faceIndex) { dracoDecoder.GetFaceFromMesh(dracoGeometry, faceIndex, face); faces[faceIndex * 3] = face.GetValue(0); faces[faceIndex * 3 + 1] = face.GetValue(1); faces[faceIndex * 3 + 2] = face.GetValue(2); } dracoDecoderModule.destroy(face); for (let attrIndex = 0; attrIndex < attributesCount; ++attrIndex) { const dracoAttribute = dracoDecoder.GetAttribute( dracoGeometry, attrIndex ); const attributeData = decodeDracoAttribute( dracoDecoderModule, dracoDecoder, dracoGeometry, dracoAttribute, vertexCount ); const dracoAttributeType = dracoAttribute.attribute_type(); let attributei3sName = "unknown"; if (dracoAttributeType === dracoDecoderModule.POSITION) { attributei3sName = "positions"; } else if (dracoAttributeType === dracoDecoderModule.NORMAL) { attributei3sName = "normals"; } else if (dracoAttributeType === dracoDecoderModule.COLOR) { attributei3sName = "colors"; } else if (dracoAttributeType === dracoDecoderModule.TEX_COORD) { attributei3sName = "uv0s"; } const metadata = dracoDecoder.GetAttributeMetadata( dracoGeometry, attrIndex ); if (metadata.ptr !== 0) { const numEntries = metadataQuerier.NumEntries(metadata); for (let entry = 0; entry < numEntries; ++entry) { const entryName = metadataQuerier.GetEntryName(metadata, entry); if (entryName === "i3s-scale_x") { decodedGeometry.scale_x = metadataQuerier.GetDoubleEntry( metadata, "i3s-scale_x" ); } else if (entryName === "i3s-scale_y") { decodedGeometry.scale_y = metadataQuerier.GetDoubleEntry( metadata, "i3s-scale_y" ); } else if (entryName === "i3s-attribute-type") { attributei3sName = metadataQuerier.GetStringEntry( metadata, "i3s-attribute-type" ); } } } if (defined_default(decodedGeometry[attributei3sName])) { console.log("Attribute already exists", attributei3sName); } decodedGeometry[attributei3sName] = attributeData; if (attributei3sName === "feature-index") { decodedGeometry.featureCount++; } } dracoDecoderModule.destroy(dracoGeometry); } dracoDecoderModule.destroy(metadataQuerier); dracoDecoderModule.destroy(dracoDecoder); return decodedGeometry; } function decodeDracoAttribute(dracoDecoderModule, dracoDecoder, dracoGeometry, dracoAttribute, vertexCount) { const bufferSize = dracoAttribute.num_components() * vertexCount; let dracoAttributeData; const handlers = [ function() { }, // DT_INVALID - 0 function() { dracoAttributeData = new dracoDecoderModule.DracoInt8Array(bufferSize); const success = dracoDecoder.GetAttributeInt8ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Int8Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { dracoAttributeData = new dracoDecoderModule.DracoInt8Array(bufferSize); const success = dracoDecoder.GetAttributeUInt8ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Uint8Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { dracoAttributeData = new dracoDecoderModule.DracoInt16Array(bufferSize); const success = dracoDecoder.GetAttributeInt16ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Int16Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { dracoAttributeData = new dracoDecoderModule.DracoInt16Array(bufferSize); const success = dracoDecoder.GetAttributeUInt16ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Uint16Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { dracoAttributeData = new dracoDecoderModule.DracoInt32Array(bufferSize); const success = dracoDecoder.GetAttributeInt32ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Int32Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { dracoAttributeData = new dracoDecoderModule.DracoInt32Array(bufferSize); const success = dracoDecoder.GetAttributeUInt32ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Uint32Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { }, function() { }, function() { dracoAttributeData = new dracoDecoderModule.DracoFloat32Array(bufferSize); const success = dracoDecoder.GetAttributeFloatForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Float32Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; }, function() { }, function() { dracoAttributeData = new dracoDecoderModule.DracoUInt8Array(bufferSize); const success = dracoDecoder.GetAttributeUInt8ForAllPoints( dracoGeometry, dracoAttribute, dracoAttributeData ); if (!success) { console.error("Bad stream"); } const attributeData2 = new Uint8Array(bufferSize); for (let i = 0; i < bufferSize; ++i) { attributeData2[i] = dracoAttributeData.GetValue(i); } return attributeData2; } ]; const attributeData = handlers[dracoAttribute.data_type()](); if (defined_default(dracoAttributeData)) { dracoDecoderModule.destroy(dracoAttributeData); } return attributeData; } var binaryAttributeDecoders = { position: function(decodedGeometry, data, offset) { const count = decodedGeometry.vertexCount * 3; decodedGeometry.positions = new Float32Array(data, offset, count); offset += count * 4; return offset; }, normal: function(decodedGeometry, data, offset) { const count = decodedGeometry.vertexCount * 3; decodedGeometry.normals = new Float32Array(data, offset, count); offset += count * 4; return offset; }, uv0: function(decodedGeometry, data, offset) { const count = decodedGeometry.vertexCount * 2; decodedGeometry.uv0s = new Float32Array(data, offset, count); offset += count * 4; return offset; }, color: function(decodedGeometry, data, offset) { const count = decodedGeometry.vertexCount * 4; decodedGeometry.colors = new Uint8Array(data, offset, count); offset += count; return offset; }, featureId: function(decodedGeometry, data, offset) { const count = decodedGeometry.featureCount; offset += count * 8; return offset; }, id: function(decodedGeometry, data, offset) { const count = decodedGeometry.featureCount; offset += count * 8; return offset; }, faceRange: function(decodedGeometry, data, offset) { const count = decodedGeometry.featureCount * 2; decodedGeometry.faceRange = new Uint32Array(data, offset, count); offset += count * 4; return offset; }, uvRegion: function(decodedGeometry, data, offset) { const count = decodedGeometry.vertexCount * 4; decodedGeometry["uv-region"] = new Uint16Array(data, offset, count); offset += count * 2; return offset; }, region: function(decodedGeometry, data, offset) { const count = decodedGeometry.vertexCount * 4; decodedGeometry["uv-region"] = new Uint16Array(data, offset, count); offset += count * 2; return offset; } }; function decodeBinaryGeometry(data, schema, bufferInfo, featureData) { const decodedGeometry = { vertexCount: 0 }; const dataView = new DataView(data); try { let offset = 0; decodedGeometry.vertexCount = dataView.getUint32(offset, 1); offset += 4; decodedGeometry.featureCount = dataView.getUint32(offset, 1); offset += 4; if (defined_default(bufferInfo)) { for (let attrIndex = 0; attrIndex < bufferInfo.attributes.length; attrIndex++) { if (defined_default(binaryAttributeDecoders[bufferInfo.attributes[attrIndex]])) { offset = binaryAttributeDecoders[bufferInfo.attributes[attrIndex]]( decodedGeometry, data, offset ); } else { console.error( "Unknown decoder for", bufferInfo.attributes[attrIndex] ); } } } else { let ordering = schema.ordering; let featureAttributeOrder = schema.featureAttributeOrder; if (defined_default(featureData) && defined_default(featureData.geometryData) && defined_default(featureData.geometryData[0]) && defined_default(featureData.geometryData[0].params)) { ordering = Object.keys( featureData.geometryData[0].params.vertexAttributes ); featureAttributeOrder = Object.keys( featureData.geometryData[0].params.featureAttributes ); } for (let i = 0; i < ordering.length; i++) { const decoder = binaryAttributeDecoders[ordering[i]]; offset = decoder(decodedGeometry, data, offset); } for (let j = 0; j < featureAttributeOrder.length; j++) { const curDecoder = binaryAttributeDecoders[featureAttributeOrder[j]]; offset = curDecoder(decodedGeometry, data, offset); } } } catch (e) { console.error(e); } decodedGeometry.scale_x = 1; decodedGeometry.scale_y = 1; return decodedGeometry; } function decodeAndCreateGltf(parameters) { const geometryData = decode( parameters.binaryData, parameters.schema, parameters.bufferInfo, parameters.featureData ); if (defined_default(parameters.geoidDataList) && parameters.geoidDataList.length > 0) { orthometricToEllipsoidal( geometryData.vertexCount, geometryData.positions, geometryData.scale_x, geometryData.scale_y, parameters.cartographicCenter, parameters.geoidDataList, false ); } transformToLocal( geometryData.vertexCount, geometryData.positions, geometryData.normals, parameters.cartographicCenter, parameters.cartesianCenter, parameters.parentRotation, parameters.ellipsoidRadiiSquare, geometryData.scale_x, geometryData.scale_y ); if (defined_default(geometryData.uv0s) && defined_default(geometryData["uv-region"])) { cropUVs( geometryData.vertexCount, geometryData.uv0s, geometryData["uv-region"] ); } let featureIndex; if (defined_default(geometryData["feature-index"])) { featureIndex = geometryData["feature-index"]; } else if (defined_default(geometryData["faceRange"])) { featureIndex = new Array(geometryData.vertexCount); for (let range = 0; range < geometryData["faceRange"].length - 1; range += 2) { const curIndex = range / 2; const rangeStart = geometryData["faceRange"][range]; const rangeEnd = geometryData["faceRange"][range + 1]; for (let i = rangeStart; i <= rangeEnd; i++) { featureIndex[i * 3] = curIndex; featureIndex[i * 3 + 1] = curIndex; featureIndex[i * 3 + 2] = curIndex; } } } if (parameters.calculateNormals) { const data = generateNormals( geometryData.vertexCount, geometryData.indices, geometryData.positions, geometryData.normals, geometryData.uv0s, geometryData.colors, featureIndex ); if (defined_default(data.normals)) { geometryData.normals = data.normals; if (defined_default(data.vertexCount)) { geometryData.vertexCount = data.vertexCount; geometryData.indices = data.indices; geometryData.positions = data.positions; geometryData.uv0s = data.uv0s; geometryData.colors = data.colors; featureIndex = data.featureIndex; } } } const meshData = generateGltfBuffer( geometryData.vertexCount, geometryData.indices, geometryData.positions, geometryData.normals, geometryData.uv0s, geometryData.colors, featureIndex, parameters ); const customAttributes = { positions: geometryData.positions, indices: geometryData.indices, featureIndex, sourceURL: parameters.url, cartesianCenter: parameters.cartesianCenter, parentRotation: parameters.parentRotation }; meshData._customAttributes = customAttributes; const results = { meshData }; return results; } async function initWorker(parameters, transferableObjects) { const wasmConfig = parameters.webAssemblyConfig; if (defined_default(wasmConfig) && defined_default(wasmConfig.wasmBinaryFile)) { draco = await (0, import_draco_decoder_nodejs.default)(wasmConfig); } else { draco = await (0, import_draco_decoder_nodejs.default)(); } return true; } function decodeI3S(parameters, transferableObjects) { const wasmConfig = parameters.webAssemblyConfig; if (defined_default(wasmConfig)) { return initWorker(parameters, transferableObjects); } return decodeAndCreateGltf(parameters, transferableObjects); } var decodeI3S_default = createTaskProcessorWorker_default(decodeI3S); export { decodeI3S_default as default };