@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.
Files changed (132) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +4 -4
  3. package/dist/converter.min.cjs +149 -158
  4. package/dist/i3s-server/bin/i3s-server.min.cjs +113 -158
  5. package/dist/index.cjs +17486 -17479
  6. package/dist/index.js +25572 -25560
  7. package/dist/v5/adapters.cjs +540 -190
  8. package/dist/v5/adapters.d.ts +4 -0
  9. package/dist/v5/adapters.js +501 -151
  10. package/dist/v5/archive-source.d.ts +1 -1
  11. package/dist/v5/browser.d.ts +1 -1
  12. package/dist/v5/conversion-api.d.ts +25 -0
  13. package/dist/v5/converter-cli.js +23 -7
  14. package/dist/v5/core.cjs +76 -17
  15. package/dist/v5/core.d.ts +1 -1
  16. package/dist/v5/core.js +69 -10
  17. package/dist/v5/feature-arrow.d.ts +1 -1
  18. package/dist/v5/i3s-mesh-conversion.d.ts +1 -1
  19. package/dist/v5/i3s-mesh-source-features.d.ts +2 -2
  20. package/dist/v5/i3s-mesh-source-material.d.ts +1 -1
  21. package/dist/v5/i3s-mesh-source.d.ts +2 -2
  22. package/dist/v5/i3s-selection-source.d.ts +3 -3
  23. package/dist/v5/index.cjs +11 -6
  24. package/dist/v5/index.d.ts +5 -1
  25. package/dist/v5/index.js +8 -0
  26. package/dist/v5/mesh-conversion.d.ts +3 -3
  27. package/dist/v5/mesh-draco.d.ts +2 -2
  28. package/dist/v5/mesh-features.d.ts +2 -2
  29. package/dist/v5/mesh-source-features.d.ts +4 -4
  30. package/dist/v5/mesh-source-schema.d.ts +2 -2
  31. package/dist/v5/mesh-source-texture.d.ts +3 -3
  32. package/dist/v5/mesh-source.d.ts +5 -5
  33. package/dist/v5/mesh-tileset-sink.d.ts +1 -1
  34. package/dist/v5/mesh.d.ts +1 -1
  35. package/dist/v5/node-conversion.d.ts +2 -0
  36. package/dist/v5/node-i3s-source.d.ts +3 -3
  37. package/dist/v5/node-source.d.ts +1 -1
  38. package/dist/v5/node.cjs +19 -6
  39. package/dist/v5/node.js +19 -6
  40. package/dist/v5/point-cloud-attributes.d.ts +19 -0
  41. package/dist/v5/point-cloud-conversion.d.ts +1 -1
  42. package/dist/v5/point-cloud-copc.d.ts +44 -0
  43. package/dist/v5/point-cloud-file.d.ts +4 -4
  44. package/dist/v5/point-cloud-potree.d.ts +3 -3
  45. package/dist/v5/point-cloud-source-encoder.d.ts +1 -1
  46. package/dist/v5/point-cloud-source.d.ts +1 -1
  47. package/dist/v5/point-cloud-tileset.d.ts +3 -3
  48. package/dist/v5/point-cloud.d.ts +1 -1
  49. package/dist/v5/spatial-conversion.d.ts +1 -1
  50. package/dist/v5/tileset-source.d.ts +1 -1
  51. package/package.json +17 -32
  52. package/src/v4/3d-tiles-converter/3d-tiles-converter.ts +11 -12
  53. package/src/v4/3d-tiles-converter/helpers/3d-tiles-content-converter.ts +7 -3
  54. package/src/v4/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.ts +2 -2
  55. package/src/v4/3d-tiles-converter/helpers/load-i3s.ts +3 -3
  56. package/src/v4/3d-tiles-converter/helpers/texture-atlas.ts +1 -1
  57. package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +2 -2
  58. package/src/v4/3d-tiles-converter/json-templates/tileset.ts +58 -39
  59. package/src/v4/converter-cli.ts +3 -3
  60. package/src/v4/deps-installer/deps-installer.ts +3 -3
  61. package/src/v4/i3s-converter/helpers/attribute-metadata-info.ts +1 -1
  62. package/src/v4/i3s-converter/helpers/batch-ids-extensions.ts +9 -10
  63. package/src/v4/i3s-converter/helpers/conversion-gltf.ts +108 -0
  64. package/src/v4/i3s-converter/helpers/coordinate-converter.ts +6 -5
  65. package/src/v4/i3s-converter/helpers/create-scene-server-path.ts +5 -6
  66. package/src/v4/i3s-converter/helpers/feature-attributes.ts +4 -4
  67. package/src/v4/i3s-converter/helpers/geometry-attributes.ts +1 -1
  68. package/src/v4/i3s-converter/helpers/geometry-converter.ts +69 -77
  69. package/src/v4/i3s-converter/helpers/gltf-attributes.ts +58 -74
  70. package/src/v4/i3s-converter/helpers/load-3d-tiles.ts +5 -5
  71. package/src/v4/i3s-converter/helpers/node-debug.ts +7 -3
  72. package/src/v4/i3s-converter/helpers/node-index-document.ts +6 -7
  73. package/src/v4/i3s-converter/helpers/node-pages.ts +3 -4
  74. package/src/v4/i3s-converter/helpers/preprocess-3d-tiles.ts +1 -1
  75. package/src/v4/i3s-converter/helpers/tileset-traversal.ts +1 -1
  76. package/src/v4/i3s-converter/i3s-converter.ts +29 -31
  77. package/src/v4/i3s-converter/json-templates/geometry-definitions.ts +71 -66
  78. package/src/v4/i3s-converter/json-templates/layers.ts +97 -132
  79. package/src/v4/i3s-converter/json-templates/metadata.ts +31 -21
  80. package/src/v4/i3s-converter/json-templates/node.ts +60 -74
  81. package/src/v4/i3s-converter/json-templates/scene-server.ts +36 -27
  82. package/src/v4/i3s-converter/json-templates/shared-resources.ts +62 -123
  83. package/src/v4/i3s-converter/json-templates/store.ts +39 -58
  84. package/src/v4/i3s-converter/types.ts +4 -4
  85. package/src/v4/i3s-server/controllers/slpk-controller.ts +3 -3
  86. package/src/v4/i3s-server/utils/create-scene-server.ts +3 -3
  87. package/src/v4/lib/utils/builder-input.ts +8 -0
  88. package/src/v4/lib/utils/conversion-dump.ts +5 -1
  89. package/src/v4/lib/utils/file-utils.ts +1 -1
  90. package/src/v4/lib/utils/hash-string.ts +21 -0
  91. package/src/v4/lib/utils/lod-conversion-utils.ts +3 -3
  92. package/src/v4/pgm-loader.ts +2 -2
  93. package/src/v5/adapters.ts +5 -0
  94. package/src/v5/archive-source.ts +4 -4
  95. package/src/v5/browser.ts +1 -0
  96. package/src/v5/conversion-api.ts +115 -8
  97. package/src/v5/conversion-archive.ts +2 -2
  98. package/src/v5/core.ts +1 -0
  99. package/src/v5/feature-arrow.ts +2 -2
  100. package/src/v5/i3s-mesh-conversion.ts +2 -2
  101. package/src/v5/i3s-mesh-source-features.ts +3 -3
  102. package/src/v5/i3s-mesh-source-material.ts +18 -11
  103. package/src/v5/i3s-mesh-source.ts +2 -2
  104. package/src/v5/i3s-selection-source.ts +4 -4
  105. package/src/v5/index.ts +15 -0
  106. package/src/v5/mesh-conversion.ts +4 -4
  107. package/src/v5/mesh-draco.ts +2 -2
  108. package/src/v5/mesh-features.ts +3 -3
  109. package/src/v5/mesh-hierarchy.ts +1 -1
  110. package/src/v5/mesh-source-features.ts +137 -55
  111. package/src/v5/mesh-source-schema.ts +10 -4
  112. package/src/v5/mesh-source-texture.ts +49 -19
  113. package/src/v5/mesh-source.ts +65 -46
  114. package/src/v5/mesh-tileset-archive.ts +1 -1
  115. package/src/v5/mesh-tileset-sink.ts +1 -1
  116. package/src/v5/mesh.ts +1 -1
  117. package/src/v5/node-cli.ts +4 -0
  118. package/src/v5/node-conversion.ts +19 -2
  119. package/src/v5/node-source.ts +2 -2
  120. package/src/v5/point-cloud-attributes.ts +113 -0
  121. package/src/v5/point-cloud-conversion.ts +1 -1
  122. package/src/v5/point-cloud-copc.ts +289 -0
  123. package/src/v5/point-cloud-file.ts +8 -8
  124. package/src/v5/point-cloud-potree.ts +8 -4
  125. package/src/v5/point-cloud-source-encoder.ts +1 -1
  126. package/src/v5/point-cloud-source.ts +1 -1
  127. package/src/v5/point-cloud-spatial.ts +2 -2
  128. package/src/v5/point-cloud-tileset.ts +4 -4
  129. package/src/v5/point-cloud.ts +3 -3
  130. package/src/v5/selected-mesh-source.ts +4 -4
  131. package/src/v5/spatial-conversion.ts +2 -2
  132. package/src/v5/tileset-source.ts +2 -2
