@loaders.gl/tile-converter 5.0.0-alpha.12 → 5.0.0-alpha.14
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/LICENSE +1 -1
- package/README.md +4 -4
- package/dist/converter.min.cjs +149 -158
- package/dist/i3s-server/bin/i3s-server.min.cjs +113 -158
- package/dist/index.cjs +17486 -17479
- package/dist/index.js +25572 -25560
- package/dist/v5/adapters.cjs +540 -190
- package/dist/v5/adapters.d.ts +4 -0
- package/dist/v5/adapters.js +501 -151
- package/dist/v5/archive-source.d.ts +1 -1
- package/dist/v5/browser.d.ts +1 -1
- package/dist/v5/conversion-api.d.ts +25 -0
- package/dist/v5/converter-cli.js +23 -7
- package/dist/v5/core.cjs +76 -17
- package/dist/v5/core.d.ts +1 -1
- package/dist/v5/core.js +69 -10
- package/dist/v5/feature-arrow.d.ts +1 -1
- package/dist/v5/i3s-mesh-conversion.d.ts +1 -1
- package/dist/v5/i3s-mesh-source-features.d.ts +2 -2
- package/dist/v5/i3s-mesh-source-material.d.ts +1 -1
- package/dist/v5/i3s-mesh-source.d.ts +2 -2
- package/dist/v5/i3s-selection-source.d.ts +3 -3
- package/dist/v5/index.cjs +11 -6
- package/dist/v5/index.d.ts +5 -1
- package/dist/v5/index.js +8 -0
- package/dist/v5/mesh-conversion.d.ts +3 -3
- package/dist/v5/mesh-draco.d.ts +2 -2
- package/dist/v5/mesh-features.d.ts +2 -2
- package/dist/v5/mesh-source-features.d.ts +4 -4
- package/dist/v5/mesh-source-schema.d.ts +2 -2
- package/dist/v5/mesh-source-texture.d.ts +3 -3
- package/dist/v5/mesh-source.d.ts +5 -5
- package/dist/v5/mesh-tileset-sink.d.ts +1 -1
- package/dist/v5/mesh.d.ts +1 -1
- package/dist/v5/node-conversion.d.ts +2 -0
- package/dist/v5/node-i3s-source.d.ts +3 -3
- package/dist/v5/node-source.d.ts +1 -1
- package/dist/v5/node.cjs +19 -6
- package/dist/v5/node.js +19 -6
- package/dist/v5/point-cloud-attributes.d.ts +19 -0
- package/dist/v5/point-cloud-conversion.d.ts +1 -1
- package/dist/v5/point-cloud-copc.d.ts +44 -0
- package/dist/v5/point-cloud-file.d.ts +4 -4
- package/dist/v5/point-cloud-potree.d.ts +3 -3
- package/dist/v5/point-cloud-source-encoder.d.ts +1 -1
- package/dist/v5/point-cloud-source.d.ts +1 -1
- package/dist/v5/point-cloud-tileset.d.ts +3 -3
- package/dist/v5/point-cloud.d.ts +1 -1
- package/dist/v5/spatial-conversion.d.ts +1 -1
- package/dist/v5/tileset-source.d.ts +1 -1
- package/package.json +17 -32
- package/src/v4/3d-tiles-converter/3d-tiles-converter.ts +11 -12
- package/src/v4/3d-tiles-converter/helpers/3d-tiles-content-converter.ts +7 -3
- package/src/v4/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.ts +2 -2
- package/src/v4/3d-tiles-converter/helpers/load-i3s.ts +3 -3
- package/src/v4/3d-tiles-converter/helpers/texture-atlas.ts +1 -1
- package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +2 -2
- package/src/v4/3d-tiles-converter/json-templates/tileset.ts +58 -39
- package/src/v4/converter-cli.ts +3 -3
- package/src/v4/deps-installer/deps-installer.ts +3 -3
- package/src/v4/i3s-converter/helpers/attribute-metadata-info.ts +1 -1
- package/src/v4/i3s-converter/helpers/batch-ids-extensions.ts +9 -10
- package/src/v4/i3s-converter/helpers/conversion-gltf.ts +108 -0
- package/src/v4/i3s-converter/helpers/coordinate-converter.ts +6 -5
- package/src/v4/i3s-converter/helpers/create-scene-server-path.ts +5 -6
- package/src/v4/i3s-converter/helpers/feature-attributes.ts +4 -4
- package/src/v4/i3s-converter/helpers/geometry-attributes.ts +1 -1
- package/src/v4/i3s-converter/helpers/geometry-converter.ts +69 -77
- package/src/v4/i3s-converter/helpers/gltf-attributes.ts +58 -74
- package/src/v4/i3s-converter/helpers/load-3d-tiles.ts +5 -5
- package/src/v4/i3s-converter/helpers/node-debug.ts +7 -3
- package/src/v4/i3s-converter/helpers/node-index-document.ts +6 -7
- package/src/v4/i3s-converter/helpers/node-pages.ts +3 -4
- package/src/v4/i3s-converter/helpers/preprocess-3d-tiles.ts +1 -1
- package/src/v4/i3s-converter/helpers/tileset-traversal.ts +1 -1
- package/src/v4/i3s-converter/i3s-converter.ts +29 -31
- package/src/v4/i3s-converter/json-templates/geometry-definitions.ts +71 -66
- package/src/v4/i3s-converter/json-templates/layers.ts +97 -132
- package/src/v4/i3s-converter/json-templates/metadata.ts +31 -21
- package/src/v4/i3s-converter/json-templates/node.ts +60 -74
- package/src/v4/i3s-converter/json-templates/scene-server.ts +36 -27
- package/src/v4/i3s-converter/json-templates/shared-resources.ts +62 -123
- package/src/v4/i3s-converter/json-templates/store.ts +39 -58
- package/src/v4/i3s-converter/types.ts +4 -4
- package/src/v4/i3s-server/controllers/slpk-controller.ts +3 -3
- package/src/v4/i3s-server/utils/create-scene-server.ts +3 -3
- package/src/v4/lib/utils/builder-input.ts +8 -0
- package/src/v4/lib/utils/conversion-dump.ts +5 -1
- package/src/v4/lib/utils/file-utils.ts +1 -1
- package/src/v4/lib/utils/hash-string.ts +21 -0
- package/src/v4/lib/utils/lod-conversion-utils.ts +3 -3
- package/src/v4/pgm-loader.ts +2 -2
- package/src/v5/adapters.ts +5 -0
- package/src/v5/archive-source.ts +4 -4
- package/src/v5/browser.ts +1 -0
- package/src/v5/conversion-api.ts +115 -8
- package/src/v5/conversion-archive.ts +2 -2
- package/src/v5/core.ts +1 -0
- package/src/v5/feature-arrow.ts +2 -2
- package/src/v5/i3s-mesh-conversion.ts +2 -2
- package/src/v5/i3s-mesh-source-features.ts +3 -3
- package/src/v5/i3s-mesh-source-material.ts +18 -11
- package/src/v5/i3s-mesh-source.ts +2 -2
- package/src/v5/i3s-selection-source.ts +4 -4
- package/src/v5/index.ts +15 -0
- package/src/v5/mesh-conversion.ts +4 -4
- package/src/v5/mesh-draco.ts +2 -2
- package/src/v5/mesh-features.ts +3 -3
- package/src/v5/mesh-hierarchy.ts +1 -1
- package/src/v5/mesh-source-features.ts +137 -55
- package/src/v5/mesh-source-schema.ts +10 -4
- package/src/v5/mesh-source-texture.ts +49 -19
- package/src/v5/mesh-source.ts +65 -46
- package/src/v5/mesh-tileset-archive.ts +1 -1
- package/src/v5/mesh-tileset-sink.ts +1 -1
- package/src/v5/mesh.ts +1 -1
- package/src/v5/node-cli.ts +4 -0
- package/src/v5/node-conversion.ts +19 -2
- package/src/v5/node-source.ts +2 -2
- package/src/v5/point-cloud-attributes.ts +113 -0
- package/src/v5/point-cloud-conversion.ts +1 -1
- package/src/v5/point-cloud-copc.ts +289 -0
- package/src/v5/point-cloud-file.ts +8 -8
- package/src/v5/point-cloud-potree.ts +8 -4
- package/src/v5/point-cloud-source-encoder.ts +1 -1
- package/src/v5/point-cloud-source.ts +1 -1
- package/src/v5/point-cloud-spatial.ts +2 -2
- package/src/v5/point-cloud-tileset.ts +4 -4
- package/src/v5/point-cloud.ts +3 -3
- package/src/v5/selected-mesh-source.ts +4 -4
- package/src/v5/spatial-conversion.ts +2 -2
- package/src/v5/tileset-source.ts +2 -2
package/dist/v5/adapters.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(adapters_exports, {
|
|
|
25
25
|
convertPointCloudSource: () => convertPointCloudSource,
|
|
26
26
|
convertPointCloudToPotree: () => convertPointCloudToPotree,
|
|
27
27
|
convertPointCloudToTileset: () => convertPointCloudToTileset,
|
|
28
|
+
createCOPCConversionCodec: () => createCOPCConversionCodec,
|
|
28
29
|
createI3SMeshConversionCodec: () => createI3SMeshConversionCodec,
|
|
29
30
|
createI3SMeshSink: () => createI3SMeshSink,
|
|
30
31
|
createI3SMeshTilesetConversionSource: () => createI3SMeshTilesetConversionSource,
|
|
@@ -43,6 +44,7 @@ __export(adapters_exports, {
|
|
|
43
44
|
createTileConversionArchiveTransport: () => createTileConversionArchiveTransport,
|
|
44
45
|
createTileConversionResourceFetcher: () => createTileConversionResourceFetcher,
|
|
45
46
|
encodeMeshTile: () => encodeMeshTile,
|
|
47
|
+
encodePointCloudCOPC: () => encodePointCloudCOPC,
|
|
46
48
|
encodePointCloudSource: () => encodePointCloudSource,
|
|
47
49
|
encodePointCloudSourceTile: () => encodePointCloudSourceTile,
|
|
48
50
|
encodePointCloudTile: () => encodePointCloudTile,
|
|
@@ -51,6 +53,7 @@ __export(adapters_exports, {
|
|
|
51
53
|
encodeTileConversionArchiveInBatches: () => encodeTileConversionArchiveInBatches,
|
|
52
54
|
extractMeshVertices: () => extractMeshVertices,
|
|
53
55
|
inspectI3SMeshConversionSource: () => inspectI3SMeshConversionSource,
|
|
56
|
+
mapPointCloudAttributes: () => mapPointCloudAttributes,
|
|
54
57
|
measureMeshBytes: () => measureMeshBytes,
|
|
55
58
|
openPointCloudFile: () => openPointCloudFile,
|
|
56
59
|
openTileConversionArchive: () => openTileConversionArchive,
|
|
@@ -59,7 +62,7 @@ __export(adapters_exports, {
|
|
|
59
62
|
module.exports = __toCommonJS(adapters_exports);
|
|
60
63
|
|
|
61
64
|
// src/v5/feature-arrow.ts
|
|
62
|
-
var import_schema_utils = require("@loaders.gl/schema-utils");
|
|
65
|
+
var import_schema_utils = require("@loaders.gl/core/schema-utils");
|
|
63
66
|
var import_core = require("@loaders.gl/tile-converter/v5/core");
|
|
64
67
|
var DEFAULT_FEATURE_ID_FIELD = "feature_id";
|
|
65
68
|
var FEATURE_CLASS_METADATA_KEY = "loaders.gl:feature-class";
|
|
@@ -381,8 +384,8 @@ function isBinaryType(dataType) {
|
|
|
381
384
|
}
|
|
382
385
|
|
|
383
386
|
// src/v5/point-cloud.ts
|
|
384
|
-
var import_d_tiles = require("@loaders.gl/3d-tiles");
|
|
385
|
-
var import_schema_utils2 = require("@loaders.gl/schema-utils");
|
|
387
|
+
var import_d_tiles = require("@loaders.gl/tiles-3d/3d-tiles");
|
|
388
|
+
var import_schema_utils2 = require("@loaders.gl/core/schema-utils");
|
|
386
389
|
var import_core2 = require("@loaders.gl/tile-converter/v5/core");
|
|
387
390
|
function encodePointCloudTile(pointBatch, options = {}) {
|
|
388
391
|
return encodePointCloudTileWithMetadata(pointBatch, options).pnts;
|
|
@@ -645,8 +648,8 @@ function validateBatchTable(batchTableJson, batchIds) {
|
|
|
645
648
|
|
|
646
649
|
// src/v5/point-cloud-spatial.ts
|
|
647
650
|
var import_core3 = require("@math.gl/core");
|
|
648
|
-
var
|
|
649
|
-
var import_schema_utils3 = require("@loaders.gl/schema-utils");
|
|
651
|
+
var import_tiles_3d = require("@loaders.gl/tiles-3d");
|
|
652
|
+
var import_schema_utils3 = require("@loaders.gl/core/schema-utils");
|
|
650
653
|
var import_core4 = require("@loaders.gl/tile-converter/v5/core");
|
|
651
654
|
async function transformPointCloudSourceTile(sourceTile, options) {
|
|
652
655
|
options.signal?.throwIfAborted();
|
|
@@ -655,7 +658,7 @@ async function transformPointCloudSourceTile(sourceTile, options) {
|
|
|
655
658
|
const reference = options.spatialContext.spatialReference;
|
|
656
659
|
const contentReference = content.spatialReference;
|
|
657
660
|
const retainTransformedEcef = contentReference?.status === "transformed" && (contentReference.targetCrs || contentReference.sourceCrs) === "EPSG:4978" && reference.status === "native" && reference.sourceCrs === "EPSG:4978" && reference.verticalUnitScale === 1 && (reference.units?.every((unit) => unit === "meter") ?? true);
|
|
658
|
-
const sourceReference = retainTransformedEcef ? (0,
|
|
661
|
+
const sourceReference = retainTransformedEcef ? (0, import_tiles_3d.createTilesetSpatialReference)({
|
|
659
662
|
sourceCrs: "EPSG:4978",
|
|
660
663
|
coordinateFrame: "geocentric",
|
|
661
664
|
axisOrder: "xyz",
|
|
@@ -669,7 +672,7 @@ async function transformPointCloudSourceTile(sourceTile, options) {
|
|
|
669
672
|
"Point content and context must agree on the input CRS, units, height reference and epoch"
|
|
670
673
|
);
|
|
671
674
|
}
|
|
672
|
-
const sourceFrame = reference.coordinateFrame === "unknown" && reference.sourceCrs ? (0,
|
|
675
|
+
const sourceFrame = reference.coordinateFrame === "unknown" && reference.sourceCrs ? (0, import_tiles_3d.getSpatialCoordinateFrame)(reference.sourceCrs) : reference.coordinateFrame;
|
|
673
676
|
const geographic = sourceFrame === "geographic";
|
|
674
677
|
if (!["xy", "xyz", "unknown"].includes(reference.axisOrder) || (geographic ? !["lnglat", "lnglat-offsets"].includes(content.coordinateSystem) : content.coordinateSystem !== "cartesian" || !["projected", "geocentric", "cartesian", "local"].includes(sourceFrame))) {
|
|
675
678
|
throw new import_core4.TileConversionError(
|
|
@@ -780,7 +783,7 @@ async function transformPointCloudSourceTile(sourceTile, options) {
|
|
|
780
783
|
maximum[axis] = Math.max(maximum[axis], value);
|
|
781
784
|
}
|
|
782
785
|
const center = minimum.map((value, axis) => value / 2 + maximum[axis] / 2);
|
|
783
|
-
const targetFrame = reference.status === "native" ? sourceFrame : (0,
|
|
786
|
+
const targetFrame = reference.status === "native" ? sourceFrame : (0, import_tiles_3d.getSpatialCoordinateFrame)(reference.targetCrs || reference.sourceCrs);
|
|
784
787
|
const targetIsGeographic = targetFrame === "geographic";
|
|
785
788
|
const attributes = {
|
|
786
789
|
...mesh.attributes,
|
|
@@ -904,7 +907,7 @@ var import_gltf = require("@loaders.gl/gltf");
|
|
|
904
907
|
var import_images = require("@loaders.gl/images");
|
|
905
908
|
|
|
906
909
|
// src/v5/mesh-features.ts
|
|
907
|
-
var import_schema_utils4 = require("@loaders.gl/schema-utils");
|
|
910
|
+
var import_schema_utils4 = require("@loaders.gl/core/schema-utils");
|
|
908
911
|
var import_core8 = require("@loaders.gl/tile-converter/v5/core");
|
|
909
912
|
function prepareMeshFeatureGeometry(mesh, features) {
|
|
910
913
|
if (!features) return mesh;
|
|
@@ -1458,7 +1461,7 @@ function validateMeshTextureTransform(transform) {
|
|
|
1458
1461
|
}
|
|
1459
1462
|
|
|
1460
1463
|
// src/v5/mesh-conversion.ts
|
|
1461
|
-
var
|
|
1464
|
+
var import_tiles_3d2 = require("@loaders.gl/tiles-3d");
|
|
1462
1465
|
var import_core11 = require("@loaders.gl/tile-converter/v5/core");
|
|
1463
1466
|
|
|
1464
1467
|
// src/v5/mesh-draco.ts
|
|
@@ -1601,7 +1604,7 @@ function createMeshConversionCodec(options) {
|
|
|
1601
1604
|
}
|
|
1602
1605
|
const spatialReference = spatialContext.spatialReference;
|
|
1603
1606
|
const outputCrs = spatialReference.targetCrs || spatialReference.sourceCrs;
|
|
1604
|
-
const outputFrame = spatialReference.status === "native" ? spatialReference.coordinateFrame : outputCrs ? (0,
|
|
1607
|
+
const outputFrame = spatialReference.status === "native" ? spatialReference.coordinateFrame : outputCrs ? (0, import_tiles_3d2.getSpatialCoordinateFrame)(outputCrs) : "unknown";
|
|
1605
1608
|
if (!["native", "transformed"].includes(spatialReference.status) || !["projected", "geocentric", "local", "cartesian"].includes(outputFrame)) {
|
|
1606
1609
|
throw new import_core11.TileConversionError(
|
|
1607
1610
|
"MESH_OUTPUT_FRAME_UNSUPPORTED",
|
|
@@ -1945,8 +1948,8 @@ function createMeshTilesetSink(options) {
|
|
|
1945
1948
|
}
|
|
1946
1949
|
|
|
1947
1950
|
// src/v5/conversion-archive.ts
|
|
1948
|
-
var import_d_tiles_archive_writer = require("@loaders.gl/3d-tiles/3d-tiles-archive-writer");
|
|
1949
|
-
var import_i3s_slpk_writer = require("@loaders.gl/i3s/i3s-slpk-writer");
|
|
1951
|
+
var import_d_tiles_archive_writer = require("@loaders.gl/tiles-3d/3d-tiles/3d-tiles-archive-writer");
|
|
1952
|
+
var import_i3s_slpk_writer = require("@loaders.gl/tiles-3d/i3s/i3s-slpk-writer");
|
|
1950
1953
|
var import_core14 = require("@loaders.gl/tile-converter/v5/core");
|
|
1951
1954
|
async function createTileConversionArchive(files, options) {
|
|
1952
1955
|
const { resources, format, maxArchiveBytes, signal } = prepareArchiveInput(files, options);
|
|
@@ -1981,7 +1984,7 @@ function prepareArchiveInput(files, options) {
|
|
|
1981
1984
|
}
|
|
1982
1985
|
|
|
1983
1986
|
// src/v5/mesh-tileset-archive.ts
|
|
1984
|
-
var import_d_tiles_archive_writer2 = require("@loaders.gl/3d-tiles/3d-tiles-archive-writer");
|
|
1987
|
+
var import_d_tiles_archive_writer2 = require("@loaders.gl/tiles-3d/3d-tiles/3d-tiles-archive-writer");
|
|
1985
1988
|
var import_core15 = require("@loaders.gl/tile-converter/v5/core");
|
|
1986
1989
|
async function createSingleMeshTilesetArchive(files, options) {
|
|
1987
1990
|
const { maxArchiveBytes, signal } = options;
|
|
@@ -2004,16 +2007,18 @@ async function createSingleMeshTilesetArchive(files, options) {
|
|
|
2004
2007
|
|
|
2005
2008
|
// src/v5/mesh-source.ts
|
|
2006
2009
|
var import_core19 = require("@math.gl/core");
|
|
2010
|
+
var import_gltf4 = require("@loaders.gl/gltf");
|
|
2007
2011
|
var import_core20 = require("@loaders.gl/tile-converter/v5/core");
|
|
2008
2012
|
var import_core21 = require("@loaders.gl/tile-converter/v5/core");
|
|
2009
2013
|
|
|
2010
2014
|
// src/v5/mesh-source-texture.ts
|
|
2011
2015
|
var import_images2 = require("@loaders.gl/images");
|
|
2016
|
+
var import_gltf2 = require("@loaders.gl/gltf");
|
|
2012
2017
|
var import_core16 = require("@loaders.gl/tile-converter/v5/core");
|
|
2013
|
-
function mapMeshSourceTexture(textureInfo) {
|
|
2014
|
-
const texture = textureInfo?.
|
|
2015
|
-
const image = texture?.source;
|
|
2016
|
-
const sampler = texture?.sampler;
|
|
2018
|
+
function mapMeshSourceTexture(gltf, textureInfo) {
|
|
2019
|
+
const texture = textureInfo ? gltf.json.textures?.[textureInfo.index] : void 0;
|
|
2020
|
+
const image = texture?.source === void 0 ? void 0 : gltf.json.images?.[texture.source];
|
|
2021
|
+
const sampler = texture?.sampler === void 0 ? void 0 : gltf.json.samplers?.[texture.sampler];
|
|
2017
2022
|
const extensions = textureInfo?.extensions || {};
|
|
2018
2023
|
const hasTransform = Object.hasOwn(extensions, "KHR_texture_transform");
|
|
2019
2024
|
const transform = extensions.KHR_texture_transform;
|
|
@@ -2023,7 +2028,7 @@ function mapMeshSourceTexture(textureInfo) {
|
|
|
2023
2028
|
(name) => !["id", "index", "texture", "texCoord", "extensions", "extras"].includes(name)
|
|
2024
2029
|
) || !texture || Object.keys(texture).some(
|
|
2025
2030
|
(name) => !["id", "source", "sampler", "name", "extensions", "extras"].includes(name)
|
|
2026
|
-
) || Object.keys(texture.extensions || {}).length || !image || image.uri !== void 0 && image.bufferView !== void 0 || Object.keys(image.extensions || {}).length || image.uri === void 0 && (
|
|
2031
|
+
) || Object.keys(texture.extensions || {}).length || !image || image.uri !== void 0 && image.bufferView !== void 0 || Object.keys(image.extensions || {}).length || image.uri === void 0 && (image.bufferView === void 0 || !gltf.json.bufferViews?.[image.bufferView] || Object.keys(gltf.json.bufferViews?.[image.bufferView]?.extensions || {}).length || !["image/png", "image/jpeg"].includes(image.mimeType || "")) || sampler && (Object.keys(sampler.extensions || {}).length || Object.keys(sampler).some(
|
|
2027
2032
|
(name) => ![
|
|
2028
2033
|
"id",
|
|
2029
2034
|
"parameters",
|
|
@@ -2048,7 +2053,7 @@ function mapMeshSourceTexture(textureInfo) {
|
|
|
2048
2053
|
minFilter: sampler.minFilter
|
|
2049
2054
|
} : void 0;
|
|
2050
2055
|
return {
|
|
2051
|
-
...mapMeshSourceImage(image),
|
|
2056
|
+
...mapMeshSourceImage(gltf, image),
|
|
2052
2057
|
...hasTransform ? {
|
|
2053
2058
|
transform: {
|
|
2054
2059
|
offset: transform.offset,
|
|
@@ -2059,9 +2064,12 @@ function mapMeshSourceTexture(textureInfo) {
|
|
|
2059
2064
|
...selectedSampler && Object.values(selectedSampler).some((value) => value !== void 0) ? { sampler: selectedSampler } : {}
|
|
2060
2065
|
};
|
|
2061
2066
|
}
|
|
2062
|
-
function mapMeshSourceImage(image) {
|
|
2067
|
+
function mapMeshSourceImage(gltf, image) {
|
|
2063
2068
|
if (image.uri === void 0) {
|
|
2064
|
-
return {
|
|
2069
|
+
return {
|
|
2070
|
+
data: new import_gltf2.GLTFScenegraph(gltf).getTypedArrayForBufferView(image.bufferView),
|
|
2071
|
+
mimeType: image.mimeType
|
|
2072
|
+
};
|
|
2065
2073
|
}
|
|
2066
2074
|
const match = typeof image.uri === "string" ? /^data:(image\/(?:png|jpeg));base64,([A-Za-z0-9+/]+={0,2})$/.exec(image.uri) : null;
|
|
2067
2075
|
if (!match || image.mimeType !== void 0 && image.mimeType !== match[1]) {
|
|
@@ -2081,10 +2089,11 @@ function mapMeshSourceImage(image) {
|
|
|
2081
2089
|
mimeType: match[1]
|
|
2082
2090
|
};
|
|
2083
2091
|
}
|
|
2084
|
-
async function resolveMeshSourceTexture(textureInfo, readExternalResource, contentUri, signal) {
|
|
2085
|
-
const
|
|
2092
|
+
async function resolveMeshSourceTexture(gltf, textureInfo, readExternalResource, contentUri, signal) {
|
|
2093
|
+
const texture = textureInfo ? gltf.json.textures?.[textureInfo.index] : void 0;
|
|
2094
|
+
const image = texture?.source === void 0 ? void 0 : gltf.json.images?.[texture.source];
|
|
2086
2095
|
if (!image || image.uri === void 0 || image.uri.startsWith("data:"))
|
|
2087
|
-
return mapMeshSourceTexture(textureInfo);
|
|
2096
|
+
return mapMeshSourceTexture(gltf, textureInfo);
|
|
2088
2097
|
if (!readExternalResource || image.bufferView !== void 0)
|
|
2089
2098
|
throw new import_core16.TileConversionError(
|
|
2090
2099
|
"MESH_SOURCE_TEXTURE_UNSUPPORTED",
|
|
@@ -2103,16 +2112,39 @@ async function resolveMeshSourceTexture(textureInfo, readExternalResource, conte
|
|
|
2103
2112
|
"MESH_SOURCE_TEXTURE_UNSUPPORTED",
|
|
2104
2113
|
"External images require matching PNG/JPEG headers"
|
|
2105
2114
|
);
|
|
2115
|
+
const resolvedImage = {
|
|
2116
|
+
...image,
|
|
2117
|
+
uri: void 0,
|
|
2118
|
+
mimeType: metadata.mimeType,
|
|
2119
|
+
bufferView: (gltf.json.bufferViews || []).length
|
|
2120
|
+
};
|
|
2106
2121
|
const resolved = {
|
|
2107
|
-
...
|
|
2108
|
-
|
|
2109
|
-
...
|
|
2110
|
-
|
|
2122
|
+
...gltf,
|
|
2123
|
+
buffers: [
|
|
2124
|
+
...gltf.buffers,
|
|
2125
|
+
{
|
|
2126
|
+
arrayBuffer: data.buffer,
|
|
2127
|
+
byteOffset: data.byteOffset,
|
|
2128
|
+
byteLength: data.byteLength
|
|
2129
|
+
}
|
|
2130
|
+
],
|
|
2131
|
+
json: {
|
|
2132
|
+
...gltf.json,
|
|
2133
|
+
images: gltf.json.images.map(
|
|
2134
|
+
(entry, index) => index === texture.source ? resolvedImage : entry
|
|
2135
|
+
),
|
|
2136
|
+
bufferViews: [
|
|
2137
|
+
...gltf.json.bufferViews || [],
|
|
2138
|
+
{ buffer: gltf.buffers.length, byteLength: data.byteLength }
|
|
2139
|
+
]
|
|
2111
2140
|
}
|
|
2112
2141
|
};
|
|
2113
|
-
return mapMeshSourceTexture(resolved);
|
|
2142
|
+
return mapMeshSourceTexture(resolved, textureInfo);
|
|
2114
2143
|
}
|
|
2115
2144
|
|
|
2145
|
+
// src/v5/mesh-source-features.ts
|
|
2146
|
+
var import_gltf3 = require("@loaders.gl/gltf");
|
|
2147
|
+
|
|
2116
2148
|
// src/v5/mesh-source-schema.ts
|
|
2117
2149
|
var import_core17 = require("@loaders.gl/tile-converter/v5/core");
|
|
2118
2150
|
var SCALAR_TYPES = {
|
|
@@ -2198,9 +2230,9 @@ function createMeshSourceFeatureOptions(gltf, options) {
|
|
|
2198
2230
|
var import_core18 = require("@loaders.gl/tile-converter/v5/core");
|
|
2199
2231
|
function extractMeshFeatures(gltf, primitive, payload, mesh, options) {
|
|
2200
2232
|
const declarations = primitive.extensions?.EXT_mesh_features?.featureIds;
|
|
2201
|
-
const metadata = gltf.extensions?.EXT_structural_metadata;
|
|
2233
|
+
const metadata = gltf.json.extensions?.EXT_structural_metadata;
|
|
2202
2234
|
const legacy = primitive.attributes._BATCHID;
|
|
2203
|
-
if (!declarations &&
|
|
2235
|
+
if (!declarations && legacy === void 0 && !metadata && !Object.keys(payload.batchTableJson || {}).length && !payload.header?.batchLength) {
|
|
2204
2236
|
if (Object.keys(primitive.attributes).some((name) => /^_FEATURE_ID_\d+$/.test(name)))
|
|
2205
2237
|
throw new import_core18.TileConversionError(
|
|
2206
2238
|
"MESH_FEATURE_MAPPING_REQUIRED",
|
|
@@ -2218,37 +2250,38 @@ function extractMeshFeatures(gltf, primitive, payload, mesh, options) {
|
|
|
2218
2250
|
"MESH_FEATURE_CLASS_REQUIRED",
|
|
2219
2251
|
"Feature metadata class must be explicit"
|
|
2220
2252
|
);
|
|
2221
|
-
const mapping = "schema" in options ? options : createMeshSourceFeatureOptions(gltf, options);
|
|
2253
|
+
const mapping = "schema" in options ? options : createMeshSourceFeatureOptions(gltf.json, options);
|
|
2254
|
+
const propertyMappings = /* @__PURE__ */ new Map();
|
|
2222
2255
|
let count;
|
|
2223
|
-
let
|
|
2256
|
+
let attributeReference = legacy;
|
|
2224
2257
|
let properties;
|
|
2225
2258
|
if (declarations) {
|
|
2226
|
-
if (legacy || declarations.length !== 1 || metadata?.propertyTables?.length !== 1 || metadata.propertyTextures?.length || metadata.propertyAttributes?.length)
|
|
2259
|
+
if (legacy !== void 0 || declarations.length !== 1 || metadata?.propertyTables?.length !== 1 || metadata.propertyTextures?.length || metadata.propertyAttributes?.length)
|
|
2227
2260
|
throw new import_core18.TileConversionError(
|
|
2228
2261
|
"MESH_FEATURE_MAPPING_UNSUPPORTED",
|
|
2229
2262
|
"Only one attribute-backed feature set and one property table are supported"
|
|
2230
2263
|
);
|
|
2231
2264
|
const declaration = declarations[0];
|
|
2232
|
-
if (!Number.isInteger(declaration.attribute) || declaration.attribute < 0 || declaration.propertyTable !== 0 || declaration.texture || declaration.implicit || declaration.nullFeatureId !== void 0)
|
|
2265
|
+
if (typeof declaration.attribute !== "number" || !Number.isInteger(declaration.attribute) || declaration.attribute < 0 || declaration.propertyTable !== 0 || declaration.texture || declaration.implicit || declaration.nullFeatureId !== void 0)
|
|
2233
2266
|
throw new import_core18.TileConversionError(
|
|
2234
2267
|
"MESH_FEATURE_MAPPING_UNSUPPORTED",
|
|
2235
2268
|
"Features require an attribute and property table 0 without null/texture/implicit IDs"
|
|
2236
2269
|
);
|
|
2237
|
-
|
|
2270
|
+
attributeReference = primitive.attributes[`_FEATURE_ID_${declaration.attribute}`];
|
|
2238
2271
|
const table = metadata.propertyTables[0];
|
|
2239
|
-
if (table.class !== options.metadataClass ||
|
|
2272
|
+
if (table.class !== options.metadataClass || !Number.isSafeInteger(declaration.featureCount) || declaration.featureCount <= 0 || declaration.featureCount > table.count)
|
|
2240
2273
|
throw new import_core18.TileConversionError(
|
|
2241
2274
|
"MESH_FEATURE_CLASS_MISMATCH",
|
|
2242
|
-
"Feature class and declared
|
|
2275
|
+
"Feature class must agree and declared feature count must fit the property table"
|
|
2243
2276
|
);
|
|
2244
2277
|
count = table.count;
|
|
2245
|
-
if (!Number.isSafeInteger(count) || count <= 0 || count >
|
|
2278
|
+
if (!Number.isSafeInteger(count) || count <= 0 || count > 4294967295) {
|
|
2246
2279
|
throw new import_core18.TileConversionError(
|
|
2247
2280
|
"MESH_FEATURE_IDS_INVALID",
|
|
2248
|
-
"Feature row count
|
|
2281
|
+
"Feature row count must fit uint32 indices"
|
|
2249
2282
|
);
|
|
2250
2283
|
}
|
|
2251
|
-
properties =
|
|
2284
|
+
properties = /* @__PURE__ */ Object.create(null);
|
|
2252
2285
|
const classProperties = metadata.schema?.classes?.[table.class]?.properties;
|
|
2253
2286
|
if (!classProperties)
|
|
2254
2287
|
throw new import_core18.TileConversionError(
|
|
@@ -2281,9 +2314,10 @@ function extractMeshFeatures(gltf, primitive, payload, mesh, options) {
|
|
|
2281
2314
|
);
|
|
2282
2315
|
}
|
|
2283
2316
|
const defaultValue = integer64 && property.default !== void 0 ? BigInt(property.default) : property.default ?? null;
|
|
2284
|
-
const decoded = data
|
|
2317
|
+
const decoded = data;
|
|
2285
2318
|
if (property.noData === void 0 || data === void 0) {
|
|
2286
|
-
properties[name] = decoded;
|
|
2319
|
+
if (decoded !== void 0) properties[name] = decoded;
|
|
2320
|
+
else propertyMappings.set(name, { defaultValue });
|
|
2287
2321
|
continue;
|
|
2288
2322
|
}
|
|
2289
2323
|
const sentinel = property.noData;
|
|
@@ -2293,10 +2327,9 @@ function extractMeshFeatures(gltf, primitive, payload, mesh, options) {
|
|
|
2293
2327
|
`Property ${name} requires a valid decoded noData mapping`
|
|
2294
2328
|
);
|
|
2295
2329
|
const comparable = integer64 ? BigInt(sentinel) : sentinel;
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
);
|
|
2330
|
+
const values = decoded;
|
|
2331
|
+
properties[name] = values;
|
|
2332
|
+
propertyMappings.set(name, { noData: comparable, defaultValue });
|
|
2300
2333
|
}
|
|
2301
2334
|
} else {
|
|
2302
2335
|
if (metadata)
|
|
@@ -2307,14 +2340,32 @@ function extractMeshFeatures(gltf, primitive, payload, mesh, options) {
|
|
|
2307
2340
|
count = payload.header?.batchLength ?? Number(payload.featureTableJson?.BATCH_LENGTH);
|
|
2308
2341
|
properties = payload.batchTableJson || {};
|
|
2309
2342
|
}
|
|
2343
|
+
const accessor = attributeReference === void 0 ? void 0 : (0, import_gltf3.getGLTFAccessor)(gltf, attributeReference);
|
|
2344
|
+
const attribute = accessor ? {
|
|
2345
|
+
...accessor,
|
|
2346
|
+
components: accessor.type === "SCALAR" ? 1 : Number(accessor.type.slice(3)),
|
|
2347
|
+
value: (0, import_gltf3.getGLTFAccessorValue)(gltf, accessor)
|
|
2348
|
+
} : void 0;
|
|
2310
2349
|
const vertexCount = mesh.attributes.POSITION.value.length / 3;
|
|
2311
|
-
if (!Number.isSafeInteger(count) || count <= 0 || !attribute || attribute.components !== 1 || attribute.normalized || attribute.value.length !== vertexCount
|
|
2312
|
-
(value) => !Number.isSafeInteger(value) || value < 0 || value >= count
|
|
2313
|
-
))
|
|
2350
|
+
if (!Number.isSafeInteger(count) || count <= 0 || !attribute || attribute.components !== 1 || attribute.normalized || attribute.value.length !== vertexCount)
|
|
2314
2351
|
throw new import_core18.TileConversionError(
|
|
2315
2352
|
"MESH_FEATURE_IDS_INVALID",
|
|
2316
2353
|
"Feature IDs must be one valid property-table row index per vertex"
|
|
2317
2354
|
);
|
|
2355
|
+
const vertexRows = declarations ? /* @__PURE__ */ new Set() : void 0;
|
|
2356
|
+
for (const value of attribute.value) {
|
|
2357
|
+
if (!Number.isSafeInteger(value) || value < 0 || value >= count)
|
|
2358
|
+
throw new import_core18.TileConversionError(
|
|
2359
|
+
"MESH_FEATURE_IDS_INVALID",
|
|
2360
|
+
"Feature IDs must reference valid property-table rows"
|
|
2361
|
+
);
|
|
2362
|
+
vertexRows?.add(Number(value));
|
|
2363
|
+
}
|
|
2364
|
+
if (declarations && vertexRows.size !== declarations[0].featureCount)
|
|
2365
|
+
throw new import_core18.TileConversionError(
|
|
2366
|
+
"MESH_FEATURE_IDS_INVALID",
|
|
2367
|
+
"Declared feature count must match distinct vertex feature IDs"
|
|
2368
|
+
);
|
|
2318
2369
|
const selectedAttribute = declarations ? `_FEATURE_ID_${declarations[0].attribute}` : "_BATCHID";
|
|
2319
2370
|
if (Object.keys(primitive.attributes).some(
|
|
2320
2371
|
(name) => (name === "_BATCHID" || /^_FEATURE_ID_\d+$/.test(name)) && name !== selectedAttribute
|
|
@@ -2327,39 +2378,70 @@ function extractMeshFeatures(gltf, primitive, payload, mesh, options) {
|
|
|
2327
2378
|
if (!values || !Array.isArray(values) && !ArrayBuffer.isView(values) || values.length !== count)
|
|
2328
2379
|
throw new import_core18.TileConversionError(
|
|
2329
2380
|
"MESH_FEATURE_PROPERTY_UNAVAILABLE",
|
|
2330
|
-
`Property ${name} must be a decoded column matching the
|
|
2381
|
+
`Property ${name} must be a decoded column matching the feature row count`
|
|
2331
2382
|
);
|
|
2332
2383
|
}
|
|
2333
2384
|
const sourceIdentifier = options.sourceFeatureIdProperty;
|
|
2334
|
-
if (sourceIdentifier && !properties[sourceIdentifier])
|
|
2385
|
+
if (sourceIdentifier && !properties[sourceIdentifier] && !propertyMappings.has(sourceIdentifier))
|
|
2335
2386
|
throw new import_core18.TileConversionError(
|
|
2336
2387
|
"MESH_FEATURE_ID_PROPERTY_REQUIRED",
|
|
2337
2388
|
"Stable source identifier property is missing"
|
|
2338
2389
|
);
|
|
2339
|
-
const batches = convertFeatureAttributesToArrowBatches(
|
|
2340
|
-
Array.from({ length: count }, (_, index) => ({
|
|
2341
|
-
featureId: sourceIdentifier ? properties[sourceIdentifier][index] : index,
|
|
2342
|
-
metadataClass: options.metadataClass,
|
|
2343
|
-
properties: Object.fromEntries(
|
|
2344
|
-
Object.entries(properties).filter(([name]) => name !== sourceIdentifier).map(([name, values]) => [name, values[index]])
|
|
2345
|
-
)
|
|
2346
|
-
})),
|
|
2347
|
-
mapping
|
|
2348
|
-
);
|
|
2349
2390
|
const indices = mesh.indices?.value;
|
|
2350
|
-
const
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2391
|
+
const cornerCount = indices?.length ?? vertexCount;
|
|
2392
|
+
if (cornerCount % 3)
|
|
2393
|
+
throw new import_core18.TileConversionError(
|
|
2394
|
+
"MESH_FEATURE_IDS_INVALID",
|
|
2395
|
+
"Triangle geometry requires complete triples"
|
|
2354
2396
|
);
|
|
2355
|
-
|
|
2356
|
-
|
|
2397
|
+
const triangleFeatureIndices = new Uint32Array(cornerCount / 3);
|
|
2398
|
+
const referencedRows = /* @__PURE__ */ new Set();
|
|
2399
|
+
const readFeatureRow = (corner) => {
|
|
2400
|
+
if (!Number.isSafeInteger(corner) || corner < 0 || corner >= vertexCount)
|
|
2401
|
+
throw new import_core18.TileConversionError(
|
|
2402
|
+
"MESH_FEATURE_IDS_INVALID",
|
|
2403
|
+
"Triangle indices must reference valid mesh vertices"
|
|
2404
|
+
);
|
|
2405
|
+
return Number(attribute.value[corner]);
|
|
2406
|
+
};
|
|
2407
|
+
for (let triangle = 0; triangle < triangleFeatureIndices.length; triangle++) {
|
|
2408
|
+
const firstCorner = indices?.[triangle * 3] ?? triangle * 3;
|
|
2409
|
+
const secondCorner = indices?.[triangle * 3 + 1] ?? triangle * 3 + 1;
|
|
2410
|
+
const thirdCorner = indices?.[triangle * 3 + 2] ?? triangle * 3 + 2;
|
|
2411
|
+
const firstRow = readFeatureRow(firstCorner);
|
|
2412
|
+
const secondRow = readFeatureRow(secondCorner);
|
|
2413
|
+
const thirdRow = readFeatureRow(thirdCorner);
|
|
2414
|
+
if ((firstRow !== secondRow || firstRow !== thirdRow) && firstCorner !== secondCorner && firstCorner !== thirdCorner && secondCorner !== thirdCorner)
|
|
2357
2415
|
throw new import_core18.TileConversionError(
|
|
2358
2416
|
"MESH_FEATURE_TRIANGLE_MIXED",
|
|
2359
2417
|
"All vertices of a nondegenerate triangle must reference the same feature row"
|
|
2360
2418
|
);
|
|
2361
|
-
triangleFeatureIndices[triangle] =
|
|
2419
|
+
triangleFeatureIndices[triangle] = firstRow;
|
|
2420
|
+
referencedRows.add(firstRow);
|
|
2362
2421
|
}
|
|
2422
|
+
const selectedRows = [...referencedRows].sort((left, right) => left - right);
|
|
2423
|
+
const denseRows = new Map(selectedRows.map((row, index) => [row, index]));
|
|
2424
|
+
for (let triangle = 0; triangle < triangleFeatureIndices.length; triangle++) {
|
|
2425
|
+
triangleFeatureIndices[triangle] = denseRows.get(triangleFeatureIndices[triangle]);
|
|
2426
|
+
}
|
|
2427
|
+
const readProperty = (name, row) => {
|
|
2428
|
+
const values = properties[name];
|
|
2429
|
+
const propertyMapping = propertyMappings.get(name);
|
|
2430
|
+
if (!values) return propertyMapping?.defaultValue;
|
|
2431
|
+
const value = values[row];
|
|
2432
|
+
return propertyMapping && value === propertyMapping.noData ? propertyMapping.defaultValue : value;
|
|
2433
|
+
};
|
|
2434
|
+
const propertyNames = [
|
|
2435
|
+
.../* @__PURE__ */ new Set([...Object.keys(properties), ...propertyMappings.keys()])
|
|
2436
|
+
].filter((name) => name !== sourceIdentifier);
|
|
2437
|
+
const batches = convertFeatureAttributesToArrowBatches(
|
|
2438
|
+
selectedRows.map((row) => ({
|
|
2439
|
+
featureId: sourceIdentifier ? readProperty(sourceIdentifier, row) : row,
|
|
2440
|
+
metadataClass: options.metadataClass,
|
|
2441
|
+
properties: Object.fromEntries(propertyNames.map((name) => [name, readProperty(name, row)]))
|
|
2442
|
+
})),
|
|
2443
|
+
mapping
|
|
2444
|
+
);
|
|
2363
2445
|
return {
|
|
2364
2446
|
batches,
|
|
2365
2447
|
triangleFeatureIndices,
|
|
@@ -2418,7 +2500,8 @@ function createMeshTilesetConversionSource(tileset, options = {}) {
|
|
|
2418
2500
|
"Mesh extraction requires decoded GLB/glTF or B3DM content"
|
|
2419
2501
|
);
|
|
2420
2502
|
}
|
|
2421
|
-
const
|
|
2503
|
+
const gltfWithBuffers = payload.gltf;
|
|
2504
|
+
const gltf = gltfWithBuffers.json;
|
|
2422
2505
|
if (gltf.animations?.length || gltf.skins?.length || Object.keys(gltf.extensions || {}).some(
|
|
2423
2506
|
(name) => !["EXT_structural_metadata", "CESIUM_RTC"].includes(name)
|
|
2424
2507
|
)) {
|
|
@@ -2444,19 +2527,20 @@ function createMeshTilesetConversionSource(tileset, options = {}) {
|
|
|
2444
2527
|
placement.multiplyRight(new import_core19.Matrix4([1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1]));
|
|
2445
2528
|
if (axis === "X")
|
|
2446
2529
|
placement.multiplyRight(new import_core19.Matrix4([0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1]));
|
|
2447
|
-
const roots = gltf.scene?.nodes || (gltf.scenes?.length === 1 ? gltf.scenes[0].nodes : void 0);
|
|
2530
|
+
const roots = (gltf.scene !== void 0 ? gltf.scenes?.[gltf.scene]?.nodes : void 0) || (gltf.scenes?.length === 1 ? gltf.scenes[0].nodes : void 0);
|
|
2448
2531
|
if (!roots?.length)
|
|
2449
2532
|
throw new import_core20.TileConversionError(
|
|
2450
2533
|
"MESH_SOURCE_SCENE_UNSUPPORTED",
|
|
2451
2534
|
"A default scene or exactly one scene is required"
|
|
2452
2535
|
);
|
|
2453
2536
|
let primitiveIndex = 0;
|
|
2454
|
-
const primitives = traverseMeshNodes(roots, placement);
|
|
2537
|
+
const primitives = traverseMeshNodes(gltfWithBuffers, roots, placement);
|
|
2455
2538
|
let current = primitives.next();
|
|
2456
2539
|
while (!current.done) {
|
|
2457
2540
|
const selected = current.value;
|
|
2458
2541
|
const next = primitives.next();
|
|
2459
2542
|
const resource = await extractPrimitive(
|
|
2543
|
+
gltfWithBuffers,
|
|
2460
2544
|
selected.primitive,
|
|
2461
2545
|
selected.transform,
|
|
2462
2546
|
`${item.tile.id}/${content.index}/${primitiveIndex++}`,
|
|
@@ -2465,7 +2549,7 @@ function createMeshTilesetConversionSource(tileset, options = {}) {
|
|
|
2465
2549
|
signal
|
|
2466
2550
|
);
|
|
2467
2551
|
const features = extractMeshFeatures(
|
|
2468
|
-
|
|
2552
|
+
gltfWithBuffers,
|
|
2469
2553
|
selected.primitive,
|
|
2470
2554
|
payload,
|
|
2471
2555
|
resource.mesh,
|
|
@@ -2488,9 +2572,10 @@ function createMeshTilesetConversionSource(tileset, options = {}) {
|
|
|
2488
2572
|
}
|
|
2489
2573
|
};
|
|
2490
2574
|
}
|
|
2491
|
-
function* traverseMeshNodes(nodes, parent, ancestors = /* @__PURE__ */ new Set()) {
|
|
2492
|
-
for (const
|
|
2493
|
-
|
|
2575
|
+
function* traverseMeshNodes(gltf, nodes, parent, ancestors = /* @__PURE__ */ new Set()) {
|
|
2576
|
+
for (const nodeIndex of nodes) {
|
|
2577
|
+
const node = gltf.json.nodes[nodeIndex];
|
|
2578
|
+
if (!node || ancestors.has(nodeIndex) || node.skin !== void 0 || node.weights || Object.keys(node.extensions || {}).length)
|
|
2494
2579
|
throw new import_core20.TileConversionError(
|
|
2495
2580
|
"MESH_SOURCE_NODE_UNSUPPORTED",
|
|
2496
2581
|
"Cyclic, skinned, morphed, or extended nodes are unsupported"
|
|
@@ -2498,18 +2583,24 @@ function* traverseMeshNodes(nodes, parent, ancestors = /* @__PURE__ */ new Set()
|
|
|
2498
2583
|
const transform = new import_core19.Matrix4(parent).multiplyRight(
|
|
2499
2584
|
node.matrix ? new import_core19.Matrix4(node.matrix) : new import_core19.Matrix4().translate(node.translation || [0, 0, 0]).multiplyRight(new import_core19.Matrix4().fromQuaternion(node.rotation || [0, 0, 0, 1])).scale(node.scale || [1, 1, 1])
|
|
2500
2585
|
);
|
|
2501
|
-
if (node.mesh) {
|
|
2502
|
-
|
|
2586
|
+
if (node.mesh !== void 0) {
|
|
2587
|
+
const mesh = gltf.json.meshes[node.mesh];
|
|
2588
|
+
if (mesh.weights || Object.keys(mesh.extensions || {}).length)
|
|
2503
2589
|
throw new import_core20.TileConversionError(
|
|
2504
2590
|
"MESH_SOURCE_NODE_UNSUPPORTED",
|
|
2505
2591
|
"Morph weights and mesh extensions are unsupported"
|
|
2506
2592
|
);
|
|
2507
|
-
for (const primitive of
|
|
2593
|
+
for (const primitive of mesh.primitives) yield { primitive, transform };
|
|
2508
2594
|
}
|
|
2509
|
-
yield* traverseMeshNodes(
|
|
2595
|
+
yield* traverseMeshNodes(
|
|
2596
|
+
gltf,
|
|
2597
|
+
node.children || [],
|
|
2598
|
+
transform,
|
|
2599
|
+
/* @__PURE__ */ new Set([...ancestors, nodeIndex])
|
|
2600
|
+
);
|
|
2510
2601
|
}
|
|
2511
2602
|
}
|
|
2512
|
-
async function extractPrimitive(primitive, transform, id, readExternalResource, contentUri, signal) {
|
|
2603
|
+
async function extractPrimitive(gltf, primitive, transform, id, readExternalResource, contentUri, signal) {
|
|
2513
2604
|
if (primitive.targets?.length || Object.keys(primitive.extensions || {}).some((name) => name !== "EXT_mesh_features"))
|
|
2514
2605
|
throw new import_core20.TileConversionError(
|
|
2515
2606
|
"MESH_SOURCE_PRIMITIVE_UNSUPPORTED",
|
|
@@ -2521,7 +2612,8 @@ async function extractPrimitive(primitive, transform, id, readExternalResource,
|
|
|
2521
2612
|
"Mesh placement requires a finite invertible affine transform with positive determinant"
|
|
2522
2613
|
);
|
|
2523
2614
|
const attributes = {};
|
|
2524
|
-
for (const [name,
|
|
2615
|
+
for (const [name, reference] of Object.entries(primitive.attributes)) {
|
|
2616
|
+
const accessor = (0, import_gltf4.getGLTFAccessor)(gltf, reference);
|
|
2525
2617
|
if (name === "_BATCHID" || /^_FEATURE_ID_\d+$/.test(name)) continue;
|
|
2526
2618
|
if (!["POSITION", "NORMAL", "COLOR_0", "TEXCOORD_0"].includes(name))
|
|
2527
2619
|
throw new import_core20.TileConversionError(
|
|
@@ -2529,17 +2621,17 @@ async function extractPrimitive(primitive, transform, id, readExternalResource,
|
|
|
2529
2621
|
`Unsupported mesh attribute ${name}`
|
|
2530
2622
|
);
|
|
2531
2623
|
attributes[name] = {
|
|
2532
|
-
value:
|
|
2533
|
-
size: accessor.
|
|
2624
|
+
value: (0, import_gltf4.getGLTFAccessorValue)(gltf, reference),
|
|
2625
|
+
size: accessor.type === "SCALAR" ? 1 : Number(accessor.type.slice(3)),
|
|
2534
2626
|
...accessor.normalized ? { normalized: true } : {}
|
|
2535
2627
|
};
|
|
2536
2628
|
}
|
|
2537
2629
|
const mesh = validateMeshGeometry(
|
|
2538
2630
|
{
|
|
2539
2631
|
topology: "triangle-list",
|
|
2540
|
-
mode: primitive.mode
|
|
2632
|
+
mode: [5, 6].includes(primitive.mode ?? 4) ? 4 : primitive.mode ?? 4,
|
|
2541
2633
|
attributes,
|
|
2542
|
-
indices: createTriangleIndices(primitive, (attributes.POSITION?.value.length ?? 0) / 3)
|
|
2634
|
+
indices: createTriangleIndices(gltf, primitive, (attributes.POSITION?.value.length ?? 0) / 3)
|
|
2543
2635
|
},
|
|
2544
2636
|
true
|
|
2545
2637
|
);
|
|
@@ -2577,14 +2669,15 @@ async function extractPrimitive(primitive, transform, id, readExternalResource,
|
|
|
2577
2669
|
mesh,
|
|
2578
2670
|
origin: minimum.map((value, axis) => value / 2 + maximum[axis] / 2),
|
|
2579
2671
|
material: await mapMeshSourceMaterial(
|
|
2580
|
-
primitive.material,
|
|
2672
|
+
primitive.material === void 0 ? void 0 : gltf.json.materials?.[primitive.material],
|
|
2581
2673
|
readExternalResource,
|
|
2582
2674
|
contentUri,
|
|
2583
|
-
signal
|
|
2675
|
+
signal,
|
|
2676
|
+
gltf
|
|
2584
2677
|
)
|
|
2585
2678
|
};
|
|
2586
2679
|
}
|
|
2587
|
-
async function mapMeshSourceMaterial(material, readExternalResource, contentUri, signal) {
|
|
2680
|
+
async function mapMeshSourceMaterial(material, readExternalResource, contentUri, signal, gltf) {
|
|
2588
2681
|
if (!material) return void 0;
|
|
2589
2682
|
const pbr = material.pbrMetallicRoughness;
|
|
2590
2683
|
if (Object.entries(material).some(
|
|
@@ -2609,6 +2702,7 @@ async function mapMeshSourceMaterial(material, readExternalResource, contentUri,
|
|
|
2609
2702
|
baseColorFactor: pbr?.baseColorFactor,
|
|
2610
2703
|
..."baseColorTexture" in (pbr || {}) ? {
|
|
2611
2704
|
baseColorTexture: await resolveMeshSourceTexture(
|
|
2705
|
+
gltf,
|
|
2612
2706
|
pbr.baseColorTexture,
|
|
2613
2707
|
readExternalResource,
|
|
2614
2708
|
contentUri,
|
|
@@ -2622,13 +2716,14 @@ async function mapMeshSourceMaterial(material, readExternalResource, contentUri,
|
|
|
2622
2716
|
doubleSided: material.doubleSided
|
|
2623
2717
|
};
|
|
2624
2718
|
}
|
|
2625
|
-
function createTriangleIndices(primitive, vertexCount) {
|
|
2626
|
-
const
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2719
|
+
function createTriangleIndices(gltf, primitive, vertexCount) {
|
|
2720
|
+
const accessor = primitive.indices === void 0 ? void 0 : (0, import_gltf4.getGLTFAccessor)(gltf, primitive.indices);
|
|
2721
|
+
const attribute = accessor ? {
|
|
2722
|
+
value: (0, import_gltf4.getGLTFAccessorValue)(gltf, accessor),
|
|
2723
|
+
size: 1,
|
|
2724
|
+
normalized: accessor.normalized
|
|
2630
2725
|
} : void 0;
|
|
2631
|
-
if (primitive.mode !== 5) return attribute;
|
|
2726
|
+
if (primitive.mode !== 5 && primitive.mode !== 6) return attribute;
|
|
2632
2727
|
const sourceIndices = validateMeshIndices(attribute, vertexCount, 5);
|
|
2633
2728
|
const indexCount = sourceIndices?.length ?? vertexCount;
|
|
2634
2729
|
if (!Number.isSafeInteger(indexCount) || indexCount < 3) {
|
|
@@ -2640,9 +2735,10 @@ function createTriangleIndices(primitive, vertexCount) {
|
|
|
2640
2735
|
const IndexArray = vertexCount < 65536 ? Uint16Array : Uint32Array;
|
|
2641
2736
|
const indices = new IndexArray((indexCount - 2) * 3);
|
|
2642
2737
|
for (let triangle = 0; triangle < indexCount - 2; triangle++) {
|
|
2643
|
-
const second = triangle + 1 + triangle % 2;
|
|
2644
|
-
const third = triangle + 2 - triangle % 2;
|
|
2645
|
-
|
|
2738
|
+
const second = primitive.mode === 6 ? triangle + 1 : triangle + 1 + triangle % 2;
|
|
2739
|
+
const third = primitive.mode === 6 ? triangle + 2 : triangle + 2 - triangle % 2;
|
|
2740
|
+
const first = primitive.mode === 6 ? 0 : triangle;
|
|
2741
|
+
indices[triangle * 3] = sourceIndices?.[first] ?? first;
|
|
2646
2742
|
indices[triangle * 3 + 1] = sourceIndices?.[second] ?? second;
|
|
2647
2743
|
indices[triangle * 3 + 2] = sourceIndices?.[third] ?? third;
|
|
2648
2744
|
}
|
|
@@ -2650,7 +2746,7 @@ function createTriangleIndices(primitive, vertexCount) {
|
|
|
2650
2746
|
}
|
|
2651
2747
|
|
|
2652
2748
|
// src/v5/i3s-mesh-conversion.ts
|
|
2653
|
-
var import_i3s = require("@loaders.gl/i3s");
|
|
2749
|
+
var import_i3s = require("@loaders.gl/tiles-3d/i3s");
|
|
2654
2750
|
var import_core22 = require("@loaders.gl/tile-converter/v5/core");
|
|
2655
2751
|
var import_core23 = require("@loaders.gl/tile-converter/v5/core");
|
|
2656
2752
|
function createI3SMeshConversionCodec(options) {
|
|
@@ -3264,6 +3360,7 @@ var import_core28 = require("@loaders.gl/tile-converter/v5/core");
|
|
|
3264
3360
|
var import_images3 = require("@loaders.gl/images");
|
|
3265
3361
|
var import_core26 = require("@loaders.gl/tile-converter/v5/core");
|
|
3266
3362
|
async function mapI3SMeshSourceMaterial(content, header, readExternalResource, contentUri, signal) {
|
|
3363
|
+
const gltf = { json: { asset: { version: "2.0" } }, buffers: [] };
|
|
3267
3364
|
const material = Object.fromEntries(
|
|
3268
3365
|
Object.entries(content.material || {}).filter(([, value]) => value !== void 0)
|
|
3269
3366
|
);
|
|
@@ -3330,7 +3427,7 @@ async function mapI3SMeshSourceMaterial(content, header, readExternalResource, c
|
|
|
3330
3427
|
}
|
|
3331
3428
|
}
|
|
3332
3429
|
const declaredFormat = resources[0]?.textureFormat;
|
|
3333
|
-
if (!image || !["image/png", "image/jpeg"].includes(image.mimeType) || declaredFormat && (declaredFormat === "png" ? image.mimeType !== "image/png" : declaredFormat === "jpg" ? image.mimeType !== "image/jpeg" : true)) {
|
|
3430
|
+
if (!(data instanceof Uint8Array) || !image || !["image/png", "image/jpeg"].includes(image.mimeType) || declaredFormat && (declaredFormat === "png" ? image.mimeType !== "image/png" : declaredFormat === "jpg" ? image.mimeType !== "image/jpeg" : true)) {
|
|
3334
3431
|
throw new import_core26.TileConversionError(
|
|
3335
3432
|
"I3S_MESH_SOURCE_TEXTURE_UNSUPPORTED",
|
|
3336
3433
|
"I3S base-color bytes must have matching PNG/JPEG headers"
|
|
@@ -3339,19 +3436,24 @@ async function mapI3SMeshSourceMaterial(content, header, readExternalResource, c
|
|
|
3339
3436
|
const sampler = Object.fromEntries(
|
|
3340
3437
|
["wrapS", "wrapT"].filter((name) => textureInfo[name] !== void 0).map((name) => [name, wrappingModes[textureInfo[name]]])
|
|
3341
3438
|
);
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
};
|
|
3439
|
+
gltf.buffers.push({
|
|
3440
|
+
arrayBuffer: data.buffer,
|
|
3441
|
+
byteOffset: data.byteOffset,
|
|
3442
|
+
byteLength: data.byteLength
|
|
3443
|
+
});
|
|
3444
|
+
gltf.json.buffers = [{ byteLength: data.byteLength }];
|
|
3445
|
+
gltf.json.bufferViews = [{ buffer: 0, byteLength: data.byteLength }];
|
|
3446
|
+
gltf.json.images = [{ mimeType: image.mimeType, bufferView: 0 }];
|
|
3447
|
+
gltf.json.samplers = [sampler];
|
|
3448
|
+
gltf.json.textures = [{ source: 0, sampler: 0 }];
|
|
3449
|
+
metallicRoughness.baseColorTexture = { texCoord: 0, index: 0 };
|
|
3349
3450
|
}
|
|
3350
3451
|
const mapped = await mapMeshSourceMaterial(
|
|
3351
3452
|
material,
|
|
3352
3453
|
void 0,
|
|
3353
3454
|
contentUri,
|
|
3354
|
-
signal
|
|
3455
|
+
signal,
|
|
3456
|
+
gltf
|
|
3355
3457
|
);
|
|
3356
3458
|
if (mapped?.baseColorTexture && !content.sourceAttributes?.uv0) {
|
|
3357
3459
|
throw new import_core26.TileConversionError(
|
|
@@ -3363,7 +3465,7 @@ async function mapI3SMeshSourceMaterial(content, header, readExternalResource, c
|
|
|
3363
3465
|
}
|
|
3364
3466
|
|
|
3365
3467
|
// src/v5/i3s-mesh-source-features.ts
|
|
3366
|
-
var import_i3s2 = require("@loaders.gl/i3s");
|
|
3468
|
+
var import_i3s2 = require("@loaders.gl/tiles-3d/i3s");
|
|
3367
3469
|
var import_core27 = require("@loaders.gl/tile-converter/v5/core");
|
|
3368
3470
|
async function extractI3SMeshFeatures(content, item, metadata, options, readExternalResource, contentUri, signal) {
|
|
3369
3471
|
const maximumAttributeBytes = options.maxAttributeBytes;
|
|
@@ -3691,19 +3793,267 @@ function createI3SMeshTilesetConversionSource(tileset, options = {}) {
|
|
|
3691
3793
|
};
|
|
3692
3794
|
}
|
|
3693
3795
|
|
|
3694
|
-
// src/v5/point-cloud-
|
|
3695
|
-
var
|
|
3796
|
+
// src/v5/point-cloud-attributes.ts
|
|
3797
|
+
var import_schema_utils5 = require("@loaders.gl/core/schema-utils");
|
|
3696
3798
|
var import_core29 = require("@loaders.gl/tile-converter/v5/core");
|
|
3799
|
+
function mapPointCloudAttributes(input, mapping) {
|
|
3800
|
+
const mesh = getPointCloudMesh(input);
|
|
3801
|
+
const attributes = /* @__PURE__ */ Object.create(null);
|
|
3802
|
+
const selected = /* @__PURE__ */ new Set();
|
|
3803
|
+
for (const [target, source] of Object.entries(mapping.attributes)) {
|
|
3804
|
+
if (!target || ["__proto__", "constructor", "prototype"].includes(target) || !Object.hasOwn(mesh.attributes, source))
|
|
3805
|
+
throw new import_core29.TileConversionError(
|
|
3806
|
+
"POINT_CLOUD_MAPPING_INVALID",
|
|
3807
|
+
`Invalid point attribute mapping ${target}: ${source}`
|
|
3808
|
+
);
|
|
3809
|
+
if (Object.hasOwn(mapping.drop || {}, source))
|
|
3810
|
+
throw new import_core29.TileConversionError(
|
|
3811
|
+
"POINT_CLOUD_MAPPING_INVALID",
|
|
3812
|
+
`Point attribute ${source} is both selected and dropped`
|
|
3813
|
+
);
|
|
3814
|
+
attributes[target] = { ...mesh.attributes[source] };
|
|
3815
|
+
selected.add(source);
|
|
3816
|
+
}
|
|
3817
|
+
const droppedAttributes = /* @__PURE__ */ Object.create(null);
|
|
3818
|
+
for (const [source, reason] of Object.entries(mapping.drop || {}).sort(
|
|
3819
|
+
([left], [right]) => left < right ? -1 : left > right ? 1 : 0
|
|
3820
|
+
)) {
|
|
3821
|
+
if (!Object.hasOwn(mesh.attributes, source) || typeof reason !== "string" || !reason.trim())
|
|
3822
|
+
throw new import_core29.TileConversionError(
|
|
3823
|
+
"POINT_CLOUD_MAPPING_INVALID",
|
|
3824
|
+
`Invalid loss declaration for ${source}`
|
|
3825
|
+
);
|
|
3826
|
+
droppedAttributes[source] = reason;
|
|
3827
|
+
}
|
|
3828
|
+
const unmapped = Object.keys(mesh.attributes).filter(
|
|
3829
|
+
(name) => !selected.has(name) && !Object.hasOwn(droppedAttributes, name)
|
|
3830
|
+
);
|
|
3831
|
+
if (unmapped.length || !attributes.POSITION)
|
|
3832
|
+
throw new import_core29.TileConversionError(
|
|
3833
|
+
"POINT_CLOUD_MAPPING_REQUIRED",
|
|
3834
|
+
`Map POSITION and explicitly retain or drop every attribute: ${unmapped.join(", ")}`
|
|
3835
|
+
);
|
|
3836
|
+
return {
|
|
3837
|
+
mesh: { ...mesh, attributes, schema: { fields: [], metadata: { ...mesh.schema?.metadata } } },
|
|
3838
|
+
droppedAttributes
|
|
3839
|
+
};
|
|
3840
|
+
}
|
|
3841
|
+
function getPointCloudMesh(input, maxInputBytes = Infinity) {
|
|
3842
|
+
const buffers = /* @__PURE__ */ new Set();
|
|
3843
|
+
let bytes = 0;
|
|
3844
|
+
const countBuffer = (buffer) => {
|
|
3845
|
+
if (!buffers.has(buffer)) {
|
|
3846
|
+
buffers.add(buffer);
|
|
3847
|
+
bytes += buffer.byteLength;
|
|
3848
|
+
}
|
|
3849
|
+
if (bytes > maxInputBytes)
|
|
3850
|
+
throw new import_core29.TileConversionError("POINT_CLOUD_INPUT_BUDGET", "Point input byte budget exceeded");
|
|
3851
|
+
};
|
|
3852
|
+
if ("shape" in input) {
|
|
3853
|
+
const checkColumn = (column) => {
|
|
3854
|
+
if (column.nullCount)
|
|
3855
|
+
throw new import_core29.TileConversionError(
|
|
3856
|
+
"POINT_CLOUD_NULL_UNSUPPORTED",
|
|
3857
|
+
"Null point values require an explicit preprocessing step"
|
|
3858
|
+
);
|
|
3859
|
+
for (const buffer of Object.values(column.buffers)) if (buffer) countBuffer(buffer.buffer);
|
|
3860
|
+
for (const view of column.variadicBuffers) countBuffer(view.buffer);
|
|
3861
|
+
for (const child of column.children) checkColumn(child);
|
|
3862
|
+
for (const dictionary of column.dictionary?.data || []) checkColumn(dictionary);
|
|
3863
|
+
};
|
|
3864
|
+
for (const batch of input.data.batches) checkColumn(batch.data);
|
|
3865
|
+
} else
|
|
3866
|
+
for (const attribute of Object.values(input.attributes)) countBuffer(attribute.value.buffer);
|
|
3867
|
+
const mesh = "shape" in input ? (0, import_schema_utils5.convertTableToMesh)(input) : input;
|
|
3868
|
+
if (mesh.topology !== "point-list" || mesh.indices)
|
|
3869
|
+
throw new import_core29.TileConversionError(
|
|
3870
|
+
"POINT_CLOUD_INPUT_INVALID",
|
|
3871
|
+
"Decoded unindexed point-list input is required"
|
|
3872
|
+
);
|
|
3873
|
+
return mesh;
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3876
|
+
// src/v5/point-cloud-copc.ts
|
|
3877
|
+
var import_copc = require("@loaders.gl/tiles-3d/copc");
|
|
3878
|
+
var import_core30 = require("@loaders.gl/tile-converter/v5/core");
|
|
3879
|
+
var SCALAR_RANGES = {
|
|
3880
|
+
intensity: [0, 65535],
|
|
3881
|
+
classification: [0, 255],
|
|
3882
|
+
nir: [0, 65535],
|
|
3883
|
+
gpsTime: [-Infinity, Infinity],
|
|
3884
|
+
scanAngle: [-32768, 32767],
|
|
3885
|
+
userData: [0, 255],
|
|
3886
|
+
pointSourceId: [0, 65535],
|
|
3887
|
+
returnNumber: [1, 15],
|
|
3888
|
+
numberOfReturns: [1, 15],
|
|
3889
|
+
scannerChannel: [0, 3],
|
|
3890
|
+
scanDirectionFlag: [0, 1],
|
|
3891
|
+
edgeOfFlightLine: [0, 1],
|
|
3892
|
+
synthetic: [0, 1],
|
|
3893
|
+
keyPoint: [0, 1],
|
|
3894
|
+
withheld: [0, 1],
|
|
3895
|
+
overlap: [0, 1]
|
|
3896
|
+
};
|
|
3897
|
+
async function encodePointCloudCOPC(input, options) {
|
|
3898
|
+
const maxInputBytes = options.maxInputBytes ?? 64 * 1024 * 1024;
|
|
3899
|
+
const maxPoints = options.maxPoints ?? 1e6;
|
|
3900
|
+
const maxOutputBytes = options.maxOutputBytes ?? 128 * 1024 * 1024;
|
|
3901
|
+
if ([maxInputBytes, maxPoints, maxOutputBytes].some(
|
|
3902
|
+
(value) => !Number.isSafeInteger(value) || value < 1
|
|
3903
|
+
) || options.scale.length !== 3 || options.scale.some((value) => !Number.isFinite(value) || value <= 0) || options.offset.length !== 3 || options.offset.some((value) => !Number.isFinite(value)) || typeof options.wkt !== "string" || !options.wkt.trim() || !Number.isFinite(options.maxPositionError) || options.maxPositionError < 0)
|
|
3904
|
+
throw new import_core30.TileConversionError(
|
|
3905
|
+
"POINT_CLOUD_COPC_OPTIONS_INVALID",
|
|
3906
|
+
"COPC requires explicit finite scale, offset, CRS, precision and positive budgets"
|
|
3907
|
+
);
|
|
3908
|
+
options.signal?.throwIfAborted();
|
|
3909
|
+
const source = getPointCloudMesh(input, maxInputBytes);
|
|
3910
|
+
const { mesh, droppedAttributes } = mapPointCloudAttributes(source, options.mapping);
|
|
3911
|
+
const position = mesh.attributes.POSITION;
|
|
3912
|
+
const pointCount = mesh.header?.vertexCount ?? position.value.length / 3;
|
|
3913
|
+
if (!Number.isSafeInteger(pointCount) || pointCount < 1 || pointCount > maxPoints)
|
|
3914
|
+
throw new import_core30.TileConversionError(
|
|
3915
|
+
"POINT_CLOUD_POINT_BUDGET",
|
|
3916
|
+
"COPC requires a nonempty batch within the point limit"
|
|
3917
|
+
);
|
|
3918
|
+
if (!(position.value instanceof Float32Array || position.value instanceof Float64Array) || position.size !== 3 || position.normalized)
|
|
3919
|
+
throw new import_core30.TileConversionError(
|
|
3920
|
+
"POINT_CLOUD_POSITION_INVALID",
|
|
3921
|
+
"COPC requires decoded floating XYZ"
|
|
3922
|
+
);
|
|
3923
|
+
const extraNames = new Set(options.extraBytes?.map((field) => field.attribute) || []);
|
|
3924
|
+
const descriptorNames = new Set(
|
|
3925
|
+
options.extraBytes?.map((field) => field.name || field.attribute) || []
|
|
3926
|
+
);
|
|
3927
|
+
if (extraNames.size !== (options.extraBytes?.length || 0) || descriptorNames.size !== extraNames.size || options.extraBytes?.some((field) => {
|
|
3928
|
+
const name = field.name || field.attribute;
|
|
3929
|
+
const description = field.description || "";
|
|
3930
|
+
return !mesh.attributes[field.attribute] || !field.attribute || !name.length || name.length > 32 || description.length > 32 || /[^\x20-\x7e]/.test(name) || /[^\x20-\x7e]/.test(description);
|
|
3931
|
+
}))
|
|
3932
|
+
throw new import_core30.TileConversionError(
|
|
3933
|
+
"POINT_CLOUD_EXTRA_BYTES_INVALID",
|
|
3934
|
+
"Extra Bytes descriptors require unique mapped attributes and names/descriptions within 32 printable ASCII bytes"
|
|
3935
|
+
);
|
|
3936
|
+
for (const name of extraNames)
|
|
3937
|
+
if (name === "POSITION" || name === "COLOR_0" || Object.hasOwn(SCALAR_RANGES, name))
|
|
3938
|
+
throw new import_core30.TileConversionError(
|
|
3939
|
+
"POINT_CLOUD_EXTRA_BYTES_INVALID",
|
|
3940
|
+
"Map standard attributes directly instead of duplicating them as Extra Bytes"
|
|
3941
|
+
);
|
|
3942
|
+
for (const [name, attribute] of Object.entries(mesh.attributes)) {
|
|
3943
|
+
const color2 = name === "COLOR_0";
|
|
3944
|
+
const extra = extraNames.has(name);
|
|
3945
|
+
if (name !== "POSITION" && !color2 && !extra && !Object.hasOwn(SCALAR_RANGES, name))
|
|
3946
|
+
throw new import_core30.TileConversionError(
|
|
3947
|
+
"POINT_CLOUD_ATTRIBUTE_UNSUPPORTED",
|
|
3948
|
+
`COPC cannot preserve ${name}; supply an explicit supported mapping or drop reason`
|
|
3949
|
+
);
|
|
3950
|
+
if (attribute.transform || attribute.byteOffset || attribute.byteStride || attribute.componentType === "float16" || attribute.value.length !== pointCount * attribute.size || !color2 && attribute.normalized || name !== "POSITION" && !color2 && (extra ? ![1, 3].includes(attribute.size) : attribute.size !== 1))
|
|
3951
|
+
throw new import_core30.TileConversionError(
|
|
3952
|
+
"POINT_CLOUD_ATTRIBUTE_INVALID",
|
|
3953
|
+
`COPC requires packed decoded attributes: ${name}`
|
|
3954
|
+
);
|
|
3955
|
+
if (color2) {
|
|
3956
|
+
if (attribute.size !== 3 || !(attribute.value instanceof Uint8Array || attribute.value instanceof Uint16Array))
|
|
3957
|
+
throw new import_core30.TileConversionError(
|
|
3958
|
+
"POINT_CLOUD_COLOR_INVALID",
|
|
3959
|
+
"COPC requires explicitly mapped uint8/uint16 RGB"
|
|
3960
|
+
);
|
|
3961
|
+
} else if (extra) {
|
|
3962
|
+
for (const value of attribute.value)
|
|
3963
|
+
if (typeof value !== "bigint" && !Number.isFinite(value))
|
|
3964
|
+
throw new import_core30.TileConversionError(
|
|
3965
|
+
"POINT_CLOUD_ATTRIBUTE_RANGE",
|
|
3966
|
+
`Nonfinite Extra Bytes value: ${name}`
|
|
3967
|
+
);
|
|
3968
|
+
} else if (name !== "POSITION") {
|
|
3969
|
+
const [minimum2, maximum2] = SCALAR_RANGES[name];
|
|
3970
|
+
for (const value of attribute.value) {
|
|
3971
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum2 || value > maximum2 || name !== "gpsTime" && !Number.isInteger(value))
|
|
3972
|
+
throw new import_core30.TileConversionError(
|
|
3973
|
+
"POINT_CLOUD_ATTRIBUTE_RANGE",
|
|
3974
|
+
`COPC value outside the qualified range: ${name}`
|
|
3975
|
+
);
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
let maximumPositionError = 0;
|
|
3980
|
+
const minimum = [Infinity, Infinity, Infinity];
|
|
3981
|
+
const maximum = [-Infinity, -Infinity, -Infinity];
|
|
3982
|
+
const errors = [0, 0, 0];
|
|
3983
|
+
for (let row = 0; row < pointCount; row++) {
|
|
3984
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
3985
|
+
const value = position.value[row * 3 + axis];
|
|
3986
|
+
const encoded = Math.round((value - options.offset[axis]) / options.scale[axis]);
|
|
3987
|
+
if (!Number.isFinite(value) || !Number.isSafeInteger(encoded) || encoded < -2147483648 || encoded > 2147483647)
|
|
3988
|
+
throw new import_core30.TileConversionError(
|
|
3989
|
+
"POINT_CLOUD_POSITION_RANGE",
|
|
3990
|
+
"COPC position exceeds signed int32 quantization"
|
|
3991
|
+
);
|
|
3992
|
+
minimum[axis] = Math.min(minimum[axis], value);
|
|
3993
|
+
maximum[axis] = Math.max(maximum[axis], value);
|
|
3994
|
+
errors[axis] = encoded * options.scale[axis] + options.offset[axis] - value;
|
|
3995
|
+
}
|
|
3996
|
+
maximumPositionError = Math.max(maximumPositionError, Math.hypot(...errors));
|
|
3997
|
+
if (maximumPositionError > options.maxPositionError)
|
|
3998
|
+
throw new import_core30.TileConversionError(
|
|
3999
|
+
"POINT_CLOUD_PRECISION_EXCEEDED",
|
|
4000
|
+
"COPC position rounding exceeds the declared error gate"
|
|
4001
|
+
);
|
|
4002
|
+
if (row % 16384 === 0) {
|
|
4003
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
4004
|
+
options.signal?.throwIfAborted();
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
const width = Math.max(...maximum.map((value, axis) => value - minimum[axis]), ...options.scale);
|
|
4008
|
+
const radius = width / 2;
|
|
4009
|
+
if (!Number.isFinite(Math.hypot(radius, radius, radius)) || minimum.some((value, axis) => {
|
|
4010
|
+
const center = value + (maximum[axis] - value) / 2;
|
|
4011
|
+
return !Number.isFinite(value + maximum[axis]) || !Number.isFinite(center - radius) || !Number.isFinite(center + radius);
|
|
4012
|
+
}))
|
|
4013
|
+
throw new import_core30.TileConversionError("POINT_CLOUD_BOUNDS_INVALID", "COPC coordinate extent overflow");
|
|
4014
|
+
options.signal?.throwIfAborted();
|
|
4015
|
+
const color = mesh.attributes.COLOR_0;
|
|
4016
|
+
const copc = import_copc.COPCWriter.encodeSync(mesh, {
|
|
4017
|
+
copc: {
|
|
4018
|
+
...options.organization,
|
|
4019
|
+
scale: [...options.scale],
|
|
4020
|
+
offset: [...options.offset],
|
|
4021
|
+
wkt: options.wkt,
|
|
4022
|
+
pointDataRecordFormat: mesh.attributes.nir ? 8 : color ? 7 : 6,
|
|
4023
|
+
colorDepth: color?.value instanceof Uint16Array ? 16 : 8,
|
|
4024
|
+
extraBytes: options.extraBytes
|
|
4025
|
+
}
|
|
4026
|
+
});
|
|
4027
|
+
options.signal?.throwIfAborted();
|
|
4028
|
+
if (copc.byteLength > maxOutputBytes)
|
|
4029
|
+
throw new import_core30.TileConversionError(
|
|
4030
|
+
"POINT_CLOUD_OUTPUT_BUDGET",
|
|
4031
|
+
"Completed COPC output exceeds the byte budget"
|
|
4032
|
+
);
|
|
4033
|
+
return { copc, pointCount, maximumPositionError, droppedAttributes };
|
|
4034
|
+
}
|
|
4035
|
+
function createCOPCConversionCodec(options) {
|
|
4036
|
+
return {
|
|
4037
|
+
async *convert(input, _inspection, signal) {
|
|
4038
|
+
const combinedSignal = options.signal && signal ? AbortSignal.any([options.signal, signal]) : options.signal || signal;
|
|
4039
|
+
yield await encodePointCloudCOPC(input, { ...options, signal: combinedSignal });
|
|
4040
|
+
}
|
|
4041
|
+
};
|
|
4042
|
+
}
|
|
4043
|
+
|
|
4044
|
+
// src/v5/point-cloud-tileset.ts
|
|
4045
|
+
var import_point_cloud_tile_source = require("@loaders.gl/tiles-3d/point-cloud-tile-source");
|
|
4046
|
+
var import_core31 = require("@loaders.gl/tile-converter/v5/core");
|
|
3697
4047
|
async function convertPointCloudToTileset(input, options) {
|
|
3698
4048
|
const reference = options.spatialReference;
|
|
3699
4049
|
if (!reference || reference.status !== "native" || reference.sourceCrs !== "EPSG:4978" || reference.targetCrs && reference.targetCrs !== "EPSG:4978" || reference.coordinateFrame !== "geocentric" || reference.axisOrder !== "xyz" || reference.heightReference !== "ellipsoidal" || reference.verticalUnitScale !== 1 || reference.units?.some((unit) => unit !== "meter")) {
|
|
3700
|
-
throw new
|
|
4050
|
+
throw new import_core31.TileConversionError(
|
|
3701
4051
|
"POINT_CLOUD_TILESET_FRAME_UNSUPPORTED",
|
|
3702
4052
|
"Point authoring requires explicit native EPSG:4978 xyz meters and ellipsoidal heights"
|
|
3703
4053
|
);
|
|
3704
4054
|
}
|
|
3705
4055
|
if (options.archive && (!Number.isSafeInteger(options.archive.maxArchiveBytes) || options.archive.maxArchiveBytes < 0)) {
|
|
3706
|
-
throw new
|
|
4056
|
+
throw new import_core31.TileConversionError(
|
|
3707
4057
|
"INVALID_ARCHIVE_BYTE_LIMIT",
|
|
3708
4058
|
"Archive byte limit must be a non-negative safe integer"
|
|
3709
4059
|
);
|
|
@@ -3754,10 +4104,10 @@ async function convertPointCloudToTileset(input, options) {
|
|
|
3754
4104
|
}
|
|
3755
4105
|
|
|
3756
4106
|
// src/v5/point-cloud-file.ts
|
|
3757
|
-
var
|
|
3758
|
-
var import_potree = require("@loaders.gl/potree");
|
|
3759
|
-
var
|
|
3760
|
-
var import_zip = require("@loaders.gl/zip");
|
|
4107
|
+
var import_copc2 = require("@loaders.gl/tiles-3d/copc");
|
|
4108
|
+
var import_potree = require("@loaders.gl/tiles-3d/potree");
|
|
4109
|
+
var import_schema_utils6 = require("@loaders.gl/core/schema-utils");
|
|
4110
|
+
var import_zip = require("@loaders.gl/archives/zip");
|
|
3761
4111
|
async function encodePotreeArchive(input, options) {
|
|
3762
4112
|
validateLimit(options.maxArchiveBytes);
|
|
3763
4113
|
const dataset = await (0, import_potree.encodePotreeDataset)(input, { potree: options.potree });
|
|
@@ -3782,7 +4132,7 @@ async function openPointCloudFile(input, options) {
|
|
|
3782
4132
|
if (input.size > options.maxFileBytes) throw new RangeError("Point file input budget exceeded");
|
|
3783
4133
|
options.signal?.throwIfAborted();
|
|
3784
4134
|
if (options.format === "copc") {
|
|
3785
|
-
const source2 =
|
|
4135
|
+
const source2 = import_copc2.COPCSourceLoader.createDataSource(input, options.sourceOptions || {});
|
|
3786
4136
|
try {
|
|
3787
4137
|
await source2.metadata;
|
|
3788
4138
|
options.signal?.throwIfAborted();
|
|
@@ -3899,7 +4249,7 @@ function extractMeshVertices(mesh, options) {
|
|
|
3899
4249
|
throw new Error(`Invalid selected mesh vertex attribute: ${name}`);
|
|
3900
4250
|
attributes[name] = attribute;
|
|
3901
4251
|
}
|
|
3902
|
-
return { topology: "point-list", mode: 0, attributes, schema: (0,
|
|
4252
|
+
return { topology: "point-list", mode: 0, attributes, schema: (0, import_schema_utils6.deduceMeshSchema)(attributes) };
|
|
3903
4253
|
}
|
|
3904
4254
|
function validatePath(path) {
|
|
3905
4255
|
if (!path || !/^[A-Za-z0-9_.\/-]+$/.test(path) || path.split("/").some((part) => !part || part === "." || part === ".."))
|
|
@@ -3911,8 +4261,8 @@ function validateLimit(value) {
|
|
|
3911
4261
|
}
|
|
3912
4262
|
|
|
3913
4263
|
// src/v5/point-cloud-potree.ts
|
|
3914
|
-
var
|
|
3915
|
-
var import_potree2 = require("@loaders.gl/potree");
|
|
4264
|
+
var import_schema_utils7 = require("@loaders.gl/core/schema-utils");
|
|
4265
|
+
var import_potree2 = require("@loaders.gl/tiles-3d/potree");
|
|
3916
4266
|
async function convertPointCloudToPotree(input, options) {
|
|
3917
4267
|
if (typeof options.projection !== "string" || !options.projection.trim()) {
|
|
3918
4268
|
throw new Error("Potree authoring requires an explicit native CRS declaration");
|
|
@@ -3930,7 +4280,7 @@ async function convertPointCloudToPotree(input, options) {
|
|
|
3930
4280
|
throw new RangeError("Potree authoring requires gathered and encoded byte limits");
|
|
3931
4281
|
}
|
|
3932
4282
|
options.signal?.throwIfAborted();
|
|
3933
|
-
const tiler = new
|
|
4283
|
+
const tiler = new import_schema_utils7.PointCloudTiler(input, {
|
|
3934
4284
|
...options.tiling,
|
|
3935
4285
|
maxNodes: Math.min(options.tiling?.maxNodes ?? 1e5, options.potree?.maxNodes ?? 1e5),
|
|
3936
4286
|
maxTileBytes: Math.min(
|
|
@@ -3982,12 +4332,12 @@ async function convertPointCloudToPotree(input, options) {
|
|
|
3982
4332
|
}
|
|
3983
4333
|
|
|
3984
4334
|
// src/v5/mesh-hierarchy.ts
|
|
3985
|
-
var
|
|
3986
|
-
var
|
|
3987
|
-
var
|
|
4335
|
+
var import_core32 = require("@math.gl/core");
|
|
4336
|
+
var import_tiles_3d3 = require("@loaders.gl/tiles-3d");
|
|
4337
|
+
var import_core33 = require("@loaders.gl/tile-converter/v5/core");
|
|
3988
4338
|
function prepareMeshHierarchy(inspection, resourceIds) {
|
|
3989
4339
|
const rejectHierarchy = (message) => {
|
|
3990
|
-
throw new
|
|
4340
|
+
throw new import_core33.TileConversionError("MESH_HIERARCHY_UNSUPPORTED", message);
|
|
3991
4341
|
};
|
|
3992
4342
|
if (!inspection.documents?.length || inspection.documents.length > 32)
|
|
3993
4343
|
rejectHierarchy(
|
|
@@ -3997,7 +4347,7 @@ function prepareMeshHierarchy(inspection, resourceIds) {
|
|
|
3997
4347
|
rejectHierarchy(
|
|
3998
4348
|
"Hierarchy preservation requires every content placement, without duplicates (at most 64)"
|
|
3999
4349
|
);
|
|
4000
|
-
const entryTransform = new
|
|
4350
|
+
const entryTransform = new import_core32.Matrix4();
|
|
4001
4351
|
if (inspection.documents[0].parentResourceId !== void 0 || !Array.isArray(inspection.documents[0].parentTransform) || inspection.documents[0].parentTransform.length !== 16 || inspection.documents[0].parentTransform.some((value, index) => value !== entryTransform[index]))
|
|
4002
4352
|
rejectHierarchy("The entry document must have identity parent placement");
|
|
4003
4353
|
const documents = inspection.documents.map((placement) => placement.tileset);
|
|
@@ -4022,9 +4372,9 @@ function prepareMeshHierarchy(inspection, resourceIds) {
|
|
|
4022
4372
|
rejectHierarchy("Dataset geometricError must be finite nonnegative meters");
|
|
4023
4373
|
}
|
|
4024
4374
|
const spatialReferences = documents.map(
|
|
4025
|
-
(document2) => (0,
|
|
4375
|
+
(document2) => (0, import_tiles_3d3.get3DTilesSpatialReference)(document2)
|
|
4026
4376
|
);
|
|
4027
|
-
const spatialReference = (0,
|
|
4377
|
+
const spatialReference = (0, import_core33.createTiles3DConversionSpatialContext)(
|
|
4028
4378
|
spatialReferences[0]
|
|
4029
4379
|
).spatialReference;
|
|
4030
4380
|
if (spatialReference.status !== "native" || spatialReference.sourceCrs !== "EPSG:4978" || spatialReference.heightReference !== "ellipsoidal" || spatialReference.axisOrder !== "xyz" || spatialReference.verticalUnitScale !== 1 || spatialReference.units?.some((unit) => unit !== "meter"))
|
|
@@ -4033,7 +4383,7 @@ function prepareMeshHierarchy(inspection, resourceIds) {
|
|
|
4033
4383
|
);
|
|
4034
4384
|
for (const reference of spatialReferences.slice(1)) {
|
|
4035
4385
|
const inherited = reference.crs.state === "absent" && reference.coordinateEpoch === void 0 && !reference.verticalCrs && !reference.warnings.length;
|
|
4036
|
-
const context = (0,
|
|
4386
|
+
const context = (0, import_core33.createTiles3DConversionSpatialContext)(inherited ? spatialReference : reference);
|
|
4037
4387
|
if (context.spatialReference.status !== "native" || context.spatialReference.sourceCrs !== spatialReference.sourceCrs || context.spatialReference.heightReference !== spatialReference.heightReference || context.spatialReference.axisOrder !== spatialReference.axisOrder || context.spatialReference.verticalUnitScale !== 1 || context.spatialReference.units?.some((unit) => unit !== "meter") || context.spatialReference.coordinateEpoch !== spatialReference.coordinateEpoch)
|
|
4038
4388
|
rejectHierarchy("External document CRS and coordinate epoch must match the entry frame");
|
|
4039
4389
|
}
|
|
@@ -4046,7 +4396,7 @@ function prepareMeshHierarchy(inspection, resourceIds) {
|
|
|
4046
4396
|
prefix: "",
|
|
4047
4397
|
path: [],
|
|
4048
4398
|
parent: -1,
|
|
4049
|
-
transform: new
|
|
4399
|
+
transform: new import_core32.Matrix4(),
|
|
4050
4400
|
refine: void 0
|
|
4051
4401
|
}
|
|
4052
4402
|
];
|
|
@@ -4072,7 +4422,7 @@ function prepareMeshHierarchy(inspection, resourceIds) {
|
|
|
4072
4422
|
const matrix = tile.transform;
|
|
4073
4423
|
if (matrix !== void 0 && (!Array.isArray(matrix) || matrix.length !== 16 || matrix.some((value) => typeof value !== "number" || !Number.isFinite(value)) || matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0 || matrix[15] !== 1))
|
|
4074
4424
|
rejectHierarchy("Hierarchy transforms must be finite affine matrices");
|
|
4075
|
-
const transform = new
|
|
4425
|
+
const transform = new import_core32.Matrix4(parentTransform).multiplyRight(matrix ?? new import_core32.Matrix4());
|
|
4076
4426
|
const columns = [0, 1, 2].map(
|
|
4077
4427
|
(column) => [0, 1, 2].reduce((sum, row) => sum + Math.abs(transform[column * 4 + row]), 0)
|
|
4078
4428
|
);
|
|
@@ -4167,11 +4517,11 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4167
4517
|
);
|
|
4168
4518
|
const { maxPositionError } = options;
|
|
4169
4519
|
if (!Number.isFinite(maxPositionError) || maxPositionError < 0 || hierarchy.nodes.some((node) => !Number.isFinite(node.geometricError + maxPositionError)) || !Number.isFinite(hierarchy.geometricError + maxPositionError))
|
|
4170
|
-
throw new
|
|
4520
|
+
throw new import_core33.TileConversionError(
|
|
4171
4521
|
"MESH_GEOMETRIC_ERROR_INVALID",
|
|
4172
4522
|
"Hierarchy position allowance and resulting errors must be finite nonnegative meters"
|
|
4173
4523
|
);
|
|
4174
|
-
const memory = (0,
|
|
4524
|
+
const memory = (0, import_core33.createBoundedMemoryTileConversionSink)(options);
|
|
4175
4525
|
const placements = /* @__PURE__ */ new Map();
|
|
4176
4526
|
const completedContents = /* @__PURE__ */ new Set();
|
|
4177
4527
|
const primitiveIdentifiers = /* @__PURE__ */ new Set();
|
|
@@ -4189,12 +4539,12 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4189
4539
|
last: true
|
|
4190
4540
|
};
|
|
4191
4541
|
if (state !== "open" || !identifier || completedContents.has(identifier) || primitiveIdentifiers.has(resource.id) || primitiveIdentifiers.size >= 64 || !Number.isSafeInteger(primitiveIndex) || primitiveIndex !== (placements.get(identifier)?.length ?? 0) || typeof lastPrimitive !== "boolean" || !hierarchy.nodes.some((node2) => node2.resourceIds.includes(identifier)))
|
|
4192
|
-
throw new
|
|
4542
|
+
throw new import_core33.TileConversionError(
|
|
4193
4543
|
"MESH_HIERARCHY_PLACEMENT_INVALID",
|
|
4194
4544
|
"Hierarchy writes require ordered, distinct primitives for declared contents before close (at most 64)"
|
|
4195
4545
|
);
|
|
4196
4546
|
if (resource.spatialReference.coordinateEpoch !== hierarchy.coordinateEpoch)
|
|
4197
|
-
throw new
|
|
4547
|
+
throw new import_core33.TileConversionError(
|
|
4198
4548
|
"MESH_SOURCE_EPOCH_MISMATCH",
|
|
4199
4549
|
"Hierarchy output coordinate epoch must match its source"
|
|
4200
4550
|
);
|
|
@@ -4203,7 +4553,7 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4203
4553
|
const node = hierarchy.nodes[nodeIndex];
|
|
4204
4554
|
const sibling = node.resourceIds.map((identifier2) => placements.get(identifier2)?.[0]).find(Boolean);
|
|
4205
4555
|
if (sibling && sibling.origin.some((value, axis) => value !== resource.origin[axis]))
|
|
4206
|
-
throw new
|
|
4556
|
+
throw new import_core33.TileConversionError(
|
|
4207
4557
|
"MESH_HIERARCHY_PLACEMENT_INVALID",
|
|
4208
4558
|
"Contents on one tile must share an encoded origin"
|
|
4209
4559
|
);
|
|
@@ -4230,7 +4580,7 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4230
4580
|
/** Publishes original topology only after every source content has completed. */
|
|
4231
4581
|
async finalize(report) {
|
|
4232
4582
|
if (state !== "open" || completedContents.size !== hierarchy.nodes.reduce((count, node) => count + node.resourceIds.length, 0))
|
|
4233
|
-
throw new
|
|
4583
|
+
throw new import_core33.TileConversionError(
|
|
4234
4584
|
"MESH_HIERARCHY_INCOMPLETE",
|
|
4235
4585
|
"Finalization requires every declared hierarchy content"
|
|
4236
4586
|
);
|
|
@@ -4239,7 +4589,7 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4239
4589
|
const bounds = new Array(hierarchy.nodes.length);
|
|
4240
4590
|
const transforms = hierarchy.nodes.map((node) => {
|
|
4241
4591
|
const placement = placements.get(node.resourceIds[0])?.[0];
|
|
4242
|
-
return placement ? new
|
|
4592
|
+
return placement ? new import_core32.Matrix4(placement.transform) : new import_core32.Matrix4();
|
|
4243
4593
|
});
|
|
4244
4594
|
for (let index = hierarchy.nodes.length - 1; index >= 0; index--) {
|
|
4245
4595
|
const node = hierarchy.nodes[index];
|
|
@@ -4268,12 +4618,12 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4268
4618
|
maximum[axis] = Math.max(maximum[axis], upper[axis]);
|
|
4269
4619
|
}
|
|
4270
4620
|
if ([...minimum, ...maximum].some((value) => !Number.isFinite(value)))
|
|
4271
|
-
throw new
|
|
4621
|
+
throw new import_core33.TileConversionError(
|
|
4272
4622
|
"MESH_TILESET_BOUNDS_INVALID",
|
|
4273
4623
|
"Hierarchy absolute bounds must remain finite"
|
|
4274
4624
|
);
|
|
4275
4625
|
bounds[index] = [minimum, maximum];
|
|
4276
|
-
const inverse = new
|
|
4626
|
+
const inverse = new import_core32.Matrix4(transforms[index]).invert();
|
|
4277
4627
|
const center = Array.from(
|
|
4278
4628
|
inverse.transformAsPoint(minimum.map((value, axis) => value / 2 + maximum[axis] / 2))
|
|
4279
4629
|
);
|
|
@@ -4286,7 +4636,7 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4286
4636
|
)
|
|
4287
4637
|
);
|
|
4288
4638
|
if ([...center, ...halfAxes].some((value) => !Number.isFinite(value)))
|
|
4289
|
-
throw new
|
|
4639
|
+
throw new import_core33.TileConversionError(
|
|
4290
4640
|
"MESH_TILESET_BOUNDS_INVALID",
|
|
4291
4641
|
"Hierarchy local bounds must remain finite"
|
|
4292
4642
|
);
|
|
@@ -4299,10 +4649,10 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4299
4649
|
...node.children.length ? {
|
|
4300
4650
|
children: node.children.map((child) => {
|
|
4301
4651
|
tiles[child].transform = Array.from(
|
|
4302
|
-
new
|
|
4652
|
+
new import_core32.Matrix4(inverse).multiplyRight(transforms[child])
|
|
4303
4653
|
);
|
|
4304
4654
|
if (tiles[child].transform.some((value) => !Number.isFinite(value)))
|
|
4305
|
-
throw new
|
|
4655
|
+
throw new import_core33.TileConversionError(
|
|
4306
4656
|
"MESH_TILESET_BOUNDS_INVALID",
|
|
4307
4657
|
"Relative hierarchy transforms must remain finite"
|
|
4308
4658
|
);
|
|
@@ -4340,10 +4690,10 @@ function createMeshHierarchyTilesetSink(options) {
|
|
|
4340
4690
|
}
|
|
4341
4691
|
|
|
4342
4692
|
// src/v5/selected-mesh-source.ts
|
|
4343
|
-
var
|
|
4344
|
-
var import_d_tiles2 = require("@loaders.gl/3d-tiles");
|
|
4345
|
-
var
|
|
4346
|
-
var
|
|
4693
|
+
var import_core34 = require("@loaders.gl/core");
|
|
4694
|
+
var import_d_tiles2 = require("@loaders.gl/tiles-3d/3d-tiles");
|
|
4695
|
+
var import_tiles_3d4 = require("@loaders.gl/tiles-3d");
|
|
4696
|
+
var import_core35 = require("@loaders.gl/tile-converter/v5/core");
|
|
4347
4697
|
var import_adapters = require("@loaders.gl/tile-converter/v5/adapters");
|
|
4348
4698
|
var SELECTED_MESH_LIMITS = {
|
|
4349
4699
|
/** Root JSON plus selected content transport bytes; also the decoded geometry/image/feature byte gate. */
|
|
@@ -4372,7 +4722,7 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4372
4722
|
} = options;
|
|
4373
4723
|
const maxInputBytes = options.maxInputBytes ?? SELECTED_MESH_LIMITS.maxInputBytes;
|
|
4374
4724
|
if (!Number.isSafeInteger(maxInputBytes) || maxInputBytes < 1 || maxInputBytes > SELECTED_MESH_LIMITS.maxInputBytes)
|
|
4375
|
-
throw new
|
|
4725
|
+
throw new import_core35.TileConversionError(
|
|
4376
4726
|
"INVALID_SELECTED_MESH_OPTIONS",
|
|
4377
4727
|
"Selected mesh input budget must be a positive safe integer at most 16 MiB"
|
|
4378
4728
|
);
|
|
@@ -4381,7 +4731,7 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4381
4731
|
))
|
|
4382
4732
|
throw new Error("Select between 1 and 64 distinct content placements.");
|
|
4383
4733
|
if (preserveHierarchy !== void 0 && typeof preserveHierarchy !== "boolean")
|
|
4384
|
-
throw new
|
|
4734
|
+
throw new import_core35.TileConversionError(
|
|
4385
4735
|
"MESH_HIERARCHY_UNSUPPORTED",
|
|
4386
4736
|
"preserveHierarchy must be a boolean"
|
|
4387
4737
|
);
|
|
@@ -4390,7 +4740,7 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4390
4740
|
(resource) => resourceIds.includes(resource.resourceId)
|
|
4391
4741
|
);
|
|
4392
4742
|
const selections = descriptors.map(
|
|
4393
|
-
(descriptor) => (0,
|
|
4743
|
+
(descriptor) => (0, import_core35.selectBrowserTilesetContent)(inspection, descriptor)
|
|
4394
4744
|
);
|
|
4395
4745
|
const selectedContents = new Map(
|
|
4396
4746
|
descriptors.map((descriptor, index) => [descriptor.resourceId, selections[index]])
|
|
@@ -4418,11 +4768,11 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4418
4768
|
try {
|
|
4419
4769
|
await qualification.tilesetInitializationPromise;
|
|
4420
4770
|
const metadata = await (0, import_adapters.createMeshTilesetConversionSource)(qualification).inspect(signal);
|
|
4421
|
-
spatialContext = (0,
|
|
4771
|
+
spatialContext = (0, import_core35.createTiles3DConversionSpatialContext)(metadata.spatialReference);
|
|
4422
4772
|
} finally {
|
|
4423
4773
|
qualification.destroy();
|
|
4424
4774
|
}
|
|
4425
|
-
const rawSource = options.source ?? (0,
|
|
4775
|
+
const rawSource = options.source ?? (0, import_core35.createBrowserTilesetConversionSource)({
|
|
4426
4776
|
input: inspection.rootUrl,
|
|
4427
4777
|
...SELECTED_MESH_LIMITS,
|
|
4428
4778
|
maxInputBytes,
|
|
@@ -4446,7 +4796,7 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4446
4796
|
for await (const raw of rawSource.read(selectedInspection, signal2)) {
|
|
4447
4797
|
const selection = selectedContents.get(raw.resourceId);
|
|
4448
4798
|
if (!selection)
|
|
4449
|
-
throw new
|
|
4799
|
+
throw new import_core35.TileConversionError(
|
|
4450
4800
|
"INVALID_BROWSER_SELECTION",
|
|
4451
4801
|
"Source yielded an uninspected content placement"
|
|
4452
4802
|
);
|
|
@@ -4473,9 +4823,9 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4473
4823
|
}
|
|
4474
4824
|
});
|
|
4475
4825
|
const metadata = await meshSource.inspect(signal2);
|
|
4476
|
-
const selectedContext = (0,
|
|
4826
|
+
const selectedContext = (0, import_core35.createTiles3DConversionSpatialContext)(metadata.spatialReference);
|
|
4477
4827
|
if (selectedContext.spatialReference.coordinateEpoch !== spatialContext.spatialReference.coordinateEpoch)
|
|
4478
|
-
throw new
|
|
4828
|
+
throw new import_core35.TileConversionError(
|
|
4479
4829
|
"MESH_SOURCE_EPOCH_MISMATCH",
|
|
4480
4830
|
"Selected content coordinate epoch must match the root; epoch transformations are unsupported"
|
|
4481
4831
|
);
|
|
@@ -4486,7 +4836,7 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4486
4836
|
throw new Error("Selected contents exceed the mesh primitive placement limit.");
|
|
4487
4837
|
decodedBytes += measureMeshBytes(resource);
|
|
4488
4838
|
if (decodedBytes > maxInputBytes)
|
|
4489
|
-
throw new
|
|
4839
|
+
throw new import_core35.TileConversionError(
|
|
4490
4840
|
"INPUT_RESOURCE_TOO_LARGE",
|
|
4491
4841
|
"Selected decoded geometry and encoded images exceed the aggregate input byte limit."
|
|
4492
4842
|
);
|
|
@@ -4513,7 +4863,7 @@ async function createSelectedMeshConversionSource(inspection, options) {
|
|
|
4513
4863
|
geometricError: Math.max(...selections.map((selection) => selection.geometricError)) + SELECTED_MESH_LIMITS.maxPositionError
|
|
4514
4864
|
};
|
|
4515
4865
|
}
|
|
4516
|
-
var SelectedTiles3DSource = class extends
|
|
4866
|
+
var SelectedTiles3DSource = class extends import_tiles_3d4.Tiles3DSource {
|
|
4517
4867
|
/** Parent frame; explicit, unknown or unresolved child declarations are never replaced. */
|
|
4518
4868
|
inheritedSpatialReference;
|
|
4519
4869
|
/** Creates a selected source with optional external-document frame inheritance. */
|
|
@@ -4560,23 +4910,23 @@ function createSelectedRuntime(document, data, signal, boundedFetcher, contentUr
|
|
|
4560
4910
|
},
|
|
4561
4911
|
"3d-tiles": { loadGLTF: true }
|
|
4562
4912
|
};
|
|
4563
|
-
return new
|
|
4913
|
+
return new import_tiles_3d4.Tileset3D(
|
|
4564
4914
|
new SelectedTiles3DSource(
|
|
4565
4915
|
{
|
|
4566
4916
|
url: contentUrl,
|
|
4567
4917
|
loader: import_d_tiles2.Tiles3DLoader,
|
|
4568
4918
|
resolver: {
|
|
4569
4919
|
/** Normalizes the selected hierarchy through the format loader, retaining ancestor transforms. */
|
|
4570
|
-
loadRoot: async (_url, loader, options) => (0,
|
|
4920
|
+
loadRoot: async (_url, loader, options) => (0, import_core34.parse)(new TextEncoder().encode(JSON.stringify(document)), loader, options),
|
|
4571
4921
|
/** Decodes only the selected bounded payload; no sibling content can be requested. */
|
|
4572
4922
|
loadResource: async (_url, loader, options) => {
|
|
4573
4923
|
signal.throwIfAborted();
|
|
4574
|
-
return (0,
|
|
4924
|
+
return (0, import_core34.parse)(data, loader, options, {
|
|
4575
4925
|
url: contentUrl,
|
|
4576
4926
|
baseUrl: contentUrl.startsWith("blob:") ? contentUrl : new URL(".", contentUrl).href,
|
|
4577
4927
|
fetch: boundedFetcher,
|
|
4578
|
-
coreApi:
|
|
4579
|
-
_parse:
|
|
4928
|
+
coreApi: import_core34.coreApi,
|
|
4929
|
+
_parse: import_core34.parse
|
|
4580
4930
|
});
|
|
4581
4931
|
}
|
|
4582
4932
|
}
|
|
@@ -4601,14 +4951,14 @@ function measureMeshBytes(resource) {
|
|
|
4601
4951
|
}
|
|
4602
4952
|
|
|
4603
4953
|
// src/v5/archive-source.ts
|
|
4604
|
-
var import_loader_utils = require("@loaders.gl/loader-utils");
|
|
4605
|
-
var import_i3s3 = require("@loaders.gl/i3s");
|
|
4606
|
-
var import_d_tiles3 = require("@loaders.gl/3d-tiles");
|
|
4607
|
-
var
|
|
4954
|
+
var import_loader_utils = require("@loaders.gl/core/loader-utils");
|
|
4955
|
+
var import_i3s3 = require("@loaders.gl/tiles-3d/i3s");
|
|
4956
|
+
var import_d_tiles3 = require("@loaders.gl/tiles-3d/3d-tiles");
|
|
4957
|
+
var import_core36 = require("@loaders.gl/tile-converter/v5/core");
|
|
4608
4958
|
async function openTileConversionArchive(descriptor, maxInputBytes, signal, fetcher = fetch) {
|
|
4609
4959
|
signal.throwIfAborted();
|
|
4610
4960
|
if (!["slpk", "3tz"].includes(descriptor.format))
|
|
4611
|
-
throw new
|
|
4961
|
+
throw new import_core36.TileConversionError("INVALID_ARCHIVE_SOURCE", "Select SLPK or 3TZ archive input");
|
|
4612
4962
|
validateArchiveEntityTag(descriptor.identity?.etag);
|
|
4613
4963
|
const transport = createTileConversionResourceFetcher({
|
|
4614
4964
|
maxInputBytes,
|
|
@@ -4675,12 +5025,12 @@ async function createTileConversionArchiveTransport(file, format, maxInputBytes,
|
|
|
4675
5025
|
const checkOpen = () => {
|
|
4676
5026
|
signal.throwIfAborted();
|
|
4677
5027
|
if (closed)
|
|
4678
|
-
throw new
|
|
5028
|
+
throw new import_core36.TileConversionError("ARCHIVE_SOURCE_CLOSED", "Conversion archive is closed");
|
|
4679
5029
|
};
|
|
4680
5030
|
try {
|
|
4681
5031
|
checkOpen();
|
|
4682
5032
|
if (!["slpk", "3tz"].includes(format) || !Number.isSafeInteger(maxInputBytes) || maxInputBytes < 1)
|
|
4683
|
-
throw new
|
|
5033
|
+
throw new import_core36.TileConversionError(
|
|
4684
5034
|
"INVALID_ARCHIVE_SOURCE",
|
|
4685
5035
|
"Archive source requires a supported format and positive safe byte budget"
|
|
4686
5036
|
);
|
|
@@ -4698,7 +5048,7 @@ async function createTileConversionArchiveTransport(file, format, maxInputBytes,
|
|
|
4698
5048
|
read: async (start, length) => {
|
|
4699
5049
|
checkOpen();
|
|
4700
5050
|
if (!Number.isSafeInteger(length) || length < 0 || length > maxInputBytes - readBytes)
|
|
4701
|
-
throw new
|
|
5051
|
+
throw new import_core36.TileConversionError(
|
|
4702
5052
|
"INPUT_RESOURCE_TOO_LARGE",
|
|
4703
5053
|
"Archive indexed reads exceed the input budget"
|
|
4704
5054
|
);
|
|
@@ -4747,7 +5097,7 @@ async function createTileConversionArchiveTransport(file, format, maxInputBytes,
|
|
|
4747
5097
|
}
|
|
4748
5098
|
function validateArchiveEntityTag(entityTag) {
|
|
4749
5099
|
if (entityTag !== void 0 && entityTag !== null && !/^"[\x21\x23-\x7e\x80-\xff]*"$/.test(entityTag))
|
|
4750
|
-
throw new
|
|
5100
|
+
throw new import_core36.TileConversionError(
|
|
4751
5101
|
"ARCHIVE_VALIDATOR_UNSUPPORTED",
|
|
4752
5102
|
"Remote archives require a strong quoted ETag, or Last-Modified without an ETag; weak/malformed ETags are unsupported"
|
|
4753
5103
|
);
|
|
@@ -4761,7 +5111,7 @@ function validateArchiveResponseValidator(headers) {
|
|
|
4761
5111
|
const modifiedTime = parseArchiveHttpDate(lastModified);
|
|
4762
5112
|
const responseTime = parseArchiveHttpDate(responseDate);
|
|
4763
5113
|
if (!Number.isFinite(modifiedTime) || !Number.isFinite(responseTime) || responseTime - modifiedTime < 6e4)
|
|
4764
|
-
throw new
|
|
5114
|
+
throw new import_core36.TileConversionError(
|
|
4765
5115
|
"ARCHIVE_VALIDATOR_UNSUPPORTED",
|
|
4766
5116
|
"Last-Modified archive identity requires a valid Date at least 60 seconds later; otherwise supply a strong ETag"
|
|
4767
5117
|
);
|
|
@@ -4772,10 +5122,10 @@ function parseArchiveHttpDate(value) {
|
|
|
4772
5122
|
}
|
|
4773
5123
|
|
|
4774
5124
|
// src/v5/i3s-selection-source.ts
|
|
4775
|
-
var
|
|
4776
|
-
var import_i3s4 = require("@loaders.gl/i3s");
|
|
4777
|
-
var
|
|
4778
|
-
var
|
|
5125
|
+
var import_core37 = require("@loaders.gl/core");
|
|
5126
|
+
var import_i3s4 = require("@loaders.gl/tiles-3d/i3s");
|
|
5127
|
+
var import_tiles_3d5 = require("@loaders.gl/tiles-3d");
|
|
5128
|
+
var import_core38 = require("@loaders.gl/tile-converter/v5/core");
|
|
4779
5129
|
function createRuntime(transport, layer, header) {
|
|
4780
5130
|
const libraries = transport.dracoLibraryOptions;
|
|
4781
5131
|
const sourceUrl = new URL(transport.rootUrl);
|
|
@@ -4798,14 +5148,14 @@ function createRuntime(transport, layer, header) {
|
|
|
4798
5148
|
const contextUrl = new URL(url);
|
|
4799
5149
|
contextUrl.search = "";
|
|
4800
5150
|
contextUrl.hash = "";
|
|
4801
|
-
return (0,
|
|
5151
|
+
return (0, import_core37.parse)(await response.arrayBuffer(), loader, loadOptions, {
|
|
4802
5152
|
url: contextUrl.href,
|
|
4803
5153
|
fetch: transport.fetcher,
|
|
4804
|
-
coreApi:
|
|
4805
|
-
_parse:
|
|
5154
|
+
coreApi: import_core37.coreApi,
|
|
5155
|
+
_parse: import_core37.parse
|
|
4806
5156
|
});
|
|
4807
5157
|
};
|
|
4808
|
-
const source = new
|
|
5158
|
+
const source = new import_tiles_3d5.I3SSource(
|
|
4809
5159
|
header && layer ? {
|
|
4810
5160
|
...layer,
|
|
4811
5161
|
root: { ...header, children: [] },
|
|
@@ -4813,17 +5163,17 @@ function createRuntime(transport, layer, header) {
|
|
|
4813
5163
|
url: sourceUrl.href,
|
|
4814
5164
|
basePath: sourceUrl.href,
|
|
4815
5165
|
loader: import_i3s4.I3SLoader,
|
|
4816
|
-
coreApi:
|
|
5166
|
+
coreApi: import_core37.coreApi
|
|
4817
5167
|
} : {
|
|
4818
5168
|
url: sourceUrl.href,
|
|
4819
5169
|
loader: import_i3s4.I3SLoader,
|
|
4820
|
-
coreApi:
|
|
5170
|
+
coreApi: import_core37.coreApi,
|
|
4821
5171
|
resolver: { loadRoot: loadResource, loadResource }
|
|
4822
5172
|
},
|
|
4823
5173
|
options
|
|
4824
5174
|
);
|
|
4825
|
-
source.coreApi = { ...
|
|
4826
|
-
return new
|
|
5175
|
+
source.coreApi = { ...import_core37.coreApi, load: loadResource };
|
|
5176
|
+
return new import_tiles_3d5.Tileset3D(source, { i3s: options.i3s });
|
|
4827
5177
|
}
|
|
4828
5178
|
async function inspectI3SMeshConversionSource(options) {
|
|
4829
5179
|
const { signal } = options;
|
|
@@ -4886,7 +5236,7 @@ async function createSelectedI3SMeshConversionSource(inspection, options) {
|
|
|
4886
5236
|
validateSelectionOptions(options);
|
|
4887
5237
|
signal.throwIfAborted();
|
|
4888
5238
|
if (inspection.rootUrl !== options.rootUrl)
|
|
4889
|
-
throw new
|
|
5239
|
+
throw new import_core38.TileConversionError(
|
|
4890
5240
|
"INVALID_I3S_SELECTION",
|
|
4891
5241
|
"Selection transport must match the inspected layer"
|
|
4892
5242
|
);
|
|
@@ -4910,7 +5260,7 @@ async function createSelectedI3SMeshConversionSource(inspection, options) {
|
|
|
4910
5260
|
try {
|
|
4911
5261
|
await qualification.tilesetInitializationPromise;
|
|
4912
5262
|
const metadata = await createI3SMeshTilesetConversionSource(qualification).inspect(signal);
|
|
4913
|
-
spatialContext = (0,
|
|
5263
|
+
spatialContext = (0, import_core38.createI3SConversionSpatialContext)(metadata.spatialReference, {
|
|
4914
5264
|
targetCrs: "EPSG:4978"
|
|
4915
5265
|
});
|
|
4916
5266
|
} finally {
|
|
@@ -4936,7 +5286,7 @@ async function createSelectedI3SMeshConversionSource(inspection, options) {
|
|
|
4936
5286
|
for await (const resource of meshSource.read(metadata, signal)) {
|
|
4937
5287
|
decodedBytes += measureMeshBytes(resource);
|
|
4938
5288
|
if (++meshCount > SELECTED_MESH_LIMITS.maxMeshResources || decodedBytes > (options.maxInputBytes ?? SELECTED_MESH_LIMITS.maxInputBytes))
|
|
4939
|
-
throw new
|
|
5289
|
+
throw new import_core38.TileConversionError(
|
|
4940
5290
|
"INPUT_RESOURCE_TOO_LARGE",
|
|
4941
5291
|
"Selected I3S decoded resources exceed the input/mesh budget"
|
|
4942
5292
|
);
|
|
@@ -4963,7 +5313,7 @@ function validateSelectionOptions(options) {
|
|
|
4963
5313
|
]
|
|
4964
5314
|
])
|
|
4965
5315
|
if (!Number.isSafeInteger(value) || value < 1 || value > maximum)
|
|
4966
|
-
throw new
|
|
5316
|
+
throw new import_core38.TileConversionError(
|
|
4967
5317
|
"INVALID_I3S_SELECTION_LIMIT",
|
|
4968
5318
|
"I3S selection limits must be positive safe integers within the bounded profile"
|
|
4969
5319
|
);
|