@loaders.gl/tile-converter 3.3.0-alpha.8 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/3d-tiles-attributes-worker.js +2 -2
  2. package/dist/3d-tiles-attributes-worker.js.map +3 -3
  3. package/dist/converter-cli.js +14 -2
  4. package/dist/converter.min.js +22 -22
  5. package/dist/deps-installer/deps-installer.d.ts.map +1 -1
  6. package/dist/deps-installer/deps-installer.js +8 -0
  7. package/dist/dist.min.js +1165 -846
  8. package/dist/es5/3d-tiles-attributes-worker.js +1 -1
  9. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -1
  10. package/dist/es5/converter-cli.js +14 -2
  11. package/dist/es5/converter-cli.js.map +1 -1
  12. package/dist/es5/deps-installer/deps-installer.js +13 -2
  13. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  14. package/dist/es5/i3s-attributes-worker.js +1 -1
  15. package/dist/es5/i3s-attributes-worker.js.map +1 -1
  16. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  17. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +16 -7
  18. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  19. package/dist/es5/i3s-converter/helpers/geometry-converter.js +363 -113
  20. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  21. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +6 -11
  22. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  23. package/dist/es5/i3s-converter/helpers/node-index-document.js +517 -0
  24. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -0
  25. package/dist/es5/i3s-converter/helpers/node-pages.js +455 -173
  26. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  27. package/dist/es5/i3s-converter/i3s-converter.js +549 -618
  28. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  29. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js +107 -0
  30. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  31. package/dist/es5/i3s-converter/json-templates/layers.js +2 -93
  32. package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -1
  33. package/dist/es5/i3s-converter/json-templates/shared-resources.js +3 -3
  34. package/dist/es5/i3s-converter/json-templates/shared-resources.js.map +1 -1
  35. package/dist/es5/i3s-converter/types.js.map +1 -1
  36. package/dist/es5/lib/utils/file-utils.js +93 -9
  37. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  38. package/dist/es5/lib/utils/write-queue.js +38 -25
  39. package/dist/es5/lib/utils/write-queue.js.map +1 -1
  40. package/dist/es5/pgm-loader.js +1 -1
  41. package/dist/es5/pgm-loader.js.map +1 -1
  42. package/dist/es5/workers/i3s-attributes-worker.js +1 -1
  43. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -1
  44. package/dist/esm/3d-tiles-attributes-worker.js +1 -1
  45. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -1
  46. package/dist/esm/converter-cli.js +14 -2
  47. package/dist/esm/converter-cli.js.map +1 -1
  48. package/dist/esm/deps-installer/deps-installer.js +9 -1
  49. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  50. package/dist/esm/i3s-attributes-worker.js +1 -1
  51. package/dist/esm/i3s-attributes-worker.js.map +1 -1
  52. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  53. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +16 -7
  54. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  55. package/dist/esm/i3s-converter/helpers/geometry-converter.js +150 -40
  56. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  57. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +6 -9
  58. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  59. package/dist/esm/i3s-converter/helpers/node-index-document.js +202 -0
  60. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -0
  61. package/dist/esm/i3s-converter/helpers/node-pages.js +162 -76
  62. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  63. package/dist/esm/i3s-converter/i3s-converter.js +115 -220
  64. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  65. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js +89 -0
  66. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  67. package/dist/esm/i3s-converter/json-templates/layers.js +2 -85
  68. package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -1
  69. package/dist/esm/i3s-converter/json-templates/shared-resources.js +3 -3
  70. package/dist/esm/i3s-converter/json-templates/shared-resources.js.map +1 -1
  71. package/dist/esm/i3s-converter/types.js.map +1 -1
  72. package/dist/esm/lib/utils/file-utils.js +44 -3
  73. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  74. package/dist/esm/lib/utils/write-queue.js +19 -10
  75. package/dist/esm/lib/utils/write-queue.js.map +1 -1
  76. package/dist/esm/pgm-loader.js +1 -1
  77. package/dist/esm/pgm-loader.js.map +1 -1
  78. package/dist/esm/workers/i3s-attributes-worker.js +1 -1
  79. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -1
  80. package/dist/i3s-attributes-worker.js +2 -2
  81. package/dist/i3s-attributes-worker.js.map +2 -2
  82. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +3 -3
  83. package/dist/i3s-converter/helpers/batch-ids-extensions.js +3 -3
  84. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  85. package/dist/i3s-converter/helpers/geometry-attributes.js +16 -10
  86. package/dist/i3s-converter/helpers/geometry-converter.d.ts +8 -4
  87. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  88. package/dist/i3s-converter/helpers/geometry-converter.js +200 -44
  89. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
  90. package/dist/i3s-converter/helpers/gltf-attributes.js +2 -3
  91. package/dist/i3s-converter/helpers/node-index-document.d.ts +95 -0
  92. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -0
  93. package/dist/i3s-converter/helpers/node-index-document.js +250 -0
  94. package/dist/i3s-converter/helpers/node-pages.d.ts +78 -43
  95. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  96. package/dist/i3s-converter/helpers/node-pages.js +195 -94
  97. package/dist/i3s-converter/i3s-converter.d.ts +33 -58
  98. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  99. package/dist/i3s-converter/i3s-converter.js +122 -233
  100. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts +7 -0
  101. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts.map +1 -0
  102. package/dist/i3s-converter/json-templates/geometry-definitions.js +87 -0
  103. package/dist/i3s-converter/json-templates/layers.d.ts +1 -30
  104. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -1
  105. package/dist/i3s-converter/json-templates/layers.js +2 -86
  106. package/dist/i3s-converter/json-templates/shared-resources.js +3 -3
  107. package/dist/i3s-converter/types.d.ts +28 -2
  108. package/dist/i3s-converter/types.d.ts.map +1 -1
  109. package/dist/lib/utils/file-utils.d.ts +17 -1
  110. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  111. package/dist/lib/utils/file-utils.js +64 -7
  112. package/dist/lib/utils/write-queue.d.ts +18 -2
  113. package/dist/lib/utils/write-queue.d.ts.map +1 -1
  114. package/dist/lib/utils/write-queue.js +18 -12
  115. package/dist/workers/i3s-attributes-worker.js +1 -1
  116. package/package.json +25 -20
  117. package/src/converter-cli.ts +22 -2
  118. package/src/deps-installer/deps-installer.ts +9 -0
  119. package/src/i3s-converter/helpers/batch-ids-extensions.ts +3 -3
  120. package/src/i3s-converter/helpers/geometry-attributes.ts +16 -11
  121. package/src/i3s-converter/helpers/geometry-converter.ts +217 -48
  122. package/src/i3s-converter/helpers/gltf-attributes.ts +2 -3
  123. package/src/i3s-converter/helpers/node-index-document.ts +315 -0
  124. package/src/i3s-converter/helpers/node-pages.ts +215 -110
  125. package/src/i3s-converter/i3s-converter.ts +170 -312
  126. package/src/i3s-converter/json-templates/geometry-definitions.ts +83 -0
  127. package/src/i3s-converter/json-templates/layers.ts +2 -91
  128. package/src/i3s-converter/json-templates/shared-resources.ts +3 -3
  129. package/src/i3s-converter/types.ts +29 -2
  130. package/src/lib/utils/file-utils.ts +62 -7
  131. package/src/lib/utils/write-queue.ts +36 -15
  132. package/src/workers/i3s-attributes-worker.ts +2 -1
