@loaders.gl/tile-converter 4.0.0-alpha.22 → 4.0.0-alpha.24

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 (137) hide show
  1. package/dist/3d-tiles-converter/helpers/load-i3s.d.ts.map +1 -1
  2. package/dist/constants.d.ts +0 -2
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/converter.min.js +106 -106
  5. package/dist/dist.min.js +1883 -1241
  6. package/dist/es5/3d-tiles-converter/helpers/load-i3s.js.map +1 -1
  7. package/dist/es5/constants.js +1 -5
  8. package/dist/es5/constants.js.map +1 -1
  9. package/dist/es5/deps-installer/deps-installer.js +1 -1
  10. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +26 -11
  11. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  12. package/dist/es5/i3s-converter/helpers/feature-attributes.js +7 -17
  13. package/dist/es5/i3s-converter/helpers/feature-attributes.js.map +1 -1
  14. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +83 -44
  15. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  16. package/dist/es5/i3s-converter/helpers/geometry-converter.js +70 -17
  17. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  18. package/dist/es5/i3s-converter/helpers/node-index-document.js +3 -2
  19. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -1
  20. package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js +1 -2
  21. package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
  22. package/dist/es5/i3s-converter/i3s-converter.js +36 -26
  23. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  24. package/dist/es5/i3s-converter/types.js.map +1 -1
  25. package/dist/es5/i3s-server/controllers/slpk-controller.js +2 -2
  26. package/dist/es5/i3s-server/controllers/slpk-controller.js.map +1 -1
  27. package/dist/es5/pgm-loader.js +11 -3
  28. package/dist/es5/pgm-loader.js.map +1 -1
  29. package/dist/es5/slpk-extractor/slpk-extractor.js +1 -1
  30. package/dist/es5/slpk-extractor/slpk-extractor.js.map +1 -1
  31. package/dist/esm/3d-tiles-converter/helpers/load-i3s.js.map +1 -1
  32. package/dist/esm/constants.js +0 -2
  33. package/dist/esm/constants.js.map +1 -1
  34. package/dist/esm/deps-installer/deps-installer.js +1 -1
  35. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +21 -6
  36. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  37. package/dist/esm/i3s-converter/helpers/feature-attributes.js +9 -7
  38. package/dist/esm/i3s-converter/helpers/feature-attributes.js.map +1 -1
  39. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +76 -34
  40. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  41. package/dist/esm/i3s-converter/helpers/geometry-converter.js +66 -13
  42. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  43. package/dist/esm/i3s-converter/helpers/node-index-document.js +2 -1
  44. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -1
  45. package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js +1 -1
  46. package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
  47. package/dist/esm/i3s-converter/i3s-converter.js +20 -17
  48. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  49. package/dist/esm/i3s-converter/types.js.map +1 -1
  50. package/dist/esm/i3s-server/bin/i3s-server.min.js +71 -71
  51. package/dist/esm/i3s-server/controllers/slpk-controller.js +1 -1
  52. package/dist/esm/i3s-server/controllers/slpk-controller.js.map +1 -1
  53. package/dist/esm/pgm-loader.js +7 -4
  54. package/dist/esm/pgm-loader.js.map +1 -1
  55. package/dist/esm/slpk-extractor/slpk-extractor.js +2 -1
  56. package/dist/esm/slpk-extractor/slpk-extractor.js.map +1 -1
  57. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
  58. package/dist/i3s-converter/helpers/feature-attributes.d.ts +6 -6
  59. package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -1
  60. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  61. package/dist/i3s-converter/helpers/geometry-converter.d.ts +2 -2
  62. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  63. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -1
  64. package/dist/i3s-converter/i3s-converter.d.ts +1 -1
  65. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  66. package/dist/i3s-converter/types.d.ts +7 -4
  67. package/dist/i3s-converter/types.d.ts.map +1 -1
  68. package/dist/pgm-loader.d.ts +9 -2
  69. package/dist/pgm-loader.d.ts.map +1 -1
  70. package/dist/slpk-extractor/slpk-extractor.d.ts.map +1 -1
  71. package/dist/slpk-extractor.min.js +38 -38
  72. package/package.json +14 -14
  73. package/src/3d-tiles-converter/helpers/load-i3s.ts +1 -0
  74. package/src/constants.ts +0 -3
  75. package/src/i3s-converter/helpers/batch-ids-extensions.ts +53 -14
  76. package/src/i3s-converter/helpers/feature-attributes.ts +20 -15
  77. package/src/i3s-converter/helpers/geometry-attributes.ts +80 -50
  78. package/src/i3s-converter/helpers/geometry-converter.ts +153 -21
  79. package/src/i3s-converter/helpers/node-index-document.ts +5 -1
  80. package/src/i3s-converter/helpers/preprocess-3d-tiles.ts +1 -1
  81. package/src/i3s-converter/i3s-converter.ts +42 -17
  82. package/src/i3s-converter/types.ts +8 -4
  83. package/src/i3s-server/controllers/slpk-controller.ts +1 -1
  84. package/src/pgm-loader.ts +15 -7
  85. package/src/slpk-extractor/slpk-extractor.ts +2 -1
  86. package/dist/3d-tiles-converter/3d-tiles-converter.js +0 -279
  87. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +0 -271
  88. package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +0 -23
  89. package/dist/3d-tiles-converter/helpers/load-i3s.js +0 -42
  90. package/dist/3d-tiles-converter/helpers/texture-atlas.js +0 -54
  91. package/dist/3d-tiles-converter/json-templates/tileset.js +0 -43
  92. package/dist/bundle.js +0 -5
  93. package/dist/constants.js +0 -6
  94. package/dist/converter-cli.js +0 -222
  95. package/dist/deps-installer/deps-installer.js +0 -89
  96. package/dist/i3s-converter/helpers/batch-ids-extensions.js +0 -158
  97. package/dist/i3s-converter/helpers/coordinate-converter.js +0 -122
  98. package/dist/i3s-converter/helpers/create-scene-server-path.js +0 -28
  99. package/dist/i3s-converter/helpers/feature-attributes.js +0 -216
  100. package/dist/i3s-converter/helpers/geometry-attributes.js +0 -203
  101. package/dist/i3s-converter/helpers/geometry-converter.js +0 -1240
  102. package/dist/i3s-converter/helpers/gltf-attributes.js +0 -129
  103. package/dist/i3s-converter/helpers/load-3d-tiles.js +0 -99
  104. package/dist/i3s-converter/helpers/node-debug.js +0 -120
  105. package/dist/i3s-converter/helpers/node-index-document.js +0 -268
  106. package/dist/i3s-converter/helpers/node-pages.js +0 -316
  107. package/dist/i3s-converter/helpers/preprocess-3d-tiles.js +0 -100
  108. package/dist/i3s-converter/helpers/tileset-traversal.js +0 -29
  109. package/dist/i3s-converter/i3s-converter.js +0 -945
  110. package/dist/i3s-converter/json-templates/geometry-definitions.js +0 -87
  111. package/dist/i3s-converter/json-templates/layers.js +0 -139
  112. package/dist/i3s-converter/json-templates/metadata.js +0 -25
  113. package/dist/i3s-converter/json-templates/node.js +0 -89
  114. package/dist/i3s-converter/json-templates/scene-server.js +0 -31
  115. package/dist/i3s-converter/json-templates/shared-resources.js +0 -129
  116. package/dist/i3s-converter/json-templates/store.js +0 -103
  117. package/dist/i3s-converter/types.js +0 -17
  118. package/dist/i3s-server/app.js +0 -29
  119. package/dist/i3s-server/bin/www.js +0 -37
  120. package/dist/i3s-server/controllers/index-controller.js +0 -31
  121. package/dist/i3s-server/controllers/slpk-controller.js +0 -33
  122. package/dist/i3s-server/routes/index.js +0 -20
  123. package/dist/i3s-server/routes/slpk-router.js +0 -34
  124. package/dist/i3s-server/utils/create-scene-server.js +0 -22
  125. package/dist/i3s-server/utils/server-utils.js +0 -66
  126. package/dist/index.js +0 -10
  127. package/dist/lib/utils/cli-utils.js +0 -82
  128. package/dist/lib/utils/compress-util.js +0 -257
  129. package/dist/lib/utils/file-utils.js +0 -139
  130. package/dist/lib/utils/geometry-utils.js +0 -18
  131. package/dist/lib/utils/lod-conversion-utils.js +0 -76
  132. package/dist/lib/utils/queue.js +0 -18
  133. package/dist/lib/utils/statistic-utills.js +0 -64
  134. package/dist/lib/utils/write-queue.js +0 -80
  135. package/dist/pgm-loader.js +0 -24
  136. package/dist/slpk-extractor/slpk-extractor.js +0 -74
  137. package/dist/slpk-extractor-cli.js +0 -102
