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

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 (170) 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 +4 -0
  6. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  7. package/dist/3d-tiles-converter/3d-tiles-converter.js +29 -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/converter.min.js +20 -20
  12. package/dist/dist.min.js +789 -645
  13. package/dist/es5/3d-tiles-attributes-worker.js +29 -0
  14. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -0
  15. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +102 -43
  16. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  17. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +21 -23
  18. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  19. package/dist/es5/i3s-attributes-worker.js +29 -0
  20. package/dist/es5/i3s-attributes-worker.js.map +1 -0
  21. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +19 -11
  22. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  23. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +2 -2
  24. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  25. package/dist/es5/i3s-converter/helpers/geometry-converter.js +267 -178
  26. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  27. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +71 -0
  28. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  29. package/dist/es5/i3s-converter/helpers/node-pages.js +47 -99
  30. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  31. package/dist/es5/i3s-converter/i3s-converter.js +230 -195
  32. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  33. package/dist/es5/index.js +8 -0
  34. package/dist/es5/index.js.map +1 -1
  35. package/dist/es5/lib/utils/compress-util.js +14 -17
  36. package/dist/es5/lib/utils/compress-util.js.map +1 -1
  37. package/dist/es5/lib/utils/file-utils.js +39 -14
  38. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  39. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  40. package/dist/es5/lib/utils/queue.js +61 -0
  41. package/dist/es5/lib/utils/queue.js.map +1 -0
  42. package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
  43. package/dist/es5/lib/utils/write-queue.js +225 -0
  44. package/dist/es5/lib/utils/write-queue.js.map +1 -0
  45. package/dist/es5/pgm-loader.js +1 -1
  46. package/dist/es5/workers/3d-tiles-attributes-worker.js +37 -0
  47. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -0
  48. package/dist/es5/workers/i3s-attributes-worker.js +40 -0
  49. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -0
  50. package/dist/esm/3d-tiles-attributes-worker.js +16 -0
  51. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -0
  52. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +30 -4
  53. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  54. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +16 -18
  55. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  56. package/dist/esm/i3s-attributes-worker.js +16 -0
  57. package/dist/esm/i3s-attributes-worker.js.map +1 -0
  58. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +19 -11
  59. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  60. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +2 -2
  61. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  62. package/dist/esm/i3s-converter/helpers/geometry-converter.js +117 -58
  63. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  64. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +54 -0
  65. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  66. package/dist/esm/i3s-converter/helpers/node-pages.js +12 -4
  67. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  68. package/dist/esm/i3s-converter/i3s-converter.js +105 -28
  69. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  70. package/dist/esm/index.js +1 -0
  71. package/dist/esm/index.js.map +1 -1
  72. package/dist/esm/lib/utils/compress-util.js +6 -8
  73. package/dist/esm/lib/utils/compress-util.js.map +1 -1
  74. package/dist/esm/lib/utils/file-utils.js +11 -1
  75. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  76. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  77. package/dist/esm/lib/utils/queue.js +19 -0
  78. package/dist/esm/lib/utils/queue.js.map +1 -0
  79. package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
  80. package/dist/esm/lib/utils/write-queue.js +88 -0
  81. package/dist/esm/lib/utils/write-queue.js.map +1 -0
  82. package/dist/esm/pgm-loader.js +1 -1
  83. package/dist/esm/workers/3d-tiles-attributes-worker.js +5 -0
  84. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -0
  85. package/dist/esm/workers/i3s-attributes-worker.js +4 -0
  86. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -0
  87. package/dist/i3s-attributes-worker.d.ts +33 -0
  88. package/dist/i3s-attributes-worker.d.ts.map +1 -0
  89. package/dist/i3s-attributes-worker.js +10 -0
  90. package/dist/i3s-attributes-worker.js.map +7 -0
  91. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +7 -7
  92. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
  93. package/dist/i3s-converter/helpers/coordinate-converter.js +25 -21
  94. package/dist/i3s-converter/helpers/geometry-attributes.d.ts +2 -2
  95. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  96. package/dist/i3s-converter/helpers/geometry-attributes.js +2 -1
  97. package/dist/i3s-converter/helpers/geometry-converter.d.ts +28 -11
  98. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  99. package/dist/i3s-converter/helpers/geometry-converter.js +220 -110
  100. package/dist/i3s-converter/helpers/gltf-attributes.d.ts +9 -0
  101. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -0
  102. package/dist/i3s-converter/helpers/gltf-attributes.js +56 -0
  103. package/dist/i3s-converter/helpers/node-pages.d.ts +6 -5
  104. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  105. package/dist/i3s-converter/helpers/node-pages.js +13 -8
  106. package/dist/i3s-converter/i3s-converter.d.ts +7 -3
  107. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  108. package/dist/i3s-converter/i3s-converter.js +88 -26
  109. package/dist/i3s-converter/types.d.ts +83 -8
  110. package/dist/i3s-converter/types.d.ts.map +1 -1
  111. package/dist/index.d.ts +1 -0
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +3 -1
  114. package/dist/lib/utils/compress-util.d.ts +44 -5
  115. package/dist/lib/utils/compress-util.d.ts.map +1 -1
  116. package/dist/lib/utils/compress-util.js +73 -6
  117. package/dist/lib/utils/file-utils.d.ts +34 -5
  118. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  119. package/dist/lib/utils/file-utils.js +40 -1
  120. package/dist/lib/utils/lod-conversion-utils.d.ts +25 -4
  121. package/dist/lib/utils/lod-conversion-utils.d.ts.map +1 -1
  122. package/dist/lib/utils/lod-conversion-utils.js +21 -2
  123. package/dist/lib/utils/queue.d.ts +7 -0
  124. package/dist/lib/utils/queue.d.ts.map +1 -0
  125. package/dist/lib/utils/queue.js +18 -0
  126. package/dist/lib/utils/statistic-utills.d.ts +2 -2
  127. package/dist/lib/utils/statistic-utills.d.ts.map +1 -1
  128. package/dist/lib/utils/write-queue.d.ts +22 -0
  129. package/dist/lib/utils/write-queue.d.ts.map +1 -0
  130. package/dist/lib/utils/write-queue.js +62 -0
  131. package/dist/workers/3d-tiles-attributes-worker.d.ts +2 -0
  132. package/dist/workers/3d-tiles-attributes-worker.d.ts.map +1 -0
  133. package/dist/workers/3d-tiles-attributes-worker.js +9 -0
  134. package/dist/workers/i3s-attributes-worker.d.ts +2 -0
  135. package/dist/workers/i3s-attributes-worker.d.ts.map +1 -0
  136. package/dist/workers/i3s-attributes-worker.js +5 -0
  137. package/package.json +20 -17
  138. package/src/3d-tiles-attributes-worker.ts +43 -0
  139. package/src/3d-tiles-converter/3d-tiles-converter.ts +44 -4
  140. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +15 -13
  141. package/src/i3s-attributes-worker.ts +46 -0
  142. package/src/i3s-converter/helpers/coordinate-converter.ts +29 -24
  143. package/src/i3s-converter/helpers/geometry-attributes.ts +4 -3
  144. package/src/i3s-converter/helpers/{geometry-converter.js → geometry-converter.ts} +421 -175
  145. package/src/i3s-converter/helpers/gltf-attributes.ts +68 -0
  146. package/src/i3s-converter/helpers/node-pages.ts +25 -17
  147. package/src/i3s-converter/i3s-converter.ts +112 -69
  148. package/src/i3s-converter/types.ts +90 -8
  149. package/src/index.ts +1 -0
  150. package/src/lib/utils/{compress-util.js → compress-util.ts} +105 -18
  151. package/src/lib/utils/file-utils.ts +84 -0
  152. package/src/lib/utils/{lod-conversion-utils.js → lod-conversion-utils.ts} +27 -5
  153. package/src/lib/utils/queue.ts +17 -0
  154. package/src/lib/utils/{statistic-utills.js → statistic-utills.ts} +0 -0
  155. package/src/lib/utils/write-queue.ts +75 -0
  156. package/src/workers/3d-tiles-attributes-worker.ts +6 -0
  157. package/src/workers/i3s-attributes-worker.ts +6 -0
  158. package/dist/es5/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  159. package/dist/es5/lib/utils/compress-util.d.ts +0 -53
  160. package/dist/es5/lib/utils/file-utils.d.ts +0 -43
  161. package/dist/es5/lib/utils/lod-conversion-utils.d.ts +0 -32
  162. package/dist/esm/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  163. package/dist/esm/lib/utils/compress-util.d.ts +0 -53
  164. package/dist/esm/lib/utils/file-utils.d.ts +0 -43
  165. package/dist/esm/lib/utils/lod-conversion-utils.d.ts +0 -32
  166. package/src/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  167. package/src/lib/utils/compress-util.d.ts +0 -53
  168. package/src/lib/utils/file-utils.d.ts +0 -43
  169. package/src/lib/utils/file-utils.js +0 -38
  170. 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} 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,12 +48,16 @@ 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 {KTX2BasisWriter} 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';
