@loaders.gl/tile-converter 5.0.0-alpha.1 → 5.0.0-alpha.11

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 (141) hide show
  1. package/LICENSE +14 -3
  2. package/README.md +497 -0
  3. package/dist/converter.min.cjs +210 -282
  4. package/dist/i3s-server/bin/i3s-server.min.cjs +106 -341
  5. package/dist/index.cjs +38586 -0
  6. package/dist/index.js +38557 -0
  7. package/dist/v5/adapters.cjs +3548 -0
  8. package/dist/v5/adapters.d.ts +33 -0
  9. package/dist/v5/adapters.js +3537 -0
  10. package/dist/v5/browser-sink.d.ts +37 -0
  11. package/dist/v5/browser-source.d.ts +38 -0
  12. package/dist/v5/browser-tileset-source.d.ts +70 -0
  13. package/dist/v5/browser.cjs +76 -0
  14. package/dist/v5/browser.d.ts +44 -0
  15. package/dist/v5/browser.js +75 -0
  16. package/dist/v5/conversion-api.d.ts +122 -0
  17. package/dist/v5/conversion-archive.d.ts +32 -0
  18. package/dist/v5/core.cjs +917 -0
  19. package/dist/v5/core.d.ts +16 -0
  20. package/dist/v5/core.js +899 -0
  21. package/dist/v5/feature-arrow.d.ts +36 -0
  22. package/dist/v5/i3s-mesh-conversion.d.ts +32 -0
  23. package/dist/v5/i3s-mesh-sink.d.ts +25 -0
  24. package/dist/v5/i3s-mesh-source-features.d.ts +13 -0
  25. package/dist/v5/i3s-mesh-source-material.d.ts +5 -0
  26. package/dist/v5/i3s-mesh-source.d.ts +30 -0
  27. package/dist/v5/index.cjs +73 -0
  28. package/dist/v5/index.d.ts +40 -0
  29. package/dist/v5/index.js +75 -0
  30. package/dist/v5/mesh-conversion.d.ts +71 -0
  31. package/dist/v5/mesh-draco.d.ts +8 -0
  32. package/dist/v5/mesh-features.d.ts +9 -0
  33. package/dist/v5/mesh-source-features.d.ts +21 -0
  34. package/dist/v5/mesh-source-texture.d.ts +6 -0
  35. package/dist/v5/mesh-source.d.ts +41 -0
  36. package/dist/v5/mesh-tileset-archive.d.ts +18 -0
  37. package/dist/v5/mesh-tileset-sink.d.ts +51 -0
  38. package/dist/v5/mesh.d.ts +86 -0
  39. package/dist/v5/point-cloud-conversion.d.ts +31 -0
  40. package/dist/v5/point-cloud-source-encoder.d.ts +46 -0
  41. package/dist/v5/point-cloud-source.d.ts +25 -0
  42. package/dist/v5/point-cloud-spatial.d.ts +22 -0
  43. package/dist/v5/point-cloud-tileset-sink.d.ts +28 -0
  44. package/dist/v5/point-cloud.d.ts +49 -0
  45. package/dist/v5/resource-fetcher.d.ts +18 -0
  46. package/dist/v5/resource-manifest.d.ts +58 -0
  47. package/dist/v5/spatial-conversion.d.ts +61 -0
  48. package/dist/v5/tileset-source.d.ts +21 -0
  49. package/package.json +52 -26
  50. package/src/common/README.md +5 -0
  51. package/src/index.ts +1 -2
  52. package/src/{3d-tiles-converter → v4/3d-tiles-converter}/3d-tiles-converter.ts +13 -2
  53. package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +124 -0
  54. package/src/{deps-installer → v4/deps-installer}/deps-installer.ts +10 -7
  55. package/src/{i3s-converter → v4/i3s-converter}/helpers/batch-ids-extensions.ts +1 -1
  56. package/src/v4/i3s-converter/helpers/encode-string-attribute.ts +23 -0
  57. package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-converter.ts +30 -55
  58. package/src/{i3s-converter → v4/i3s-converter}/helpers/gltf-attributes.ts +5 -4
  59. package/src/{i3s-converter → v4/i3s-converter}/helpers/load-3d-tiles.ts +5 -9
  60. package/src/{i3s-converter → v4/i3s-converter}/i3s-converter.ts +6 -7
  61. package/src/{i3s-server → v4/i3s-server}/README.md +2 -2
  62. package/src/{i3s-server → v4/i3s-server}/routes/slpk-router.ts +1 -0
  63. package/src/v4/index.ts +2 -0
  64. package/src/{lib → v4/lib}/utils/compress-util.ts +8 -7
  65. package/src/v5/adapters.ts +75 -0
  66. package/src/v5/browser-sink.ts +130 -0
  67. package/src/v5/browser-source.ts +155 -0
  68. package/src/v5/browser-tileset-source.ts +328 -0
  69. package/src/v5/browser.ts +139 -0
  70. package/src/v5/conversion-api.ts +287 -0
  71. package/src/v5/conversion-archive.ts +85 -0
  72. package/src/v5/core.ts +61 -0
  73. package/src/v5/feature-arrow.ts +429 -0
  74. package/src/v5/i3s-mesh-conversion.ts +192 -0
  75. package/src/v5/i3s-mesh-sink.ts +351 -0
  76. package/src/v5/i3s-mesh-source-features.ts +279 -0
  77. package/src/v5/i3s-mesh-source-material.ts +157 -0
  78. package/src/v5/i3s-mesh-source.ts +227 -0
  79. package/src/v5/index.ts +131 -0
  80. package/src/v5/mesh-conversion.ts +230 -0
  81. package/src/v5/mesh-draco.ts +182 -0
  82. package/src/v5/mesh-features.ts +319 -0
  83. package/src/v5/mesh-source-features.ts +263 -0
  84. package/src/v5/mesh-source-texture.ts +169 -0
  85. package/src/v5/mesh-source.ts +422 -0
  86. package/src/v5/mesh-tileset-archive.ts +50 -0
  87. package/src/v5/mesh-tileset-sink.ts +324 -0
  88. package/src/v5/mesh.ts +526 -0
  89. package/src/v5/point-cloud-conversion.ts +88 -0
  90. package/src/v5/point-cloud-source-encoder.ts +116 -0
  91. package/src/v5/point-cloud-source.ts +84 -0
  92. package/src/v5/point-cloud-spatial.ts +280 -0
  93. package/src/v5/point-cloud-tileset-sink.ts +234 -0
  94. package/src/v5/point-cloud.ts +398 -0
  95. package/src/v5/resource-fetcher.ts +110 -0
  96. package/src/v5/resource-manifest.ts +213 -0
  97. package/src/v5/spatial-conversion.ts +389 -0
  98. package/src/v5/tileset-source.ts +54 -0
  99. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/3d-tiles-content-converter.ts +0 -0
  100. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/i3s-obb-to-3d-tiles-obb.ts +0 -0
  101. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/load-i3s.ts +0 -0
  102. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/texture-atlas.ts +0 -0
  103. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/json-templates/tileset.ts +0 -0
  104. /package/src/{constants.ts → v4/constants.ts} +0 -0
  105. /package/src/{converter-cli.ts → v4/converter-cli.ts} +0 -0
  106. /package/src/{i3s-converter → v4/i3s-converter}/helpers/attribute-metadata-info.ts +0 -0
  107. /package/src/{i3s-converter → v4/i3s-converter}/helpers/coordinate-converter.ts +0 -0
  108. /package/src/{i3s-converter → v4/i3s-converter}/helpers/create-scene-server-path.ts +0 -0
  109. /package/src/{i3s-converter → v4/i3s-converter}/helpers/feature-attributes.ts +0 -0
  110. /package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-attributes.ts +0 -0
  111. /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-debug.ts +0 -0
  112. /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-index-document.ts +0 -0
  113. /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-pages.ts +0 -0
  114. /package/src/{i3s-converter → v4/i3s-converter}/helpers/preprocess-3d-tiles.ts +0 -0
  115. /package/src/{i3s-converter → v4/i3s-converter}/helpers/progress.ts +0 -0
  116. /package/src/{i3s-converter → v4/i3s-converter}/helpers/tileset-traversal.ts +0 -0
  117. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/geometry-definitions.ts +0 -0
  118. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/layers.ts +0 -0
  119. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/metadata.ts +0 -0
  120. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/node.ts +0 -0
  121. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/scene-server.ts +0 -0
  122. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/shared-resources.ts +0 -0
  123. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/store.ts +0 -0
  124. /package/src/{i3s-converter → v4/i3s-converter}/types.ts +0 -0
  125. /package/src/{i3s-server → v4/i3s-server}/app.ts +0 -0
  126. /package/src/{i3s-server → v4/i3s-server}/bin/www.ts +0 -0
  127. /package/src/{i3s-server → v4/i3s-server}/certs/cert.pem +0 -0
  128. /package/src/{i3s-server → v4/i3s-server}/certs/key.pem +0 -0
  129. /package/src/{i3s-server → v4/i3s-server}/controllers/slpk-controller.ts +0 -0
  130. /package/src/{i3s-server → v4/i3s-server}/utils/create-scene-server.ts +0 -0
  131. /package/src/{i3s-server → v4/i3s-server}/utils/server-utils.ts +0 -0
  132. /package/src/{lib → v4/lib}/json-schemas/conversion-dump-json-schema.ts +0 -0
  133. /package/src/{lib → v4/lib}/utils/cli-utils.ts +0 -0
  134. /package/src/{lib → v4/lib}/utils/conversion-dump.ts +0 -0
  135. /package/src/{lib → v4/lib}/utils/file-utils.ts +0 -0
  136. /package/src/{lib → v4/lib}/utils/geometry-utils.ts +0 -0
  137. /package/src/{lib → v4/lib}/utils/lod-conversion-utils.ts +0 -0
  138. /package/src/{lib → v4/lib}/utils/queue.ts +0 -0
  139. /package/src/{lib → v4/lib}/utils/statistic-utils.ts +0 -0
  140. /package/src/{lib → v4/lib}/utils/write-queue.ts +0 -0
  141. /package/src/{pgm-loader.ts → v4/pgm-loader.ts} +0 -0