@@ -1,945 +0,0 @@
1
- "use strict";
2
- // loaders.gl, MIT license
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
26
- var __importDefault = (this && this.__importDefault) || function (mod) {
27
- return (mod && mod.__esModule) ? mod : { "default": mod };
28
- };
29
- Object.defineProperty(exports, "__esModule", { value: true });
30
- const core_1 = require("@loaders.gl/core");
31
- const _3d_tiles_1 = require("@loaders.gl/3d-tiles");
32
- const path_1 = require("path");
33
- const uuid_1 = require("uuid");
34
- const process_1 = __importDefault(require("process"));
35
- const json_map_transform_1 = __importDefault(require("json-map-transform"));
36
- const md5_1 = __importDefault(require("md5"));
37
- const node_pages_1 = __importDefault(require("./helpers/node-pages"));
38
- const file_utils_1 = require("../lib/utils/file-utils");
39
- const compress_util_1 = require("../lib/utils/compress-util");
40
- const statistic_utills_1 = require("../lib/utils/statistic-utills");
41
- const geometry_converter_1 = __importStar(require("./helpers/geometry-converter"));
42
- const coordinate_converter_1 = require("./helpers/coordinate-converter");
43
- const create_scene_server_path_1 = require("./helpers/create-scene-server-path");
44
- const lod_conversion_utils_1 = require("../lib/utils/lod-conversion-utils");
45
- const pgm_loader_1 = require("../pgm-loader");
46
- const layers_1 = require("./json-templates/layers");
47
- const geometry_definitions_1 = require("./json-templates/geometry-definitions");
48
- const shared_resources_1 = require("./json-templates/shared-resources");
49
- const node_debug_1 = require("./helpers/node-debug");
50
- const textures_1 = require("@loaders.gl/textures");
51
- const images_1 = require("@loaders.gl/images");
52
- const types_1 = require("./types");
53
- const worker_utils_1 = require("@loaders.gl/worker-utils");
54
- const write_queue_1 = __importDefault(require("../lib/utils/write-queue"));
55
- const constants_1 = require("../constants");
56
- const feature_attributes_1 = require("./helpers/feature-attributes");
57
- const node_index_document_1 = require("./helpers/node-index-document");
58
- const load_3d_tiles_1 = require("./helpers/load-3d-tiles");
59
- const core_2 = require("@math.gl/core");
60
- const tiles_1 = require("@loaders.gl/tiles");
61
- const tileset_traversal_1 = require("./helpers/tileset-traversal");
62
- const preprocess_3d_tiles_1 = require("./helpers/preprocess-3d-tiles");
63
- const ION_DEFAULT_TOKEN = process_1.default.env?.IonToken;
64
- const HARDCODED_NODES_PER_PAGE = 64;
65
- const _3D_TILES = '3DTILES';
66
- const _3D_OBJECT_LAYER_TYPE = '3DObject';
67
- const REFRESH_TOKEN_TIMEOUT = 1800; // 30 minutes in seconds
68
- const CESIUM_DATASET_PREFIX = 'https://';
69
- // const FS_FILE_TOO_LARGE = 'ERR_FS_FILE_TOO_LARGE';
70
- /**
71
- * Converter from 3d-tiles tileset to i3s layer
72
- */
73
- class I3SConverter {
74
- constructor() {
75
- this.boundingVolumeWarnings = [];
76
- this.conversionStartTime = [0, 0];
77
- this.refreshTokenTime = [0, 0];
78
- this.sourceTileset = null;
79
- this.loadOptions = {
80
- _nodeWorkers: true,
81
- reuseWorkers: true,
82
- useLocalLibraries: true,
83
- basis: {
84
- format: 'rgba32',
85
- // We need to load local fs workers because nodejs can't load workers from the Internet
86
- workerUrl: './modules/textures/dist/basis-worker-node.js'
87
- },
88
- // We need to load local fs workers because nodejs can't load workers from the Internet
89
- draco: { workerUrl: './modules/draco/dist/draco-worker-node.js' },
90
- fetch: {},
91
- modules: {}
92
- };
93
- this.geoidHeightModel = null;
94
- this.Loader = _3d_tiles_1.Tiles3DLoader;
95
- this.workerSource = {};
96
- this.writeQueue = new write_queue_1.default();
97
- this.compressList = null;
98
- this.preprocessData = {
99
- meshTopologyTypes: new Set(),
100
- metadataClasses: new Set()
101
- };
102
- this.nodePages = new node_pages_1.default(file_utils_1.writeFile, HARDCODED_NODES_PER_PAGE, this);
103
- this.options = {};
104
- this.layers0Path = '';
105
- this.materialMap = new Map();
106
- this.materialDefinitions = [];
107
- this.geometryMap = new Map();
108
- this.geometryConfigs = [];
109
- this.vertexCounter = 0;
110
- this.layers0 = null;
111
- this.featuresHashArray = [];
112
- this.refinementCounter = {
113
- tilesCount: 0,
114
- tilesWithAddRefineCount: 0
115
- };
116
- this.validate = false;
117
- this.generateTextures = false;
118
- this.generateBoundingVolumes = false;
119
- this.layersHasTexture = false;
120
- this.compressList = null;
121
- }
122
- /**
123
- * Convert a 3d tileset
124
- * @param options
125
- * @param options.inputUrl the url to read the tileset from
126
- * @param options.outputPath the output filename
127
- * @param options.tilesetName the output name of the tileset
128
- * @param options.maxDepth The max tree depth of conversion
129
- * @param options.slpk Generate slpk (Scene Layer Packages) output file
130
- * @param options.sevenZipExe Location of 7z.exe archiver to create slpk on Windows
131
- * @param options.egmFilePath location of *.pgm file to convert heights from ellipsoidal to gravity-related format
132
- * @param options.token Token for Cesium ION tilesets authentication
133
- * @param options.draco Generate I3S 1.7 draco compressed geometries
134
- * @param options.validate -enable validation
135
- * @param options.generateTextures - generate alternative type of textures (to have non-compressed jpeg/png and compressed ktx2)
136
- * @param options.generateBoundingVolumes - generate bounding volumes from vertices coordinates instead of source tiles bounding volumes
137
- * @param options.instantNodeWriting - Keep created 3DNodeIndexDocument files on disk instead of memory. This option reduce memory usage but decelerates conversion speed
138
- */
139
- async convert(options) {
140
- if (core_1.isBrowser) {
141
- console.log(constants_1.BROWSER_ERROR_MESSAGE);
142
- return constants_1.BROWSER_ERROR_MESSAGE;
143
- }
144
- this.conversionStartTime = process_1.default.hrtime();
145
- const { tilesetName, slpk, egmFilePath, inputUrl, validate, outputPath, draco = true, sevenZipExe, maxDepth, token, generateTextures, generateBoundingVolumes, instantNodeWriting = false, mergeMaterials = true, inquirer, metadataClass } = options;
146
- this.options = {
147
- maxDepth,
148
- slpk,
149
- sevenZipExe,
150
- egmFilePath,
151
- draco,
152
- token,
153
- inputUrl,
154
- instantNodeWriting,
155
- mergeMaterials,
156
- inquirer,
157
- metadataClass
158
- };
159
- this.compressList = (this.options.instantNodeWriting && []) || null;
160
- this.validate = Boolean(validate);
161
- this.Loader = inputUrl.indexOf(CESIUM_DATASET_PREFIX) !== -1 ? _3d_tiles_1.CesiumIonLoader : _3d_tiles_1.Tiles3DLoader;
162
- this.generateTextures = Boolean(generateTextures);
163
- this.generateBoundingVolumes = Boolean(generateBoundingVolumes);
164
- this.writeQueue = new write_queue_1.default();
165
- this.writeQueue.startListening();
166
- console.log('Loading egm file...'); // eslint-disable-line
167
- this.geoidHeightModel = await (0, core_1.load)(egmFilePath, pgm_loader_1.PGMLoader);
168
- console.log('Loading egm file completed!'); // eslint-disable-line
169
- if (slpk) {
170
- this.nodePages.useWriteFunction(file_utils_1.writeFileForSlpk);
171
- }
172
- try {
173
- const preloadOptions = await this._fetchPreloadOptions();
174
- let tilesetUrl = inputUrl;
175
- if (preloadOptions.url) {
176
- tilesetUrl = preloadOptions.url;
177
- }
178
- if (preloadOptions.headers) {
179
- this.loadOptions.fetch = { headers: preloadOptions.headers };
180
- }
181
- this.sourceTileset = await (0, load_3d_tiles_1.loadFromArchive)(tilesetUrl, this.Loader, this.loadOptions);
182
- const preprocessResult = await this.preprocessConversion();
183
- if (preprocessResult) {
184
- await this._createAndSaveTileset(outputPath, tilesetName);
185
- await this._finishConversion({ slpk: Boolean(slpk), outputPath, tilesetName });
186
- }
187
- }
188
- catch (error) {
189
- throw error;
190
- }
191
- finally {
192
- await this.writeQueue.finalize();
193
- // Clean up worker pools
194
- const workerFarm = worker_utils_1.WorkerFarm.getWorkerFarm({});
195
- workerFarm.destroy();
196
- }
197
- return 'success';
198
- }
199
- /**
200
- * Preprocess stage of the tile converter. Traverse all the tiles tree and
201
- * check a tile content to be sure that the data is supported
202
- * @returns true - the conversion is possible, false - the tileset's content is not supported
203
- */
204
- async preprocessConversion() {
205
- console.log(`Analyze source tileset`);
206
- const sourceRootTile = this.sourceTileset.root;
207
- await (0, tileset_traversal_1.traverseDatasetWith)(sourceRootTile, null, this.analyzeTile.bind(this), undefined, this.options.maxDepth);
208
- const { meshTopologyTypes, metadataClasses } = this.preprocessData;
209
- console.log(`------------------------------------------------`);
210
- console.log(`Preprocess results:`);
211
- console.log(`glTF mesh topology types: ${Array.from(meshTopologyTypes).join(', ')}`);
212
- if (metadataClasses.size) {
213
- console.log(`Feature metadata classes have been found: ${Array.from(metadataClasses).join(', ')}`);
214
- }
215
- else {
216
- console.log('Feature metadata classes have not been found');
217
- }
218
- console.log(`------------------------------------------------`);
219
- if (!meshTopologyTypes.has(types_1.GLTFPrimitiveModeString.TRIANGLES) &&
220
- !meshTopologyTypes.has(types_1.GLTFPrimitiveModeString.TRIANGLE_STRIP)) {
221
- console.log('The tileset is of unsupported mesh topology types. The conversion will be interrupted.');
222
- console.log(`------------------------------------------------`);
223
- return false;
224
- }
225
- if (metadataClasses.size > 1) {
226
- if (this.options.metadataClass?.length) {
227
- console.log(`${this.options.metadataClass} has been selected`);
228
- }
229
- else if (this.options.inquirer) {
230
- const result = await this.options.inquirer.prompt([
231
- {
232
- name: 'metadataClass',
233
- type: 'list',
234
- message: 'Select feature metadata data class to convert...',
235
- choices: Array.from(metadataClasses)
236
- }
237
- ]);
238
- this.options.metadataClass = result.metadataClass;
239
- console.log(`${result.metadataClass} has been selected`);
240
- }
241
- else {
242
- console.log(`A feature metadata class has not been selected. Start the converter with option "--metadata-class". For example, "npx tile-converter ... --metadata-class ${Array.from(metadataClasses)[0]}"`);
243
- console.log(`------------------------------------------------`);
244
- return false;
245
- }
246
- }
247
- return true;
248
- }
249
- /**
250
- * Analyze a tile content. The callback for preprocess stage.
251
- * @param sourceTile - 3DTiles tile JSON metadata
252
- * @param traversalProps - mandatory argument but it is not used for the preprocess stage
253
- * @returns - nothing
254
- */
255
- async analyzeTile(sourceTile, traversalProps) {
256
- const isTileset = (0, load_3d_tiles_1.isNestedTileset)(sourceTile);
257
- if (isTileset) {
258
- await (0, load_3d_tiles_1.loadNestedTileset)(this.sourceTileset, sourceTile, this.loadOptions);
259
- return null;
260
- }
261
- if (sourceTile.id) {
262
- console.log(`[analyze]: ${sourceTile.id}`); // eslint-disable-line
263
- }
264
- let tileContent = null;
265
- try {
266
- tileContent = await (0, load_3d_tiles_1.loadTile3DContent)(this.sourceTileset, sourceTile, {
267
- ...this.loadOptions,
268
- '3d-tiles': { ...this.loadOptions['3d-tiles'], loadGLTF: false }
269
- });
270
- }
271
- catch (error) {
272
- console.log(`[warning]: Failed to load ${sourceTile.contentUrl}. An I3S tile with empty content will be added to the output tileset`);
273
- }
274
- const tilePreprocessData = await (0, preprocess_3d_tiles_1.analyzeTileContent)(tileContent);
275
- (0, preprocess_3d_tiles_1.mergePreprocessData)(this.preprocessData, tilePreprocessData);
276
- return null;
277
- }
278
- /**
279
- * Convert and save the layer and embedded tiles
280
- * @param outputPath - path to save output data
281
- * @param tilesetName - new tileset path
282
- */
283
- async _createAndSaveTileset(outputPath, tilesetName) {
284
- const tilesetPath = (0, path_1.join)(`${outputPath}`, `${tilesetName}`);
285
- // Removing the tilesetPath needed to exclude erroneous files after conversion
286
- try {
287
- await (0, file_utils_1.removeDir)(tilesetPath);
288
- }
289
- catch (e) {
290
- // do nothing
291
- }
292
- this.layers0Path = (0, path_1.join)(tilesetPath, 'SceneServer', 'layers', '0');
293
- this.materialDefinitions = [];
294
- this.materialMap = new Map();
295
- const sourceRootTile = this.sourceTileset.root;
296
- const sourceBoundingVolume = (0, tiles_1.createBoundingVolume)(sourceRootTile.boundingVolume, new core_2.Matrix4(sourceRootTile.transform), null);
297
- this._formLayers0(tilesetName, sourceBoundingVolume, this.sourceTileset?.root?.boundingVolume?.region);
298
- const boundingVolumes = (0, coordinate_converter_1.createBoundingVolumes)(sourceBoundingVolume, this.geoidHeightModel);
299
- await this.nodePages.push({
300
- index: 0,
301
- lodThreshold: 0,
302
- obb: boundingVolumes.obb,
303
- children: []
304
- });
305
- const rootNode = await node_index_document_1.NodeIndexDocument.createRootNode(boundingVolumes, this);
306
- await (0, tileset_traversal_1.traverseDatasetWith)(sourceRootTile, {
307
- transform: new core_2.Matrix4(sourceRootTile.transform),
308
- parentNodes: [rootNode]
309
- }, this.convertTile.bind(this), this.finalizeTile.bind(this), this.options.maxDepth);
310
- this.layers0.materialDefinitions = this.materialDefinitions;
311
- // @ts-ignore
312
- this.layers0.geometryDefinitions = (0, json_map_transform_1.default)(this.geometryConfigs.map((config) => ({
313
- geometryConfig: { ...config, draco: this.options.draco }
314
- })), (0, geometry_definitions_1.GEOMETRY_DEFINITION)());
315
- if (this.layersHasTexture === false) {
316
- this.layers0.store.defaultGeometrySchema.ordering =
317
- this.layers0.store.defaultGeometrySchema.ordering.filter((attribute) => attribute !== 'uv0');
318
- }
319
- await this._writeLayers0();
320
- (0, create_scene_server_path_1.createSceneServerPath)(tilesetName, this.layers0, tilesetPath);
321
- for (const filePath of this.compressList || []) {
322
- await (0, compress_util_1.compressFileWithGzip)(filePath);
323
- await (0, file_utils_1.removeFile)(filePath);
324
- }
325
- await this.nodePages.save();
326
- await this.writeQueue.finalize();
327
- await this._createSlpk(tilesetPath);
328
- }
329
- /**
330
- * Form object of 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
331
- * @param tilesetName - Name of layer
332
- * @param sourceBoundingVolume - initialized bounding volume of the source root tile
333
- * @param boundingVolumeRegion - region bounding volume of the source root tile
334
- */
335
- _formLayers0(tilesetName, sourceBoundingVolume, boundingVolumeRegion) {
336
- if (!this.sourceTileset?.root) {
337
- return;
338
- }
339
- const fullExtent = (0, coordinate_converter_1.convertBoundingVolumeToI3SFullExtent)(sourceBoundingVolume);
340
- if (boundingVolumeRegion) {
341
- fullExtent.zmin = boundingVolumeRegion[4];
342
- fullExtent.zmax = boundingVolumeRegion[5];
343
- }
344
- const extent = [fullExtent.xmin, fullExtent.ymin, fullExtent.xmax, fullExtent.ymax];
345
- const layers0data = {
346
- version: `{${(0, uuid_1.v4)().toUpperCase()}}`,
347
- id: 0,
348
- name: tilesetName,
349
- href: './layers/0',
350
- store: {
351
- id: `{${(0, uuid_1.v4)().toUpperCase()}}`,
352
- extent
353
- },
354
- nodePages: {
355
- nodesPerPage: HARDCODED_NODES_PER_PAGE
356
- },
357
- compressGeometry: this.options.draco,
358
- fullExtent
359
- };
360
- this.layers0 = (0, json_map_transform_1.default)(layers0data, (0, layers_1.LAYERS)());
361
- }
362
- /**
363
- * Write 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md in file
364
- */
365
- async _writeLayers0() {
366
- if (this.options.slpk) {
367
- await this.writeQueue.enqueue({
368
- archiveKey: '3dSceneLayer.json.gz',
369
- writePromise: () => (0, file_utils_1.writeFileForSlpk)(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
370
- });
371
- }
372
- else {
373
- await this.writeQueue.enqueue({
374
- writePromise: () => (0, file_utils_1.writeFile)(this.layers0Path, JSON.stringify(this.layers0))
375
- });
376
- }
377
- }
378
- /**
379
- * Pack files into *.slpk archive
380
- * @param tilesetPath - Path to save file
381
- */
382
- async _createSlpk(tilesetPath) {
383
- if (this.options.slpk) {
384
- const slpkTilesetPath = (0, path_1.join)(tilesetPath, 'SceneServer', 'layers', '0');
385
- const slpkFileName = `${tilesetPath}.slpk`;
386
- await (0, compress_util_1.compressWithChildProcess)(slpkTilesetPath, slpkFileName, 0, '.', this.options.sevenZipExe);
387
- // TODO: `addFileToZip` corrupts archive so it can't be validated with windows i3s_converter.exe
388
- // const fileHash128Path = `${tilesetPath}/@specialIndexFileHASH128@`;
389
- // try {
390
- // await generateHash128FromZip(slpkFileName, fileHash128Path);
391
- // await addFileToZip(
392
- // tilesetPath,
393
- // '@specialIndexFileHASH128@',
394
- // slpkFileName,
395
- // this.options.sevenZipExe
396
- // );
397
- // } catch (error) {
398
- // if (error.code === FS_FILE_TOO_LARGE) {
399
- // console.warn(`${slpkFileName} file is too big to generate a hash`); // eslint-disable-line
400
- // } else {
401
- // console.error(error); // eslint-disable-line
402
- // }
403
- // }
404
- // All converted files are contained in slpk now they can be deleted
405
- try {
406
- await (0, file_utils_1.removeDir)(tilesetPath);
407
- }
408
- catch (e) {
409
- // do nothing
410
- }
411
- }
412
- }
413
- /**
414
- * Convert the specific 3DTiles tile to I3S nodes.
415
- * This is callback function for the traversal generic function
416
- * @param sourceTile - current 3DTiles tile JSON metadata
417
- * @param traversalProps - traversal properties calculated recursively
418
- * @returns - traversal properties for the child tiles
419
- */
420
- async convertTile(sourceTile, traversalProps) {
421
- const isTileset = (0, load_3d_tiles_1.isNestedTileset)(sourceTile);
422
- if (isTileset || sourceTile.type === 'empty') {
423
- if (isTileset) {
424
- if (sourceTile.id) {
425
- console.log(`[load]: ${sourceTile.id}`); // eslint-disable-line
426
- }
427
- await (0, load_3d_tiles_1.loadNestedTileset)(this.sourceTileset, sourceTile, this.loadOptions);
428
- }
429
- return traversalProps;
430
- }
431
- if (sourceTile.id) {
432
- console.log(`[convert]: ${sourceTile.id}`); // eslint-disable-line
433
- }
434
- const { parentNodes, transform } = traversalProps;
435
- let transformationMatrix = transform.clone();
436
- if (sourceTile.transform) {
437
- transformationMatrix = transformationMatrix.multiplyRight(sourceTile.transform);
438
- }
439
- const parentNode = parentNodes[0];
440
- const childNodes = await this._createNode(parentNode, sourceTile, transformationMatrix);
441
- await parentNode.addChildren(childNodes);
442
- const newTraversalProps = {
443
- transform: transformationMatrix,
444
- parentNodes: childNodes
445
- };
446
- return newTraversalProps;
447
- }
448
- /**
449
- * Do final action with nodes after the current node and all child nodes been converted.
450
- * @param conversionResults - array of conversion results of the current node
451
- * @param currentTraversalProps - traversal properties of the current node
452
- */
453
- async finalizeTile(conversionResults, currentTraversalProps) {
454
- for (const result of conversionResults) {
455
- for (const node of result.parentNodes) {
456
- await node.addNeighbors();
457
- }
458
- }
459
- for (const node of currentTraversalProps.parentNodes) {
460
- await node.save();
461
- }
462
- }
463
- /**
464
- * Convert tile to one or more I3S nodes
465
- * @param parentNode - 3DNodeIndexDocument of parent node
466
- * @param sourceTile - source 3DTile data
467
- * @param transformationMatrix - transformation matrix of the current tile, calculated recursively multiplying
468
- * transform of all parent tiles and transform of the current tile
469
- * @param level - tree level
470
- */
471
- async _createNode(parentNode, sourceTile, transformationMatrix) {
472
- this._checkAddRefinementTypeForTile(sourceTile);
473
- await this._updateTilesetOptions();
474
- let tileContent = null;
475
- try {
476
- tileContent = await (0, load_3d_tiles_1.loadTile3DContent)(this.sourceTileset, sourceTile, this.loadOptions);
477
- }
478
- catch (error) {
479
- console.log(`[warning]: Failed to load ${sourceTile.contentUrl}`);
480
- }
481
- const sourceBoundingVolume = (0, tiles_1.createBoundingVolume)(sourceTile.boundingVolume, transformationMatrix, null);
482
- let boundingVolumes = (0, coordinate_converter_1.createBoundingVolumes)(sourceBoundingVolume, this.geoidHeightModel);
483
- const propertyTable = (0, geometry_converter_1.getPropertyTable)(tileContent, this.options.metadataClass);
484
- if (propertyTable && !this.layers0?.attributeStorageInfo?.length) {
485
- this._convertPropertyTableToNodeAttributes(propertyTable);
486
- }
487
- const resourcesData = await this._convertResources(sourceTile, transformationMatrix, sourceBoundingVolume, tileContent, parentNode.inPageId, propertyTable);
488
- const nodes = [];
489
- const nodeIds = [];
490
- const nodesInPage = [];
491
- const emptyResources = {
492
- geometry: null,
493
- compressedGeometry: null,
494
- texture: null,
495
- hasUvRegions: false,
496
- sharedResources: null,
497
- meshMaterial: null,
498
- vertexCount: null,
499
- attributes: null,
500
- featureCount: null,
501
- boundingVolumes: null
502
- };
503
- for (const resources of resourcesData || [emptyResources]) {
504
- this.layersHasTexture = this.layersHasTexture || Boolean(resources.texture);
505
- if (this.generateBoundingVolumes && resources.boundingVolumes) {
506
- boundingVolumes = resources.boundingVolumes;
507
- }
508
- const lodSelection = (0, lod_conversion_utils_1.convertGeometricErrorToScreenThreshold)(sourceTile, boundingVolumes);
509
- const maxScreenThresholdSQ = lodSelection.find((val) => val.metricType === 'maxScreenThresholdSQ') || { maxError: 0 };
510
- const nodeInPage = await this._updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentNode.inPageId, resources);
511
- const nodeData = await node_index_document_1.NodeIndexDocument.createNodeIndexDocument(parentNode, boundingVolumes, lodSelection, nodeInPage, resources);
512
- const node = await new node_index_document_1.NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
513
- nodes.push(node);
514
- if (nodeInPage.mesh) {
515
- await this._writeResources(resources, node.id);
516
- }
517
- if (this.validate) {
518
- this.boundingVolumeWarnings = (0, node_debug_1.validateNodeBoundingVolumes)(nodeData);
519
- if (this.boundingVolumeWarnings && this.boundingVolumeWarnings.length) {
520
- console.warn('Bounding Volume Warnings: ', ...this.boundingVolumeWarnings); //eslint-disable-line
521
- }
522
- }
523
- nodeIds.push(nodeInPage.index);
524
- nodesInPage.push(nodeInPage);
525
- }
526
- return nodes;
527
- }
528
- /**
529
- * Convert tile to one or more I3S nodes
530
- * @param sourceTile - source tile (3DTile)
531
- * @param transformationMatrix - transformation matrix of the current tile, calculated recursively multiplying
532
- * transform of all parent tiles and transform of the current tile
533
- * @param boundingVolume - initialized bounding volume of the source tile
534
- * @param tileContent - content of the source tile
535
- * @param parentId - id of parent node in node pages
536
- * @param propertyTable - batch table from b3dm / feature properties from EXT_FEATURE_METADATA
537
- * @returns - converted node resources
538
- */
539
- async _convertResources(sourceTile, transformationMatrix, boundingVolume, tileContent, parentId, propertyTable) {
540
- if (!this.isContentSupported(sourceTile) || !tileContent) {
541
- return null;
542
- }
543
- const draftObb = {
544
- center: [],
545
- halfSize: [],
546
- quaternion: []
547
- };
548
- const resourcesData = await (0, geometry_converter_1.default)(tileContent, transformationMatrix, boundingVolume, async () => (await this.nodePages.push({ index: 0, obb: draftObb }, parentId)).index, propertyTable, this.featuresHashArray, this.layers0?.attributeStorageInfo, this.options.draco, this.generateBoundingVolumes, this.options.mergeMaterials, this.geoidHeightModel, this.loadOptions.modules, this.options.metadataClass);
549
- return resourcesData;
550
- }
551
- /**
552
- * Update node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
553
- * in node pages (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/nodePage.cmn.md)
554
- * @param maxScreenThresholdSQ - Level of Details (LOD) metric
555
- * @param boundingVolumes - Bounding volumes
556
- * @param sourceTile - source tile (3DTile)
557
- * @param parentId - id of parent node in node pages
558
- * @param resources - the node resources data
559
- * @param resources.meshMaterial - PBR-like material object
560
- * @param resources.texture - texture image
561
- * @param resources.vertexCount - number of vertices in geometry
562
- * @param resources.featureCount - number of features
563
- * @param resources.geometry - Uint8Array with geometry attributes
564
- * @return the node object in node pages
565
- */
566
- async _updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources) {
567
- const { meshMaterial, texture, vertexCount, featureCount, geometry, hasUvRegions } = resources;
568
- const nodeInPage = {
569
- index: 0,
570
- lodThreshold: maxScreenThresholdSQ.maxError,
571
- obb: boundingVolumes.obb,
572
- children: []
573
- };
574
- if (geometry && this.isContentSupported(sourceTile)) {
575
- nodeInPage.mesh = {
576
- geometry: {
577
- definition: this.findOrCreateGeometryDefinition(Boolean(texture), hasUvRegions),
578
- resource: 0
579
- },
580
- attribute: {
581
- resource: 0
582
- },
583
- material: {
584
- definition: 0
585
- }
586
- };
587
- }
588
- let nodeId = resources.nodeId;
589
- let node;
590
- if (!nodeId) {
591
- node = await this.nodePages.push(nodeInPage, parentId);
592
- }
593
- else {
594
- node = await this.nodePages.getNodeById(nodeId);
595
- }
596
- if (!nodeInPage.mesh) {
597
- console.log(`[warning]: node ${node.index} is created with empty content`);
598
- }
599
- node_pages_1.default.updateAll(node, nodeInPage);
600
- if (meshMaterial) {
601
- node_pages_1.default.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
602
- }
603
- if (texture) {
604
- const texelCountHint = texture.image.height * texture.image.width;
605
- node_pages_1.default.updateTexelCountHintByNodeId(node, texelCountHint);
606
- }
607
- if (vertexCount) {
608
- this.vertexCounter += vertexCount;
609
- node_pages_1.default.updateVertexCountByNodeId(node, vertexCount);
610
- }
611
- node_pages_1.default.updateNodeAttributeByNodeId(node);
612
- if (featureCount) {
613
- node_pages_1.default.updateFeatureCountByNodeId(node, featureCount);
614
- }
615
- this.nodePages.saveNode(node);
616
- return node;
617
- }
618
- /**
619
- * Write node resources in files
620
- * @param resources - source tile (3DTile)
621
- * @param resources.geometry - Uint8Array with geometry attributes
622
- * @param resources.compressedGeometry - Uint8Array with compressed (draco) geometry
623
- * @param resources.texture - texture image
624
- * @param resources.sharedResources - shared resource data object
625
- * @param resources.attributes - feature attributes
626
- * @return {Promise<void>}
627
- */
628
- async _writeResources(resources, nodePath) {
629
- const { geometry: geometryBuffer, compressedGeometry, texture, sharedResources, attributes } = resources;
630
- const childPath = (0, path_1.join)(this.layers0Path, 'nodes', nodePath);
631
- const slpkChildPath = (0, path_1.join)('nodes', nodePath);
632
- await this._writeGeometries(geometryBuffer, compressedGeometry, childPath, slpkChildPath);
633
- await this._writeShared(sharedResources, childPath, slpkChildPath, nodePath);
634
- await this._writeTexture(texture, childPath, slpkChildPath);
635
- await this._writeAttributes(attributes, childPath, slpkChildPath);
636
- }
637
- /**
638
- * Write non-compressed and compressed geometries in files
639
- * @param geometryBuffer - Uint8Array with geometry attributes
640
- * @param compressedGeometry - Uint8Array with compressed (draco) geometry
641
- * @param childPath - a child path to write resources
642
- * @param slpkChildPath - resource path inside *slpk file
643
- */
644
- async _writeGeometries(geometryBuffer, compressedGeometry, childPath, slpkChildPath) {
645
- if (this.options.slpk) {
646
- const slpkGeometryPath = (0, path_1.join)(childPath, 'geometries');
647
- await this.writeQueue.enqueue({
648
- archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
649
- writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkGeometryPath, geometryBuffer, '0.bin')
650
- });
651
- }
652
- else {
653
- const geometryPath = (0, path_1.join)(childPath, 'geometries/0/');
654
- await this.writeQueue.enqueue({
655
- writePromise: () => (0, file_utils_1.writeFile)(geometryPath, geometryBuffer, 'index.bin')
656
- });
657
- }
658
- if (this.options.draco) {
659
- if (this.options.slpk) {
660
- const slpkCompressedGeometryPath = (0, path_1.join)(childPath, 'geometries');
661
- await this.writeQueue.enqueue({
662
- archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
663
- writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
664
- });
665
- }
666
- else {
667
- const compressedGeometryPath = (0, path_1.join)(childPath, 'geometries/1/');
668
- await this.writeQueue.enqueue({
669
- writePromise: () => (0, file_utils_1.writeFile)(compressedGeometryPath, compressedGeometry, 'index.bin')
670
- });
671
- }
672
- }
673
- }
674
- /**
675
- * Write shared resources in a file
676
- * @param sharedResources - shared resource data object
677
- * @param childPath - a child path to write resources
678
- * @param slpkChildPath - resource path inside *slpk file
679
- * @param nodePath - a node path
680
- */
681
- async _writeShared(sharedResources, childPath, slpkChildPath, nodePath) {
682
- if (!sharedResources) {
683
- return;
684
- }
685
- sharedResources.nodePath = nodePath;
686
- const sharedData = (0, json_map_transform_1.default)(sharedResources, (0, shared_resources_1.SHARED_RESOURCES)());
687
- const sharedDataStr = JSON.stringify(sharedData);
688
- if (this.options.slpk) {
689
- const slpkSharedPath = (0, path_1.join)(childPath, 'shared');
690
- await this.writeQueue.enqueue({
691
- archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
692
- writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkSharedPath, sharedDataStr, 'sharedResource.json')
693
- });
694
- }
695
- else {
696
- const sharedPath = (0, path_1.join)(childPath, 'shared/');
697
- await this.writeQueue.enqueue({ writePromise: () => (0, file_utils_1.writeFile)(sharedPath, sharedDataStr) });
698
- }
699
- }
700
- /**
701
- * Generates textures based on texture mime type and fill in textureSetDefinitions data.
702
- * @param texture - the texture image
703
- * @param childPath - a child path to write resources
704
- * @param slpkChildPath - the resource path inside *slpk file
705
- */
706
- async _writeTexture(texture, childPath, slpkChildPath) {
707
- if (texture) {
708
- const format = this._getFormatByMimeType(texture?.mimeType);
709
- const formats = [];
710
- const textureData = texture.bufferView.data;
711
- switch (format) {
712
- case 'jpg':
713
- case 'png': {
714
- formats.push({ name: '0', format });
715
- await this.writeTextureFile(textureData, '0', format, childPath, slpkChildPath);
716
- if (this.generateTextures) {
717
- formats.push({ name: '1', format: 'ktx2' });
718
- // For Node.js texture.image.data is type of Buffer
719
- const copyArrayBuffer = texture.image.data.subarray();
720
- const arrayToEncode = new Uint8Array(copyArrayBuffer);
721
- const ktx2TextureData = (0, core_1.encode)({ ...texture.image, data: arrayToEncode }, textures_1.KTX2BasisWriterWorker, {
722
- ...textures_1.KTX2BasisWriterWorker.options,
723
- ['ktx2-basis-writer']: {
724
- // We need to load local fs workers because nodejs can't load workers from the Internet
725
- workerUrl: './modules/textures/dist/ktx2-basis-writer-worker-node.js'
726
- },
727
- reuseWorkers: true,
728
- _nodeWorkers: true,
729
- useLocalLibraries: true
730
- });
731
- await this.writeTextureFile(ktx2TextureData, '1', 'ktx2', childPath, slpkChildPath);
732
- }
733
- break;
734
- }
735
- case 'ktx2': {
736
- formats.push({ name: '1', format });
737
- await this.writeTextureFile(textureData, '1', format, childPath, slpkChildPath);
738
- if (this.generateTextures) {
739
- formats.push({ name: '0', format: 'jpg' });
740
- const decodedFromKTX2TextureData = (0, core_1.encode)(texture.image.data[0], images_1.ImageWriter);
741
- await this.writeTextureFile(decodedFromKTX2TextureData, '0', 'jpg', childPath, slpkChildPath);
742
- }
743
- }
744
- }
745
- if (!this.layers0.textureSetDefinitions.length) {
746
- this.layers0.textureSetDefinitions.push({ formats });
747
- this.layers0.textureSetDefinitions.push({ formats, atlas: true });
748
- }
749
- }
750
- }
751
- /**
752
- * Write the texture image in a file
753
- * @param textureData
754
- * @param name
755
- * @param format
756
- * @param childPath
757
- * @param slpkChildPath
758
- */
759
- async writeTextureFile(textureData, name, format, childPath, slpkChildPath) {
760
- if (this.options.slpk) {
761
- const slpkTexturePath = (0, path_1.join)(childPath, 'textures');
762
- const compress = false;
763
- await this.writeQueue.enqueue({
764
- archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
765
- writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkTexturePath, textureData, `${name}.${format}`, compress)
766
- });
767
- }
768
- else {
769
- const texturePath = (0, path_1.join)(childPath, `textures/${name}/`);
770
- await this.writeQueue.enqueue({
771
- writePromise: () => (0, file_utils_1.writeFile)(texturePath, textureData, `index.${format}`)
772
- });
773
- }
774
- }
775
- /**
776
- * Write feature attributes in files
777
- * @param attributes - feature attributes
778
- * @param childPath - a child path to write resources
779
- * @param slpkChildPath - the resource path inside *slpk file
780
- */
781
- async _writeAttributes(attributes = [], childPath, slpkChildPath) {
782
- if (attributes?.length && this.layers0?.attributeStorageInfo?.length) {
783
- for (let index = 0; index < attributes.length; index++) {
784
- const folderName = this.layers0.attributeStorageInfo[index].key;
785
- const fileBuffer = new Uint8Array(attributes[index]);
786
- if (this.options.slpk) {
787
- const slpkAttributesPath = (0, path_1.join)(childPath, 'attributes', folderName);
788
- await this.writeQueue.enqueue({
789
- archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
790
- writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkAttributesPath, fileBuffer, '0.bin')
791
- });
792
- }
793
- else {
794
- const attributesPath = (0, path_1.join)(childPath, `attributes/${folderName}/0`);
795
- await this.writeQueue.enqueue({
796
- writePromise: () => (0, file_utils_1.writeFile)(attributesPath, fileBuffer, 'index.bin')
797
- });
798
- }
799
- }
800
- }
801
- }
802
- /**
803
- * Return file format by its MIME type
804
- * @param mimeType - feature attributes
805
- */
806
- _getFormatByMimeType(mimeType) {
807
- switch (mimeType) {
808
- case 'image/jpeg':
809
- return 'jpg';
810
- case 'image/png':
811
- return 'png';
812
- case 'image/ktx2':
813
- return 'ktx2';
814
- default:
815
- return 'jpg';
816
- }
817
- }
818
- /**
819
- * Find or create material in materialDefinitions array
820
- * @param material - end-to-end index of the node
821
- * @return material id
822
- */
823
- _findOrCreateMaterial(material) {
824
- const hash = (0, md5_1.default)(JSON.stringify(material));
825
- if (this.materialMap.has(hash)) {
826
- return this.materialMap.get(hash) || 0;
827
- }
828
- const newMaterialId = this.materialDefinitions.push(material) - 1;
829
- this.materialMap.set(hash, newMaterialId);
830
- return newMaterialId;
831
- }
832
- /**
833
- * Get unique geometry configuration index
834
- * In the end of conversion configurations will be transformed to geometryDefinitions array
835
- * @param hasTexture
836
- * @param hasUvRegions
837
- * @returns
838
- */
839
- findOrCreateGeometryDefinition(hasTexture, hasUvRegions) {
840
- const geometryConfig = { hasTexture, hasUvRegions };
841
- const hash = (0, md5_1.default)(JSON.stringify(geometryConfig));
842
- if (this.geometryMap.has(hash)) {
843
- return this.geometryMap.get(hash) || 0;
844
- }
845
- const newGeometryId = this.geometryConfigs.push(geometryConfig) - 1;
846
- this.geometryMap.set(hash, newGeometryId);
847
- return newGeometryId;
848
- }
849
- /**
850
- * Do conversion of 3DTiles property table to I3s node attributes.
851
- * @param propertyTable - Table with layer meta data.
852
- */
853
- _convertPropertyTableToNodeAttributes(propertyTable) {
854
- let attributeIndex = 0;
855
- const propertyTableWithObjectId = {
856
- OBJECTID: [0],
857
- ...propertyTable
858
- };
859
- for (const key in propertyTableWithObjectId) {
860
- const firstAttribute = propertyTableWithObjectId[key][0];
861
- const attributeType = (0, feature_attributes_1.getAttributeType)(key, firstAttribute);
862
- const storageAttribute = (0, feature_attributes_1.createdStorageAttribute)(attributeIndex, key, attributeType);
863
- const fieldAttributeType = (0, feature_attributes_1.getFieldAttributeType)(attributeType);
864
- const fieldAttribute = (0, feature_attributes_1.createFieldAttribute)(key, fieldAttributeType);
865
- const popupInfo = (0, feature_attributes_1.createPopupInfo)(propertyTableWithObjectId);
866
- this.layers0.attributeStorageInfo.push(storageAttribute);
867
- this.layers0.fields.push(fieldAttribute);
868
- this.layers0.popupInfo = popupInfo;
869
- this.layers0.layerType = _3D_OBJECT_LAYER_TYPE;
870
- attributeIndex += 1;
871
- }
872
- }
873
- /**
874
- * Print statistics in the end of conversion
875
- * @param params - output files data
876
- */
877
- async _finishConversion(params) {
878
- const { tilesCount, tilesWithAddRefineCount } = this.refinementCounter;
879
- const addRefinementPercentage = tilesWithAddRefineCount
880
- ? (tilesWithAddRefineCount / tilesCount) * 100
881
- : 0;
882
- const filesSize = await (0, statistic_utills_1.calculateFilesSize)(params);
883
- const diff = process_1.default.hrtime(this.conversionStartTime);
884
- const conversionTime = (0, statistic_utills_1.timeConverter)(diff);
885
- console.log(`------------------------------------------------`); // eslint-disable-line no-undef, no-console
886
- console.log(`Finishing conversion of ${_3D_TILES}`); // eslint-disable-line no-undef, no-console
887
- console.log(`Total conversion time: ${conversionTime}`); // eslint-disable-line no-undef, no-console
888
- console.log(`Vertex count: `, this.vertexCounter); // eslint-disable-line no-undef, no-console
889
- console.log(`File(s) size: `, filesSize, ' bytes'); // eslint-disable-line no-undef, no-console
890
- console.log(`Percentage of tiles with "ADD" refinement type:`, addRefinementPercentage, '%'); // eslint-disable-line no-undef, no-console
891
- console.log(`------------------------------------------------`); // eslint-disable-line no-undef, no-console
892
- }
893
- /**
894
- * Fetch preload options for ION tileset
895
- */
896
- async _fetchPreloadOptions() {
897
- if (!this.Loader.preload) {
898
- return {};
899
- }
900
- const options = {
901
- 'cesium-ion': { accessToken: this.options.token || ION_DEFAULT_TOKEN }
902
- };
903
- const preloadOptions = await this.Loader.preload(this.options.inputUrl, options);
904
- this.refreshTokenTime = process_1.default.hrtime();
905
- return { ...options, ...preloadOptions };
906
- }
907
- /**
908
- * Update options of source tileset
909
- */
910
- async _updateTilesetOptions() {
911
- const diff = process_1.default.hrtime(this.refreshTokenTime);
912
- if (diff[0] < REFRESH_TOKEN_TIMEOUT) {
913
- return;
914
- }
915
- this.refreshTokenTime = process_1.default.hrtime();
916
- const preloadOptions = await this._fetchPreloadOptions();
917
- if (preloadOptions.headers) {
918
- this.loadOptions.fetch = {
919
- ...this.loadOptions.fetch,
920
- headers: preloadOptions.headers
921
- };
922
- console.log('Authorization Bearer token has been updated'); // eslint-disable-line no-undef, no-console
923
- }
924
- }
925
- /** Do calculations of all tiles and tiles with "ADD" type of refinement.
926
- * @param tile
927
- */
928
- _checkAddRefinementTypeForTile(tile) {
929
- const ADD_TILE_REFINEMENT = 1;
930
- if (tile.refine === ADD_TILE_REFINEMENT) {
931
- this.refinementCounter.tilesWithAddRefineCount += 1;
932
- console.warn('This tile uses "ADD" type of refinement'); // eslint-disable-line
933
- }
934
- this.refinementCounter.tilesCount += 1;
935
- }
936
- /**
937
- * Check if the tile's content format is supported by the converter
938
- * @param sourceTile
939
- * @returns
940
- */
941
- isContentSupported(sourceTile) {
942
- return ['b3dm', 'glTF', 'scenegraph'].includes(sourceTile.type || '');
943
- }
944
- }
945
- exports.default = I3SConverter;