58
61
 
59
62
  const ION_DEFAULT_TOKEN =
60
63
  process.env.IonToken || // eslint-disable-line
@@ -75,7 +78,6 @@ const CESIUM_DATASET_PREFIX = 'https://';
75
78
  */
76
79
  export default class I3SConverter {
77
80
  nodePages: NodePages;
78
- fileMap: {[key: string]: string};
79
81
  options: any;
80
82
  layers0Path: string;
81
83
  materialMap: Map<any, any>;
@@ -97,10 +99,11 @@ export default class I3SConverter {
97
99
  generateTextures: boolean;
98
100
  generateBoundingVolumes: boolean;
99
101
  layersHasTexture: boolean;
102
+ workerSource: {[key: string]: string} = {};
103
+ writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue();
100
104
 
101
105
  constructor() {
102
106
  this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE);
103
- this.fileMap = {};
104
107
  this.options = {};
105
108
  this.layers0Path = '';
106
109
  this.materialMap = new Map();
@@ -169,6 +172,9 @@ export default class I3SConverter {
169
172
  this.generateTextures = Boolean(generateTextures);
170
173
  this.generateBoundingVolumes = Boolean(generateBoundingVolumes);
171
174
 
175
+ this.writeQueue = new WriteQueue();
176
+ this.writeQueue.startListening();
177
+
172
178
  console.log('Loading egm file...'); // eslint-disable-line
173
179
  this.geoidHeightModel = await load(egmFilePath, PGMLoader);
174
180
  console.log('Loading egm file completed!'); // eslint-disable-line
@@ -177,6 +183,8 @@ export default class I3SConverter {
177
183
  this.nodePages.useWriteFunction(writeFileForSlpk);
178
184
  }
179
185
 
186
+ await this.loadWorkers();
187
+
180
188
  const preloadOptions = await this._fetchPreloadOptions();
181
189
  const tilesetOptions: Tileset3DProps = {loadOptions: {basis: {format: 'rgba32'}}};
182
190
  if (preloadOptions.headers) {
@@ -189,6 +197,11 @@ export default class I3SConverter {
189
197
 
190
198
  await this._createAndSaveTileset(outputPath, tilesetName);
191
199
  await this._finishConversion({slpk: Boolean(slpk), outputPath, tilesetName});
200
+
201
+ // Clean up worker pools
202
+ const workerFarm = WorkerFarm.getWorkerFarm({});
203
+ workerFarm.destroy();
204
+
192
205
  return sourceTilesetJson;
193
206
  }
194
207
 
@@ -239,7 +252,8 @@ export default class I3SConverter {
239
252
  await this._writeLayers0();
240
253
  createSceneServerPath(tilesetName, this.layers0!, tilesetPath);
241
254
  await this._writeNodeIndexDocument(root0, 'root', join(this.layers0Path, 'nodes', 'root'));
242
- await this.nodePages.save(this.layers0Path, this.fileMap, isCreateSlpk);
255
+ await this.nodePages.save(this.layers0Path, this.writeQueue, isCreateSlpk);
256
+ await this.writeQueue.finalize();
243
257
  await this._createSlpk(tilesetPath);
244
258
  }
245
259
 
@@ -248,7 +262,10 @@ export default class I3SConverter {
248
262
  * @param tilesetName - Name of layer
249
263
  */
250
264
  private _formLayers0(tilesetName: string): void {
251
- const extent = convertCommonToI3SExtentCoordinate(this.sourceTileset);
265
+ const fullExtent = convertBoundingVolumeToI3SFullExtent(
266
+ this.sourceTileset?.boundingVolume || this.sourceTileset?.root?.boundingVolume
267
+ );
268
+ const extent = [fullExtent.xmin, fullExtent.ymin, fullExtent.xmax, fullExtent.ymax];
252
269
  const layers0data = {
253
270
  version: `{${uuidv4().toUpperCase()}}`,
254
271
  id: 0,
@@ -318,13 +335,16 @@ export default class I3SConverter {
318
335
  const childPath = join(this.layers0Path, 'nodes', child.path!);
319
336
 
320
337
  if (this.options.slpk) {
321
- this.fileMap['nodes/1/3dNodeIndexDocument.json.gz'] = await writeFileForSlpk(
322
- childPath,
323
- JSON.stringify(child),
324
- '3dNodeIndexDocument.json'
325
- );
338
+ this.writeQueue.enqueue({
339
+ archiveKey: 'nodes/1/3dNodeIndexDocument.json.gz',
340
+ writePromise: writeFileForSlpk(
341
+ childPath,
342
+ JSON.stringify(child),
343
+ '3dNodeIndexDocument.json'
344
+ )
345
+ });
326
346
  } else {
327
- await writeFile(childPath, JSON.stringify(child));
347
+ this.writeQueue.enqueue({writePromise: writeFile(childPath, JSON.stringify(child))});
328
348
  }
329
349
  } else {
330
350
  await this._addChildrenWithNeighborsAndWriteFile({
@@ -342,13 +362,18 @@ export default class I3SConverter {
342
362
  */
343
363
  private async _writeLayers0(): Promise<void> {
344
364
  if (this.options.slpk) {
345
- this.fileMap['3dSceneLayer.json.gz'] = await writeFileForSlpk(
346
- this.layers0Path,
347
- JSON.stringify(this.layers0),
348
- '3dSceneLayer.json'
349
- );
365
+ this.writeQueue.enqueue({
366
+ archiveKey: '3dSceneLayer.json.gz',
367
+ writePromise: writeFileForSlpk(
368
+ this.layers0Path,
369
+ JSON.stringify(this.layers0),
370
+ '3dSceneLayer.json'
371
+ )
372
+ });
350
373
  } else {
351
- await writeFile(this.layers0Path, JSON.stringify(this.layers0));
374
+ this.writeQueue.enqueue({
375
+ writePromise: writeFile(this.layers0Path, JSON.stringify(this.layers0))
376
+ });
352
377
  }
353
378
  }
354
379
 
@@ -361,13 +386,12 @@ export default class I3SConverter {
361
386
  rootPath: string
362
387
  ): Promise<void> {
363
388
  if (this.options.slpk) {
364
- this.fileMap[`nodes/${nodePath}/3dNodeIndexDocument.json.gz`] = await writeFileForSlpk(
365
- rootPath,
366
- JSON.stringify(root0),
367
- '3dNodeIndexDocument.json'
368
- );
389
+ this.writeQueue.enqueue({
390
+ archiveKey: `nodes/${nodePath}/3dNodeIndexDocument.json.gz`,
391
+ writePromise: writeFileForSlpk(rootPath, JSON.stringify(root0), '3dNodeIndexDocument.json')
392
+ });
369
393
  } else {
370
- await writeFile(rootPath, JSON.stringify(root0));
394
+ this.writeQueue.enqueue({writePromise: writeFile(rootPath, JSON.stringify(root0))});
371
395
  }
372
396
  }
373
397
 
@@ -384,7 +408,6 @@ export default class I3SConverter {
384
408
  slpkFileName,
385
409
  0,
386
410
  '.',
387
- // @ts-expect-error
388
411
  this.options.sevenZipExe
389
412
  );
390
413
 
@@ -656,7 +679,8 @@ export default class I3SConverter {
656
679
  this.layers0?.attributeStorageInfo,
657
680
  this.options.draco,
658
681
  this.generateBoundingVolumes,
659
- this.geoidHeightModel!
682
+ this.geoidHeightModel!,
683
+ this.workerSource
660
684
  );
661
685
  return resourcesData;
662
686
  }
@@ -806,7 +830,7 @@ export default class I3SConverter {
806
830
  const slpkChildPath = join('nodes', nodePath);
807
831
 
808
832
  await this._writeGeometries(geometryBuffer!, compressedGeometry!, childPath, slpkChildPath);
809
- await this._writeShared(sharedResources!, childPath, slpkChildPath, nodePath);
833
+ await this._writeShared(sharedResources, childPath, slpkChildPath, nodePath);
810
834
  await this._writeTexture(texture, childPath, slpkChildPath);
811
835
  await this._writeAttributes(attributes, childPath, slpkChildPath);
812
836
  }
@@ -820,33 +844,35 @@ export default class I3SConverter {
820
844
  */
821
845
  private async _writeGeometries(
822
846
  geometryBuffer: ArrayBuffer,
823
- compressedGeometry: ArrayBuffer,
847
+ compressedGeometry: Promise<ArrayBuffer>,
824
848
  childPath: string,
825
849
  slpkChildPath: string
826
850
  ): Promise<void> {
827
851
  if (this.options.slpk) {
828
852
  const slpkGeometryPath = join(childPath, 'geometries');
829
- this.fileMap[`${slpkChildPath}/geometries/0.bin.gz`] = await writeFileForSlpk(
830
- slpkGeometryPath,
831
- geometryBuffer,
832
- '0.bin'
833
- );
853
+ this.writeQueue.enqueue({
854
+ archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
855
+ writePromise: writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
856
+ });
834
857
  } else {
835
858
  const geometryPath = join(childPath, 'geometries/0/');
836
- await writeFile(geometryPath, geometryBuffer, 'index.bin');
859
+ this.writeQueue.enqueue({
860
+ writePromise: writeFile(geometryPath, geometryBuffer, 'index.bin')
861
+ });
837
862
  }
838
863
 
839
864
  if (this.options.draco) {
840
865
  if (this.options.slpk) {
841
866
  const slpkCompressedGeometryPath = join(childPath, 'geometries');
842
- this.fileMap[`${slpkChildPath}/geometries/1.bin.gz`] = await writeFileForSlpk(
843
- slpkCompressedGeometryPath,
844
- compressedGeometry,
845
- '1.bin'
846
- );
867
+ this.writeQueue.enqueue({
868
+ archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
869
+ writePromise: writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
870
+ });
847
871
  } else {
848
872
  const compressedGeometryPath = join(childPath, 'geometries/1/');
849
- await writeFile(compressedGeometryPath, compressedGeometry, 'index.bin');
873
+ this.writeQueue.enqueue({
874
+ writePromise: writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
875
+ });
850
876
  }
851
877
  }
852
878
  }
@@ -859,24 +885,26 @@ export default class I3SConverter {
859
885
  * @param nodePath - a node path
860
886
  */
861
887
  private async _writeShared(
862
- sharedResources: SharedResources,
888
+ sharedResources: SharedResourcesArrays | null,
863
889
  childPath: string,
864
890
  slpkChildPath: string,
865
891
  nodePath: string
866
892
  ): Promise<void> {
893
+ if (!sharedResources) {
894
+ return;
895
+ }
867
896
  sharedResources.nodePath = nodePath;
868
897
  const sharedData = transform(sharedResources, sharedResourcesTemplate());
869
898
  const sharedDataStr = JSON.stringify(sharedData);
870
899
  if (this.options.slpk) {
871
900
  const slpkSharedPath = join(childPath, 'shared');
872
- this.fileMap[`${slpkChildPath}/shared/sharedResource.json.gz`] = await writeFileForSlpk(
873
- slpkSharedPath,
874
- sharedDataStr,
875
- 'sharedResource.json'
876
- );
901
+ this.writeQueue.enqueue({
902
+ archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
903
+ writePromise: writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
904
+ });
877
905
  } else {
878
906
  const sharedPath = join(childPath, 'shared/');
879
- await writeFile(sharedPath, sharedDataStr);
907
+ this.writeQueue.enqueue({writePromise: writeFile(sharedPath, sharedDataStr)});
880
908
  }
881
909
  }
882
910
 
@@ -904,9 +932,7 @@ export default class I3SConverter {
904
932
 
905
933
  if (this.generateTextures) {
906
934
  formats.push({name: '1', format: 'ktx2'});
907
- const ktx2TextureData = new Uint8Array(
908
- await encode(texture.image, KTX2BasisUniversalTextureWriter)
909
- );
935
+ const ktx2TextureData = new Uint8Array(await encode(texture.image, KTX2BasisWriter));
910
936
  await this.writeTextureFile(ktx2TextureData, '1', 'ktx2', childPath, slpkChildPath);
911
937
  }
912
938
 
@@ -958,15 +984,15 @@ export default class I3SConverter {
958
984
  const slpkTexturePath = join(childPath, 'textures');
959
985
  const compress = false;
960
986
 
961
- this.fileMap[`${slpkChildPath}/textures/${name}.${format}`] = await writeFileForSlpk(
962
- slpkTexturePath,
963
- textureData,
964
- `${name}.${format}`,
965
- compress
966
- );
987
+ this.writeQueue.enqueue({
988
+ archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
989
+ writePromise: writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
990
+ });
967
991
  } else {
968
992
  const texturePath = join(childPath, `textures/${name}/`);
969
- await writeFile(texturePath, textureData, `index.${format}`);
993
+ this.writeQueue.enqueue({
994
+ writePromise: writeFile(texturePath, textureData, `index.${format}`)
995
+ });
970
996
  }
971
997
  }
972
998
 
@@ -977,25 +1003,26 @@ export default class I3SConverter {
977
1003
  * @param slpkChildPath - the resource path inside *slpk file
978
1004
  */
979
1005
  private async _writeAttributes(
980
- attributes: ArrayBuffer[],
1006
+ attributes: ArrayBuffer[] | null = [],
981
1007
  childPath: string,
982
1008
  slpkChildPath: string
983
1009
  ): Promise<void> {
984
- if (attributes.length && this.layers0?.attributeStorageInfo?.length) {
1010
+ if (attributes?.length && this.layers0?.attributeStorageInfo?.length) {
985
1011
  for (let index = 0; index < attributes.length; index++) {
986
1012
  const folderName = this.layers0.attributeStorageInfo[index].key;
987
1013
  const fileBuffer = new Uint8Array(attributes[index]);
988
1014
 
989
1015
  if (this.options.slpk) {
990
1016
  const slpkAttributesPath = join(childPath, 'attributes', folderName);
991
- this.fileMap[`${slpkChildPath}/attributes/${folderName}.bin.gz`] = await writeFileForSlpk(
992
- slpkAttributesPath,
993
- fileBuffer,
994
- '0.bin'
995
- );
1017
+ this.writeQueue.enqueue({
1018
+ archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
1019
+ writePromise: writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
1020
+ });
996
1021
  } else {
997
1022
  const attributesPath = join(childPath, `attributes/${folderName}/0`);
998
- await writeFile(attributesPath, fileBuffer, 'index.bin');
1023
+ this.writeQueue.enqueue({
1024
+ writePromise: writeFile(attributesPath, fileBuffer, 'index.bin')
1025
+ });
999
1026
  }
1000
1027
  }
1001
1028
  }
@@ -1309,4 +1336,20 @@ export default class I3SConverter {
1309
1336
  private isContentSupported(sourceRootTile: Tile3D): boolean {
1310
1337
  return ['b3dm', 'glTF'].includes(sourceRootTile?.content?.type);
1311
1338
  }
1339
+
1340
+ private async loadWorkers(): Promise<void> {
1341
+ console.log(`Loading workers source...`); // eslint-disable-line no-undef, no-console
1342
+ if (this.options.draco) {
1343
+ const url = getWorkerURL(DracoWriterWorker, {...getLoaderOptions()});
1344
+ const sourceResponse = await fetchFile(url);
1345
+ const source = await sourceResponse.text();
1346
+ this.workerSource.draco = source;
1347
+ }
1348
+
1349
+ const i3sAttributesWorkerUrl = getWorkerURL(I3SAttributesWorker, {...getLoaderOptions()});
1350
+ const sourceResponse = await fetchFile(i3sAttributesWorkerUrl);
1351
+ const source = await sourceResponse.text();
1352
+ this.workerSource.I3SAttributes = source;
1353
+ console.log(`Loading workers source completed!`); // eslint-disable-line no-undef, no-console
1354
+ }
1312
1355
  }
@@ -1,42 +1,124 @@
1
- import {BoundingVolumes, I3SMaterialDefinition, SharedResources} from '@loaders.gl/i3s';
1
+ import {
2
+ BoundingVolumes,
3
+ I3SMaterialDefinition,
4
+ MaterialDefinitionInfo,
5
+ TextureDefinitionInfo
6
+ } from '@loaders.gl/i3s';
7
+ import {ImageDataType} from '@loaders.gl/images';
2
8
 
9
+ /** Converted resources for specific node */
3
10
  export type I3SConvertedResources = {
11
+ /** Non-compressed geometry buffer that have structure met
12
+ * https://github.com/Esri/i3s-spec/blob/master/docs/1.8/defaultGeometrySchema.cmn.md
13
+ * (Geometry buffer)
14
+ */
4
15
  geometry: ArrayBuffer | null;
5
- compressedGeometry?: ArrayBuffer | null;
16
+ /**
17
+ * Draco compressed geometry
18
+ */
19
+ compressedGeometry?: Promise<ArrayBuffer> | null;
20
+ /**
21
+ * Texture image content
22
+ */
6
23
  texture: any | null;
7
- sharedResources: SharedResources | null;
24
+ /**
25
+ * Shared resources built from GLTF material
26
+ */
27
+ sharedResources: SharedResourcesArrays | null;
28
+ /**
29
+ * Material definition of the node
30
+ */
8
31
  meshMaterial?: I3SMaterialDefinition | null;
32
+ /**
33
+ * Number of vertices in the node
34
+ */
9
35
  vertexCount: number | null;
10
- attributes: any | null;
36
+ /**
37
+ * Feature attributes contents
38
+ */
39
+ attributes: ArrayBuffer[] | null;
40
+ /**
41
+ * Number of features in the node
42
+ */
11
43
  featureCount: number | null;
12
- geometryBuffer?: ArrayBuffer;
44
+ /**
45
+ * MBS and/or OBB bounding volumes of the node
46
+ */
13
47
  boundingVolumes: BoundingVolumes | null;
14
48
  };
15
49
 
16
- export type AttributesData = {
50
+ /**
51
+ * Geometry and feature attributes converted from GLTF primitives
52
+ */
53
+ export type ConvertedAttributes = {
54
+ /** POSITION attribute value */
17
55
  positions: Float32Array;
56
+ /** NORMAL attribute value */
18
57
  normals: Float32Array;
58
+ /** TEXCOORD_0 attribute value */
19
59
  texCoords: Float32Array;
60
+ /** COLOR_0 attribute value */
20
61
  colors: Uint8Array;
62
+ /** Feature indices grouped by ...
63
+ * converted from "batch ids" of GLTF
64
+ */
65
+ featureIndicesGroups?: number[][];
66
+ /** Feature indices converted from "batch ids" */
21
67
  featureIndices: number[];
22
- triangleCount: number;
23
- boundingVolumes?: BoundingVolumes | null;
68
+ /**
69
+ * MBS and/or OBB bounding volumes of the node
70
+ */
71
+ boundingVolumes: null | BoundingVolumes;
24
72
  };
25
73
 
74
+ /** Postprocessed geometry and feature attributes
75
+ * https://github.com/Esri/i3s-spec/blob/master/docs/1.8/defaultGeometrySchema.cmn.md
76
+ */
26
77
  export type GeometryAttributes = {
78
+ /** POSITION attribute value */
27
79
  positions: Float32Array;
80
+ /** NORMAL attribute value */
28
81
  normals: Float32Array;
82
+ /** TEXCOORD_0 attribute value */
29
83
  texCoords: Float32Array;
84
+ /** COLOR_0 attribute value */
30
85
  colors: Uint8Array;
86
+ /** faceRanges attribute value */
31
87
  faceRange: Uint32Array;
88
+ /** feature Ids attribute value */
32
89
  featureIds: number[];
90
+ /** number of features in the node */
33
91
  featureCount: number;
34
92
  };
35
93
 
94
+ /** Geometry attributes specific for the particular feature */
36
95
  export type GroupedByFeatureIdAttributes = {
96
+ /** Feature Id */
37
97
  featureId: number;
98
+ /** POSITION attribute value */
38
99
  positions: Float32Array;
100
+ /** NORMAL attribute value */
39
101
  normals: Float32Array;
102
+ /** COLOR_0 attribute value */
40
103
  colors: Uint8Array;
104
+ /** TEXCOORD_0 attribute value */
41
105
  texCoords: Float32Array;
42
106
  };
107
+
108
+ /** Shared resources made from GLTF material */
109
+ export type SharedResourcesArrays = {
110
+ /** material definitions list https://github.com/Esri/i3s-spec/blob/master/docs/1.8/materialDefinitionInfo.cmn.md */
111
+ materialDefinitionInfos?: MaterialDefinitionInfo[];
112
+ /** texture definitions list https://github.com/Esri/i3s-spec/blob/master/docs/1.8/textureDefinitionInfo.cmn.md*/
113
+ textureDefinitionInfos?: TextureDefinitionInfo[];
114
+ /** node id to make unique SharedResource ids */
115
+ nodePath?: string;
116
+ };
117
+
118
+ /** I3S material definition and texture content taken from GLTF material */
119
+ export type I3SMaterialWithTexture = {
120
+ /** Material definition https://github.com/Esri/i3s-spec/blob/master/docs/1.8/materialDefinitions.cmn.md */
121
+ material: I3SMaterialDefinition;
122
+ /** Texture content (image) */
123
+ texture?: ImageDataType;
124
+ };
package/src/index.ts CHANGED
@@ -4,3 +4,4 @@ export {default as NodePages} from './i3s-converter/helpers/node-pages';
4
4
  export {default as Tiles3DConverter} from './3d-tiles-converter/3d-tiles-converter';
5
5
 
6
6
  export {DepsInstaller} from './deps-installer/deps-installer';
7
+ export {prepareDataForAttributesConversion} from './i3s-converter/helpers/gltf-attributes';