@@ -0,0 +1,157 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {I3STileContent, I3STileHeader} from '@loaders.gl/i3s';
6
+ import type {GLTFMaterialPostprocessed} from '@loaders.gl/gltf';
7
+ import {getBinaryImageMetadata} from '@loaders.gl/images';
8
+ import {TileConversionError} from '@loaders.gl/tile-converter/v5/core';
9
+ import type {MeshTilesetSourceOptions} from './mesh-source.js';
10
+ import {mapMeshSourceMaterial} from './mesh-source.js';
11
+ import type {MeshTileMaterial} from './mesh.js';
12
+
13
+ /** Maps normalized I3S factors and one encoded base-color PNG/JPEG with explicit wrapping. */
14
+ export async function mapI3SMeshSourceMaterial(
15
+ content: I3STileContent,
16
+ header: Partial<I3STileHeader>,
17
+ readExternalResource: MeshTilesetSourceOptions['readExternalResource'],
18
+ contentUri: string | undefined,
19
+ signal?: AbortSignal
20
+ ): Promise<MeshTileMaterial | undefined> {
21
+ const material = Object.fromEntries(
22
+ Object.entries(content.material || {}).filter(([, value]) => value !== undefined)
23
+ );
24
+ const metallicRoughness = material.pbrMetallicRoughness
25
+ ? Object.fromEntries(
26
+ Object.entries(material.pbrMetallicRoughness).filter(([, value]) => value !== undefined)
27
+ )
28
+ : {};
29
+ material.pbrMetallicRoughness = metallicRoughness;
30
+ if (material.cullFace !== undefined && material.cullFace !== 'back') {
31
+ throw new TileConversionError(
32
+ 'I3S_MESH_SOURCE_MATERIAL_UNSUPPORTED',
33
+ 'Only back-face culling is supported'
34
+ );
35
+ }
36
+ delete material.cullFace;
37
+ let textureInfo = metallicRoughness.baseColorTexture
38
+ ? {...(metallicRoughness.baseColorTexture as Record<string, unknown>)}
39
+ : undefined;
40
+ const resources = header.textureUrls?.length
41
+ ? header.textureUrls
42
+ : header.textureUrl
43
+ ? [
44
+ {
45
+ textureSetDefinitionId: textureInfo?.textureSetDefinitionId ?? 0,
46
+ textureUrl: header.textureUrl,
47
+ textureFormat: header.textureFormat || 'jpg'
48
+ }
49
+ ]
50
+ : [];
51
+ // Legacy singleton textures without a material definition are implicit base-color maps.
52
+ if (!textureInfo && !header.materialDefinition && resources.length === 1) {
53
+ textureInfo = {textureSetDefinitionId: resources[0].textureSetDefinitionId};
54
+ }
55
+ const encodedTextures = content.textures || {};
56
+ if (
57
+ !textureInfo &&
58
+ (resources.length || content.texture || Object.keys(encodedTextures).length)
59
+ ) {
60
+ throw new TileConversionError(
61
+ 'I3S_MESH_SOURCE_TEXTURE_UNSUPPORTED',
62
+ 'Texture resources require a base-color mapping'
63
+ );
64
+ }
65
+ if (textureInfo) {
66
+ const definitionId = textureInfo.textureSetDefinitionId;
67
+ const wrappingModes: Record<string, number> = {none: 33071, repeat: 10497, mirror: 33648};
68
+ if (
69
+ typeof definitionId !== 'number' ||
70
+ !Number.isSafeInteger(definitionId) ||
71
+ definitionId < 0 ||
72
+ (textureInfo.texCoord !== undefined && textureInfo.texCoord !== 0) ||
73
+ Object.keys(textureInfo).some(
74
+ name => !['textureSetDefinitionId', 'texCoord', 'wrapS', 'wrapT', 'texture'].includes(name)
75
+ ) ||
76
+ (['wrapS', 'wrapT'] as const).some(
77
+ name =>
78
+ textureInfo![name] !== undefined &&
79
+ (typeof textureInfo![name] !== 'string' ||
80
+ !Object.hasOwn(wrappingModes, textureInfo![name] as string))
81
+ ) ||
82
+ resources.length > 1 ||
83
+ resources.some(resource => resource.textureSetDefinitionId !== definitionId) ||
84
+ Object.keys(encodedTextures).some(key => key !== String(definitionId))
85
+ ) {
86
+ throw new TileConversionError(
87
+ 'I3S_MESH_SOURCE_TEXTURE_UNSUPPORTED',
88
+ 'Only one base-color texture set on TEXCOORD_0 with qualified wrapping is supported'
89
+ );
90
+ }
91
+ let encoded =
92
+ encodedTextures[String(definitionId)] ||
93
+ content.texture ||
94
+ (textureInfo.texture as {source?: {image?: unknown}} | undefined)?.source?.image;
95
+ if (!encoded) {
96
+ if (!resources.length || !readExternalResource) {
97
+ throw new TileConversionError(
98
+ 'I3S_MESH_SOURCE_TEXTURE_UNSUPPORTED',
99
+ 'Encoded texture bytes or an explicit bounded resource reader are required'
100
+ );
101
+ }
102
+ signal?.throwIfAborted();
103
+ encoded = await readExternalResource(resources[0].textureUrl, contentUri, signal);
104
+ signal?.throwIfAborted();
105
+ }
106
+ const data = encoded instanceof ArrayBuffer ? new Uint8Array(encoded) : encoded;
107
+ let image;
108
+ if (data instanceof Uint8Array) {
109
+ try {
110
+ image = getBinaryImageMetadata(new DataView(data.buffer, data.byteOffset, data.byteLength));
111
+ } catch {
112
+ /* Reject malformed or compressed image resources below. */
113
+ }
114
+ }
115
+ const declaredFormat = resources[0]?.textureFormat;
116
+ if (
117
+ !image ||
118
+ !['image/png', 'image/jpeg'].includes(image.mimeType) ||
119
+ (declaredFormat &&
120
+ (declaredFormat === 'png'
121
+ ? image.mimeType !== 'image/png'
122
+ : declaredFormat === 'jpg'
123
+ ? image.mimeType !== 'image/jpeg'
124
+ : true))
125
+ ) {
126
+ throw new TileConversionError(
127
+ 'I3S_MESH_SOURCE_TEXTURE_UNSUPPORTED',
128
+ 'I3S base-color bytes must have matching PNG/JPEG headers'
129
+ );
130
+ }
131
+ const sampler = Object.fromEntries(
132
+ ['wrapS', 'wrapT']
133
+ .filter(name => textureInfo![name] !== undefined)
134
+ .map(name => [name, wrappingModes[textureInfo![name] as string]])
135
+ );
136
+ metallicRoughness.baseColorTexture = {
137
+ texCoord: 0,
138
+ texture: {
139
+ source: {mimeType: image.mimeType, bufferView: {data}},
140
+ ...(Object.keys(sampler).length ? {sampler} : {})
141
+ }
142
+ };
143
+ }
144
+ const mapped = await mapMeshSourceMaterial(
145
+ material as GLTFMaterialPostprocessed,
146
+ undefined,
147
+ contentUri,
148
+ signal
149
+ );
150
+ if (mapped?.baseColorTexture && !content.sourceAttributes?.uv0) {
151
+ throw new TileConversionError(
152
+ 'MESH_TEXCOORD_REQUIRED',
153
+ 'Base-color textures require TEXCOORD_0'
154
+ );
155
+ }
156
+ return mapped;
157
+ }
@@ -0,0 +1,227 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {I3STileContent, I3SMeshFeatures} from '@loaders.gl/i3s';
6
+ import type {
7
+ Tileset3D,
8
+ TilesetSourceMetadata,
9
+ TilesetContentTraversalItem
10
+ } from '@loaders.gl/tiles';
11
+ import {
12
+ TileConversionError,
13
+ createTilesetConversionSource
14
+ } from '@loaders.gl/tile-converter/v5/core';
15
+ import type {
16
+ TileConversionSource,
17
+ TilesetConversionSourceOptions
18
+ } from '@loaders.gl/tile-converter/v5/core';
19
+ import type {MeshSourceResource} from './mesh-source.js';
20
+ import type {MeshTilesetSourceOptions} from './mesh-source.js';
21
+ import {mapI3SMeshSourceMaterial} from './i3s-mesh-source-material.js';
22
+ import {extractI3SMeshFeatures} from './i3s-mesh-source-features.js';
23
+ import type {I3SMeshSourceFeatureOptions} from './i3s-mesh-source-features.js';
24
+ import {validateMeshGeometry} from './mesh.js';
25
+ export type {I3SMeshSourceFeatureOptions} from './i3s-mesh-source-features.js';
26
+
27
+ /** Selected I3S triangle, encoded base-color appearance and explicit-schema feature profile. */
28
+ export interface I3SMeshTilesetSourceOptions extends TilesetConversionSourceOptions {
29
+ /** Read scalar/string attribute resources with an explicit schema and geometry OID mapping. */
30
+ readonly features?: I3SMeshSourceFeatureOptions;
31
+ /** Application-owned bounded reader, including archive resolution, authentication and decompression. */
32
+ readonly readExternalResource?: MeshTilesetSourceOptions['readExternalResource'];
33
+ /** Custom alternative to features, for source semantics outside the scalar resource profile. */
34
+ readonly getFeatures?: (
35
+ content: I3STileContent,
36
+ item: TilesetContentTraversalItem,
37
+ metadata: TilesetSourceMetadata,
38
+ signal?: AbortSignal
39
+ ) => I3SMeshFeatures | Promise<I3SMeshFeatures>;
40
+ }
41
+
42
+ /**
43
+ * Reads original absolute I3S positions through camera-independent traversal.
44
+ * Use a dedicated runtime with i3s.geometryMode='source'. The shared I3S spatial codec owns
45
+ * units, elevation and reprojection; this source never consumes renderer placement matrices.
46
+ * Pair the GLB codec with autoOrigin=true, or select an explicit target origin on the resources.
47
+ * Positions/normals/TEXCOORD_0, basic PBR factors and one encoded PNG/JPEG base-color texture
48
+ * are supported. Vertex colors, UV regions, additional attributes and segmentation fail explicitly.
49
+ * Features require an explicit schema/resource reader or a custom Arrow mapper.
50
+ * Unsafe decoded numeric geometry identifiers are rejected; exact property IDs use bigint.
51
+ * @param tileset - Dedicated I3S runtime using source-coordinate content decoding.
52
+ * @param options - Feature mapping and lifetime policy for content loaded during traversal.
53
+ * @returns A portable source of one absolute mesh per I3S node content.
54
+ */
55
+ export function createI3SMeshTilesetConversionSource(
56
+ tileset: Tileset3D,
57
+ options: I3SMeshTilesetSourceOptions = {}
58
+ ): TileConversionSource<TilesetSourceMetadata, MeshSourceResource> {
59
+ const source = createTilesetConversionSource(tileset, options);
60
+ return {
61
+ /** Validates the layer profile and explicit source decode policy before reading. */
62
+ async inspect(signal) {
63
+ if (options.features && options.getFeatures) {
64
+ throw new TileConversionError(
65
+ 'I3S_MESH_SOURCE_FEATURE_MAPPING_REQUIRED',
66
+ 'Choose explicit resource features or a custom getFeatures mapper, not both'
67
+ );
68
+ }
69
+ const metadata = await source.inspect(signal);
70
+ if (
71
+ metadata.type !== 'I3S' ||
72
+ !['3DObject', 'IntegratedMesh'].includes(metadata.tileset.layerType) ||
73
+ tileset.options.i3s?.geometryMode !== 'source'
74
+ ) {
75
+ throw new TileConversionError(
76
+ 'I3S_MESH_SOURCE_PROFILE_UNSUPPORTED',
77
+ 'I3S mesh extraction requires a 3DObject/IntegratedMesh runtime with geometryMode=source'
78
+ );
79
+ }
80
+ if (!metadata.spatialReference?.sourceCrs) {
81
+ throw new TileConversionError(
82
+ 'I3S_MESH_SOURCE_REFERENCE_REQUIRED',
83
+ 'I3S conversion requires an explicit source CRS'
84
+ );
85
+ }
86
+ return metadata;
87
+ },
88
+ /** Converts each supported content entry before shared traversal releases its buffers. */
89
+ async *read(metadata, signal) {
90
+ for await (const item of source.read(metadata, signal)) {
91
+ for (const entry of item.contents) {
92
+ signal?.throwIfAborted();
93
+ const content = entry.payload as I3STileContent;
94
+ const attributes = content?.sourceAttributes;
95
+ if (
96
+ content?.geometryMode !== 'source' ||
97
+ content.topology !== 'triangle-list' ||
98
+ !attributes ||
99
+ !(attributes.position?.value instanceof Float64Array) ||
100
+ content.spatialReference?.status !== 'native' ||
101
+ (
102
+ [
103
+ 'sourceCrs',
104
+ 'verticalCrs',
105
+ 'axisOrder',
106
+ 'units',
107
+ 'verticalUnitScale',
108
+ 'heightReference',
109
+ 'elevationMode',
110
+ 'elevationOffset',
111
+ 'elevationUnitScale',
112
+ 'coordinateEpoch'
113
+ ] as const
114
+ ).some(
115
+ field =>
116
+ JSON.stringify(content.spatialReference?.[field]) !==
117
+ JSON.stringify(metadata.spatialReference?.[field])
118
+ )
119
+ ) {
120
+ throw new TileConversionError(
121
+ 'I3S_MESH_SOURCE_GEOMETRY_UNSUPPORTED',
122
+ 'I3S extraction requires original source-frame Float64 triangle geometry'
123
+ );
124
+ }
125
+ if (
126
+ !['earth-centered', 'vertex-reference-frame'].includes(
127
+ content.normalReferenceFrame || ''
128
+ ) ||
129
+ content.normalReferenceFrame !==
130
+ (metadata.tileset.store?.normalReferenceFrame || 'earth-centered')
131
+ ) {
132
+ throw new TileConversionError(
133
+ 'I3S_MESH_SOURCE_NORMAL_FRAME_UNSUPPORTED',
134
+ 'Unknown I3S vector basis'
135
+ );
136
+ }
137
+ if (
138
+ content.meshSegmentation ||
139
+ Object.entries(attributes).some(
140
+ ([name, value]) =>
141
+ value && !['position', 'normal', 'uv0', 'id', 'faceRange'].includes(name)
142
+ )
143
+ ) {
144
+ throw new TileConversionError(
145
+ 'I3S_MESH_SOURCE_ATTRIBUTE_UNSUPPORTED',
146
+ 'Only positions, normals, TEXCOORD_0 and explicitly mapped feature associations are supported'
147
+ );
148
+ }
149
+ const hasFeatures =
150
+ content.featureIds.length > 0 ||
151
+ metadata.tileset.fields?.length ||
152
+ metadata.tileset.attributeStorageInfo?.length;
153
+ if (Array.from(content.featureIds).some(value => !Number.isSafeInteger(value))) {
154
+ throw new TileConversionError(
155
+ 'I3S_MESH_SOURCE_FEATURE_ID_UNSUPPORTED',
156
+ 'Decoded numeric feature IDs must be exact safe integers'
157
+ );
158
+ }
159
+ if (hasFeatures && !options.getFeatures && !options.features) {
160
+ throw new TileConversionError(
161
+ 'I3S_MESH_SOURCE_FEATURE_MAPPING_REQUIRED',
162
+ 'I3S feature data requires explicit resource features or a custom Arrow mapper'
163
+ );
164
+ }
165
+ const mesh = validateMeshGeometry(
166
+ {
167
+ mode: 4,
168
+ topology: 'triangle-list',
169
+ attributes: {
170
+ POSITION: attributes.position,
171
+ ...(attributes.normal ? {NORMAL: attributes.normal} : {}),
172
+ ...(attributes.uv0 ? {TEXCOORD_0: attributes.uv0} : {})
173
+ },
174
+ ...(content.indices ? {indices: {value: content.indices, size: 1}} : {})
175
+ },
176
+ true
177
+ );
178
+ if (mesh.attributes.POSITION.value.length / 3 !== content.vertexCount) {
179
+ throw new TileConversionError(
180
+ 'I3S_MESH_SOURCE_COUNT_INVALID',
181
+ 'I3S vertexCount must match the decoded geometry'
182
+ );
183
+ }
184
+ const features = options.getFeatures
185
+ ? await options.getFeatures(content, item, metadata, signal)
186
+ : options.features
187
+ ? await extractI3SMeshFeatures(
188
+ content,
189
+ item,
190
+ metadata,
191
+ options.features,
192
+ options.readExternalResource,
193
+ entry.uri,
194
+ signal
195
+ )
196
+ : undefined;
197
+ signal?.throwIfAborted();
198
+ if (hasFeatures && !features) {
199
+ throw new TileConversionError(
200
+ 'I3S_MESH_SOURCE_FEATURE_MAPPING_REQUIRED',
201
+ 'The feature mapper must return all declared feature data'
202
+ );
203
+ }
204
+ const mappedMaterial = await mapI3SMeshSourceMaterial(
205
+ content,
206
+ item.tile.header,
207
+ options.readExternalResource,
208
+ entry.uri,
209
+ signal
210
+ );
211
+ signal?.throwIfAborted();
212
+ yield {
213
+ id: `${item.tile.id}/${entry.index}`,
214
+ origin: [0, 0, 0],
215
+ mesh,
216
+ normalReferenceFrame:
217
+ content.normalReferenceFrame === 'vertex-reference-frame'
218
+ ? 'vertex-reference-frame'
219
+ : 'earth-centered',
220
+ features,
221
+ material: mappedMaterial
222
+ };
223
+ }
224
+ }
225
+ }
226
+ };
227
+ }
@@ -0,0 +1,131 @@
1
+ export {
2
+ convertTileset,
3
+ inspectTileset,
4
+ TileConversionError,
5
+ validateTileset
6
+ } from '@loaders.gl/tile-converter/v5/core';
7
+ export type {
8
+ ConvertTilesetOptions,
9
+ TileConversionCodec,
10
+ TileConversionDiagnostic,
11
+ TileConversionProgress,
12
+ TileConversionReport,
13
+ TileConversionSink,
14
+ TileConversionSource,
15
+ TileValidationReport,
16
+ ValidateTilesetOptions
17
+ } from '@loaders.gl/tile-converter/v5/core';
18
+ export {createTilesetConversionSource} from '@loaders.gl/tile-converter/v5/core';
19
+ export type {TilesetConversionSourceOptions} from '@loaders.gl/tile-converter/v5/core';
20
+ export {
21
+ createI3SConversionSpatialContext,
22
+ createTiles3DConversionSpatialContext
23
+ } from '@loaders.gl/tile-converter/v5/core';
24
+ export type {
25
+ I3SConversionSpatialContext,
26
+ Tiles3DConversionSpatialContext
27
+ } from '@loaders.gl/tile-converter/v5/core';
28
+ export {convertFeatureAttributesToArrowBatches} from '@loaders.gl/tile-converter/v5/adapters';
29
+ export type {
30
+ FeatureArrowBatchOptions,
31
+ TileFeatureAttributes
32
+ } from '@loaders.gl/tile-converter/v5/adapters';
33
+ export {
34
+ encodePointCloudTile,
35
+ encodePointCloudTileWithMetadata
36
+ } from '@loaders.gl/tile-converter/v5/adapters';
37
+ export type {
38
+ EncodePointCloudTileOptions,
39
+ EncodedPointCloudTile
40
+ } from '@loaders.gl/tile-converter/v5/adapters';
41
+ export {traversePointCloudSource} from '@loaders.gl/tile-converter/v5/core';
42
+ export type {
43
+ PointCloudSourceTile,
44
+ TraversePointCloudSourceOptions
45
+ } from '@loaders.gl/tile-converter/v5/core';
46
+ export {
47
+ encodePointCloudSource,
48
+ encodePointCloudSourceTile
49
+ } from '@loaders.gl/tile-converter/v5/adapters';
50
+ export type {
51
+ EncodedPointCloudSourceTile,
52
+ EncodePointCloudSourceOptions
53
+ } from '@loaders.gl/tile-converter/v5/adapters';
54
+ export {convertPointCloudSource} from '@loaders.gl/tile-converter/v5/adapters';
55
+ export type {ConvertPointCloudSourceOptions} from '@loaders.gl/tile-converter/v5/adapters';
56
+ export {createManifestBackedTileConversionSink} from '@loaders.gl/tile-converter/v5/core';
57
+ export type {
58
+ ManifestBackedTileConversionSinkOptions,
59
+ TileResourceManifest,
60
+ TileResourceManifestEntry,
61
+ TileResourceManifestStore
62
+ } from '@loaders.gl/tile-converter/v5/core';
63
+ export {encodeMeshTile} from '@loaders.gl/tile-converter/v5/adapters';
64
+ export type {
65
+ MeshTileMaterial,
66
+ MeshTileOptions,
67
+ MeshTileTexture,
68
+ MeshTileSampler,
69
+ MeshTileTextureTransform
70
+ } from '@loaders.gl/tile-converter/v5/adapters';
71
+ export {createMeshConversionCodec} from '@loaders.gl/tile-converter/v5/adapters';
72
+ export type {
73
+ MeshConversionInput,
74
+ EncodedMeshConversionResource,
75
+ MeshConversionCodecOptions
76
+ } from '@loaders.gl/tile-converter/v5/adapters';
77
+ export {createSingleMeshTilesetSink} from '@loaders.gl/tile-converter/v5/adapters';
78
+ export type {
79
+ SingleMeshTilesetSink,
80
+ SingleMeshTilesetSinkOptions
81
+ } from '@loaders.gl/tile-converter/v5/adapters';
82
+
83
+ export {
84
+ createTileConversionArchive,
85
+ encodeTileConversionArchiveInBatches
86
+ } from '@loaders.gl/tile-converter/v5/adapters';
87
+ export type {TileConversionArchiveOptions} from '@loaders.gl/tile-converter/v5/adapters';
88
+ export {createSingleMeshTilesetArchive} from '@loaders.gl/tile-converter/v5/adapters';
89
+ export type {SingleMeshTilesetArchiveOptions} from '@loaders.gl/tile-converter/v5/adapters';
90
+
91
+ export {createMeshTilesetConversionSource} from '@loaders.gl/tile-converter/v5/adapters';
92
+ export type {
93
+ MeshSourceResource,
94
+ MeshTilesetSourceOptions,
95
+ MeshSourceFeatureOptions
96
+ } from '@loaders.gl/tile-converter/v5/adapters';
97
+ export {
98
+ createI3SMeshConversionCodec,
99
+ createSingleMeshI3SSink
100
+ } from '@loaders.gl/tile-converter/v5/adapters';
101
+ export type {
102
+ I3SMeshConversionResource,
103
+ I3SMeshConversionCodecOptions,
104
+ SingleMeshI3SSink
105
+ } from '@loaders.gl/tile-converter/v5/adapters';
106
+
107
+ export {
108
+ createI3SMeshSink,
109
+ createTileConversionResourceFetcher
110
+ } from '@loaders.gl/tile-converter/v5/adapters';
111
+ export type {
112
+ I3SMeshSink,
113
+ I3SMeshSinkOptions,
114
+ TileConversionResourceFetcherOptions,
115
+ MeshTileFeatures
116
+ } from '@loaders.gl/tile-converter/v5/adapters';
117
+
118
+ export {createPointCloudTilesetSink} from '@loaders.gl/tile-converter/v5/adapters';
119
+ export type {
120
+ PointCloudTilesetSink,
121
+ PointCloudTilesetSinkOptions
122
+ } from '@loaders.gl/tile-converter/v5/adapters';
123
+
124
+ export {transformPointCloudSourceTile} from '@loaders.gl/tile-converter/v5/adapters';
125
+ export type {PointCloudSpatialOptions} from '@loaders.gl/tile-converter/v5/adapters';
126
+
127
+ export {createI3SMeshTilesetConversionSource} from '@loaders.gl/tile-converter/v5/adapters';
128
+ export type {
129
+ I3SMeshTilesetSourceOptions,
130
+ I3SMeshSourceFeatureOptions
131
+ } from '@loaders.gl/tile-converter/v5/adapters';