@loaders.gl/tile-converter 3.2.0-alpha.1 → 3.2.0-alpha.4

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 (203) hide show
  1. package/dist/3d-tiles-attributes-worker.d.ts +28 -0
  2. package/dist/3d-tiles-attributes-worker.d.ts.map +1 -0
  3. package/dist/3d-tiles-attributes-worker.js +4 -0
  4. package/dist/3d-tiles-attributes-worker.js.map +7 -0
  5. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +5 -1
  6. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  7. package/dist/3d-tiles-converter/3d-tiles-converter.js +34 -3
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +5 -4
  9. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
  10. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +10 -10
  11. package/dist/constants.d.ts +2 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +4 -0
  14. package/dist/converter-cli.d.ts +2 -0
  15. package/dist/converter-cli.d.ts.map +1 -0
  16. package/dist/converter-cli.js +232 -0
  17. package/dist/converter.min.js +68 -68
  18. package/dist/deps-installer/deps-installer.d.ts +11 -1
  19. package/dist/deps-installer/deps-installer.d.ts.map +1 -1
  20. package/dist/deps-installer/deps-installer.js +10 -0
  21. package/dist/dist.min.js +910 -790
  22. package/dist/es5/3d-tiles-attributes-worker.js +29 -0
  23. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -0
  24. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +116 -46
  25. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  26. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +21 -23
  27. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  28. package/dist/es5/constants.js +9 -0
  29. package/dist/es5/constants.js.map +1 -0
  30. package/dist/es5/converter-cli.js +306 -0
  31. package/dist/es5/converter-cli.js.map +1 -0
  32. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  33. package/dist/es5/i3s-attributes-worker.js +29 -0
  34. package/dist/es5/i3s-attributes-worker.js.map +1 -0
  35. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +19 -11
  36. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  37. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +2 -2
  38. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  39. package/dist/es5/i3s-converter/helpers/geometry-converter.js +271 -182
  40. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  41. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +71 -0
  42. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  43. package/dist/es5/i3s-converter/helpers/node-pages.js +47 -99
  44. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  45. package/dist/es5/i3s-converter/i3s-converter.js +293 -223
  46. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  47. package/dist/es5/i3s-converter/json-templates/layers.js +29 -0
  48. package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -1
  49. package/dist/es5/index.js +0 -16
  50. package/dist/es5/index.js.map +1 -1
  51. package/dist/es5/lib/utils/compress-util.js +14 -17
  52. package/dist/es5/lib/utils/compress-util.js.map +1 -1
  53. package/dist/es5/lib/utils/file-utils.js +39 -14
  54. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  55. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  56. package/dist/es5/lib/utils/queue.js +61 -0
  57. package/dist/es5/lib/utils/queue.js.map +1 -0
  58. package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
  59. package/dist/es5/lib/utils/write-queue.js +225 -0
  60. package/dist/es5/lib/utils/write-queue.js.map +1 -0
  61. package/dist/es5/pgm-loader.js +1 -1
  62. package/dist/es5/workers/3d-tiles-attributes-worker.js +37 -0
  63. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -0
  64. package/dist/es5/workers/i3s-attributes-worker.js +40 -0
  65. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -0
  66. package/dist/esm/3d-tiles-attributes-worker.js +16 -0
  67. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -0
  68. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +36 -4
  69. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  70. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +16 -18
  71. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  72. package/dist/esm/constants.js +2 -0
  73. package/dist/esm/constants.js.map +1 -0
  74. package/dist/esm/converter-cli.js +230 -0
  75. package/dist/esm/converter-cli.js.map +1 -0
  76. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  77. package/dist/esm/i3s-attributes-worker.js +16 -0
  78. package/dist/esm/i3s-attributes-worker.js.map +1 -0
  79. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +19 -11
  80. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  81. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +2 -2
  82. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  83. package/dist/esm/i3s-converter/helpers/geometry-converter.js +121 -62
  84. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  85. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +54 -0
  86. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  87. package/dist/esm/i3s-converter/helpers/node-pages.js +12 -4
  88. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  89. package/dist/esm/i3s-converter/i3s-converter.js +157 -52
  90. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  91. package/dist/esm/i3s-converter/json-templates/layers.js +25 -0
  92. package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -1
  93. package/dist/esm/index.js +0 -2
  94. package/dist/esm/index.js.map +1 -1
  95. package/dist/esm/lib/utils/compress-util.js +6 -8
  96. package/dist/esm/lib/utils/compress-util.js.map +1 -1
  97. package/dist/esm/lib/utils/file-utils.js +11 -1
  98. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  99. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  100. package/dist/esm/lib/utils/queue.js +19 -0
  101. package/dist/esm/lib/utils/queue.js.map +1 -0
  102. package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
  103. package/dist/esm/lib/utils/write-queue.js +88 -0
  104. package/dist/esm/lib/utils/write-queue.js.map +1 -0
  105. package/dist/esm/pgm-loader.js +1 -1
  106. package/dist/esm/workers/3d-tiles-attributes-worker.js +5 -0
  107. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -0
  108. package/dist/esm/workers/i3s-attributes-worker.js +4 -0
  109. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -0
  110. package/dist/i3s-attributes-worker.d.ts +33 -0
  111. package/dist/i3s-attributes-worker.d.ts.map +1 -0
  112. package/dist/i3s-attributes-worker.js +10 -0
  113. package/dist/i3s-attributes-worker.js.map +7 -0
  114. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +7 -7
  115. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
  116. package/dist/i3s-converter/helpers/coordinate-converter.js +25 -21
  117. package/dist/i3s-converter/helpers/geometry-attributes.d.ts +2 -2
  118. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  119. package/dist/i3s-converter/helpers/geometry-attributes.js +2 -1
  120. package/dist/i3s-converter/helpers/geometry-converter.d.ts +28 -11
  121. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  122. package/dist/i3s-converter/helpers/geometry-converter.js +223 -113
  123. package/dist/i3s-converter/helpers/gltf-attributes.d.ts +9 -0
  124. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -0
  125. package/dist/i3s-converter/helpers/gltf-attributes.js +56 -0
  126. package/dist/i3s-converter/helpers/node-pages.d.ts +6 -5
  127. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  128. package/dist/i3s-converter/helpers/node-pages.js +13 -8
  129. package/dist/i3s-converter/i3s-converter.d.ts +7 -5
  130. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  131. package/dist/i3s-converter/i3s-converter.js +126 -40
  132. package/dist/i3s-converter/json-templates/layers.d.ts +4 -0
  133. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -1
  134. package/dist/i3s-converter/json-templates/layers.js +24 -0
  135. package/dist/i3s-converter/types.d.ts +83 -8
  136. package/dist/i3s-converter/types.d.ts.map +1 -1
  137. package/dist/index.d.ts +0 -2
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +1 -5
  140. package/dist/lib/utils/compress-util.d.ts +44 -5
  141. package/dist/lib/utils/compress-util.d.ts.map +1 -1
  142. package/dist/lib/utils/compress-util.js +73 -6
  143. package/dist/lib/utils/file-utils.d.ts +34 -5
  144. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  145. package/dist/lib/utils/file-utils.js +40 -1
  146. package/dist/lib/utils/lod-conversion-utils.d.ts +25 -4
  147. package/dist/lib/utils/lod-conversion-utils.d.ts.map +1 -1
  148. package/dist/lib/utils/lod-conversion-utils.js +21 -2
  149. package/dist/lib/utils/queue.d.ts +7 -0
  150. package/dist/lib/utils/queue.d.ts.map +1 -0
  151. package/dist/lib/utils/queue.js +18 -0
  152. package/dist/lib/utils/statistic-utills.d.ts +2 -2
  153. package/dist/lib/utils/statistic-utills.d.ts.map +1 -1
  154. package/dist/lib/utils/write-queue.d.ts +22 -0
  155. package/dist/lib/utils/write-queue.d.ts.map +1 -0
  156. package/dist/lib/utils/write-queue.js +62 -0
  157. package/dist/workers/3d-tiles-attributes-worker.d.ts +2 -0
  158. package/dist/workers/3d-tiles-attributes-worker.d.ts.map +1 -0
  159. package/dist/workers/3d-tiles-attributes-worker.js +9 -0
  160. package/dist/workers/i3s-attributes-worker.d.ts +2 -0
  161. package/dist/workers/i3s-attributes-worker.d.ts.map +1 -0
  162. package/dist/workers/i3s-attributes-worker.js +5 -0
  163. package/package.json +23 -18
  164. package/src/3d-tiles-attributes-worker.ts +43 -0
  165. package/src/3d-tiles-converter/3d-tiles-converter.ts +50 -5
  166. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +15 -13
  167. package/src/constants.ts +2 -0
  168. package/src/converter-cli.ts +310 -0
  169. package/src/deps-installer/{deps-installer.js → deps-installer.ts} +11 -1
  170. package/src/i3s-attributes-worker.ts +46 -0
  171. package/src/i3s-converter/helpers/coordinate-converter.ts +29 -24
  172. package/src/i3s-converter/helpers/geometry-attributes.ts +4 -3
  173. package/src/i3s-converter/helpers/{geometry-converter.js → geometry-converter.ts} +425 -179
  174. package/src/i3s-converter/helpers/gltf-attributes.ts +68 -0
  175. package/src/i3s-converter/helpers/node-pages.ts +25 -17
  176. package/src/i3s-converter/i3s-converter.ts +150 -90
  177. package/src/i3s-converter/json-templates/layers.ts +25 -0
  178. package/src/i3s-converter/types.ts +90 -8
  179. package/src/index.ts +0 -4
  180. package/src/lib/utils/{compress-util.js → compress-util.ts} +105 -18
  181. package/src/lib/utils/file-utils.ts +84 -0
  182. package/src/lib/utils/{lod-conversion-utils.js → lod-conversion-utils.ts} +27 -5
  183. package/src/lib/utils/queue.ts +17 -0
  184. package/src/lib/utils/{statistic-utills.js → statistic-utills.ts} +0 -0
  185. package/src/lib/utils/write-queue.ts +75 -0
  186. package/src/workers/3d-tiles-attributes-worker.ts +6 -0
  187. package/src/workers/i3s-attributes-worker.ts +6 -0
  188. package/dist/es5/deps-installer/deps-installer.d.ts +0 -10
  189. package/dist/es5/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  190. package/dist/es5/lib/utils/compress-util.d.ts +0 -53
  191. package/dist/es5/lib/utils/file-utils.d.ts +0 -43
  192. package/dist/es5/lib/utils/lod-conversion-utils.d.ts +0 -32
  193. package/dist/esm/deps-installer/deps-installer.d.ts +0 -10
  194. package/dist/esm/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  195. package/dist/esm/lib/utils/compress-util.d.ts +0 -53
  196. package/dist/esm/lib/utils/file-utils.d.ts +0 -43
  197. package/dist/esm/lib/utils/lod-conversion-utils.d.ts +0 -32
  198. package/src/deps-installer/deps-installer.d.ts +0 -10
  199. package/src/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  200. package/src/lib/utils/compress-util.d.ts +0 -53
  201. package/src/lib/utils/file-utils.d.ts +0 -43
  202. package/src/lib/utils/file-utils.js +0 -38
  203. package/src/lib/utils/lod-conversion-utils.d.ts +0 -32