@@ -1,4 +1,4 @@
1
- import type { HttpFileIdentity, ReadableFile } from '@loaders.gl/loader-utils';
1
+ import type { HttpFileIdentity, ReadableFile } from '@loaders.gl/core/loader-utils';
2
2
  /** Cloneable archive input; a remote identity is retained across inspection and conversion. */
3
3
  export interface TileConversionArchiveInput {
4
4
  /** Immutable local Blob or HTTP(S) archive URL, including any query credentials. */
@@ -1,7 +1,7 @@
1
1
  export { convertTileset, inspectTileset, TileConversionError, validateTileset } from '@loaders.gl/tile-converter/v5/core';
2
2
  export { createTilesetConversionSource } from '@loaders.gl/tile-converter/v5/core';
3
3
  export type { TilesetConversionSourceOptions } from '@loaders.gl/tile-converter/v5/core';
4
- export type { ConvertTilesetOptions, TileConversionCodec, TileConversionDiagnostic, TileConversionProgress, TileConversionReport, TileConversionSink, TileConversionSource, TileValidationReport, ValidateTilesetOptions } from '@loaders.gl/tile-converter/v5/core';
4
+ export type { ConvertTilesetOptions, TileConversionCodec, TileConversionDiagnostic, TileConversionProgress, TileConversionReport, TileConversionTimings, TileConversionSink, TileConversionSource, TileValidationReport, ValidateTilesetOptions } from '@loaders.gl/tile-converter/v5/core';
5
5
  export { createBoundedMemoryTileConversionSink } from '@loaders.gl/tile-converter/v5/core';
6
6
  export { createBrowserTileConversionSource } from '@loaders.gl/tile-converter/v5/core';
7
7
  export type { BoundedMemoryTileConversionSink, BoundedMemoryTileConversionSinkOptions, BrowserTileConversionFile, BrowserTileConversionResource } from '@loaders.gl/tile-converter/v5/core';
@@ -31,8 +31,31 @@ export interface TileConversionProgress {
31
31
  /** Number of output bytes written so far. */
32
32
  readonly outputBytes: number;
33
33
  }
34
+ /** Elapsed milliseconds for awaited adapter work; stages exclude downstream backpressure. */
35
+ export interface TileConversionTimings {
36
+ /** Elapsed inspect adapter time in milliseconds. */
37
+ readonly inspectMilliseconds: number;
38
+ /** Elapsed read adapter time in milliseconds. */
39
+ readonly readMilliseconds: number;
40
+ /** Elapsed convert adapter time in milliseconds. */
41
+ readonly convertMilliseconds: number;
42
+ /** Elapsed validate adapter time in milliseconds. */
43
+ readonly validateMilliseconds: number;
44
+ /** Elapsed write adapter time in milliseconds. */
45
+ readonly writeMilliseconds: number;
46
+ /** Elapsed finalize adapter time in milliseconds. */
47
+ readonly finalizeMilliseconds: number;
48
+ /** Elapsed end-to-end conversion time in milliseconds. */
49
+ readonly totalMilliseconds: number;
50
+ /** Node transport preparation, including inspection and selection, when available. */
51
+ readonly setupMilliseconds?: number;
52
+ /** Node archive serialization and destination publication, when available. */
53
+ readonly outputMilliseconds?: number;
54
+ }
34
55
  /** Summary returned after a tileset conversion completes. */
35
56
  export interface TileConversionReport {
57
+ /** Optional stage timings, attached after successful destination finalization. */
58
+ readonly timings?: TileConversionTimings;
36
59
  /** Completed conversion state. Failed conversions reject with their cause. */
37
60
  readonly state: 'completed';
38
61
  /** Number of input resources consumed. */
@@ -73,6 +96,8 @@ export interface TileConversionCodec<TInspection, TInput, TOutput> {
73
96
  }
74
97
  /** Options for the portable `convertTileset` operation. */
75
98
  export interface ConvertTilesetOptions<TInspection, TInput, TOutput> {
99
+ /** Measure awaited adapter work and total elapsed time; disabled by default. */
100
+ readonly profile?: boolean;
76
101
  /** Injected input resolver and resource reader. */
77
102
  readonly source: TileConversionSource<TInspection, TInput>;
78
103
  /** Injected output codec. */
@@ -119,9 +119,9 @@ var init_resource_fetcher = __esm({
119
119
  });
120
120
 
121
121
  // src/v5/archive-source.ts
122
- import { BlobFile, HttpFile } from "@loaders.gl/loader-utils";
123
- import { parseSLPKArchive } from "@loaders.gl/i3s";
124
- import { parse3DTilesArchive } from "@loaders.gl/3d-tiles";
122
+ import { BlobFile, HttpFile } from "@loaders.gl/core/loader-utils";
123
+ import { parseSLPKArchive } from "@loaders.gl/tiles-3d/i3s";
124
+ import { parse3DTilesArchive } from "@loaders.gl/tiles-3d/3d-tiles";
125
125
  import { TileConversionError as TileConversionError3 } from "@loaders.gl/tile-converter/v5/core";
126
126
  async function openTileConversionArchive(descriptor, maxInputBytes, signal, fetcher = fetch) {
127
127
  signal.throwIfAborted();
@@ -299,7 +299,7 @@ var init_archive_source = __esm({
299
299
  import { open as open2, realpath } from "node:fs/promises";
300
300
  import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
301
301
  import { fileURLToPath } from "node:url";
302
- import { parse3DTilesArchive as parse3DTilesArchive2 } from "@loaders.gl/3d-tiles";
302
+ import { parse3DTilesArchive as parse3DTilesArchive2 } from "@loaders.gl/tiles-3d/3d-tiles";
303
303
  import {
304
304
  createBrowserTilesetConversionSource,
305
305
  TileConversionError as TileConversionError4
@@ -696,6 +696,8 @@ import {
696
696
  encodeTileConversionArchiveInBatches
697
697
  } from "@loaders.gl/tile-converter/v5/adapters";
698
698
  async function convertNodeTileset(options) {
699
+ const started = options.profile ? performance.now() : 0;
700
+ let setupMilliseconds = 0;
699
701
  const signal = options.signal ?? new AbortController().signal;
700
702
  const maxOutputBytes = options.maxOutputBytes ?? SELECTED_MESH_LIMITS.maxOutputBytes;
701
703
  if (!["3d-tiles", "3tz", "slpk"].includes(options.outputFormat) || !Number.isSafeInteger(maxOutputBytes) || maxOutputBytes < 1 || maxOutputBytes > SELECTED_MESH_LIMITS.maxOutputBytes)
@@ -736,7 +738,7 @@ async function convertNodeTileset(options) {
736
738
  let report;
737
739
  try {
738
740
  const inspection = await rawSource.inspect(signal);
739
- await import("@loaders.gl/polyfills");
741
+ await import("@loaders.gl/core/polyfills");
740
742
  const { getDracoLibraryOptions } = await import("@loaders.gl/draco/bundled");
741
743
  const dracoLibraryOptions = getDracoLibraryOptions({
742
744
  decoderProfile: "full",
@@ -764,7 +766,9 @@ async function convertNodeTileset(options) {
764
766
  }
765
767
  );
766
768
  const { source, spatialContext, geometricError } = selection;
769
+ setupMilliseconds = options.profile ? performance.now() - started : 0;
767
770
  const common = {
771
+ profile: options.profile,
768
772
  source,
769
773
  signal,
770
774
  measureInputBytes: measureMeshBytes,
@@ -815,6 +819,7 @@ async function convertNodeTileset(options) {
815
819
  } finally {
816
820
  await rawSource.close();
817
821
  }
822
+ const outputStarted = options.profile ? performance.now() : 0;
818
823
  signal.throwIfAborted();
819
824
  if (options.outputFormat !== "3d-tiles" && !options.output) {
820
825
  for await (const chunk of encodeTileConversionArchiveInBatches(files, {
@@ -832,7 +837,15 @@ async function convertNodeTileset(options) {
832
837
  maxOutputBytes,
833
838
  signal
834
839
  );
835
- return report;
840
+ return report.timings ? {
841
+ ...report,
842
+ timings: {
843
+ ...report.timings,
844
+ setupMilliseconds,
845
+ outputMilliseconds: performance.now() - outputStarted,
846
+ totalMilliseconds: performance.now() - started
847
+ }
848
+ } : report;
836
849
  }
837
850
  async function writeNodeTileConversionOutput(files, output, format, maxOutputBytes, signal) {
838
851
  signal.throwIfAborted();
@@ -1064,6 +1077,7 @@ var HELP = `Usage: tile-converter-v5 inspect|convert|validate <input path or URL
1064
1077
  --max-resources N Lower the 1,000 content-declaration limit
1065
1078
  --max-documents N Lower the 32 metadata-document limit
1066
1079
  --max-output-bytes N Lower the 32 MiB output/archive budget
1080
+ --profile Include elapsed conversion stage timings in JSON
1067
1081
  --help Show this help
1068
1082
 
1069
1083
  Inspect reads metadata only, following declared .json external tilesets.
@@ -1081,6 +1095,7 @@ async function runTileConverterCLI(argumentsList, output, signal) {
1081
1095
  allowPositionals: true,
1082
1096
  options: {
1083
1097
  help: { type: "boolean" },
1098
+ profile: { type: "boolean" },
1084
1099
  "preserve-hierarchy": { type: "boolean" },
1085
1100
  "input-format": { type: "string", default: "3d-tiles" },
1086
1101
  "max-input-bytes": { type: "string", default: String(NODE_TILESET_LIMITS.maxInputBytes) },
@@ -1136,6 +1151,7 @@ async function runTileConverterCLI(argumentsList, output, signal) {
1136
1151
  ...sourceOptions,
1137
1152
  ...features,
1138
1153
  resourceIds: values.resource,
1154
+ profile: values.profile,
1139
1155
  preserveHierarchy: values["preserve-hierarchy"],
1140
1156
  outputFormat: values["output-format"],
1141
1157
  output: values.output,
@@ -1149,7 +1165,7 @@ async function runTileConverterCLI(argumentsList, output, signal) {
1149
1165
  );
1150
1166
  return 0;
1151
1167
  }
1152
- if (values["feature-schema"] !== void 0 || values["preserve-hierarchy"] !== void 0 || values["geometric-error"] !== void 0 || values["integrated-mesh-policy"] !== void 0 || values.resource || values.output || values["output-format"] !== "3tz" || values["max-output-bytes"] !== String(32 * 1024 * 1024))
1168
+ if (values.profile !== void 0 || values["feature-schema"] !== void 0 || values["preserve-hierarchy"] !== void 0 || values["geometric-error"] !== void 0 || values["integrated-mesh-policy"] !== void 0 || values.resource || values.output || values["output-format"] !== "3tz" || values["max-output-bytes"] !== String(32 * 1024 * 1024))
1153
1169
  throw new TileConversionError7(
1154
1170
  "CLI_USAGE_ERROR",
1155
1171
  "Inspect does not accept conversion/output options"
package/dist/v5/core.cjs CHANGED
@@ -72,6 +72,16 @@ async function convertTileset(options) {
72
72
  signal,
73
73
  onProgress
74
74
  } = options;
75
+ const started = options.profile ? performance.now() : 0;
76
+ const timings = options.profile ? {
77
+ inspectMilliseconds: 0,
78
+ readMilliseconds: 0,
79
+ convertMilliseconds: 0,
80
+ validateMilliseconds: 0,
81
+ writeMilliseconds: 0,
82
+ finalizeMilliseconds: 0,
83
+ totalMilliseconds: 0
84
+ } : void 0;
75
85
  let inputResources = 0;
76
86
  let outputResources = 0;
77
87
  let inputBytes = 0;
@@ -98,8 +108,16 @@ async function convertTileset(options) {
98
108
  }
99
109
  }
100
110
  reportProgress("inspect");
101
- const inspection = await inspectTileset(source, signal);
102
- for await (const inputResource of source.read(inspection, signal)) {
111
+ const inspection = await measureConversionOperation(
112
+ timings,
113
+ "inspectMilliseconds",
114
+ () => inspectTileset(source, signal)
115
+ );
116
+ for await (const inputResource of measureConversionIterable(
117
+ source.read(inspection, signal),
118
+ timings,
119
+ "readMilliseconds"
120
+ )) {
103
121
  throwIfAborted(signal);
104
122
  checkConversionTotal(inputResources, 1, maxInputResources, "INPUT_COUNT_LIMIT_EXCEEDED");
105
123
  const inputResourceBytes = measureInputBytes(inputResource);
@@ -124,12 +142,24 @@ async function convertTileset(options) {
124
142
  inputResources++;
125
143
  inputBytes += inputResourceBytes;
126
144
  reportProgress("convert");
127
- const convertedResources = await codec.convert(inputResource, inspection, signal);
128
- for await (const outputResource of convertedResources) {
145
+ const convertedResources = await measureConversionOperation(
146
+ timings,
147
+ "convertMilliseconds",
148
+ () => codec.convert(inputResource, inspection, signal)
149
+ );
150
+ for await (const outputResource of measureConversionIterable(
151
+ convertedResources,
152
+ timings,
153
+ "convertMilliseconds"
154
+ )) {
129
155
  throwIfAborted(signal);
130
156
  checkConversionTotal(outputResources, 1, maxOutputResources, "OUTPUT_COUNT_LIMIT_EXCEEDED");
131
157
  reportProgress("validate");
132
- const resourceDiagnostics = await codec.validateOutput?.(outputResource, signal) || [];
158
+ const resourceDiagnostics = await measureConversionOperation(
159
+ timings,
160
+ "validateMilliseconds",
161
+ () => codec.validateOutput?.(outputResource, signal)
162
+ ) || [];
133
163
  diagnostics.push(...resourceDiagnostics);
134
164
  const outputResourceBytes = measureOutputBytes(outputResource);
135
165
  if (!Number.isSafeInteger(outputResourceBytes) || outputResourceBytes < 0) {
@@ -158,7 +188,11 @@ async function convertTileset(options) {
158
188
  );
159
189
  }
160
190
  throwIfAborted(signal);
161
- await sink.write(outputResource, signal);
191
+ await measureConversionOperation(
192
+ timings,
193
+ "writeMilliseconds",
194
+ () => sink.write(outputResource, signal)
195
+ );
162
196
  throwIfAborted(signal);
163
197
  largestOutputResourceBytes = Math.max(largestOutputResourceBytes, outputResourceBytes);
164
198
  outputResources++;
@@ -177,8 +211,9 @@ async function convertTileset(options) {
177
211
  };
178
212
  throwIfAborted(signal);
179
213
  reportProgress("finalize");
180
- await sink.finalize(report);
181
- return report;
214
+ await measureConversionOperation(timings, "finalizeMilliseconds", () => sink.finalize(report));
215
+ if (timings) timings.totalMilliseconds = Math.max(0, performance.now() - started);
216
+ return timings ? { ...report, timings } : report;
182
217
  } catch (error) {
183
218
  try {
184
219
  await sink.abort(error);
@@ -219,6 +254,30 @@ function checkConversionTotal(current, increment, limit, code) {
219
254
  );
220
255
  }
221
256
  }
257
+ function measureConversionOperation(timings, stage, operation) {
258
+ if (!timings) return operation();
259
+ const started = performance.now();
260
+ return (async () => {
261
+ try {
262
+ return await operation();
263
+ } finally {
264
+ timings[stage] += Math.max(0, performance.now() - started);
265
+ }
266
+ })();
267
+ }
268
+ function measureConversionIterable(iterable, timings, stage) {
269
+ if (!timings) return iterable;
270
+ return {
271
+ [Symbol.asyncIterator]() {
272
+ const iterator = iterable[Symbol.asyncIterator]();
273
+ return {
274
+ next: async () => measureConversionOperation(timings, stage, () => iterator.next()),
275
+ ...iterator.return ? { return: iterator.return.bind(iterator) } : {},
276
+ ...iterator.throw ? { throw: iterator.throw.bind(iterator) } : {}
277
+ };
278
+ }
279
+ };
280
+ }
222
281
 
223
282
  // src/v5/browser-source.ts
224
283
  function createBrowserTileConversionSource(options) {
@@ -351,7 +410,7 @@ function throwIfAborted3(signal) {
351
410
  }
352
411
 
353
412
  // src/v5/spatial-conversion.ts
354
- var import_tiles = require("@loaders.gl/tiles");
413
+ var import_tiles_3d = require("@loaders.gl/tiles-3d");
355
414
  var import_core = require("@math.gl/core");
356
415
  function createTiles3DConversionSpatialContext(discovered, options = {}) {
357
416
  const spatialReference = createConversionSpatialReference(discovered, options);
@@ -366,9 +425,9 @@ function createTiles3DConversionSpatialContext(discovered, options = {}) {
366
425
  }
367
426
  const transformer = spatialReference.status === "native" ? void 0 : createSpatialTransformer(
368
427
  spatialReference,
369
- () => new import_tiles.Tiles3DSpatialTransformer(spatialReference, options)
428
+ () => new import_tiles_3d.Tiles3DSpatialTransformer(spatialReference, options)
370
429
  );
371
- const outputSpatialReference = transformer ? (0, import_tiles.markTilesetSpatialReferenceTransformed)(spatialReference) : spatialReference;
430
+ const outputSpatialReference = transformer ? (0, import_tiles_3d.markTilesetSpatialReferenceTransformed)(spatialReference) : spatialReference;
372
431
  return {
373
432
  spatialReference: outputSpatialReference,
374
433
  transformPositions: (positions) => transformer ? transformer.transformPositions(positions) : copyNativePositions(positions),
@@ -389,7 +448,7 @@ function createI3SConversionSpatialContext(discovered, options = {}) {
389
448
  }
390
449
  const transformer = spatialReference.status === "native" ? void 0 : createSpatialTransformer(
391
450
  spatialReference,
392
- () => new import_tiles.I3SSpatialTransformer(spatialReference, options)
451
+ () => new import_tiles_3d.I3SSpatialTransformer(spatialReference, options)
393
452
  );
394
453
  const outputSpatialReference = transformer ? transformer.spatialReference : spatialReference;
395
454
  let nativeNormalTransformer;
@@ -401,7 +460,7 @@ function createI3SConversionSpatialContext(discovered, options = {}) {
401
460
  }
402
461
  nativeNormalTransformer ||= createSpatialTransformer(
403
462
  spatialReference,
404
- () => new import_tiles.I3SSpatialTransformer(
463
+ () => new import_tiles_3d.I3SSpatialTransformer(
405
464
  {
406
465
  ...spatialReference,
407
466
  status: "transformable",
@@ -453,7 +512,7 @@ function createSpatialConversionError(spatialReference, cause) {
453
512
  }
454
513
  function createConversionSpatialReference(discovered, options) {
455
514
  if (!("status" in discovered)) {
456
- return (0, import_tiles.createTilesetSpatialReference)(discovered, options);
515
+ return (0, import_tiles_3d.createTilesetSpatialReference)(discovered, options);
457
516
  }
458
517
  if (discovered.status === "transformed") {
459
518
  throw createSpatialConversionError(
@@ -486,7 +545,7 @@ function createConversionSpatialReference(discovered, options) {
486
545
  targetHeightReference: options.targetHeightReference ?? discovered.targetHeightReference,
487
546
  outputCoordinates: options.outputCoordinates ?? discovered.outputCoordinates
488
547
  };
489
- return (0, import_tiles.createTilesetSpatialReference)(sourceMetadata, retainedOptions);
548
+ return (0, import_tiles_3d.createTilesetSpatialReference)(sourceMetadata, retainedOptions);
490
549
  }
491
550
  function createSpatialTransformer(spatialReference, createTransformer) {
492
551
  try {
@@ -607,7 +666,7 @@ function validateNormalReferenceFrame(frame) {
607
666
  }
608
667
 
609
668
  // src/v5/tileset-source.ts
610
- var import_tiles2 = require("@loaders.gl/tiles");
669
+ var import_tiles_3d2 = require("@loaders.gl/tiles-3d");
611
670
  function createTilesetConversionSource(tileset, options = {}) {
612
671
  return {
613
672
  async inspect(signal) {
@@ -622,7 +681,7 @@ function createTilesetConversionSource(tileset, options = {}) {
622
681
  }
623
682
  return tileset.source.getMetadata();
624
683
  },
625
- read: (_inspection, signal) => (0, import_tiles2.traverseTilesetContents)(tileset, { unloadContent: options.unloadContent, signal })
684
+ read: (_inspection, signal) => (0, import_tiles_3d2.traverseTilesetContents)(tileset, { unloadContent: options.unloadContent, signal })
626
685
  };
627
686
  }
628
687
 
package/dist/v5/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { TileConversionError, inspectTileset, convertTileset, validateTileset } from './conversion-api.js';
2
- export type { TileConversionDiagnostic, TileConversionProgress, TileConversionReport, TileConversionSource, TileConversionSink, TileConversionCodec, ConvertTilesetOptions, ValidateTilesetOptions, TileValidationReport } from './conversion-api.js';
2
+ export type { TileConversionDiagnostic, TileConversionProgress, TileConversionReport, TileConversionTimings, TileConversionSource, TileConversionSink, TileConversionCodec, ConvertTilesetOptions, ValidateTilesetOptions, TileValidationReport } from './conversion-api.js';
3
3
  export { createBrowserTileConversionSource } from './browser-source.js';
4
4
  export type { BrowserTileConversionInspection, BrowserTileConversionInputResource, BrowserTileConversionSourceOptions } from './browser-source.js';
5
5
  export { traversePointCloudSource } from './point-cloud-source.js';
package/dist/v5/core.js CHANGED
@@ -34,6 +34,16 @@ async function convertTileset(options) {
34
34
  signal,
35
35
  onProgress
36
36
  } = options;
37
+ const started = options.profile ? performance.now() : 0;
38
+ const timings = options.profile ? {
39
+ inspectMilliseconds: 0,
40
+ readMilliseconds: 0,
41
+ convertMilliseconds: 0,
42
+ validateMilliseconds: 0,
43
+ writeMilliseconds: 0,
44
+ finalizeMilliseconds: 0,
45
+ totalMilliseconds: 0
46
+ } : void 0;
37
47
  let inputResources = 0;
38
48
  let outputResources = 0;
39
49
  let inputBytes = 0;
@@ -60,8 +70,16 @@ async function convertTileset(options) {
60
70
  }
61
71
  }
62
72
  reportProgress("inspect");
63
- const inspection = await inspectTileset(source, signal);
64
- for await (const inputResource of source.read(inspection, signal)) {
73
+ const inspection = await measureConversionOperation(
74
+ timings,
75
+ "inspectMilliseconds",
76
+ () => inspectTileset(source, signal)
77
+ );
78
+ for await (const inputResource of measureConversionIterable(
79
+ source.read(inspection, signal),
80
+ timings,
81
+ "readMilliseconds"
82
+ )) {
65
83
  throwIfAborted(signal);
66
84
  checkConversionTotal(inputResources, 1, maxInputResources, "INPUT_COUNT_LIMIT_EXCEEDED");
67
85
  const inputResourceBytes = measureInputBytes(inputResource);
@@ -86,12 +104,24 @@ async function convertTileset(options) {
86
104
  inputResources++;
87
105
  inputBytes += inputResourceBytes;
88
106
  reportProgress("convert");
89
- const convertedResources = await codec.convert(inputResource, inspection, signal);
90
- for await (const outputResource of convertedResources) {
107
+ const convertedResources = await measureConversionOperation(
108
+ timings,
109
+ "convertMilliseconds",
110
+ () => codec.convert(inputResource, inspection, signal)
111
+ );
112
+ for await (const outputResource of measureConversionIterable(
113
+ convertedResources,
114
+ timings,
115
+ "convertMilliseconds"
116
+ )) {
91
117
  throwIfAborted(signal);
92
118
  checkConversionTotal(outputResources, 1, maxOutputResources, "OUTPUT_COUNT_LIMIT_EXCEEDED");
93
119
  reportProgress("validate");
94
- const resourceDiagnostics = await codec.validateOutput?.(outputResource, signal) || [];
120
+ const resourceDiagnostics = await measureConversionOperation(
121
+ timings,
122
+ "validateMilliseconds",
123
+ () => codec.validateOutput?.(outputResource, signal)
124
+ ) || [];
95
125
  diagnostics.push(...resourceDiagnostics);
96
126
  const outputResourceBytes = measureOutputBytes(outputResource);
97
127
  if (!Number.isSafeInteger(outputResourceBytes) || outputResourceBytes < 0) {
@@ -120,7 +150,11 @@ async function convertTileset(options) {
120
150
  );
121
151
  }
122
152
  throwIfAborted(signal);
123
- await sink.write(outputResource, signal);
153
+ await measureConversionOperation(
154
+ timings,
155
+ "writeMilliseconds",
156
+ () => sink.write(outputResource, signal)
157
+ );
124
158
  throwIfAborted(signal);
125
159
  largestOutputResourceBytes = Math.max(largestOutputResourceBytes, outputResourceBytes);
126
160
  outputResources++;
@@ -139,8 +173,9 @@ async function convertTileset(options) {
139
173
  };
140
174
  throwIfAborted(signal);
141
175
  reportProgress("finalize");
142
- await sink.finalize(report);
143
- return report;
176
+ await measureConversionOperation(timings, "finalizeMilliseconds", () => sink.finalize(report));
177
+ if (timings) timings.totalMilliseconds = Math.max(0, performance.now() - started);
178
+ return timings ? { ...report, timings } : report;
144
179
  } catch (error) {
145
180
  try {
146
181
  await sink.abort(error);
@@ -181,6 +216,30 @@ function checkConversionTotal(current, increment, limit, code) {
181
216
  );
182
217
  }
183
218
  }
219
+ function measureConversionOperation(timings, stage, operation) {
220
+ if (!timings) return operation();
221
+ const started = performance.now();
222
+ return (async () => {
223
+ try {
224
+ return await operation();
225
+ } finally {
226
+ timings[stage] += Math.max(0, performance.now() - started);
227
+ }
228
+ })();
229
+ }
230
+ function measureConversionIterable(iterable, timings, stage) {
231
+ if (!timings) return iterable;
232
+ return {
233
+ [Symbol.asyncIterator]() {
234
+ const iterator = iterable[Symbol.asyncIterator]();
235
+ return {
236
+ next: async () => measureConversionOperation(timings, stage, () => iterator.next()),
237
+ ...iterator.return ? { return: iterator.return.bind(iterator) } : {},
238
+ ...iterator.throw ? { throw: iterator.throw.bind(iterator) } : {}
239
+ };
240
+ }
241
+ };
242
+ }
184
243
 
185
244
  // src/v5/browser-source.ts
186
245
  function createBrowserTileConversionSource(options) {
@@ -318,7 +377,7 @@ import {
318
377
  I3SSpatialTransformer,
319
378
  markTilesetSpatialReferenceTransformed,
320
379
  Tiles3DSpatialTransformer
321
- } from "@loaders.gl/tiles";
380
+ } from "@loaders.gl/tiles-3d";
322
381
  import { Matrix4 } from "@math.gl/core";
323
382
  function createTiles3DConversionSpatialContext(discovered, options = {}) {
324
383
  const spatialReference = createConversionSpatialReference(discovered, options);
@@ -574,7 +633,7 @@ function validateNormalReferenceFrame(frame) {
574
633
  }
575
634
 
576
635
  // src/v5/tileset-source.ts
577
- import { traverseTilesetContents } from "@loaders.gl/tiles";
636
+ import { traverseTilesetContents } from "@loaders.gl/tiles-3d";
578
637
  function createTilesetConversionSource(tileset, options = {}) {
579
638
  return {
580
639
  async inspect(signal) {
@@ -1,4 +1,4 @@
1
- import type { ArrowTableBatch, Schema } from '@loaders.gl/schema';
1
+ import type { ArrowTableBatch, Schema } from '@loaders.gl/core/schema';
2
2
  /** Feature attributes and source identifier ready for Arrow normalization. */
3
3
  export interface TileFeatureAttributes {
4
4
  /** Stable feature identifier decoded from the source's feature-ID descriptor. */
@@ -1,4 +1,4 @@
1
- import type { EncodedI3SMeshLayer, I3SMeshWriterOptions, I3SDracoLibraryOptions } from '@loaders.gl/i3s';
1
+ import type { EncodedI3SMeshLayer, I3SMeshWriterOptions, I3SDracoLibraryOptions } from '@loaders.gl/tiles-3d/i3s';
2
2
  import type { TileConversionCodec, TileConversionSink } from '@loaders.gl/tile-converter/v5/core';
3
3
  import type { Tiles3DConversionSpatialContext, I3SConversionSpatialContext } from '@loaders.gl/tile-converter/v5/core';
4
4
  import type { MeshSourceResource } from './mesh-source.js';
@@ -1,5 +1,5 @@
1
- import type { I3STileContent, I3SMeshFeatures } from '@loaders.gl/i3s';
2
- import type { TilesetContentTraversalItem, TilesetSourceMetadata } from '@loaders.gl/tiles';
1
+ import type { I3STileContent, I3SMeshFeatures } from '@loaders.gl/tiles-3d/i3s';
2
+ import type { TilesetContentTraversalItem, TilesetSourceMetadata } from '@loaders.gl/tiles-3d';
3
3
  import type { MeshSourceFeatureOptions } from './mesh-source-features.js';
4
4
  import type { MeshTilesetSourceOptions } from './mesh-source.js';
5
5
  /** Explicit mapping of scalar I3S attribute resources and their geometry identifiers. */
@@ -1,4 +1,4 @@
1
- import type { I3STileContent, I3STileHeader } from '@loaders.gl/i3s';
1
+ import type { I3STileContent, I3STileHeader } from '@loaders.gl/tiles-3d/i3s';
2
2
  import type { MeshTilesetSourceOptions } from './mesh-source.js';
3
3
  import type { MeshTileMaterial } from './mesh.js';
4
4
  /** Maps normalized I3S factors and one encoded base-color PNG/JPEG with explicit wrapping. */
@@ -1,5 +1,5 @@
1
- import type { I3STileContent, I3SMeshFeatures } from '@loaders.gl/i3s';
2
- import type { Tileset3D, TilesetSourceMetadata, TilesetContentTraversalItem } from '@loaders.gl/tiles';
1
+ import type { I3STileContent, I3SMeshFeatures } from '@loaders.gl/tiles-3d/i3s';
2
+ import type { Tileset3D, TilesetSourceMetadata, TilesetContentTraversalItem } from '@loaders.gl/tiles-3d';
3
3
  import type { TileConversionSource, TilesetConversionSourceOptions } from '@loaders.gl/tile-converter/v5/core';
4
4
  import type { MeshSourceResource } from './mesh-source.js';
5
5
  import type { MeshTilesetSourceOptions } from './mesh-source.js';
@@ -1,4 +1,4 @@
1
- import type { I3STileHeader, SceneLayer3D } from '@loaders.gl/i3s';
1
+ import type { I3STileHeader, SceneLayer3D } from '@loaders.gl/tiles-3d/i3s';
2
2
  import type { I3SMeshSourceFeatureOptions } from './i3s-mesh-source.js';
3
3
  import type { SelectedMeshSourceOptions } from './selected-mesh-source.js';
4
4
  /** Inspected leaf mesh identity and immutable normalized header. */
@@ -53,14 +53,14 @@ export declare function createSelectedI3SMeshConversionSource(inspection: I3SMes
53
53
  /** Releases each dedicated node runtime before moving on or closing early. */
54
54
  read(): AsyncGenerator<{
55
55
  id: string;
56
- features?: import("@loaders.gl/i3s").I3SMeshFeatures;
56
+ features?: import("@loaders.gl/tiles-3d/i3s").I3SMeshFeatures;
57
57
  sourceLayerType?: "3DObject" | "IntegratedMesh";
58
58
  contentResourceId?: string;
59
59
  contentPrimitive?: {
60
60
  readonly index: number;
61
61
  readonly last: boolean;
62
62
  };
63
- mesh: import("@loaders.gl/schema").MeshGeometry;
63
+ mesh: import("@loaders.gl/core/schema").MeshGeometry;
64
64
  normalReferenceFrame?: "earth-centered" | "vertex-reference-frame";
65
65
  material?: import("./mesh.js").MeshTileMaterial;
66
66
  origin: readonly [number, number, number];
package/dist/v5/index.cjs CHANGED
@@ -23,16 +23,17 @@ __export(index_exports, {
23
23
  TileConversionError: () => import_core.TileConversionError,
24
24
  convertFeatureAttributesToArrowBatches: () => import_adapters.convertFeatureAttributesToArrowBatches,
25
25
  convertPointCloudSource: () => import_adapters4.convertPointCloudSource,
26
- convertPointCloudToPotree: () => import_adapters19.convertPointCloudToPotree,
27
- convertPointCloudToTileset: () => import_adapters16.convertPointCloudToTileset,
26
+ convertPointCloudToPotree: () => import_adapters21.convertPointCloudToPotree,
27
+ convertPointCloudToTileset: () => import_adapters18.convertPointCloudToTileset,
28
28
  convertTileset: () => import_core.convertTileset,
29
+ createCOPCConversionCodec: () => import_adapters17.createCOPCConversionCodec,
29
30
  createI3SConversionSpatialContext: () => import_core3.createI3SConversionSpatialContext,
30
31
  createI3SMeshConversionCodec: () => import_adapters11.createI3SMeshConversionCodec,
31
32
  createI3SMeshSink: () => import_adapters12.createI3SMeshSink,
32
33
  createI3SMeshTilesetConversionSource: () => import_adapters15.createI3SMeshTilesetConversionSource,
33
34
  createManifestBackedTileConversionSink: () => import_core5.createManifestBackedTileConversionSink,
34
35
  createMeshConversionCodec: () => import_adapters6.createMeshConversionCodec,
35
- createMeshSourceFeatureOptions: () => import_adapters18.createMeshSourceFeatureOptions,
36
+ createMeshSourceFeatureOptions: () => import_adapters20.createMeshSourceFeatureOptions,
36
37
  createMeshTilesetConversionSource: () => import_adapters10.createMeshTilesetConversionSource,
37
38
  createPointCloudTilesetSink: () => import_adapters13.createPointCloudTilesetSink,
38
39
  createSingleMeshI3SSink: () => import_adapters11.createSingleMeshI3SSink,
@@ -43,15 +44,17 @@ __export(index_exports, {
43
44
  createTiles3DConversionSpatialContext: () => import_core3.createTiles3DConversionSpatialContext,
44
45
  createTilesetConversionSource: () => import_core2.createTilesetConversionSource,
45
46
  encodeMeshTile: () => import_adapters5.encodeMeshTile,
47
+ encodePointCloudCOPC: () => import_adapters17.encodePointCloudCOPC,
46
48
  encodePointCloudSource: () => import_adapters3.encodePointCloudSource,
47
49
  encodePointCloudSourceTile: () => import_adapters3.encodePointCloudSourceTile,
48
50
  encodePointCloudTile: () => import_adapters2.encodePointCloudTile,
49
51
  encodePointCloudTileWithMetadata: () => import_adapters2.encodePointCloudTileWithMetadata,
50
- encodePotreeArchive: () => import_adapters17.encodePotreeArchive,
52
+ encodePotreeArchive: () => import_adapters19.encodePotreeArchive,
51
53
  encodeTileConversionArchiveInBatches: () => import_adapters8.encodeTileConversionArchiveInBatches,
52
- extractMeshVertices: () => import_adapters17.extractMeshVertices,
54
+ extractMeshVertices: () => import_adapters19.extractMeshVertices,
53
55
  inspectTileset: () => import_core.inspectTileset,
54
- openPointCloudFile: () => import_adapters17.openPointCloudFile,
56
+ mapPointCloudAttributes: () => import_adapters16.mapPointCloudAttributes,
57
+ openPointCloudFile: () => import_adapters19.openPointCloudFile,
55
58
  transformPointCloudSourceTile: () => import_adapters14.transformPointCloudSourceTile,
56
59
  traversePointCloudSource: () => import_core4.traversePointCloudSource,
57
60
  validateTileset: () => import_core.validateTileset
@@ -81,3 +84,5 @@ var import_adapters16 = require("@loaders.gl/tile-converter/v5/adapters");
81
84
  var import_adapters17 = require("@loaders.gl/tile-converter/v5/adapters");
82
85
  var import_adapters18 = require("@loaders.gl/tile-converter/v5/adapters");
83
86
  var import_adapters19 = require("@loaders.gl/tile-converter/v5/adapters");
87
+ var import_adapters20 = require("@loaders.gl/tile-converter/v5/adapters");
88
+ var import_adapters21 = require("@loaders.gl/tile-converter/v5/adapters");
@@ -1,5 +1,5 @@
1
1
  export { convertTileset, inspectTileset, TileConversionError, validateTileset } from '@loaders.gl/tile-converter/v5/core';
2
- export type { ConvertTilesetOptions, TileConversionCodec, TileConversionDiagnostic, TileConversionProgress, TileConversionReport, TileConversionSink, TileConversionSource, TileValidationReport, ValidateTilesetOptions } from '@loaders.gl/tile-converter/v5/core';
2
+ export type { ConvertTilesetOptions, TileConversionCodec, TileConversionDiagnostic, TileConversionProgress, TileConversionReport, TileConversionTimings, TileConversionSink, TileConversionSource, TileValidationReport, ValidateTilesetOptions } from '@loaders.gl/tile-converter/v5/core';
3
3
  export { createTilesetConversionSource } from '@loaders.gl/tile-converter/v5/core';
4
4
  export type { TilesetConversionSourceOptions } from '@loaders.gl/tile-converter/v5/core';
5
5
  export { createI3SConversionSpatialContext, createTiles3DConversionSpatialContext } from '@loaders.gl/tile-converter/v5/core';
@@ -38,6 +38,10 @@ export { transformPointCloudSourceTile } from '@loaders.gl/tile-converter/v5/ada
38
38
  export type { PointCloudSpatialOptions } from '@loaders.gl/tile-converter/v5/adapters';
39
39
  export { createI3SMeshTilesetConversionSource } from '@loaders.gl/tile-converter/v5/adapters';
40
40
  export type { I3SMeshTilesetSourceOptions, I3SMeshSourceFeatureOptions } from '@loaders.gl/tile-converter/v5/adapters';
41
+ export { mapPointCloudAttributes } from '@loaders.gl/tile-converter/v5/adapters';
42
+ export type { PointCloudAttributeMapping, MappedPointCloud } from '@loaders.gl/tile-converter/v5/adapters';
43
+ export { encodePointCloudCOPC, createCOPCConversionCodec } from '@loaders.gl/tile-converter/v5/adapters';
44
+ export type { EncodePointCloudCOPCOptions, EncodedPointCloudCOPC } from '@loaders.gl/tile-converter/v5/adapters';
41
45
  export { convertPointCloudToTileset } from '@loaders.gl/tile-converter/v5/adapters';
42
46
  export type { ConvertPointCloudToTilesetOptions, ConvertedPointCloudTileset } from '@loaders.gl/tile-converter/v5/adapters';
43
47
  export { encodePotreeArchive, openPointCloudFile, extractMeshVertices } from '@loaders.gl/tile-converter/v5/adapters';