@loaders.gl/tile-converter 4.5.3 → 5.0.0-alpha.10
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 +14 -3
- package/README.md +464 -0
- package/dist/converter.min.cjs +199 -260
- package/dist/i3s-server/bin/i3s-server.min.cjs +106 -341
- package/dist/index.cjs +38482 -0
- package/dist/index.js +38453 -0
- package/dist/v5/adapters.cjs +1992 -0
- package/dist/v5/adapters.d.ts +22 -0
- package/dist/v5/adapters.js +1972 -0
- package/dist/v5/browser-sink.d.ts +37 -0
- package/dist/v5/browser-source.d.ts +38 -0
- package/dist/v5/browser-tileset-source.d.ts +70 -0
- package/dist/v5/browser.cjs +64 -0
- package/dist/v5/browser.d.ts +34 -0
- package/dist/v5/browser.js +57 -0
- package/dist/v5/conversion-api.d.ts +122 -0
- package/dist/v5/conversion-archive.d.ts +32 -0
- package/dist/v5/core.cjs +863 -0
- package/dist/v5/core.d.ts +16 -0
- package/dist/v5/core.js +845 -0
- package/dist/v5/feature-arrow.d.ts +36 -0
- package/dist/v5/i3s-mesh-conversion.d.ts +26 -0
- package/dist/v5/index.cjs +63 -0
- package/dist/v5/index.d.ts +32 -0
- package/dist/v5/index.js +59 -0
- package/dist/v5/mesh-conversion.d.ts +62 -0
- package/dist/v5/mesh-draco.d.ts +8 -0
- package/dist/v5/mesh-source-features.d.ts +21 -0
- package/dist/v5/mesh-source-texture.d.ts +4 -0
- package/dist/v5/mesh-source.d.ts +34 -0
- package/dist/v5/mesh-tileset-archive.d.ts +18 -0
- package/dist/v5/mesh-tileset-sink.d.ts +51 -0
- package/dist/v5/mesh.d.ts +81 -0
- package/dist/v5/point-cloud-conversion.d.ts +31 -0
- package/dist/v5/point-cloud-source-encoder.d.ts +49 -0
- package/dist/v5/point-cloud-source.d.ts +25 -0
- package/dist/v5/point-cloud.d.ts +24 -0
- package/dist/v5/resource-manifest.d.ts +58 -0
- package/dist/v5/spatial-conversion.d.ts +59 -0
- package/dist/v5/tileset-source.d.ts +21 -0
- package/package.json +53 -27
- package/src/common/README.md +5 -0
- package/src/index.ts +1 -2
- package/src/{3d-tiles-converter → v4/3d-tiles-converter}/3d-tiles-converter.ts +14 -3
- package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/3d-tiles-content-converter.ts +2 -2
- package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +124 -0
- package/src/{3d-tiles-converter → v4/3d-tiles-converter}/json-templates/tileset.ts +4 -4
- package/src/{converter-cli.ts → v4/converter-cli.ts} +4 -4
- package/src/{deps-installer → v4/deps-installer}/deps-installer.ts +10 -7
- package/src/{i3s-converter → v4/i3s-converter}/helpers/attribute-metadata-info.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/helpers/batch-ids-extensions.ts +1 -1
- package/src/v4/i3s-converter/helpers/encode-string-attribute.ts +23 -0
- package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-attributes.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-converter.ts +34 -59
- package/src/{i3s-converter → v4/i3s-converter}/helpers/gltf-attributes.ts +7 -6
- package/src/{i3s-converter → v4/i3s-converter}/helpers/load-3d-tiles.ts +5 -9
- package/src/{i3s-converter → v4/i3s-converter}/helpers/node-debug.ts +5 -6
- package/src/{i3s-converter → v4/i3s-converter}/i3s-converter.ts +16 -19
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/geometry-definitions.ts +4 -4
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/layers.ts +6 -6
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/node.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/scene-server.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/shared-resources.ts +1 -1
- package/src/{i3s-converter → v4/i3s-converter}/json-templates/store.ts +1 -1
- package/src/{i3s-server → v4/i3s-server}/README.md +2 -2
- package/src/{i3s-server → v4/i3s-server}/controllers/slpk-controller.ts +1 -1
- package/src/{i3s-server → v4/i3s-server}/routes/slpk-router.ts +2 -1
- package/src/v4/index.ts +2 -0
- package/src/{lib → v4/lib}/utils/compress-util.ts +8 -7
- package/src/{lib → v4/lib}/utils/conversion-dump.ts +4 -4
- package/src/{lib → v4/lib}/utils/file-utils.ts +2 -2
- package/src/{lib → v4/lib}/utils/lod-conversion-utils.ts +2 -4
- package/src/v5/adapters.ts +56 -0
- package/src/v5/browser-sink.ts +130 -0
- package/src/v5/browser-source.ts +155 -0
- package/src/v5/browser-tileset-source.ts +328 -0
- package/src/v5/browser.ts +105 -0
- package/src/v5/conversion-api.ts +287 -0
- package/src/v5/conversion-archive.ts +85 -0
- package/src/v5/core.ts +61 -0
- package/src/v5/feature-arrow.ts +429 -0
- package/src/v5/i3s-mesh-conversion.ts +152 -0
- package/src/v5/index.ts +99 -0
- package/src/v5/mesh-conversion.ts +200 -0
- package/src/v5/mesh-draco.ts +138 -0
- package/src/v5/mesh-source-features.ts +232 -0
- package/src/v5/mesh-source-texture.ts +122 -0
- package/src/v5/mesh-source.ts +360 -0
- package/src/v5/mesh-tileset-archive.ts +50 -0
- package/src/v5/mesh-tileset-sink.ts +324 -0
- package/src/v5/mesh.ts +517 -0
- package/src/v5/point-cloud-conversion.ts +80 -0
- package/src/v5/point-cloud-source-encoder.ts +105 -0
- package/src/v5/point-cloud-source.ts +84 -0
- package/src/v5/point-cloud.ts +271 -0
- package/src/v5/resource-manifest.ts +213 -0
- package/src/v5/spatial-conversion.ts +305 -0
- package/src/v5/tileset-source.ts +54 -0
- /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/i3s-obb-to-3d-tiles-obb.ts +0 -0
- /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/load-i3s.ts +0 -0
- /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/texture-atlas.ts +0 -0
- /package/src/{constants.ts → v4/constants.ts} +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/coordinate-converter.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/create-scene-server-path.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/feature-attributes.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-index-document.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-pages.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/preprocess-3d-tiles.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/progress.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/helpers/tileset-traversal.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/json-templates/metadata.ts +0 -0
- /package/src/{i3s-converter → v4/i3s-converter}/types.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/app.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/bin/www.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/certs/cert.pem +0 -0
- /package/src/{i3s-server → v4/i3s-server}/certs/key.pem +0 -0
- /package/src/{i3s-server → v4/i3s-server}/utils/create-scene-server.ts +0 -0
- /package/src/{i3s-server → v4/i3s-server}/utils/server-utils.ts +0 -0
- /package/src/{lib → v4/lib}/json-schemas/conversion-dump-json-schema.ts +0 -0
- /package/src/{lib → v4/lib}/utils/cli-utils.ts +0 -0
- /package/src/{lib → v4/lib}/utils/geometry-utils.ts +0 -0
- /package/src/{lib → v4/lib}/utils/queue.ts +0 -0
- /package/src/{lib → v4/lib}/utils/statistic-utils.ts +0 -0
- /package/src/{lib → v4/lib}/utils/write-queue.ts +0 -0
- /package/src/{pgm-loader.ts → v4/pgm-loader.ts} +0 -0
package/LICENSE
CHANGED
|
@@ -24,8 +24,20 @@ THE SOFTWARE.
|
|
|
24
24
|
|
|
25
25
|
Copyright (c) 2015 Uber Technologies, Inc.
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
Portions of modules/images/src/lib/category-api/binary-image-api.ts are based on
|
|
28
|
+
binary-gltf-utils (https://github.com/Qantas94Heavy/binary-gltf-utils) under the
|
|
29
|
+
MIT License reproduced above.
|
|
30
|
+
|
|
31
|
+
Copyright (c) 2016-17 Karl Cheng
|
|
32
|
+
|
|
33
|
+
Portions of modules/schema-utils/src/lib/utils/async-queue.ts are adapted from
|
|
34
|
+
async-iter-demo (https://github.com/rauschma/async-iter-demo) under the MIT
|
|
35
|
+
License reproduced above.
|
|
36
|
+
|
|
37
|
+
Copyright (c) 2016 Axel Rauschmayer
|
|
38
|
+
|
|
39
|
+
loaders.gl includes certain files from Cesium (https://github.com/CesiumGS/cesium)
|
|
40
|
+
under the Apache 2.0 License, including files in modules/3d-tiles.
|
|
29
41
|
|
|
30
42
|
Copyright 2011-2018 CesiumJS Contributors
|
|
31
43
|
|
|
@@ -38,4 +50,3 @@ Unless required by applicable law or agreed to in writing, software
|
|
|
38
50
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
39
51
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
40
52
|
See the License for the specific language governing permissions and limitations under the License.
|
|
41
|
-
|
package/README.md
CHANGED
|
@@ -6,8 +6,472 @@ This module contains command line scripts and JavaScript APIs for converting bet
|
|
|
6
6
|
|
|
7
7
|
For documentation please visit the [website](https://loaders.gl).
|
|
8
8
|
|
|
9
|
+
## Source layout
|
|
10
|
+
|
|
11
|
+
The original converter implementation lives in `src/v4`, and the newer conversion APIs live in
|
|
12
|
+
`src/v5`. The package root remains the compatibility entrypoint for the original converter. Shared
|
|
13
|
+
implementation belongs in `src/common` only when it is intentionally used by multiple versions.
|
|
14
|
+
|
|
15
|
+
## Portable core and format adapters
|
|
16
|
+
|
|
17
|
+
The v5 implementation is split into two entrypoints inside this application:
|
|
18
|
+
|
|
19
|
+
- `@loaders.gl/tile-converter/v5/core`: portable conversion orchestration, source traversal,
|
|
20
|
+
spatial preparation and bounded Blob or manifest-backed sinks.
|
|
21
|
+
- `@loaders.gl/tile-converter/v5/adapters`: format encoders, source mesh extraction,
|
|
22
|
+
Arrow feature mapping, output packaging and archive helpers.
|
|
23
|
+
|
|
24
|
+
The existing `/v5` and `/v5/browser` imports remain compatible. The adapters consume the
|
|
25
|
+
same core functions, types and error class. No implementation or dependencies move into
|
|
26
|
+
other packages; CLI and v4 code are unchanged. Applications supply platform I/O adapters.
|
|
27
|
+
|
|
28
|
+
## V5 source-backed mesh traversal
|
|
29
|
+
|
|
30
|
+
`createTilesetConversionSource(tileset)` adapts an initializing or initialized `Tileset3D` backed
|
|
31
|
+
by `Tiles3DSource`, `I3SSource`, or a compatible archive source to the v5 conversion core. Inspection
|
|
32
|
+
returns normalized source metadata after initialization. Reading delegates to shared
|
|
33
|
+
camera-independent traversal and yields one placement with all its ordered decoded content entries,
|
|
34
|
+
including empty placements. A codec can inspect each content's payload, feature descriptors and
|
|
35
|
+
bounds together with the tile's placement transform.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import {createTilesetConversionSource, convertTileset} from '@loaders.gl/tile-converter/v5';
|
|
39
|
+
|
|
40
|
+
const report = await convertTileset({
|
|
41
|
+
source: createTilesetConversionSource(tileset, {unloadContent: true}),
|
|
42
|
+
codec: meshCodec,
|
|
43
|
+
sink: outputSink,
|
|
44
|
+
measureInputBytes: measureDecodedTileBytes,
|
|
45
|
+
measureOutputBytes: measureEncodedResourceBytes,
|
|
46
|
+
maxInputResourceBytes: 16 * 1024 * 1024,
|
|
47
|
+
signal: abortController.signal
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Writes are awaited by the core before traversal advances. The example uses a runtime dedicated to
|
|
52
|
+
conversion and enables `unloadContent` to release newly loaded payloads after their codec and writes
|
|
53
|
+
finish. Cleanup also runs when iteration closes on failure or cancellation, including rejection by
|
|
54
|
+
the input-size gate. Consume payloads before advancing; codecs and sinks must not retain them after
|
|
55
|
+
their work completes. Preloaded payloads are retained. Omit the option to keep all loaded content
|
|
56
|
+
attached, as before. Applications still own tileset destruction and source/archive lifetimes.
|
|
57
|
+
With `Tiles3DSource`, repeated reads reuse installed nested roots and descendants while reloading
|
|
58
|
+
their payloads. Separate content slots and parent placements retain their own nested roots even
|
|
59
|
+
when they reference the same resource URL.
|
|
60
|
+
|
|
61
|
+
This adapter does not bound aggregate input memory, apply CRS transforms, or supply a mesh codec
|
|
62
|
+
or output packaging. Inspection observes
|
|
63
|
+
cancellation before and after initialization; initialization and in-flight content reads retain the
|
|
64
|
+
underlying source's cancellation behavior.
|
|
65
|
+
|
|
66
|
+
`maxInputResourceBytes` limits one decoded input placement before the codec runs. The example
|
|
67
|
+
allows up to 16 MiB as measured by the application's `measureInputBytes` callback, which must return
|
|
68
|
+
a nonnegative safe integer and account for all decoded contents in the placement. Equality is
|
|
69
|
+
allowed; zero permits only empty inputs. Omit the limit or use `Infinity` for no limit. Oversized
|
|
70
|
+
inputs throw `INPUT_RESOURCE_TOO_LARGE`, close source iteration, and abort the destination.
|
|
71
|
+
This check runs after the source read, so decoding allocations and retained source content still
|
|
72
|
+
require source-level controls. `convertPointCloudSource` accepts the same option for decoded tiles.
|
|
73
|
+
|
|
74
|
+
## V5 single mesh encoding
|
|
75
|
+
|
|
76
|
+
`encodeMeshTile(mesh, {material})` is available from both `/v5` and `/v5/browser`. It encodes one
|
|
77
|
+
triangle-list `MeshGeometry` (`mode: 4`) into a self-contained glTF 2.0 GLB.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import {encodeMeshTile} from '@loaders.gl/tile-converter/v5/browser';
|
|
81
|
+
|
|
82
|
+
const glb = encodeMeshTile({
|
|
83
|
+
topology: 'triangle-list',
|
|
84
|
+
mode: 4,
|
|
85
|
+
attributes: {
|
|
86
|
+
POSITION: {value: new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]), size: 3}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The initial profile accepts finite packed Float32 `POSITION` and optional `NORMAL` xyz
|
|
92
|
+
triples. Normals must have unit length within 0.0001 and match the vertex count. Optional
|
|
93
|
+
indices are packed Uint8, Uint16, or Uint32 scalars forming complete triangles, referencing
|
|
94
|
+
existing vertices and excluding each type's maximum primitive-restart value. Typed array
|
|
95
|
+
subviews are supported; descriptor offsets/strides and encoded transforms
|
|
96
|
+
are rejected. Normalization is supported only for the selected integer colors and UVs below. Other attributes fail with typed diagnostics instead of disappearing.
|
|
97
|
+
|
|
98
|
+
The encoder preserves coordinates and does not mutate input arrays. Callers select a local
|
|
99
|
+
coordinate frame and own CRS conversion, double-precision origins, placement, source
|
|
100
|
+
material mapping, feature mappings, and tileset packaging. This geometry helper does not extract an entire
|
|
101
|
+
source scene or preserve its metadata and appearance automatically.
|
|
102
|
+
|
|
103
|
+
### Selected appearance
|
|
104
|
+
|
|
105
|
+
Optional `COLOR_0` contains packed Float32 linear RGB (`size: 3`) or RGBA (`size: 4`)
|
|
106
|
+
values in [0, 1], or packed `Uint8Array`/`Uint16Array` values with `normalized: true`, one per
|
|
107
|
+
position. Integer colors represent linear values divided by 255 or 65535, including alpha;
|
|
108
|
+
no sRGB conversion is performed. Component types, normalization, and subview values are preserved.
|
|
109
|
+
Other color sets remain unsupported.
|
|
110
|
+
|
|
111
|
+
One optional `MeshTileMaterial` applies to every triangle:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const glb = encodeMeshTile(mesh, {
|
|
115
|
+
material: {
|
|
116
|
+
baseColorFactor: [0.8, 0.5, 0.2, 0.75],
|
|
117
|
+
metallicFactor: 0,
|
|
118
|
+
roughnessFactor: 1,
|
|
119
|
+
alphaMode: 'BLEND',
|
|
120
|
+
doubleSided: true
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Base color is a linear RGBA multiplier in [0, 1], multiplied by `COLOR_0` when present.
|
|
126
|
+
Metallic/roughness factors are in [0, 1]. Alpha mode is `OPAQUE`, `MASK`, or `BLEND`;
|
|
127
|
+
finite nonnegative `alphaCutoff` is allowed only with `MASK`. Omitted properties retain
|
|
128
|
+
[glTF defaults](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#materials):
|
|
129
|
+
white base color, metallic/roughness 1, opaque alpha, mask cutoff 0.5, and single-sided rendering.
|
|
130
|
+
No material is added unless explicitly supplied. Unsupported material properties and extensions
|
|
131
|
+
fail with `MESH_MATERIAL_UNSUPPORTED`; invalid values fail with
|
|
132
|
+
`MESH_MATERIAL_INVALID`. Invalid color values/counts/types fail with `MESH_COLOR_INVALID`.
|
|
133
|
+
Inputs are not mutated. Applications explicitly map source colors and materials into this
|
|
134
|
+
subset; other texture maps, multiple materials, and
|
|
135
|
+
feature mappings remain open work.
|
|
136
|
+
|
|
137
|
+
Optional `TEXCOORD_0` contains packed finite Float32 or explicitly normalized Uint8/Uint16
|
|
138
|
+
UV pairs (`size: 2`), one per position. Float32 values outside [0, 1] are allowed for repeating
|
|
139
|
+
textures; integer values represent [0, 1] after division by 255 or 65535. Integer storage requires
|
|
140
|
+
`normalized: true`; signed, Uint32, and normalized floating-point appearance attributes are rejected.
|
|
141
|
+
The glTF writer pads vertex elements to four-byte alignment without changing their values.
|
|
142
|
+
Texture transforms apply to the normalized UV values. A selected `baseColorTexture` requires
|
|
143
|
+
these UVs and embeds an already encoded PNG or JPEG:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const glb = encodeMeshTile(meshWithUvs, {
|
|
147
|
+
material: {
|
|
148
|
+
baseColorTexture: {
|
|
149
|
+
data: encodedImageBytes,
|
|
150
|
+
mimeType: 'image/png',
|
|
151
|
+
sampler: {wrapS: 33071, wrapT: 33071, minFilter: 9729, magFilter: 9729},
|
|
152
|
+
transform: {offset: [0, 1], scale: [1, -1]}
|
|
153
|
+
},
|
|
154
|
+
metallicFactor: 0,
|
|
155
|
+
roughnessFactor: 1
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`MeshTileTexture.data` is a `Uint8Array`; subviews preserve only their selected bytes. The
|
|
161
|
+
encoder checks header MIME type and positive dimensions, then copies the encoded bytes
|
|
162
|
+
without decoding, re-encoding, flipping UVs, or changing the selected sampling controls. Applications
|
|
163
|
+
supply valid encoded image payloads and map source sampling conventions explicitly. Base-color
|
|
164
|
+
images use glTF's sRGB interpretation and multiply the linear material factor and vertex colors.
|
|
165
|
+
Optional `MeshTileSampler` preserves glTF `wrapS`/`wrapT` (33071 clamp-to-edge,
|
|
166
|
+
33648 mirrored-repeat, 10497 repeat), `magFilter` (9728 nearest, 9729 linear), and
|
|
167
|
+
`minFilter` (9728/9729 or mipmap filters 9984–9987). Omitted wrapping uses repeat;
|
|
168
|
+
omitted filters are chosen by the renderer. An omitted sampler emits no sampler resource;
|
|
169
|
+
an explicitly selected `{}` emits an empty sampler using the same defaults. Invalid values
|
|
170
|
+
or malformed selected samplers fail with `MESH_SAMPLER_INVALID`; unsupported sampler
|
|
171
|
+
properties fail with `MESH_SAMPLER_UNSUPPORTED`. Inputs are not mutated. Mipmap filter
|
|
172
|
+
selection does not generate mip levels; source adapters own sampling and image conventions.
|
|
173
|
+
Optional `MeshTileTextureTransform` preserves finite `offset`/`scale` UV pairs and a finite
|
|
174
|
+
counterclockwise `rotation` in radians through
|
|
175
|
+
[KHR_texture_transform](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_transform/README.md).
|
|
176
|
+
The reader applies scale, then rotation about the UV origin, then offset. Omitted controls use
|
|
177
|
+
[0, 0], 0, and [1, 1]; zero/negative scales are supported. An omitted transform adds no extension;
|
|
178
|
+
a selected `{}` adds the default transform. The extension is declared required because no baked
|
|
179
|
+
fallback UV set is generated. UV/image bytes are unchanged and inputs are not mutated.
|
|
180
|
+
Malformed/nonfinite controls fail with `MESH_TEXTURE_TRANSFORM_INVALID`; unsupported properties
|
|
181
|
+
(including a `texCoord` override) fail with `MESH_TEXTURE_TRANSFORM_UNSUPPORTED`.
|
|
182
|
+
Source transform extraction/mapping, external image URLs, other UV sets, and other texture
|
|
183
|
+
extensions remain unsupported.
|
|
184
|
+
Invalid selected UVs fail with `MESH_TEXCOORD_INVALID`, missing UVs with
|
|
185
|
+
`MESH_TEXCOORD_REQUIRED`, and invalid/unsupported image descriptors or headers with
|
|
186
|
+
`MESH_TEXTURE_INVALID`. The spatial mesh codec forwards the same selected UVs, images, sampling, and transforms.
|
|
187
|
+
|
|
188
|
+
## V5 spatial mesh codec
|
|
189
|
+
|
|
190
|
+
`createMeshConversionCodec` connects the mesh encoder to `convertTileset`. Supply
|
|
191
|
+
selected triangle geometries with **absolute source-frame positions**, matching normals, a
|
|
192
|
+
resource ID, an explicit target-frame origin, and an optional selected `material`. Positions
|
|
193
|
+
may be packed Float32 or Float64; the remaining geometry restrictions match `encodeMeshTile`.
|
|
194
|
+
The input byte estimator must include selected image bytes as well as geometry buffers.
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import {
|
|
198
|
+
convertTileset,
|
|
199
|
+
createMeshConversionCodec,
|
|
200
|
+
createTiles3DConversionSpatialContext
|
|
201
|
+
} from '@loaders.gl/tile-converter/v5/browser';
|
|
202
|
+
|
|
203
|
+
const spatialContext = createTiles3DConversionSpatialContext(sourceSpatialReference, {
|
|
204
|
+
targetCrs: 'EPSG:3857'
|
|
205
|
+
});
|
|
206
|
+
const report = await convertTileset({
|
|
207
|
+
source: selectedMeshSource, // Yields {id, mesh, origin, material?}; origin is in the target frame.
|
|
208
|
+
codec: createMeshConversionCodec({spatialContext, maxPositionError: 0.001}),
|
|
209
|
+
sink: meshSink,
|
|
210
|
+
measureInputBytes: measureDecodedMeshBytes,
|
|
211
|
+
measureOutputBytes: resource => resource.glb.byteLength,
|
|
212
|
+
maxInputResourceBytes: 16 * 1024 * 1024,
|
|
213
|
+
maxOutputResourceBytes: 16 * 1024 * 1024,
|
|
214
|
+
signal: abortController.signal
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The codec applies the shared position/normal operations once, subtracts the selected origin
|
|
219
|
+
in double precision, then encodes local Float32 positions. `maxPositionError` is required,
|
|
220
|
+
finite and nonnegative: it limits Euclidean reconstruction error per vertex in **target
|
|
221
|
+
coordinate units** (0.001 meters for EPSG:3857). Equality is allowed; zero requires exact
|
|
222
|
+
reconstruction. Geographic/unknown output frames are rejected. Native coordinates require
|
|
223
|
+
an explicitly declared Cartesian frame in the discovered spatial metadata.
|
|
224
|
+
|
|
225
|
+
Each output contains `{id, glb, origin, boundingBox, localBoundingBox, spatialReference, maximumPositionError}`.
|
|
226
|
+
`localBoundingBox` bounds the actual encoded Float32 positions before adding the origin; use
|
|
227
|
+
it for packaging to avoid precision loss from subtracting large absolute coordinates.
|
|
228
|
+
Accepted rounding is recorded as an informational `MESH_POSITION_ROUNDING` diagnostic in
|
|
229
|
+
the conversion report, with its resource ID and measured error. Bounds describe the
|
|
230
|
+
reconstructed encoded vertices in the target frame, including float32 rounding. Preserve
|
|
231
|
+
this metadata when writing resources: the GLB itself contains local coordinates and does
|
|
232
|
+
not embed its absolute origin or CRS. Source arrays are not mutated. The conversion core
|
|
233
|
+
awaits writes, checks byte limits, reports progress, finalizes on success, and aborts on
|
|
234
|
+
read/codec/write/cancellation failure.
|
|
235
|
+
|
|
236
|
+
Applications still select source geometry, apply source placement and corresponding normal
|
|
237
|
+
transforms before conversion, reconcile format axis conventions, and package hierarchy,
|
|
238
|
+
refinement and geometric error. This increment does not extract complete scenes, convert
|
|
239
|
+
I3S elevation placement, map full source materials/features, or emit a complete tileset.
|
|
240
|
+
|
|
241
|
+
## V5 single-mesh browser package
|
|
242
|
+
|
|
243
|
+
`createSingleMeshTilesetSink` connects the spatial mesh codec to a bounded **3D Tiles 1.1**
|
|
244
|
+
output package. It accepts exactly one unmodified codec output, with resolved **EPSG:4978**
|
|
245
|
+
ECEF xyz coordinates in meters and ellipsoidal heights. The CRS must use the compact string
|
|
246
|
+
`'EPSG:4978'`; other output frames and identifiers are rejected in this initial profile.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import {createSingleMeshTilesetSink} from '@loaders.gl/tile-converter/v5/browser';
|
|
250
|
+
|
|
251
|
+
const meshSink = createSingleMeshTilesetSink({
|
|
252
|
+
maxTotalBytes: 16 * 1024 * 1024,
|
|
253
|
+
geometricError: 0.001 // Meters; include source geometric error and position rounding.
|
|
254
|
+
});
|
|
255
|
+
// Pass meshSink to convertTileset with a mesh codec targeting EPSG:4978.
|
|
256
|
+
// After conversion completes, save both files together in the same directory:
|
|
257
|
+
const files = meshSink.getFiles(); // [{resourceId: 'mesh.glb', blob}, {resourceId: 'tileset.json', blob}]
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The package uses fixed relative names, a single root tile with `REPLACE` refinement, and
|
|
261
|
+
explicit geometric error. The tile transform cancels the standard glTF y-up to z-up rotation
|
|
262
|
+
and adds the ECEF origin; its box encloses encoded local positions in the corresponding tile
|
|
263
|
+
frame. The supplied `geometricError` must be finite, nonnegative, and at least the codec's
|
|
264
|
+
measured reconstruction error. It is the application's responsibility to include source
|
|
265
|
+
LOD or simplification error; the sink does not estimate it.
|
|
266
|
+
|
|
267
|
+
`maxTotalBytes` is captured when the sink is created and includes the GLB and UTF-8 JSON Blob sizes. This bounds **retained output**,
|
|
268
|
+
not peak conversion or serialization memory. Conversion report counts/byte totals describe
|
|
269
|
+
codec resources (one GLB), while this sink retains two files. Files are exposed only after
|
|
270
|
+
successful finalization; failed writes, cancellation, zero/multiple meshes, or conversion
|
|
271
|
+
failure abort and clear the package through the core lifecycle. The sink trusts codec GLB
|
|
272
|
+
and local-bound metadata; applications must not alter them before writing. Download UI,
|
|
273
|
+
workers, multi-tile hierarchy, and source-scene extraction remain separate work.
|
|
274
|
+
|
|
275
|
+
### Download a 3TZ archive
|
|
276
|
+
|
|
277
|
+
`createSingleMeshTilesetArchive` packages the finalized sink's two files into a **3TZ archive**
|
|
278
|
+
with a final `@3dtilesIndex1@` path-hash index. The format writer lives in `@loaders.gl/3d-tiles`,
|
|
279
|
+
uses typed arrays and native Blobs, and needs no filesystem or Node.js Buffer.
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
import {createSingleMeshTilesetArchive} from '@loaders.gl/tile-converter/v5/browser';
|
|
283
|
+
|
|
284
|
+
const archive = await createSingleMeshTilesetArchive(meshSink.getFiles(), {
|
|
285
|
+
maxArchiveBytes: 16 * 1024 * 1024
|
|
286
|
+
});
|
|
287
|
+
const downloadUrl = URL.createObjectURL(archive);
|
|
288
|
+
// Attach downloadUrl to an application-owned link with download="tileset.3tz".
|
|
289
|
+
// When the link is no longer needed:
|
|
290
|
+
URL.revokeObjectURL(downloadUrl);
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The required budget includes all ZIP headers and the index (368 bytes of overhead for this
|
|
294
|
+
fixed two-file profile) and is checked **before either Blob is read**. STORE compression,
|
|
295
|
+
fixed timestamps, stable file order, and relative paths produce deterministic bytes. The
|
|
296
|
+
returned Blob uses `application/vnd.maxar.archive.3tz+zip`; save it with `.3tz`. Inputs must be
|
|
297
|
+
unmodified output from a successfully finalized sink. The budget covers archive size, not
|
|
298
|
+
peak memory: the input Blobs and transient ZIP buffers remain additional allocations.
|
|
299
|
+
Both archive helpers accept an optional `signal` for cooperative cancellation between block
|
|
300
|
+
reads and header encodes. Cancellation rejects with its reason and exposes no partial archive;
|
|
301
|
+
active reads/encodes finish first. The example also terminates its worker for immediate cancellation.
|
|
302
|
+
Packaging reads/copies payloads in blocks of at most 64 KiB, using a checksum pass before each
|
|
303
|
+
populated header and a second pass into the final archive buffer. Caller-owned inputs, index
|
|
304
|
+
metadata, the final archive, and Blob/worker transfer copies still require memory. Total
|
|
305
|
+
peak-memory qualification remains open.
|
|
306
|
+
|
|
307
|
+
### Stream an archive to storage
|
|
308
|
+
|
|
309
|
+
`encodeTileConversionArchiveInBatches` accepts the same finalized files and options as
|
|
310
|
+
`createTileConversionArchive`, and yields byte-identical SLPK/3TZ output without allocating a
|
|
311
|
+
complete archive buffer. Conversion code remains in this application; format layout and encoding
|
|
312
|
+
stay in their owning modules.
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
import {encodeTileConversionArchiveInBatches} from '@loaders.gl/tile-converter/v5/adapters';
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
for await (const chunk of encodeTileConversionArchiveInBatches(sink.getFiles(), {
|
|
319
|
+
format: 'slpk', // or '3tz', with resources authored for that format
|
|
320
|
+
maxArchiveBytes: 32 * 1024 * 1024,
|
|
321
|
+
signal
|
|
322
|
+
})) {
|
|
323
|
+
await destination.write(chunk); // Application-owned storage; respect the byte view.
|
|
324
|
+
}
|
|
325
|
+
await destination.close();
|
|
326
|
+
} catch (error) {
|
|
327
|
+
await destination.abort(error); // Discard partial output; do not publish it as a finished archive.
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The iterator checks every declaration and the full budget on its first pull, before output. It
|
|
333
|
+
emits the next header or payload block only when pulled, so awaiting storage writes supplies
|
|
334
|
+
backpressure within each entry. Returning early prevents further I/O. Callers own storage finalization and discarding partial bytes
|
|
335
|
+
on failure/cancellation. Payload reads/copies are at most 64 KiB: one checksum pass precedes
|
|
336
|
+
each populated header, then output blocks are read on demand. Inputs and index/directory metadata
|
|
337
|
+
remain in memory; this does not cap total decoding/conversion heap usage.
|
|
338
|
+
|
|
339
|
+
The legacy v4 I3S converter already writes **SLPK** archives. Portable v5 SLPK output requires
|
|
340
|
+
an I3S scene-layer writer and its node/resource layout; a 3D Tiles package cannot be saved as
|
|
341
|
+
SLPK merely by changing its extension.
|
|
342
|
+
|
|
343
|
+
## V5 spatial conversion
|
|
344
|
+
|
|
345
|
+
The `@loaders.gl/tile-converter/v5` entrypoint can reuse the CRS and elevation operations from
|
|
346
|
+
`@loaders.gl/tiles` when preparing conversion resources. Discover source metadata with
|
|
347
|
+
`get3DTilesSpatialReference` or `getI3SSpatialReference`, then create the matching conversion
|
|
348
|
+
context with an explicit target CRS or height reference when transformation is required. The
|
|
349
|
+
context provides double-precision positions, transformed normals and conservative bounds, plus the
|
|
350
|
+
spatial reference that belongs in output metadata. Required geoid grids and terrain or scene
|
|
351
|
+
providers are passed by the application; the conversion core does not guess a CRS or fetch spatial
|
|
352
|
+
resources implicitly.
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
import {createI3SConversionSpatialContext} from '@loaders.gl/tile-converter/v5';
|
|
356
|
+
import {getI3SSpatialReference} from '@loaders.gl/tiles';
|
|
357
|
+
|
|
358
|
+
const spatial = createI3SConversionSpatialContext(
|
|
359
|
+
getI3SSpatialReference(layerMetadata),
|
|
360
|
+
{targetCrs: 'EPSG:3857'}
|
|
361
|
+
);
|
|
362
|
+
const transformed = spatial.transformPositions(positions, nodeOrigin);
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## V5 feature attributes
|
|
366
|
+
|
|
367
|
+
`convertFeatureAttributesToArrowBatches` writes decoded feature attributes using an explicit Arrow
|
|
368
|
+
schema. The schema owns property types, nested list/struct mappings, enum representations, and the
|
|
369
|
+
feature ID type. IDs may be strings or exact integer values (`bigint` for values outside JavaScript's
|
|
370
|
+
safe integer range). Unknown properties fail instead of disappearing. Supply a binary
|
|
371
|
+
`rawMetadataField` to retain the original encoded metadata alongside interpreted values. Pass each
|
|
372
|
+
source metadata class separately so its name remains attached to the batch schema.
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
import {convertFeatureAttributesToArrowBatches} from '@loaders.gl/tile-converter/v5';
|
|
376
|
+
|
|
377
|
+
const batches = convertFeatureAttributesToArrowBatches(features, {
|
|
378
|
+
schema: {
|
|
379
|
+
fields: [
|
|
380
|
+
{name: 'feature_id', type: 'int64', nullable: false},
|
|
381
|
+
{name: 'name', type: 'utf8', nullable: true}
|
|
382
|
+
],
|
|
383
|
+
metadata: {}
|
|
384
|
+
},
|
|
385
|
+
batchSize: 65536
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## V5 restartable output sinks
|
|
390
|
+
|
|
391
|
+
`createManifestBackedTileConversionSink` resumes matching resources using caller-provided IDs and
|
|
392
|
+
fingerprints. Applications provide an atomic manifest store and an idempotent resource sink, keeping
|
|
393
|
+
filesystem and archive choices outside the conversion API.
|
|
394
|
+
|
|
395
|
+
## V5 point-cloud sources
|
|
396
|
+
|
|
397
|
+
`traversePointCloudSource` walks an I3S Point Cloud, COPC, or compatible source independently of a
|
|
398
|
+
render camera. It yields each reachable tile's header and decoded Mesh Arrow content in
|
|
399
|
+
depth-first order, retaining source bounds, coordinate-system metadata, and placement information
|
|
400
|
+
for the output encoder. `encodePointCloudSource` streams non-empty PNTS resources, each paired with
|
|
401
|
+
its original header, coordinate system, origin, and transform. `encodePointCloudSourceTile` encodes
|
|
402
|
+
one yielded tile. Set `maxDepth` to bound traversal; pass an `AbortSignal` to stop between source
|
|
403
|
+
operations. These helpers do not transform coordinates or package a tileset manifest.
|
|
404
|
+
|
|
405
|
+
Pass encoder options directly to `encodePointCloudSourceTile`, or select them for each non-empty
|
|
406
|
+
tile with `encodePointCloudSource`'s `getTileEncodingOptions` callback. A declared `rtcCenter` in the
|
|
407
|
+
point-position coordinate frame is subtracted before float32 encoding and stored as PNTS
|
|
408
|
+
`RTC_CENTER`, retaining small offsets in large double-precision coordinates. `batchTableJson`
|
|
409
|
+
supplies properties for existing `BATCH_ID` values. An explicit `constantRGBA` overrides the source
|
|
410
|
+
constant color; the source origin and placement transform remain attached to the encoded tile.
|
|
411
|
+
|
|
412
|
+
The PNTS encoder accepts `POSITION`, `NORMAL`, `BATCH_ID`, and one color attribute (`COLOR_0` or
|
|
413
|
+
`COLOR`). Other attributes, including classification, intensity, and an additional color column,
|
|
414
|
+
raise `POINT_CLOUD_ATTRIBUTE_UNSUPPORTED` rather than silently disappearing. Applications must
|
|
415
|
+
explicitly map unsupported fields to supported batch-table properties or remove them before
|
|
416
|
+
encoding; this initial encoder does not automatically map point attributes.
|
|
417
|
+
|
|
418
|
+
`convertPointCloudSource` connects the same traversal and encoder to a
|
|
419
|
+
`TileConversionSink<EncodedPointCloudSourceTile>`. Writes are awaited before reading the next tile;
|
|
420
|
+
the sink is finalized on success and aborted on failures or cancellation. Set
|
|
421
|
+
`maxOutputResourceBytes` to limit each PNTS resource and use `onProgress` for the shared v5 progress
|
|
422
|
+
report. `maxDepth`, `signal`, and `getTileEncodingOptions` have the same meanings as above.
|
|
423
|
+
Applications provide `measureInputBytes` for decoded input accounting, returning zero for empty
|
|
424
|
+
tiles when appropriate. Reports count visited tile headers as inputs, including empty tiles, and
|
|
425
|
+
encoded PNTS tiles as outputs. Applications own source cleanup and output naming and packaging.
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
import {convertPointCloudSource} from '@loaders.gl/tile-converter/v5';
|
|
429
|
+
|
|
430
|
+
const report = await convertPointCloudSource(pointCloudSource, {
|
|
431
|
+
sink: outputSink,
|
|
432
|
+
measureInputBytes: measureDecodedTileBytes,
|
|
433
|
+
maxOutputResourceBytes: 8 * 1024 * 1024,
|
|
434
|
+
signal: abortController.signal
|
|
435
|
+
});
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## V5 browser entrypoint
|
|
439
|
+
|
|
440
|
+
Import `@loaders.gl/tile-converter/v5/browser` for the portable conversion API,
|
|
441
|
+
`createBrowserTileConversionSource`, `createBrowserTilesetConversionSource`, and
|
|
442
|
+
`createBoundedMemoryTileConversionSink`. The single-resource source reads one URL or Blob. The
|
|
443
|
+
tileset source traverses explicit 3D Tiles 1.0 and 1.1 documents in depth-first order and reads each
|
|
444
|
+
declared content placement under aggregate byte and resource limits. It rejects implicit tiling and
|
|
445
|
+
nested JSON content. Both sources yield raw bytes to an application-provided codec. The sink retains
|
|
446
|
+
named Blob outputs under a required total-byte limit; applications remain responsible for codecs,
|
|
447
|
+
packaging, and triggering downloads.
|
|
448
|
+
|
|
9
449
|
## Installation
|
|
10
450
|
|
|
11
451
|
```bash
|
|
12
452
|
npm install @loaders.gl/tile-converter
|
|
13
453
|
```
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
## V5 partial mesh collections
|
|
457
|
+
|
|
458
|
+
`createMeshTilesetSink` from `@loaders.gl/tile-converter/v5/adapters` packages independent
|
|
459
|
+
`createMeshConversionCodec` outputs as a flat **3D Tiles 1.1** collection. Supply
|
|
460
|
+
`maxTotalBytes`, `maxMeshes`, and a conservative `geometricError` in meters. The ECEF and
|
|
461
|
+
ellipsoidal-height requirements match `createSingleMeshTilesetSink`.
|
|
462
|
+
|
|
463
|
+
Each unique placement gets `meshes/0.glb`, `meshes/1.glb`, etc.; source IDs never become paths.
|
|
464
|
+
A contentless ADD root encloses all encoded leaf bounds, and each leaf retains its own
|
|
465
|
+
transform. The contentless root's geometric error covers the enclosing box diagonal;
|
|
466
|
+
leaf errors retain the supplied source/rounding budget. This keeps exact leaves discoverable
|
|
467
|
+
when their error is zero. Files become visible through `getFiles()` only after successful finalization.
|
|
468
|
+
Duplicate placement IDs, excess meshes, failed writes, cancellation and final-JSON budget
|
|
469
|
+
failures clear output through the conversion core. The byte budget includes GLBs and JSON;
|
|
470
|
+
the mesh count bounds retained hierarchy metadata. Neither bounds peak serialization memory.
|
|
471
|
+
Pass finalized files to `createTileConversionArchive` with `format: '3tz'`.
|
|
472
|
+
|
|
473
|
+
Applications must explicitly select independent leaf representations and preserve source
|
|
474
|
+
error in the supplied budget. This sink does not infer source LOD relationships or retile.
|
|
475
|
+
The [browser example](../../examples/website/i3s-slpk/README.md) demonstrates up to 64
|
|
476
|
+
selected leaf contents, aggregate transport/decoded byte gates, download and incremental
|
|
477
|
+
preview. SLPK still uses the single-mesh sink; multi-node I3S authoring is a separate increment.
|