@@ -0,0 +1,68 @@
1
+ import type {B3DMContent} from '@loaders.gl/3d-tiles';
2
+ import type {Accessor} from 'modules/gltf/src/lib/types/gltf-postprocessed-schema';
3
+ import type {B3DMAttributesData} from '../../i3s-attributes-worker';
4
+
5
+ type AttributesObject = {
6
+ [k: string]: Accessor;
7
+ };
8
+
9
+ /**
10
+ * Keep only values for B3DM attributes to pass data to worker thread.
11
+ * @param attributes
12
+ */
13
+ function getB3DMAttributesWithoutBufferView(attributes: AttributesObject): AttributesObject {
14
+ const attributesWithoutBufferView = {};
15
+
16
+ for (const attributeName in attributes) {
17
+ attributesWithoutBufferView[attributeName] = {
18
+ value: attributes[attributeName].value
19
+ };
20
+ }
21
+
22
+ return attributesWithoutBufferView;
23
+ }
24
+
25
+ /**
26
+ * Prepare attributes for conversion to avoid binary data breaking in worker thread.
27
+ * @param tileContent
28
+ * @returns
29
+ */
30
+ export function prepareDataForAttributesConversion(tileContent: B3DMContent): B3DMAttributesData {
31
+ const gltfMaterials = tileContent.gltf?.materials?.map((material) => ({id: material.id}));
32
+ let nodes =
33
+ tileContent.gltf?.scene?.nodes ||
34
+ tileContent.gltf?.scenes?.[0]?.nodes ||
35
+ tileContent.gltf?.nodes ||
36
+ [];
37
+
38
+ const prepearedNodes = nodes.map((node) => {
39
+ if (!node.mesh) {
40
+ return node;
41
+ }
42
+
43
+ return {
44
+ ...node,
45
+ mesh: {
46
+ ...node.mesh,
47
+ primitives: node.mesh?.primitives.map((primitive) => ({
48
+ ...primitive,
49
+ indices: {value: primitive?.indices?.value},
50
+ attributes: getB3DMAttributesWithoutBufferView(primitive.attributes),
51
+ material: {
52
+ id: primitive?.material?.id
53
+ }
54
+ }))
55
+ }
56
+ };
57
+ });
58
+
59
+ const cartographicOrigin = tileContent.cartographicOrigin;
60
+ const cartesianModelMatrix = tileContent.cartesianModelMatrix;
61
+
62
+ return {
63
+ gltfMaterials,
64
+ nodes: prepearedNodes,
65
+ cartographicOrigin,
66
+ cartesianModelMatrix
67
+ };
68
+ }
@@ -1,7 +1,10 @@
1
+ import type {WriteQueueItem} from '../../lib/utils/write-queue';
2
+
1
3
  import {join} from 'path';