@@ -1,5 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
2
  var _process$env;
3
+
3
4
  import { load, encode, fetchFile, getLoaderOptions, isBrowser } from '@loaders.gl/core';
4
5
  import { Tileset3D } from '@loaders.gl/tiles';
5
6
  import { CesiumIonLoader, Tiles3DLoader } from '@loaders.gl/3d-tiles';
@@ -9,8 +10,8 @@ import process from 'process';
9
10
  import transform from 'json-map-transform';
10
11
  import md5 from 'md5';
11
12
  import NodePages from './helpers/node-pages';
12
- import { writeFile, removeDir, writeFileForSlpk } from '../lib/utils/file-utils';
13
- import { compressWithChildProcess
13
+ import { writeFile, removeDir, writeFileForSlpk, removeFile } from '../lib/utils/file-utils';
14
+ import { compressFileWithGzip, compressWithChildProcess
14
15
  } from '../lib/utils/compress-util';
15
16
  import { calculateFilesSize, timeConverter } from '../lib/utils/statistic-utills';
16
17
  import convertB3dmToI3sGeometry, { getPropertyTable } from './helpers/geometry-converter';
@@ -19,9 +20,10 @@ import { createSceneServerPath } from './helpers/create-scene-server-path';
19
20
  import { convertGeometricErrorToScreenThreshold } from '../lib/utils/lod-conversion-utils';
20
21
  import { PGMLoader } from '../pgm-loader';
21
22
  import { LAYERS as layersTemplate } from './json-templates/layers';
22
- import { NODE as nodeTemplate } from './json-templates/node';
23
+ import { GEOMETRY_DEFINITION as geometryDefinitionTemlate } from './json-templates/geometry-definitions';
23
24
  import { SHARED_RESOURCES as sharedResourcesTemplate } from './json-templates/shared-resources';
24
25
  import { validateNodeBoundingVolumes } from './helpers/node-debug';
26
+
25
27
  import { KTX2BasisWriterWorker } from '@loaders.gl/textures';
26
28
  import { ImageWriter } from '@loaders.gl/images';
27
29
  import { getWorkerURL, WorkerFarm } from '@loaders.gl/worker-utils';
@@ -30,6 +32,7 @@ import WriteQueue from '../lib/utils/write-queue';
30
32
  import { I3SAttributesWorker } from '../i3s-attributes-worker';
31
33
  import { BROWSER_ERROR_MESSAGE } from '../constants';
32
34
  import { createdStorageAttribute, createFieldAttribute, createPopupInfo, getAttributeType, getFieldAttributeType } from './helpers/feature-attributes';
35
+ import { NodeIndexDocument } from './helpers/node-index-document';
33
36
  const ION_DEFAULT_TOKEN = ((_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.IonToken) ||
34
37
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlYWMxMzcyYy0zZjJkLTQwODctODNlNi01MDRkZmMzMjIxOWIiLCJpZCI6OTYyMCwic2NvcGVzIjpbImFzbCIsImFzciIsImdjIl0sImlhdCI6MTU2Mjg2NjI3M30.1FNiClUyk00YH_nWfSGpiQAjR5V2OvREDq1PJ5QMjWQ';
35
38
  const HARDCODED_NODES_PER_PAGE = 64;
@@ -45,6 +48,8 @@ export default class I3SConverter {
45
48
  _defineProperty(this, "layers0Path", void 0);
46
49
  _defineProperty(this, "materialMap", void 0);
47
50
  _defineProperty(this, "materialDefinitions", void 0);
51
+ _defineProperty(this, "geometryMap", void 0);
52
+ _defineProperty(this, "geometryConfigs", void 0);
48
53
  _defineProperty(this, "vertexCounter", void 0);
49
54
  _defineProperty(this, "layers0", void 0);
50
55
  _defineProperty(this, "featuresHashArray", void 0);
@@ -61,11 +66,14 @@ export default class I3SConverter {
61
66
  _defineProperty(this, "layersHasTexture", void 0);
62
67
  _defineProperty(this, "workerSource", {});
63
68
  _defineProperty(this, "writeQueue", new WriteQueue());
64
- this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE);
69
+ _defineProperty(this, "compressList", null);
70
+ this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE, this);
65
71
  this.options = {};
66
72
  this.layers0Path = '';
67
73
  this.materialMap = new Map();
68
74
  this.materialDefinitions = [];
75
+ this.geometryMap = new Map();
76
+ this.geometryConfigs = [];
69
77
  this.vertexCounter = 0;
70
78
  this.layers0 = null;
71
79
  this.featuresHashArray = [];
@@ -77,6 +85,7 @@ export default class I3SConverter {
77
85
  this.generateTextures = false;
78
86
  this.generateBoundingVolumes = false;
79
87
  this.layersHasTexture = false;
88
+ this.compressList = null;
80
89
  }
81
90
 
82
91
  async convert(options) {
@@ -92,12 +101,14 @@ export default class I3SConverter {
92
101
  inputUrl,
93
102
  validate,
94
103
  outputPath,
95
- draco,
104
+ draco = true,
96
105
  sevenZipExe,
97
106
  maxDepth,
98
107
  token,
99
108
  generateTextures,
100
- generateBoundingVolumes
109
+ generateBoundingVolumes,
110
+ instantNodeWriting = false,
111
+ mergeMaterials = true
101
112
  } = options;
102
113
  this.options = {
103
114
  maxDepth,
@@ -106,8 +117,11 @@ export default class I3SConverter {
106
117
  egmFilePath,
107
118
  draco,
108
119
  token,
109
- inputUrl
120
+ inputUrl,
121
+ instantNodeWriting,
122
+ mergeMaterials
110
123
  };
124
+ this.compressList = this.options.instantNodeWriting && [] || null;
111
125
  this.validate = Boolean(validate);
112
126
  this.Loader = inputUrl.indexOf(CESIUM_DATASET_PREFIX) !== -1 ? CesiumIonLoader : Tiles3DLoader;
113
127
  this.generateTextures = Boolean(generateTextures);
@@ -176,23 +190,31 @@ export default class I3SConverter {
176
190
  this.materialMap = new Map();
177
191
  const sourceRootTile = this.sourceTileset.root;
178
192
  const boundingVolumes = createBoundingVolumes(sourceRootTile, this.geoidHeightModel);
179
- const parentId = this.nodePages.push({
193
+ await this.nodePages.push({
180
194
  index: 0,
181
195
  lodThreshold: 0,
182
196
  obb: boundingVolumes.obb,
183
197
  children: []
184
198
  });
185
- const isCreateSlpk = this.options.slpk;
186
- const root0 = this._formRootNodeIndexDocument(boundingVolumes);
187
- await this._convertNodesTree(root0, sourceRootTile, parentId, boundingVolumes);
199
+ const rootNode = await NodeIndexDocument.createRootNode(boundingVolumes, this);
200
+ await this._convertNodesTree(rootNode, sourceRootTile);
188
201
  this.layers0.materialDefinitions = this.materialDefinitions;
202
+ this.layers0.geometryDefinitions = transform(this.geometryConfigs.map(config => ({
203
+ geometryConfig: {
204
+ ...config,
205
+ draco: this.options.draco
206
+ }
207
+ })), geometryDefinitionTemlate());
189
208
  if (this.layersHasTexture === false) {
190
209
  this.layers0.store.defaultGeometrySchema.ordering = this.layers0.store.defaultGeometrySchema.ordering.filter(attribute => attribute !== 'uv0');
191
210
  }
192
211
  await this._writeLayers0();
193
212
  createSceneServerPath(tilesetName, this.layers0, tilesetPath);
194
- await this._writeNodeIndexDocument(root0, 'root', join(this.layers0Path, 'nodes', 'root'));
195
- await this.nodePages.save(this.layers0Path, this.writeQueue, isCreateSlpk);
213
+ for (const filePath of this.compressList || []) {
214
+ await compressFileWithGzip(filePath);
215
+ await removeFile(filePath);
216
+ }
217
+ await this.nodePages.save();
196
218
  await this.writeQueue.finalize();
197
219
  await this._createSlpk(tilesetPath);
198
220
  }
@@ -223,78 +245,34 @@ export default class I3SConverter {
223
245
  this.layers0 = transform(layers0data, layersTemplate());
224
246
  }
225
247
 
226
- _formRootNodeIndexDocument(boundingVolumes) {
227
- const root0data = {
228
- version: "{".concat(uuidv4().toUpperCase(), "}"),
229
- id: 'root',
230
- level: 0,
231
- lodSelection: [{
232
- metricType: 'maxScreenThresholdSQ',
233
- maxError: 0
234
- }, {
235
- metricType: 'maxScreenThreshold',
236
- maxError: 0
237
- }],
238
- ...boundingVolumes,
239
- children: []
240
- };
241
- return transform(root0data, nodeTemplate());
242
- }
243
-
244
- async _convertNodesTree(root0, sourceRootTile, parentId, boundingVolumes) {
248
+ async _convertNodesTree(rootNode, sourceRootTile) {
245
249
  await this.sourceTileset._loadTile(sourceRootTile);
246
250
  if (this.isContentSupported(sourceRootTile)) {
247
- root0.children = root0.children || [];
248
- root0.children.push({
249
- id: '1',
250
- href: './1',
251
- ...boundingVolumes
252
- });
253
- const [child] = await this._createNode(root0, sourceRootTile, parentId, 0);
254
- const childPath = join(this.layers0Path, 'nodes', child.path);
255
- if (this.options.slpk) {
256
- await this.writeQueue.enqueue({
257
- archiveKey: 'nodes/1/3dNodeIndexDocument.json.gz',
258
- writePromise: writeFileForSlpk(childPath, JSON.stringify(child), '3dNodeIndexDocument.json')
259
- });
260
- } else {
261
- await this.writeQueue.enqueue({
262
- writePromise: writeFile(childPath, JSON.stringify(child))
263
- });
251
+ const childNodes = await this._createNode(rootNode, sourceRootTile, 0);
252
+ for (const childNode of childNodes) {
253
+ await childNode.save();
264
254
  }
255
+ await rootNode.addChildren(childNodes);
265
256
  } else {
266
257
  await this._addChildrenWithNeighborsAndWriteFile({
267
- parentNode: root0,
258
+ parentNode: rootNode,
268
259
  sourceTiles: sourceRootTile.children,
269
- parentId,
270
260
  level: 1
271
261
  });
272
262
  }
273
263
  await sourceRootTile.unloadContent();
264
+ await rootNode.save();
274
265
  }
275
266
 
276
267
  async _writeLayers0() {
277
268
  if (this.options.slpk) {
278
269
  await this.writeQueue.enqueue({
279
270
  archiveKey: '3dSceneLayer.json.gz',
280
- writePromise: writeFileForSlpk(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
281
- });
282
- } else {
283
- await this.writeQueue.enqueue({
284
- writePromise: writeFile(this.layers0Path, JSON.stringify(this.layers0))
285
- });
286
- }
287
- }
288
-
289
- async _writeNodeIndexDocument(root0, nodePath, rootPath) {
290
- if (this.options.slpk) {
291
- await this.writeQueue.enqueue({
292
- archiveKey: "nodes/".concat(nodePath, "/3dNodeIndexDocument.json.gz"),
293
- writePromise: writeFileForSlpk(rootPath, JSON.stringify(root0), '3dNodeIndexDocument.json')
271
+ writePromise: () => writeFileForSlpk(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
294
272
  });
295
273
  } else {
296
274
  await this.writeQueue.enqueue({
297
- writePromise: writeFile(rootPath, JSON.stringify(root0))
275
+ writePromise: () => writeFile(this.layers0Path, JSON.stringify(this.layers0))
298
276
  });
299
277
  }
300
278
  }
@@ -313,28 +291,20 @@ export default class I3SConverter {
313
291
  }
314
292
 
315
293
  async _addChildrenWithNeighborsAndWriteFile(data) {
316
- const childNodes = [];
317
- await this._addChildren({
318
- ...data,
319
- childNodes
320
- });
321
- await this._addNeighborsAndWriteFile(data.parentNode, childNodes);
294
+ await this._addChildren(data);
295
+ await data.parentNode.addNeighbors();
322
296
  }
323
297
 
324
298
  async convertNestedTileset(_ref) {
325
299
  let {
326
- sourceTile,
327
300
  parentNode,
328
- childNodes,
329
- parentId,
301
+ sourceTile,
330
302
  level
331
303
  } = _ref;
332
304
  await this.sourceTileset._loadTile(sourceTile);
333
305
  await this._addChildren({
334
306
  parentNode,
335
307
  sourceTiles: sourceTile.children,
336
- childNodes,
337
- parentId,
338
308
  level: level + 1
339
309
  });
340
310
  await sourceTile.unloadContent();
@@ -342,91 +312,44 @@ export default class I3SConverter {
342
312
 
343
313
  async convertNode(_ref2) {
344
314
  let {
345
- sourceTile,
346
315
  parentNode,
347
- childNodes,
348
- parentId,
316
+ sourceTile,
349
317
  level
350
318
  } = _ref2;
351
- const children = await this._createNode(parentNode, sourceTile, parentId, level);
352
- parentNode.children = parentNode.children || [];
353
- for (const child of children) {
354
- parentNode.children.push({
355
- id: child.id,
356
- href: "../".concat(child.path),
357
- obb: child.obb,
358
- mbs: child.mbs
359
- });
360
- childNodes.push(child);
361
- }
319
+ const childNodes = await this._createNode(parentNode, sourceTile, level);
320
+ await parentNode.addChildren(childNodes);
362
321
  }
363
322
 
364
323
  async _addChildren(data) {
365
324
  const {
366
- childNodes,
367
325
  sourceTiles,
368
326
  parentNode,
369
- parentId,
370
327
  level
371
328
  } = data;
372
329
  if (this.options.maxDepth && level > this.options.maxDepth) {
373
330
  return;
374
331
  }
375
- const promises = [];
376
332
  for (const sourceTile of sourceTiles) {
377
333
  if (sourceTile.type === 'json') {
378
- promises.push(this.convertNestedTileset({
379
- sourceTile,
334
+ await this.convertNestedTileset({
380
335
  parentNode,
381
- childNodes,
382
- parentId,
336
+ sourceTile,
383
337
  level
384
- }));
338
+ });
385
339
  } else {
386
- promises.push(this.convertNode({
387
- sourceTile,
340
+ await this.convertNode({
388
341
  parentNode,
389
- childNodes,
390
- parentId,
342
+ sourceTile,
391
343
  level
392
- }));
344
+ });
393
345
  }
394
- await Promise.all(promises);
395
346
  if (sourceTile.id) {
396
347
  console.log(sourceTile.id);
397
348
  }
398
349
  }
399
350
  }
400
351
 
401
- async _addNeighborsAndWriteFile(parentNode, childNodes) {
402
- for (const node of childNodes) {
403
- var _parentNode$children;
404
- const childPath = join(this.layers0Path, 'nodes', node.path);
405
- const nodePath = node.path;
406
- delete node.path;
407
-
408
- if (Number(parentNode === null || parentNode === void 0 ? void 0 : (_parentNode$children = parentNode.children) === null || _parentNode$children === void 0 ? void 0 : _parentNode$children.length) < 1000) {
409
- for (const neighbor of parentNode.children || []) {
410
- if (node.id === neighbor.id) {
411
- continue;
412
- }
413
-
414
- if (node.neighbors) {
415
- node.neighbors.push({
416
- ...neighbor
417
- });
418
- }
419
- }
420
- } else {
421
- console.warn("Node ".concat(node.id, ": neighbors attribute is omited because of large number of neigbors"));
422
- delete node.neighbors;
423
- }
424
- await this._writeNodeIndexDocument(node, nodePath, childPath);
425
- node.neighbors = [];
426
- }
427
- }
428
-
429
- async _createNode(parentTile, sourceTile, parentId, level) {
352
+ async _createNode(parentNode, sourceTile, level) {
430
353
  var _this$layers, _this$layers$attribut;
431
354
  this._checkAddRefinementTypeForTile(sourceTile);
432
355
  await this._updateTilesetOptions();
@@ -436,13 +359,15 @@ export default class I3SConverter {
436
359
  if (propertyTable && !((_this$layers = this.layers0) !== null && _this$layers !== void 0 && (_this$layers$attribut = _this$layers.attributeStorageInfo) !== null && _this$layers$attribut !== void 0 && _this$layers$attribut.length)) {
437
360
  this._convertPropertyTableToNodeAttributes(propertyTable);
438
361
  }
439
- const resourcesData = await this._convertResources(sourceTile, parentId, propertyTable);
362
+ const resourcesData = await this._convertResources(sourceTile, parentNode.inPageId, propertyTable);
440
363
  const nodes = [];
364
+ const nodeIds = [];
441
365
  const nodesInPage = [];
442
366
  const emptyResources = {
443
367
  geometry: null,
444
368
  compressedGeometry: null,
445
369
  texture: null,
370
+ hasUvRegions: false,
446
371
  sharedResources: null,
447
372
  meshMaterial: null,
448
373
  vertexCount: null,
@@ -459,26 +384,27 @@ export default class I3SConverter {
459
384
  const maxScreenThresholdSQ = lodSelection.find(val => val.metricType === 'maxScreenThresholdSQ') || {
460
385
  maxError: 0
461
386
  };
462
- const nodeInPage = this._updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources);
463
- const node = this._createNodeIndexDocument(parentTile, boundingVolumes, lodSelection, nodeInPage, resources);
387
+ const nodeInPage = await this._updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentNode.inPageId, resources);
388
+ const nodeData = await NodeIndexDocument.createNodeIndexDocument(parentNode, boundingVolumes, lodSelection, nodeInPage, resources);
389
+ const node = await new NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
390
+ nodes.push(node);
464
391
  if (nodeInPage.mesh) {
465
- await this._writeResources(resources, node.path);
392
+ await this._writeResources(resources, node.id);
466
393
  }
467
394
  if (this.validate) {
468
- this.boundingVolumeWarnings = validateNodeBoundingVolumes(node);
395
+ this.boundingVolumeWarnings = validateNodeBoundingVolumes(nodeData);
469
396
  if (this.boundingVolumeWarnings && this.boundingVolumeWarnings.length) {
470
397
  console.warn('Bounding Volume Warnings: ', ...this.boundingVolumeWarnings);
471
398
  }
472
399
  }
473
400
 
474
- nodes.push(node);
401
+ nodeIds.push(nodeInPage.index);
475
402
  nodesInPage.push(nodeInPage);
476
403
  }
477
404
  sourceTile.unloadContent();
478
405
  await this._addChildrenWithNeighborsAndWriteFile({
479
406
  parentNode: nodes[0],
480
407
  sourceTiles: sourceTile.children,
481
- parentId: nodesInPage[0].index,
482
408
  level: level + 1
483
409
  });
484
410
  return nodes;
@@ -494,20 +420,21 @@ export default class I3SConverter {
494
420
  halfSize: [],
495
421
  quaternion: []
496
422
  };
497
- const resourcesData = await convertB3dmToI3sGeometry(sourceTile.content, () => this.nodePages.push({
423
+ const resourcesData = await convertB3dmToI3sGeometry(sourceTile.content, async () => (await this.nodePages.push({
498
424
  index: 0,
499
425
  obb: draftObb
500
- }, parentId), propertyTable, this.featuresHashArray, (_this$layers2 = this.layers0) === null || _this$layers2 === void 0 ? void 0 : _this$layers2.attributeStorageInfo, this.options.draco, this.generateBoundingVolumes, this.geoidHeightModel, this.workerSource);
426
+ }, parentId)).index, propertyTable, this.featuresHashArray, (_this$layers2 = this.layers0) === null || _this$layers2 === void 0 ? void 0 : _this$layers2.attributeStorageInfo, this.options.draco, this.generateBoundingVolumes, this.options.mergeMaterials, this.geoidHeightModel, this.workerSource);
501
427
  return resourcesData;
502
428
  }
503
429
 
504
- _updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources) {
430
+ async _updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources) {
505
431
  const {
506
432
  meshMaterial,
507
433
  texture,
508
434
  vertexCount,
509
435
  featureCount,
510
- geometry
436
+ geometry,
437
+ hasUvRegions
511
438
  } = resources;
512
439
  const nodeInPage = {
513
440
  index: 0,
@@ -518,7 +445,7 @@ export default class I3SConverter {
518
445
  if (geometry && this.isContentSupported(sourceTile)) {
519
446
  nodeInPage.mesh = {
520
447
  geometry: {
521
- definition: texture ? 0 : 1,
448
+ definition: this.findOrCreateGeometryDefinition(Boolean(texture), hasUvRegions),
522
449
  resource: 0
523
450
  },
524
451
  attribute: {
@@ -530,79 +457,29 @@ export default class I3SConverter {
530
457
  };
531
458
  }
532
459
  let nodeId = resources.nodeId;
533
- if (nodeId) {
534
- this.nodePages.updateAll(nodeId, nodeInPage);
535
- const node = this.nodePages.getNodeById(nodeId);
536
- this.nodePages.updateResourceInMesh(node);
460
+ let node;
461
+ if (!nodeId) {
462
+ node = await this.nodePages.push(nodeInPage, parentId);
537
463
  } else {
538
- nodeId = this.nodePages.push(nodeInPage, parentId);
464
+ node = await this.nodePages.getNodeById(nodeId);
539
465
  }
466
+ NodePages.updateAll(node, nodeInPage);
540
467
  if (meshMaterial) {
541
- this.nodePages.updateMaterialByNodeId(nodeId, this._findOrCreateMaterial(meshMaterial));
468
+ NodePages.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
542
469
  }
543
470
  if (texture) {
544
471
  const texelCountHint = texture.image.height * texture.image.width;
545
- this.nodePages.updateTexelCountHintByNodeId(nodeId, texelCountHint);
472
+ NodePages.updateTexelCountHintByNodeId(node, texelCountHint);
546
473
  }
547
474
  if (vertexCount) {
548
475
  this.vertexCounter += vertexCount;
549
- this.nodePages.updateVertexCountByNodeId(nodeId, vertexCount);
476
+ NodePages.updateVertexCountByNodeId(node, vertexCount);
550
477
  }
551
- this.nodePages.updateNodeAttributeByNodeId(nodeId);
478
+ NodePages.updateNodeAttributeByNodeId(node);
552
479
  if (featureCount) {
553
- this.nodePages.updateFeatureCountByNodeId(nodeId, featureCount);
554
- }
555
- return this.nodePages.getNodeById(nodeId);
556
- }
557
-
558
- _createNodeIndexDocument(parentNode, boundingVolumes, lodSelection, nodeInPage, resources) {
559
- const {
560
- texture,
561
- attributes
562
- } = resources;
563
- const nodeId = nodeInPage.index;
564
- const nodeData = {
565
- version: parentNode.version,
566
- id: nodeId.toString(),
567
- path: nodeId.toString(),
568
- level: parentNode.level + 1,
569
- ...boundingVolumes,
570
- lodSelection,
571
- parentNode: {
572
- id: parentNode.id,
573
- href: "../".concat(parentNode.id),
574
- mbs: parentNode.mbs,
575
- obb: parentNode.obb
576
- },
577
- children: [],
578
- neighbors: []
579
- };
580
- const node = transform(nodeData, nodeTemplate());
581
- if (nodeInPage.mesh) {
582
- var _this$layers3, _this$layers3$attribu;
583
- node.geometryData = [{
584
- href: './geometries/0'
585
- }];
586
- node.sharedResource = {
587
- href: './shared'
588
- };
589
- if (texture) {
590
- node.textureData = [{
591
- href: './textures/0'
592
- }, {
593
- href: './textures/1'
594
- }];
595
- }
596
- if (attributes && attributes.length && (_this$layers3 = this.layers0) !== null && _this$layers3 !== void 0 && (_this$layers3$attribu = _this$layers3.attributeStorageInfo) !== null && _this$layers3$attribu !== void 0 && _this$layers3$attribu.length) {
597
- node.attributeData = [];
598
- for (let index = 0; index < attributes.length; index++) {
599
- const folderName = this.layers0.attributeStorageInfo[index].key;
600
- node.attributeData.push({
601
- href: "./attributes/".concat(folderName, "/0")
602
- });
603
- }
604
- }
480
+ NodePages.updateFeatureCountByNodeId(node, featureCount);
605
481
  }
482
+ this.nodePages.saveNode(node);
606
483
  return node;
607
484
  }
608
485
 
@@ -627,12 +504,12 @@ export default class I3SConverter {
627
504
  const slpkGeometryPath = join(childPath, 'geometries');
628
505
  await this.writeQueue.enqueue({
629
506
  archiveKey: "".concat(slpkChildPath, "/geometries/0.bin.gz"),
630
- writePromise: writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
507
+ writePromise: () => writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
631
508
  });
632
509
  } else {
633
510
  const geometryPath = join(childPath, 'geometries/0/');
634
511
  await this.writeQueue.enqueue({
635
- writePromise: writeFile(geometryPath, geometryBuffer, 'index.bin')
512
+ writePromise: () => writeFile(geometryPath, geometryBuffer, 'index.bin')
636
513
  });
637
514
  }
638
515
  if (this.options.draco) {
@@ -640,12 +517,12 @@ export default class I3SConverter {
640
517
  const slpkCompressedGeometryPath = join(childPath, 'geometries');
641
518
  await this.writeQueue.enqueue({
642
519
  archiveKey: "".concat(slpkChildPath, "/geometries/1.bin.gz"),
643
- writePromise: writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
520
+ writePromise: () => writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
644
521
  });
645
522
  } else {
646
523
  const compressedGeometryPath = join(childPath, 'geometries/1/');
647
524
  await this.writeQueue.enqueue({
648
- writePromise: writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
525
+ writePromise: () => writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
649
526
  });
650
527
  }
651
528
  }
@@ -662,12 +539,12 @@ export default class I3SConverter {
662
539
  const slpkSharedPath = join(childPath, 'shared');
663
540
  await this.writeQueue.enqueue({
664
541
  archiveKey: "".concat(slpkChildPath, "/shared/sharedResource.json.gz"),
665
- writePromise: writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
542
+ writePromise: () => writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
666
543
  });
667
544
  } else {
668
545
  const sharedPath = join(childPath, 'shared/');
669
546
  await this.writeQueue.enqueue({
670
- writePromise: writeFile(sharedPath, sharedDataStr)
547
+ writePromise: () => writeFile(sharedPath, sharedDataStr)
671
548
  });
672
549
  }
673
550
  }
@@ -727,6 +604,10 @@ export default class I3SConverter {
727
604
  this.layers0.textureSetDefinitions.push({
728
605
  formats
729
606
  });
607
+ this.layers0.textureSetDefinitions.push({
608
+ formats,
609
+ atlas: true
610
+ });
730
611
  }
731
612
  }
732
613
  }
@@ -737,22 +618,22 @@ export default class I3SConverter {
737
618
  const compress = false;
738
619
  await this.writeQueue.enqueue({
739
620
  archiveKey: "".concat(slpkChildPath, "/textures/").concat(name, ".").concat(format),
740
- writePromise: writeFileForSlpk(slpkTexturePath, textureData, "".concat(name, ".").concat(format), compress)
621
+ writePromise: () => writeFileForSlpk(slpkTexturePath, textureData, "".concat(name, ".").concat(format), compress)
741
622
  });
742
623
  } else {
743
624
  const texturePath = join(childPath, "textures/".concat(name, "/"));
744
625
  await this.writeQueue.enqueue({
745
- writePromise: writeFile(texturePath, textureData, "index.".concat(format))
626
+ writePromise: () => writeFile(texturePath, textureData, "index.".concat(format))
746
627
  });
747
628
  }
748
629
  }
749
630
 
750
631
  async _writeAttributes() {
751
- var _this$layers4, _this$layers4$attribu;
632
+ var _this$layers3, _this$layers3$attribu;
752
633
  let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
753
634
  let childPath = arguments.length > 1 ? arguments[1] : undefined;
754
635
  let slpkChildPath = arguments.length > 2 ? arguments[2] : undefined;
755
- if (attributes !== null && attributes !== void 0 && attributes.length && (_this$layers4 = this.layers0) !== null && _this$layers4 !== void 0 && (_this$layers4$attribu = _this$layers4.attributeStorageInfo) !== null && _this$layers4$attribu !== void 0 && _this$layers4$attribu.length) {
636
+ if (attributes !== null && attributes !== void 0 && attributes.length && (_this$layers3 = this.layers0) !== null && _this$layers3 !== void 0 && (_this$layers3$attribu = _this$layers3.attributeStorageInfo) !== null && _this$layers3$attribu !== void 0 && _this$layers3$attribu.length) {
756
637
  for (let index = 0; index < attributes.length; index++) {
757
638
  const folderName = this.layers0.attributeStorageInfo[index].key;
758
639
  const fileBuffer = new Uint8Array(attributes[index]);
@@ -760,12 +641,12 @@ export default class I3SConverter {
760
641
  const slpkAttributesPath = join(childPath, 'attributes', folderName);
761
642
  await this.writeQueue.enqueue({
762
643
  archiveKey: "".concat(slpkChildPath, "/attributes/").concat(folderName, ".bin.gz"),
763
- writePromise: writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
644
+ writePromise: () => writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
764
645
  });
765
646
  } else {
766
647
  const attributesPath = join(childPath, "attributes/".concat(folderName, "/0"));
767
648
  await this.writeQueue.enqueue({
768
- writePromise: writeFile(attributesPath, fileBuffer, 'index.bin')
649
+ writePromise: () => writeFile(attributesPath, fileBuffer, 'index.bin')
769
650
  });
770
651
  }
771
652
  }
@@ -788,13 +669,27 @@ export default class I3SConverter {
788
669
  _findOrCreateMaterial(material) {
789
670
  const hash = md5(JSON.stringify(material));
790
671
  if (this.materialMap.has(hash)) {
791
- return this.materialMap.get(hash);
672
+ return this.materialMap.get(hash) || 0;
792
673
  }
793
674
  const newMaterialId = this.materialDefinitions.push(material) - 1;
794
675
  this.materialMap.set(hash, newMaterialId);
795
676
  return newMaterialId;
796
677
  }
797
678
 
679
+ findOrCreateGeometryDefinition(hasTexture, hasUvRegions) {
680
+ const geometryConfig = {
681
+ hasTexture,
682
+ hasUvRegions
683
+ };
684
+ const hash = md5(JSON.stringify(geometryConfig));
685
+ if (this.geometryMap.has(hash)) {
686
+ return this.geometryMap.get(hash) || 0;
687
+ }
688
+ const newGeometryId = this.geometryConfigs.push(geometryConfig) - 1;
689
+ this.geometryMap.set(hash, newGeometryId);
690
+ return newGeometryId;
691
+ }
692
+
798
693
  _convertPropertyTableToNodeAttributes(propertyTable) {
799
694
  let attributeIndex = 0;
800
695
  const propertyTableWithObjectId = {