2
4
  import transform from 'json-map-transform';
3
5
  import {METADATA as metadataTemplate} from '../json-templates/metadata';
4
6
  import {NodeInPage} from '@loaders.gl/i3s';
7
+ import WriteQueue from '../../lib/utils/write-queue';
5
8
 
6
9
  // @ts-nocheck
7
10
  /**
@@ -188,35 +191,40 @@ export default class NodePages {
188
191
  /**
189
192
  * Save all the node pages
190
193
  * Run this method when all nodes is pushed in nodePages
191
- * @param {string} layers0Path - path of layer
192
- * @param {Object} fileMap - fileMap which keep info for slpk archive
193
- * @param {boolean} slpk
194
- * @return {promise}
194
+ * @param layers0Path - path of layer
195
+ * @param writeQueue - write queue that controlls files write concurrency
196
+ * @param slpk
195
197
  */
196
- async save(layers0Path: string, fileMap: Object, slpk: boolean = false): Promise<void> {
198
+ async save(
199
+ layers0Path: string,
200
+ writeQueue: WriteQueue<WriteQueueItem>,
201
+ slpk: boolean = false
202
+ ): Promise<void> {
197
203
  if (slpk) {
198
204
  for (const [index, nodePage] of this.nodePages.entries()) {
199
205
  const nodePageStr = JSON.stringify(nodePage);
200
206
  const slpkPath = join(layers0Path, 'nodepages');
201
- fileMap[`nodePages/${index.toString()}.json.gz`] = await this.writeFile(
202
- slpkPath,
203
- nodePageStr,
204
- `${index.toString()}.json`
205
- );
207
+ writeQueue.enqueue({
208
+ archiveKey: `nodePages/${index.toString()}.json.gz`,
209
+ writePromise: this.writeFile(slpkPath, nodePageStr, `${index.toString()}.json`)
210
+ });
206
211
  }
207
212
  const metadata = transform({nodeCount: this.nodesCounter}, metadataTemplate());
208
213
  const compress = false;
209
- fileMap['metadata.json'] = await this.writeFile(
210
- layers0Path,
211
- JSON.stringify(metadata),
212
- 'metadata.json',
213
- compress
214
- );
214
+ writeQueue.enqueue({
215
+ archiveKey: 'metadata.json',
216
+ writePromise: this.writeFile(
217
+ layers0Path,
218
+ JSON.stringify(metadata),
219
+ 'metadata.json',
220
+ compress
221
+ )
222
+ });
215
223
  } else {
216
224
  for (const [index, nodePage] of this.nodePages.entries()) {
217
225
  const nodePageStr = JSON.stringify(nodePage);
218
226
  const nodePagePath = join(layers0Path, 'nodepages', index.toString());
219
- await this.writeFile(nodePagePath, nodePageStr);
227
+ writeQueue.enqueue({writePromise: this.writeFile(nodePagePath, nodePageStr)});
220
228
  }
221
229
  }
222
230
  }
@@ -1,6 +1,6 @@
1
1
  import type {Tile3D, Tileset3DProps} from '@loaders.gl/tiles';
2
2
  import type {BatchTableJson, B3DMContent} from '@loaders.gl/3d-tiles';
3
-
3
+ import type {WriteQueueItem} from '../lib/utils/write-queue';
4
4
  import type {
5
5
  AttributeStorageInfo,
6
6
  SceneLayer3D,
@@ -10,14 +10,13 @@ import type {
10
10
  MaxScreenThresholdSQ,
11
11
  NodeInPage,
12
12
  LodSelection,
13
- SharedResources,
14
13
  Attribute,
15
14
  ESRIField,
16
15
  Field,
17
16
  PopupInfo,
18
17
  FieldInfo
19
18
  } from '@loaders.gl/i3s';
20
- import {load, encode} from '@loaders.gl/core';
19
+ import {load, encode, fetchFile, getLoaderOptions, isBrowser} from '@loaders.gl/core';
21
20
  import {Tileset3D} from '@loaders.gl/tiles';
22
21
  import {CesiumIonLoader, Tiles3DLoader} from '@loaders.gl/3d-tiles';
23
22
  import {Geoid} from '@math.gl/geoid';
@@ -38,7 +37,7 @@ import {calculateFilesSize, timeConverter} from '../lib/utils/statistic-utills';
38
37
  import convertB3dmToI3sGeometry from './helpers/geometry-converter';
39
38
  import {
40
39
  createBoundingVolumes,
41
- convertCommonToI3SExtentCoordinate
40
+ convertBoundingVolumeToI3SFullExtent
42
41
  } from './helpers/coordinate-converter';
43
42
  import {createSceneServerPath} from './helpers/create-scene-server-path';
44
43
  import {convertGeometricErrorToScreenThreshold} from '../lib/utils/lod-conversion-utils';
@@ -49,15 +48,20 @@ import {NODE as nodeTemplate} from './json-templates/node';
49
48
  import {SHARED_RESOURCES as sharedResourcesTemplate} from './json-templates/shared-resources';
50
49
  import {validateNodeBoundingVolumes} from './helpers/node-debug';
51
50
  import TileHeader from '@loaders.gl/tiles/src/tileset/tile-3d';
52
- import {KTX2BasisUniversalTextureWriter} from '@loaders.gl/textures';
51
+ import {KTX2BasisWriterWorker} from '@loaders.gl/textures';
53
52
  import {LoaderWithParser} from '@loaders.gl/loader-utils';
54
53
  import {I3SMaterialDefinition, TextureSetDefinitionFormats} from '@loaders.gl/i3s/src/types';
55
54
  import {ImageWriter} from '@loaders.gl/images';
56
55
  import {GLTFImagePostprocessed} from '@loaders.gl/gltf';
57
- import {I3SConvertedResources} from './types';
56
+ import {I3SConvertedResources, SharedResourcesArrays} from './types';
57
+ import {getWorkerURL, WorkerFarm} from '@loaders.gl/worker-utils';
58
+ import {DracoWriterWorker} from '@loaders.gl/draco';
59
+ import WriteQueue from '../lib/utils/write-queue';
60
+ import {I3SAttributesWorker} from '../i3s-attributes-worker';
61
+ import {BROWSER_ERROR_MESSAGE} from '../constants';
58
62
 
59
63
  const ION_DEFAULT_TOKEN =
60
- process.env.IonToken || // eslint-disable-line
64
+ process.env?.IonToken || // eslint-disable-line
61
65
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlYWMxMzcyYy0zZjJkLTQwODctODNlNi01MDRkZmMzMjIxOWIiLCJpZCI6OTYyMCwic2NvcGVzIjpbImFzbCIsImFzciIsImdjIl0sImlhdCI6MTU2Mjg2NjI3M30.1FNiClUyk00YH_nWfSGpiQAjR5V2OvREDq1PJ5QMjWQ'; // eslint-disable-line
62
66
  const HARDCODED_NODES_PER_PAGE = 64;
63
67
  const _3D_TILES = '3DTILES';
@@ -75,7 +79,6 @@ const CESIUM_DATASET_PREFIX = 'https://';
75
79
  */
76
80
  export default class I3SConverter {
77
81
  nodePages: NodePages;
78
- fileMap: {[key: string]: string};
79
82
  options: any;
80
83
  layers0Path: string;
81
84
  materialMap: Map<any, any>;
@@ -97,10 +100,11 @@ export default class I3SConverter {
97
100
  generateTextures: boolean;
98
101
  generateBoundingVolumes: boolean;
99
102
  layersHasTexture: boolean;
103
+ workerSource: {[key: string]: string} = {};
104
+ writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue();
100
105
 
101
106
  constructor() {
102
107
  this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE);
103
- this.fileMap = {};
104
108
  this.options = {};
105
109
  this.layers0Path = '';
106
110
  this.materialMap = new Map();
@@ -145,9 +149,11 @@ export default class I3SConverter {
145
149
  validate?: boolean;
146
150
  generateTextures?: boolean;
147
151
  generateBoundingVolumes?: boolean;
148
- /** @deprecated */
149
- inputType?: string;
150
152
  }): Promise<any> {
153
+ if (isBrowser) {
154
+ console.log(BROWSER_ERROR_MESSAGE);
155
+ return BROWSER_ERROR_MESSAGE;
156
+ }
151
157
  this.conversionStartTime = process.hrtime();
152
158
  const {
153
159
  tilesetName,
@@ -169,6 +175,9 @@ export default class I3SConverter {
169
175
  this.generateTextures = Boolean(generateTextures);
170
176
  this.generateBoundingVolumes = Boolean(generateBoundingVolumes);
171
177
 
178
+ this.writeQueue = new WriteQueue();
179
+ this.writeQueue.startListening();
180
+
172
181
  console.log('Loading egm file...'); // eslint-disable-line
173
182
  this.geoidHeightModel = await load(egmFilePath, PGMLoader);
174
183
  console.log('Loading egm file completed!'); // eslint-disable-line
@@ -177,19 +186,29 @@ export default class I3SConverter {
177
186
  this.nodePages.useWriteFunction(writeFileForSlpk);
178
187
  }
179
188
 
180
- const preloadOptions = await this._fetchPreloadOptions();
181
- const tilesetOptions: Tileset3DProps = {loadOptions: {basis: {format: 'rgba32'}}};
182
- if (preloadOptions.headers) {
183
- tilesetOptions.loadOptions!.fetch = {headers: preloadOptions.headers};
189
+ await this.loadWorkers();
190
+
191
+ try {
192
+ const preloadOptions = await this._fetchPreloadOptions();
193
+ const tilesetOptions: Tileset3DProps = {loadOptions: {basis: {format: 'rgba32'}}};
194
+ if (preloadOptions.headers) {
195
+ tilesetOptions.loadOptions!.fetch = {headers: preloadOptions.headers};
196
+ }
197
+ Object.assign(tilesetOptions, preloadOptions);
198
+ const sourceTilesetJson = await load(inputUrl, this.Loader, tilesetOptions.loadOptions);
199
+ // console.log(tilesetJson); // eslint-disable-line
200
+ this.sourceTileset = new Tileset3D(sourceTilesetJson, tilesetOptions);
201
+
202
+ await this._createAndSaveTileset(outputPath, tilesetName);
203
+ await this._finishConversion({slpk: Boolean(slpk), outputPath, tilesetName});
204
+ return sourceTilesetJson;
205
+ } catch (error) {
206
+ throw error;
207
+ } finally {
208
+ // Clean up worker pools
209
+ const workerFarm = WorkerFarm.getWorkerFarm({});
210
+ workerFarm.destroy();
184
211
  }
185
- Object.assign(tilesetOptions, preloadOptions);
186
- const sourceTilesetJson = await load(inputUrl, this.Loader, tilesetOptions.loadOptions);
187
- // console.log(tilesetJson); // eslint-disable-line
188
- this.sourceTileset = new Tileset3D(sourceTilesetJson, tilesetOptions);
189
-
190
- await this._createAndSaveTileset(outputPath, tilesetName);
191
- await this._finishConversion({slpk: Boolean(slpk), outputPath, tilesetName});
192
- return sourceTilesetJson;
193
212
  }
194
213
 
195
214
  /**
@@ -239,7 +258,8 @@ export default class I3SConverter {
239
258
  await this._writeLayers0();
240
259
  createSceneServerPath(tilesetName, this.layers0!, tilesetPath);
241
260
  await this._writeNodeIndexDocument(root0, 'root', join(this.layers0Path, 'nodes', 'root'));
242
- await this.nodePages.save(this.layers0Path, this.fileMap, isCreateSlpk);
261
+ await this.nodePages.save(this.layers0Path, this.writeQueue, isCreateSlpk);
262
+ await this.writeQueue.finalize();
243
263
  await this._createSlpk(tilesetPath);
244
264
  }
245
265
 
@@ -248,7 +268,10 @@ export default class I3SConverter {
248
268
  * @param tilesetName - Name of layer
249
269
  */
250
270
  private _formLayers0(tilesetName: string): void {
251
- const extent = convertCommonToI3SExtentCoordinate(this.sourceTileset);
271
+ const fullExtent = convertBoundingVolumeToI3SFullExtent(
272
+ this.sourceTileset?.boundingVolume || this.sourceTileset?.root?.boundingVolume
273
+ );
274
+ const extent = [fullExtent.xmin, fullExtent.ymin, fullExtent.xmax, fullExtent.ymax];
252
275
  const layers0data = {
253
276
  version: `{${uuidv4().toUpperCase()}}`,
254
277
  id: 0,
@@ -261,9 +284,9 @@ export default class I3SConverter {
261
284
  nodePages: {
262
285
  nodesPerPage: HARDCODED_NODES_PER_PAGE
263
286
  },
264
- compressGeometry: this.options.draco
287
+ compressGeometry: this.options.draco,
288
+ fullExtent
265
289
  };
266
-
267
290
  this.layers0 = transform(layers0data, layersTemplate());
268
291
  }
269
292
 
@@ -318,13 +341,16 @@ export default class I3SConverter {
318
341
  const childPath = join(this.layers0Path, 'nodes', child.path!);
319
342
 
320
343
  if (this.options.slpk) {
321
- this.fileMap['nodes/1/3dNodeIndexDocument.json.gz'] = await writeFileForSlpk(
322
- childPath,
323
- JSON.stringify(child),
324
- '3dNodeIndexDocument.json'
325
- );
344
+ this.writeQueue.enqueue({
345
+ archiveKey: 'nodes/1/3dNodeIndexDocument.json.gz',
346
+ writePromise: writeFileForSlpk(
347
+ childPath,
348
+ JSON.stringify(child),
349
+ '3dNodeIndexDocument.json'
350
+ )
351
+ });
326
352
  } else {
327
- await writeFile(childPath, JSON.stringify(child));
353
+ this.writeQueue.enqueue({writePromise: writeFile(childPath, JSON.stringify(child))});
328
354
  }
329
355
  } else {
330
356
  await this._addChildrenWithNeighborsAndWriteFile({
@@ -342,13 +368,18 @@ export default class I3SConverter {
342
368
  */
343
369
  private async _writeLayers0(): Promise<void> {
344
370
  if (this.options.slpk) {
345
- this.fileMap['3dSceneLayer.json.gz'] = await writeFileForSlpk(
346
- this.layers0Path,
347
- JSON.stringify(this.layers0),
348
- '3dSceneLayer.json'
349
- );
371
+ this.writeQueue.enqueue({
372
+ archiveKey: '3dSceneLayer.json.gz',
373
+ writePromise: writeFileForSlpk(
374
+ this.layers0Path,
375
+ JSON.stringify(this.layers0),
376
+ '3dSceneLayer.json'
377
+ )
378
+ });
350
379
  } else {
351
- await writeFile(this.layers0Path, JSON.stringify(this.layers0));
380
+ this.writeQueue.enqueue({
381
+ writePromise: writeFile(this.layers0Path, JSON.stringify(this.layers0))
382
+ });
352
383
  }
353
384
  }
354
385
 
@@ -361,13 +392,12 @@ export default class I3SConverter {
361
392
  rootPath: string
362
393
  ): Promise<void> {
363
394
  if (this.options.slpk) {
364
- this.fileMap[`nodes/${nodePath}/3dNodeIndexDocument.json.gz`] = await writeFileForSlpk(
365
- rootPath,
366
- JSON.stringify(root0),
367
- '3dNodeIndexDocument.json'
368
- );
395
+ this.writeQueue.enqueue({
396
+ archiveKey: `nodes/${nodePath}/3dNodeIndexDocument.json.gz`,
397
+ writePromise: writeFileForSlpk(rootPath, JSON.stringify(root0), '3dNodeIndexDocument.json')
398
+ });
369
399
  } else {
370
- await writeFile(rootPath, JSON.stringify(root0));
400
+ this.writeQueue.enqueue({writePromise: writeFile(rootPath, JSON.stringify(root0))});
371
401
  }
372
402
  }
373
403
 
@@ -384,7 +414,6 @@ export default class I3SConverter {
384
414
  slpkFileName,
385
415
  0,
386
416
  '.',
387
- // @ts-expect-error
388
417
  this.options.sevenZipExe
389
418
  );
390
419
 
@@ -656,7 +685,8 @@ export default class I3SConverter {
656
685
  this.layers0?.attributeStorageInfo,
657
686
  this.options.draco,
658
687
  this.generateBoundingVolumes,
659
- this.geoidHeightModel!
688
+ this.geoidHeightModel!,
689
+ this.workerSource
660
690
  );
661
691
  return resourcesData;
662
692
  }
@@ -806,7 +836,7 @@ export default class I3SConverter {
806
836
  const slpkChildPath = join('nodes', nodePath);
807
837
 
808
838
  await this._writeGeometries(geometryBuffer!, compressedGeometry!, childPath, slpkChildPath);
809
- await this._writeShared(sharedResources!, childPath, slpkChildPath, nodePath);
839
+ await this._writeShared(sharedResources, childPath, slpkChildPath, nodePath);
810
840
  await this._writeTexture(texture, childPath, slpkChildPath);
811
841
  await this._writeAttributes(attributes, childPath, slpkChildPath);
812
842
  }
@@ -820,33 +850,35 @@ export default class I3SConverter {
820
850
  */
821
851
  private async _writeGeometries(
822
852
  geometryBuffer: ArrayBuffer,
823
- compressedGeometry: ArrayBuffer,
853
+ compressedGeometry: Promise<ArrayBuffer>,
824
854
  childPath: string,
825
855
  slpkChildPath: string
826
856
  ): Promise<void> {
827
857
  if (this.options.slpk) {
828
858
  const slpkGeometryPath = join(childPath, 'geometries');
829
- this.fileMap[`${slpkChildPath}/geometries/0.bin.gz`] = await writeFileForSlpk(
830
- slpkGeometryPath,
831
- geometryBuffer,
832
- '0.bin'
833
- );
859
+ this.writeQueue.enqueue({
860
+ archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
861
+ writePromise: writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
862
+ });
834
863
  } else {
835
864
  const geometryPath = join(childPath, 'geometries/0/');
836
- await writeFile(geometryPath, geometryBuffer, 'index.bin');
865
+ this.writeQueue.enqueue({
866
+ writePromise: writeFile(geometryPath, geometryBuffer, 'index.bin')
867
+ });
837
868
  }
838
869
 
839
870
  if (this.options.draco) {
840
871
  if (this.options.slpk) {
841
872
  const slpkCompressedGeometryPath = join(childPath, 'geometries');
842
- this.fileMap[`${slpkChildPath}/geometries/1.bin.gz`] = await writeFileForSlpk(
843
- slpkCompressedGeometryPath,
844
- compressedGeometry,
845
- '1.bin'
846
- );
873
+ this.writeQueue.enqueue({
874
+ archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
875
+ writePromise: writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
876
+ });
847
877
  } else {
848
878
  const compressedGeometryPath = join(childPath, 'geometries/1/');
849
- await writeFile(compressedGeometryPath, compressedGeometry, 'index.bin');
879
+ this.writeQueue.enqueue({
880
+ writePromise: writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
881
+ });
850
882
  }
851
883
  }
852
884
  }
@@ -859,24 +891,26 @@ export default class I3SConverter {
859
891
  * @param nodePath - a node path
860
892
  */
861
893
  private async _writeShared(
862
- sharedResources: SharedResources,
894
+ sharedResources: SharedResourcesArrays | null,
863
895
  childPath: string,
864
896
  slpkChildPath: string,
865
897
  nodePath: string
866
898
  ): Promise<void> {
899
+ if (!sharedResources) {
900
+ return;
901
+ }
867
902
  sharedResources.nodePath = nodePath;
868
903
  const sharedData = transform(sharedResources, sharedResourcesTemplate());
869
904
  const sharedDataStr = JSON.stringify(sharedData);
870
905
  if (this.options.slpk) {
871
906
  const slpkSharedPath = join(childPath, 'shared');
872
- this.fileMap[`${slpkChildPath}/shared/sharedResource.json.gz`] = await writeFileForSlpk(
873
- slpkSharedPath,
874
- sharedDataStr,
875
- 'sharedResource.json'
876
- );
907
+ this.writeQueue.enqueue({
908
+ archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
909
+ writePromise: writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
910
+ });
877
911
  } else {
878
912
  const sharedPath = join(childPath, 'shared/');
879
- await writeFile(sharedPath, sharedDataStr);
913
+ this.writeQueue.enqueue({writePromise: writeFile(sharedPath, sharedDataStr)});
880
914
  }
881
915
  }
882
916
 
@@ -904,9 +938,13 @@ export default class I3SConverter {
904
938
 
905
939
  if (this.generateTextures) {
906
940
  formats.push({name: '1', format: 'ktx2'});
907
- const ktx2TextureData = new Uint8Array(
908
- await encode(texture.image, KTX2BasisUniversalTextureWriter)
909
- );
941
+ const ktx2TextureData = encode(texture.image, KTX2BasisWriterWorker, {
942
+ ...KTX2BasisWriterWorker.options,
943
+ source: this.workerSource.ktx2,
944
+ reuseWorkers: true,
945
+ _nodeWorkers: true
946
+ });
947
+
910
948
  await this.writeTextureFile(ktx2TextureData, '1', 'ktx2', childPath, slpkChildPath);
911
949
  }
912
950
 
@@ -919,9 +957,7 @@ export default class I3SConverter {
919
957
 
920
958
  if (this.generateTextures) {
921
959
  formats.push({name: '0', format: 'jpg'});
922
- const decodedFromKTX2TextureData = new Uint8Array(
923
- await encode(texture.image!.data[0], ImageWriter)
924
- );
960
+ const decodedFromKTX2TextureData = encode(texture.image!.data[0], ImageWriter);
925
961
  await this.writeTextureFile(
926
962
  decodedFromKTX2TextureData,
927
963
  '0',
@@ -948,7 +984,7 @@ export default class I3SConverter {
948
984
  * @param slpkChildPath
949
985
  */
950
986
  private async writeTextureFile(
951
- textureData: ArrayBuffer,
987
+ textureData: Promise<ArrayBuffer>,
952
988
  name: string,
953
989
  format: 'jpg' | 'png' | 'ktx2',
954
990
  childPath: string,
@@ -958,15 +994,15 @@ export default class I3SConverter {
958
994
  const slpkTexturePath = join(childPath, 'textures');
959
995
  const compress = false;
960
996
 
961
- this.fileMap[`${slpkChildPath}/textures/${name}.${format}`] = await writeFileForSlpk(
962
- slpkTexturePath,
963
- textureData,
964
- `${name}.${format}`,
965
- compress
966
- );
997
+ this.writeQueue.enqueue({
998
+ archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
999
+ writePromise: writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
1000
+ });
967
1001
  } else {
968
1002
  const texturePath = join(childPath, `textures/${name}/`);
969
- await writeFile(texturePath, textureData, `index.${format}`);
1003
+ this.writeQueue.enqueue({
1004
+ writePromise: writeFile(texturePath, textureData, `index.${format}`)
1005
+ });
970
1006
  }
971
1007
  }
972
1008
 
@@ -977,25 +1013,26 @@ export default class I3SConverter {
977
1013
  * @param slpkChildPath - the resource path inside *slpk file
978
1014
  */
979
1015
  private async _writeAttributes(
980
- attributes: ArrayBuffer[],
1016
+ attributes: ArrayBuffer[] | null = [],
981
1017
  childPath: string,
982
1018
  slpkChildPath: string
983
1019
  ): Promise<void> {
984
- if (attributes.length && this.layers0?.attributeStorageInfo?.length) {
1020
+ if (attributes?.length && this.layers0?.attributeStorageInfo?.length) {
985
1021
  for (let index = 0; index < attributes.length; index++) {
986
1022
  const folderName = this.layers0.attributeStorageInfo[index].key;
987
1023
  const fileBuffer = new Uint8Array(attributes[index]);
988
1024
 
989
1025
  if (this.options.slpk) {
990
1026
  const slpkAttributesPath = join(childPath, 'attributes', folderName);
991
- this.fileMap[`${slpkChildPath}/attributes/${folderName}.bin.gz`] = await writeFileForSlpk(
992
- slpkAttributesPath,
993
- fileBuffer,
994
- '0.bin'
995
- );
1027
+ this.writeQueue.enqueue({
1028
+ archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
1029
+ writePromise: writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
1030
+ });
996
1031
  } else {
997
1032
  const attributesPath = join(childPath, `attributes/${folderName}/0`);
998
- await writeFile(attributesPath, fileBuffer, 'index.bin');
1033
+ this.writeQueue.enqueue({
1034
+ writePromise: writeFile(attributesPath, fileBuffer, 'index.bin')
1035
+ });
999
1036
  }
1000
1037
  }
1001
1038
  }
@@ -1309,4 +1346,27 @@ export default class I3SConverter {
1309
1346
  private isContentSupported(sourceRootTile: Tile3D): boolean {
1310
1347
  return ['b3dm', 'glTF'].includes(sourceRootTile?.content?.type);
1311
1348
  }
1349
+
1350
+ private async loadWorkers(): Promise<void> {
1351
+ console.log(`Loading workers source...`); // eslint-disable-line no-undef, no-console
1352
+ if (this.options.draco) {
1353
+ const url = getWorkerURL(DracoWriterWorker, {...getLoaderOptions()});
1354
+ const sourceResponse = await fetchFile(url);
1355
+ const source = await sourceResponse.text();
1356
+ this.workerSource.draco = source;
1357
+ }
1358
+
1359
+ if (this.generateTextures) {
1360
+ const url = getWorkerURL(KTX2BasisWriterWorker, {...getLoaderOptions()});
1361
+ const sourceResponse = await fetchFile(url);
1362
+ const source = await sourceResponse.text();
1363
+ this.workerSource.ktx2 = source;
1364
+ }
1365
+
1366
+ const i3sAttributesWorkerUrl = getWorkerURL(I3SAttributesWorker, {...getLoaderOptions()});
1367
+ const sourceResponse = await fetchFile(i3sAttributesWorkerUrl);
1368
+ const source = await sourceResponse.text();
1369
+ this.workerSource.I3SAttributes = source;
1370
+ console.log(`Loading workers source completed!`); // eslint-disable-line no-undef, no-console
1371
+ }
1312
1372
  }
@@ -115,6 +115,27 @@ const NODE_PAGES = () => ({
115
115
  }
116
116
  });
117
117
 
118
+ const FULL_EXTENT = () => ({
119
+ xmin: {
120
+ path: 'xmin'
121
+ },
122
+ ymin: {
123
+ path: 'ymin'
124
+ },
125
+ xmax: {
126
+ path: 'xmax'
127
+ },
128
+ ymax: {
129
+ path: 'ymax'
130
+ },
131
+ zmin: {
132
+ path: 'zmin'
133
+ },
134
+ zmax: {
135
+ path: 'zmax'
136
+ }
137
+ });
138
+
118
139
  export const LAYERS = () => ({
119
140
  version: {
120
141
  path: 'version',
@@ -147,6 +168,10 @@ export const LAYERS = () => ({
147
168
  path: 'store',
148
169
  transform: (val) => transform(val, STORE)
149
170
  },
171
+ fullExtent: {
172
+ path: 'fullExtent',
173
+ transform: (val) => transform(val, FULL_EXTENT())
174
+ },
150
175
  heightModelInfo: {
151
176
  path: 'heightModelInfo',
152
177
  transform: (val) => transform(val, HEIGHT_MODEL_INFO())