@loaders.gl/tile-converter 4.1.0-alpha.1 → 4.1.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/converter-cli.js +41 -4
- package/dist/converter-cli.js.map +1 -1
- package/dist/converter.min.cjs +110 -110
- package/dist/deps-installer/deps-installer.d.ts.map +1 -1
- package/dist/deps-installer/deps-installer.js +4 -3
- package/dist/deps-installer/deps-installer.js.map +1 -1
- package/dist/i3s-converter/i3s-converter.d.ts +14 -0
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.js +71 -17
- package/dist/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/i3s-converter/types.d.ts +7 -0
- package/dist/i3s-converter/types.d.ts.map +1 -1
- package/dist/i3s-converter/types.js +8 -0
- package/dist/i3s-converter/types.js.map +1 -1
- package/dist/i3s-server/bin/i3s-server.min.cjs +72 -72
- package/dist/index.cjs +347 -38
- package/dist/lib/utils/conversion-dump.d.ts +80 -0
- package/dist/lib/utils/conversion-dump.d.ts.map +1 -0
- package/dist/lib/utils/conversion-dump.js +127 -0
- package/dist/lib/utils/conversion-dump.js.map +1 -0
- package/dist/lib/utils/statistic-utills.d.ts +23 -6
- package/dist/lib/utils/write-queue.d.ts +6 -1
- package/dist/lib/utils/write-queue.d.ts.map +1 -1
- package/dist/lib/utils/write-queue.js +15 -3
- package/dist/lib/utils/write-queue.js.map +1 -1
- package/dist/pgm-loader.js +1 -1
- package/dist/pgm-loader.js.map +1 -1
- package/dist/slpk-extractor.min.cjs +46 -46
- package/package.json +16 -16
- package/src/constants.ts +1 -0
- package/src/converter-cli.ts +58 -4
- package/src/deps-installer/deps-installer.ts +3 -2
- package/src/i3s-converter/i3s-converter.ts +189 -21
- package/src/i3s-converter/types.ts +8 -0
- package/src/lib/utils/conversion-dump.ts +198 -0
- package/src/lib/utils/write-queue.ts +15 -2
- package/dist/lib/utils/statistic-utills.d.js +0 -2
- package/dist/lib/utils/statistic-utills.d.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loaders.gl/tile-converter",
|
|
3
|
-
"version": "4.1.0-alpha.
|
|
3
|
+
"version": "4.1.0-alpha.10",
|
|
4
4
|
"description": "Converter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"module": "dist/index.js",
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
24
25
|
"import": "./dist/index.js",
|
|
25
|
-
"require": "./dist/index.cjs"
|
|
26
|
-
"types": "./dist/index.d.ts"
|
|
26
|
+
"require": "./dist/index.cjs"
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"sideEffects": false,
|
|
@@ -52,18 +52,18 @@
|
|
|
52
52
|
"build-i3s-server-bundle": "esbuild src/i3s-server/bin/www.ts --outfile=dist/i3s-server/bin/i3s-server.min.cjs --platform=node --target=esnext,node14 --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\""
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@loaders.gl/3d-tiles": "4.1.0-alpha.
|
|
56
|
-
"@loaders.gl/crypto": "4.1.0-alpha.
|
|
57
|
-
"@loaders.gl/draco": "4.1.0-alpha.
|
|
58
|
-
"@loaders.gl/gltf": "4.1.0-alpha.
|
|
59
|
-
"@loaders.gl/i3s": "4.1.0-alpha.
|
|
60
|
-
"@loaders.gl/images": "4.1.0-alpha.
|
|
61
|
-
"@loaders.gl/loader-utils": "4.1.0-alpha.
|
|
62
|
-
"@loaders.gl/polyfills": "4.1.0-alpha.
|
|
63
|
-
"@loaders.gl/textures": "4.1.0-alpha.
|
|
64
|
-
"@loaders.gl/tiles": "4.1.0-alpha.
|
|
65
|
-
"@loaders.gl/worker-utils": "4.1.0-alpha.
|
|
66
|
-
"@loaders.gl/zip": "4.1.0-alpha.
|
|
55
|
+
"@loaders.gl/3d-tiles": "4.1.0-alpha.10",
|
|
56
|
+
"@loaders.gl/crypto": "4.1.0-alpha.10",
|
|
57
|
+
"@loaders.gl/draco": "4.1.0-alpha.10",
|
|
58
|
+
"@loaders.gl/gltf": "4.1.0-alpha.10",
|
|
59
|
+
"@loaders.gl/i3s": "4.1.0-alpha.10",
|
|
60
|
+
"@loaders.gl/images": "4.1.0-alpha.10",
|
|
61
|
+
"@loaders.gl/loader-utils": "4.1.0-alpha.10",
|
|
62
|
+
"@loaders.gl/polyfills": "4.1.0-alpha.10",
|
|
63
|
+
"@loaders.gl/textures": "4.1.0-alpha.10",
|
|
64
|
+
"@loaders.gl/tiles": "4.1.0-alpha.10",
|
|
65
|
+
"@loaders.gl/worker-utils": "4.1.0-alpha.10",
|
|
66
|
+
"@loaders.gl/zip": "4.1.0-alpha.10",
|
|
67
67
|
"@math.gl/core": "^4.0.0",
|
|
68
68
|
"@math.gl/culling": "^4.0.0",
|
|
69
69
|
"@math.gl/geoid": "^4.0.0",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"join-images": "^1.1.3",
|
|
88
88
|
"sharp": "^0.31.3"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "19f43c2d90d8b50860c3f8e487429779a386287d",
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@types/express": "^4.17.17",
|
|
93
93
|
"@types/node": "^20.4.2"
|
package/src/constants.ts
CHANGED
package/src/converter-cli.ts
CHANGED
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
getURLValue,
|
|
12
12
|
validateOptionsWithEqual
|
|
13
13
|
} from './lib/utils/cli-utils';
|
|
14
|
+
import {addOneFile, composeHashFile} from '@loaders.gl/zip';
|
|
15
|
+
import {FileHandleFile} from '@loaders.gl/loader-utils';
|
|
16
|
+
import {copyFile} from 'node:fs/promises';
|
|
14
17
|
|
|
15
18
|
type TileConversionOptions = {
|
|
16
19
|
/** "I3S" - for I3S to 3DTiles conversion, "3DTILES" for 3DTiles to I3S conversion */
|
|
@@ -50,6 +53,8 @@ type TileConversionOptions = {
|
|
|
50
53
|
maxDepth?: number;
|
|
51
54
|
/** 3DTiles->I3S only. Whether the converter generates *.slpk (Scene Layer Package) I3S output file */
|
|
52
55
|
slpk: boolean;
|
|
56
|
+
/** adds hash file to the slpk if there's no one */
|
|
57
|
+
addHash: boolean;
|
|
53
58
|
/** Feature metadata class from EXT_FEATURE_METADATA or EXT_STRUCTURAL_METADATA extensions */
|
|
54
59
|
metadataClass?: string;
|
|
55
60
|
/** With this options the tileset content will be analyzed without conversion */
|
|
@@ -92,6 +97,48 @@ async function main() {
|
|
|
92
97
|
return;
|
|
93
98
|
}
|
|
94
99
|
|
|
100
|
+
if (options.addHash) {
|
|
101
|
+
const validatedOptions = validateOptions(options, true);
|
|
102
|
+
let finalPath = validatedOptions.tileset;
|
|
103
|
+
if (validatedOptions.output === 'data') {
|
|
104
|
+
const nameWithoutExt = validatedOptions.tileset.substring(
|
|
105
|
+
0,
|
|
106
|
+
validatedOptions.tileset.length - 5
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const result = await inquirer.prompt<{isNewFileRequired: boolean}>([
|
|
110
|
+
{
|
|
111
|
+
name: 'isNewFileRequired',
|
|
112
|
+
type: 'list',
|
|
113
|
+
message: 'What would you like to do?',
|
|
114
|
+
choices: [
|
|
115
|
+
{
|
|
116
|
+
name: 'Add hash file to the current SLPK file',
|
|
117
|
+
value: false
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: `Create a new file ${nameWithoutExt}-hash.slpk with hash file inside`,
|
|
121
|
+
value: true
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
if (result.isNewFileRequired) {
|
|
128
|
+
finalPath = `${nameWithoutExt}-hash.slpk`;
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
finalPath = validatedOptions.output;
|
|
132
|
+
}
|
|
133
|
+
if (finalPath !== validatedOptions.tileset) {
|
|
134
|
+
await copyFile(validatedOptions.tileset, finalPath);
|
|
135
|
+
}
|
|
136
|
+
const hashTable = await composeHashFile(new FileHandleFile(finalPath));
|
|
137
|
+
await addOneFile(finalPath, hashTable, '@specialIndexFileHASH128@');
|
|
138
|
+
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
95
142
|
const validatedOptions: ValidatedTileConversionOptions = validateOptions(options);
|
|
96
143
|
|
|
97
144
|
await convert(validatedOptions);
|
|
@@ -199,7 +246,10 @@ async function convert(options: ValidatedTileConversionOptions) {
|
|
|
199
246
|
* @param options - input options of the CLI command
|
|
200
247
|
* @returns validated options
|
|
201
248
|
*/
|
|
202
|
-
function validateOptions(
|
|
249
|
+
function validateOptions(
|
|
250
|
+
options: TileConversionOptions,
|
|
251
|
+
addHash?: boolean
|
|
252
|
+
): ValidatedTileConversionOptions {
|
|
203
253
|
const mandatoryOptionsWithExceptions: {
|
|
204
254
|
[key: string]: {
|
|
205
255
|
getMessage: () => void;
|
|
@@ -208,7 +258,7 @@ function validateOptions(options: TileConversionOptions): ValidatedTileConversio
|
|
|
208
258
|
} = {
|
|
209
259
|
name: {
|
|
210
260
|
getMessage: () => console.log('Missed: --name [Tileset name]'),
|
|
211
|
-
condition: (value: any) => Boolean(value) || Boolean(options.analyze)
|
|
261
|
+
condition: (value: any) => addHash || Boolean(value) || Boolean(options.analyze)
|
|
212
262
|
},
|
|
213
263
|
output: {getMessage: () => console.log('Missed: --output [Output path name]')},
|
|
214
264
|
sevenZipExe: {getMessage: () => console.log('Missed: --7zExe [7z archiver executable path]')},
|
|
@@ -218,7 +268,7 @@ function validateOptions(options: TileConversionOptions): ValidatedTileConversio
|
|
|
218
268
|
getMessage: () =>
|
|
219
269
|
console.log('Missed/Incorrect: --input-type [tileset input type: I3S or 3DTILES]'),
|
|
220
270
|
condition: (value) =>
|
|
221
|
-
Boolean(value) && Object.values(TILESET_TYPE).includes(value.toUpperCase())
|
|
271
|
+
addHash || (Boolean(value) && Object.values(TILESET_TYPE).includes(value.toUpperCase()))
|
|
222
272
|
}
|
|
223
273
|
};
|
|
224
274
|
const exceptions: (() => void)[] = [];
|
|
@@ -256,7 +306,8 @@ function parseOptions(args: string[]): TileConversionOptions {
|
|
|
256
306
|
generateTextures: false,
|
|
257
307
|
generateBoundingVolumes: false,
|
|
258
308
|
validate: false,
|
|
259
|
-
slpk: false
|
|
309
|
+
slpk: false,
|
|
310
|
+
addHash: false
|
|
260
311
|
};
|
|
261
312
|
|
|
262
313
|
// eslint-disable-next-line complexity
|
|
@@ -287,6 +338,9 @@ function parseOptions(args: string[]): TileConversionOptions {
|
|
|
287
338
|
case '--slpk':
|
|
288
339
|
opts.slpk = getBooleanValue(index, args);
|
|
289
340
|
break;
|
|
341
|
+
case '--add-hash':
|
|
342
|
+
opts.addHash = getBooleanValue(index, args);
|
|
343
|
+
break;
|
|
290
344
|
case '--7zExe':
|
|
291
345
|
opts.sevenZipExe = getStringValue(index, args);
|
|
292
346
|
break;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {load, fetchFile} from '@loaders.gl/core';
|
|
2
2
|
import {ZipLoader} from '@loaders.gl/zip';
|
|
3
3
|
import {writeFile} from '../lib/utils/file-utils';
|
|
4
|
-
import {join} from 'path';
|
|
4
|
+
import {join, dirname} from 'path';
|
|
5
5
|
import {ChildProcessProxy} from '@loaders.gl/worker-utils';
|
|
6
6
|
import {DRACO_EXTERNAL_LIBRARIES, DRACO_EXTERNAL_LIBRARY_URLS} from '@loaders.gl/draco';
|
|
7
7
|
import {BASIS_EXTERNAL_LIBRARIES} from '@loaders.gl/textures';
|
|
@@ -80,8 +80,9 @@ export class DepsInstaller {
|
|
|
80
80
|
|
|
81
81
|
console.log('Installing "join-images" npm package');
|
|
82
82
|
const childProcess = new ChildProcessProxy();
|
|
83
|
+
const nodeDir = dirname(process.execPath);
|
|
83
84
|
await childProcess.start({
|
|
84
|
-
command: process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
85
|
+
command: `${nodeDir}/${process.platform === 'win32' ? 'npm.cmd' : 'npm'}`,
|
|
85
86
|
// `npm install sharp join-images` works unstable. It fails because installed `sharp` version
|
|
86
87
|
// may be different from the version required by `join-images`. Pointing to specific versions
|
|
87
88
|
// resolve this issue
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// loaders.gl
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
2
3
|
// Copyright (c) vis.gl contributors
|
|
3
4
|
|
|
4
5
|
import {AttributeMetadataInfo} from './helpers/attribute-metadata-info';
|
|
@@ -50,7 +51,7 @@ import {GEOMETRY_DEFINITION as geometryDefinitionTemlate} from './json-templates
|
|
|
50
51
|
import {SHARED_RESOURCES as sharedResourcesTemplate} from './json-templates/shared-resources';
|
|
51
52
|
import {validateNodeBoundingVolumes} from './helpers/node-debug';
|
|
52
53
|
import {KTX2BasisWriterWorker} from '@loaders.gl/textures';
|
|
53
|
-
import {LoaderWithParser} from '@loaders.gl/loader-utils';
|
|
54
|
+
import {FileHandleFile, LoaderWithParser} from '@loaders.gl/loader-utils';
|
|
54
55
|
import {I3SMaterialDefinition, TextureSetDefinitionFormats} from '@loaders.gl/i3s';
|
|
55
56
|
import {ImageWriter} from '@loaders.gl/images';
|
|
56
57
|
import {GLTFImagePostprocessed} from '@loaders.gl/gltf';
|
|
@@ -58,6 +59,7 @@ import {
|
|
|
58
59
|
GLTFPrimitiveModeString,
|
|
59
60
|
I3SConvertedResources,
|
|
60
61
|
PreprocessData,
|
|
62
|
+
ResourceType,
|
|
61
63
|
SharedResourcesArrays
|
|
62
64
|
} from './types';
|
|
63
65
|
import {WorkerFarm} from '@loaders.gl/worker-utils';
|
|
@@ -80,6 +82,8 @@ import {createBoundingVolume} from '@loaders.gl/tiles';
|
|
|
80
82
|
import {TraversalConversionProps, traverseDatasetWith} from './helpers/tileset-traversal';
|
|
81
83
|
import {analyzeTileContent, mergePreprocessData} from './helpers/preprocess-3d-tiles';
|
|
82
84
|
import {Progress} from './helpers/progress';
|
|
85
|
+
import {addOneFile, composeHashFile} from '@loaders.gl/zip';
|
|
86
|
+
import {ConversionDump, ConversionDumpOptions} from '../lib/utils/conversion-dump';
|
|
83
87
|
|
|
84
88
|
const ION_DEFAULT_TOKEN = process.env?.IonToken;
|
|
85
89
|
const HARDCODED_NODES_PER_PAGE = 64;
|
|
@@ -134,13 +138,14 @@ export default class I3SConverter {
|
|
|
134
138
|
generateBoundingVolumes: boolean;
|
|
135
139
|
layersHasTexture: boolean;
|
|
136
140
|
workerSource: {[key: string]: string} = {};
|
|
137
|
-
writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue();
|
|
141
|
+
writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue(new ConversionDump());
|
|
138
142
|
compressList: string[] | null = null;
|
|
139
143
|
preprocessData: PreprocessData = {
|
|
140
144
|
meshTopologyTypes: new Set(),
|
|
141
145
|
metadataClasses: new Set()
|
|
142
146
|
};
|
|
143
147
|
progresses: Record<string, Progress> = {};
|
|
148
|
+
conversionDump: ConversionDump;
|
|
144
149
|
|
|
145
150
|
constructor() {
|
|
146
151
|
this.attributeMetadataInfo = new AttributeMetadataInfo();
|
|
@@ -163,6 +168,7 @@ export default class I3SConverter {
|
|
|
163
168
|
this.generateBoundingVolumes = false;
|
|
164
169
|
this.layersHasTexture = false;
|
|
165
170
|
this.compressList = null;
|
|
171
|
+
this.conversionDump = new ConversionDump();
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
/**
|
|
@@ -226,6 +232,8 @@ export default class I3SConverter {
|
|
|
226
232
|
analyze = false
|
|
227
233
|
} = options;
|
|
228
234
|
this.options = {
|
|
235
|
+
outputPath,
|
|
236
|
+
tilesetName,
|
|
229
237
|
maxDepth,
|
|
230
238
|
slpk,
|
|
231
239
|
sevenZipExe,
|
|
@@ -245,7 +253,7 @@ export default class I3SConverter {
|
|
|
245
253
|
this.generateTextures = Boolean(generateTextures);
|
|
246
254
|
this.generateBoundingVolumes = Boolean(generateBoundingVolumes);
|
|
247
255
|
|
|
248
|
-
this.writeQueue = new WriteQueue();
|
|
256
|
+
this.writeQueue = new WriteQueue(this.conversionDump);
|
|
249
257
|
this.writeQueue.startListening();
|
|
250
258
|
|
|
251
259
|
console.log('Loading egm file...'); // eslint-disable-line
|
|
@@ -256,6 +264,9 @@ export default class I3SConverter {
|
|
|
256
264
|
this.nodePages.useWriteFunction(writeFileForSlpk);
|
|
257
265
|
}
|
|
258
266
|
|
|
267
|
+
//create a dump file with convertion options
|
|
268
|
+
await this.conversionDump.createDumpFile(options as ConversionDumpOptions);
|
|
269
|
+
|
|
259
270
|
try {
|
|
260
271
|
const preloadOptions = await this._fetchPreloadOptions();
|
|
261
272
|
let tilesetUrl = inputUrl;
|
|
@@ -552,6 +563,7 @@ export default class I3SConverter {
|
|
|
552
563
|
* @param tilesetPath - Path to save file
|
|
553
564
|
*/
|
|
554
565
|
private async _createSlpk(tilesetPath: string): Promise<void> {
|
|
566
|
+
await this.conversionDump.deleteDumpFile();
|
|
555
567
|
if (this.options.slpk) {
|
|
556
568
|
const slpkTilesetPath = join(tilesetPath, 'SceneServer', 'layers', '0');
|
|
557
569
|
const slpkFileName = `${tilesetPath}.slpk`;
|
|
@@ -563,6 +575,9 @@ export default class I3SConverter {
|
|
|
563
575
|
this.options.sevenZipExe
|
|
564
576
|
);
|
|
565
577
|
|
|
578
|
+
const hashTable = await composeHashFile(new FileHandleFile(slpkFileName));
|
|
579
|
+
await addOneFile(slpkFileName, hashTable, '@specialIndexFileHASH128@');
|
|
580
|
+
|
|
566
581
|
// TODO: `addFileToZip` corrupts archive so it can't be validated with windows i3s_converter.exe
|
|
567
582
|
// const fileHash128Path = `${tilesetPath}/@specialIndexFileHASH128@`;
|
|
568
583
|
// try {
|
|
@@ -613,6 +628,7 @@ export default class I3SConverter {
|
|
|
613
628
|
if (sourceTile.id) {
|
|
614
629
|
console.log(`[convert]: ${sourceTile.id}`); // eslint-disable-line
|
|
615
630
|
}
|
|
631
|
+
|
|
616
632
|
const {parentNodes, transform} = traversalProps;
|
|
617
633
|
let transformationMatrix: Matrix4 = transform.clone();
|
|
618
634
|
if (sourceTile.transform) {
|
|
@@ -751,7 +767,13 @@ export default class I3SConverter {
|
|
|
751
767
|
nodes.push(node);
|
|
752
768
|
|
|
753
769
|
if (nodeInPage.mesh) {
|
|
754
|
-
|
|
770
|
+
//update a record in a dump file
|
|
771
|
+
if (sourceTile.id) {
|
|
772
|
+
await this.conversionDump.addNode(sourceTile.id, nodeInPage.index);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
//write resources
|
|
776
|
+
await this._writeResources(resources, node.id, sourceTile);
|
|
755
777
|
}
|
|
756
778
|
|
|
757
779
|
if (this.validate) {
|
|
@@ -900,9 +922,15 @@ export default class I3SConverter {
|
|
|
900
922
|
* @param resources.texture - texture image
|
|
901
923
|
* @param resources.sharedResources - shared resource data object
|
|
902
924
|
* @param resources.attributes - feature attributes
|
|
925
|
+
* @param nodePath - node path
|
|
926
|
+
* @param sourceTile - source tile (3DTile)
|
|
903
927
|
* @return {Promise<void>}
|
|
904
928
|
*/
|
|
905
|
-
private async _writeResources(
|
|
929
|
+
private async _writeResources(
|
|
930
|
+
resources: I3SConvertedResources,
|
|
931
|
+
nodePath: string,
|
|
932
|
+
sourceTile: Tiles3DTileJSONPostprocessed
|
|
933
|
+
): Promise<void> {
|
|
906
934
|
const {
|
|
907
935
|
geometry: geometryBuffer,
|
|
908
936
|
compressedGeometry,
|
|
@@ -913,10 +941,36 @@ export default class I3SConverter {
|
|
|
913
941
|
const childPath = join(this.layers0Path, 'nodes', nodePath);
|
|
914
942
|
const slpkChildPath = join('nodes', nodePath);
|
|
915
943
|
|
|
916
|
-
await this._writeGeometries(
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
944
|
+
await this._writeGeometries(
|
|
945
|
+
geometryBuffer!,
|
|
946
|
+
compressedGeometry!,
|
|
947
|
+
childPath,
|
|
948
|
+
slpkChildPath,
|
|
949
|
+
sourceTile.id || '',
|
|
950
|
+
parseInt(nodePath)
|
|
951
|
+
);
|
|
952
|
+
await this._writeShared(
|
|
953
|
+
sharedResources,
|
|
954
|
+
childPath,
|
|
955
|
+
slpkChildPath,
|
|
956
|
+
nodePath,
|
|
957
|
+
sourceTile.id || '',
|
|
958
|
+
parseInt(nodePath)
|
|
959
|
+
);
|
|
960
|
+
await this._writeTexture(
|
|
961
|
+
texture,
|
|
962
|
+
childPath,
|
|
963
|
+
slpkChildPath,
|
|
964
|
+
sourceTile.id || '',
|
|
965
|
+
parseInt(nodePath)
|
|
966
|
+
);
|
|
967
|
+
await this._writeAttributes(
|
|
968
|
+
attributes,
|
|
969
|
+
childPath,
|
|
970
|
+
slpkChildPath,
|
|
971
|
+
sourceTile.id || '',
|
|
972
|
+
parseInt(nodePath)
|
|
973
|
+
);
|
|
920
974
|
}
|
|
921
975
|
|
|
922
976
|
/**
|
|
@@ -925,37 +979,57 @@ export default class I3SConverter {
|
|
|
925
979
|
* @param compressedGeometry - Uint8Array with compressed (draco) geometry
|
|
926
980
|
* @param childPath - a child path to write resources
|
|
927
981
|
* @param slpkChildPath - resource path inside *slpk file
|
|
982
|
+
* @param sourceId - source filename
|
|
983
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
928
984
|
*/
|
|
929
985
|
private async _writeGeometries(
|
|
930
986
|
geometryBuffer: ArrayBuffer,
|
|
931
987
|
compressedGeometry: Promise<ArrayBuffer>,
|
|
932
988
|
childPath: string,
|
|
933
|
-
slpkChildPath: string
|
|
989
|
+
slpkChildPath: string,
|
|
990
|
+
sourceId: string,
|
|
991
|
+
nodeId: number
|
|
934
992
|
): Promise<void> {
|
|
993
|
+
this.conversionDump.updateDoneStatus(sourceId, nodeId, ResourceType.GEOMETRY, false);
|
|
994
|
+
|
|
935
995
|
if (this.options.slpk) {
|
|
936
996
|
const slpkGeometryPath = join(childPath, 'geometries');
|
|
937
997
|
await this.writeQueue.enqueue({
|
|
938
998
|
archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
|
|
999
|
+
sourceId,
|
|
1000
|
+
outputId: nodeId,
|
|
1001
|
+
resourceType: ResourceType.GEOMETRY,
|
|
939
1002
|
writePromise: () => writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
|
|
940
1003
|
});
|
|
941
1004
|
} else {
|
|
942
1005
|
const geometryPath = join(childPath, 'geometries/0/');
|
|
943
1006
|
await this.writeQueue.enqueue({
|
|
1007
|
+
sourceId,
|
|
1008
|
+
outputId: nodeId,
|
|
1009
|
+
resourceType: ResourceType.GEOMETRY,
|
|
944
1010
|
writePromise: () => writeFile(geometryPath, geometryBuffer, 'index.bin')
|
|
945
1011
|
});
|
|
946
1012
|
}
|
|
947
1013
|
|
|
948
1014
|
if (this.options.draco) {
|
|
1015
|
+
this.conversionDump.updateDoneStatus(sourceId, nodeId, ResourceType.DRACO_GEOMETRY, false);
|
|
1016
|
+
|
|
949
1017
|
if (this.options.slpk) {
|
|
950
1018
|
const slpkCompressedGeometryPath = join(childPath, 'geometries');
|
|
951
1019
|
await this.writeQueue.enqueue({
|
|
952
1020
|
archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
|
|
1021
|
+
sourceId,
|
|
1022
|
+
outputId: nodeId,
|
|
1023
|
+
resourceType: ResourceType.DRACO_GEOMETRY,
|
|
953
1024
|
writePromise: () =>
|
|
954
1025
|
writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
|
|
955
1026
|
});
|
|
956
1027
|
} else {
|
|
957
1028
|
const compressedGeometryPath = join(childPath, 'geometries/1/');
|
|
958
1029
|
await this.writeQueue.enqueue({
|
|
1030
|
+
sourceId,
|
|
1031
|
+
outputId: nodeId,
|
|
1032
|
+
resourceType: ResourceType.DRACO_GEOMETRY,
|
|
959
1033
|
writePromise: () => writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
|
|
960
1034
|
});
|
|
961
1035
|
}
|
|
@@ -968,12 +1042,16 @@ export default class I3SConverter {
|
|
|
968
1042
|
* @param childPath - a child path to write resources
|
|
969
1043
|
* @param slpkChildPath - resource path inside *slpk file
|
|
970
1044
|
* @param nodePath - a node path
|
|
1045
|
+
* @param sourceId - source filename
|
|
1046
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
971
1047
|
*/
|
|
972
1048
|
private async _writeShared(
|
|
973
1049
|
sharedResources: SharedResourcesArrays | null,
|
|
974
1050
|
childPath: string,
|
|
975
1051
|
slpkChildPath: string,
|
|
976
|
-
nodePath: string
|
|
1052
|
+
nodePath: string,
|
|
1053
|
+
sourceId: string,
|
|
1054
|
+
nodeId: number
|
|
977
1055
|
): Promise<void> {
|
|
978
1056
|
if (!sharedResources) {
|
|
979
1057
|
return;
|
|
@@ -981,15 +1059,24 @@ export default class I3SConverter {
|
|
|
981
1059
|
sharedResources.nodePath = nodePath;
|
|
982
1060
|
const sharedData = transform(sharedResources, sharedResourcesTemplate());
|
|
983
1061
|
const sharedDataStr = JSON.stringify(sharedData);
|
|
1062
|
+
this.conversionDump.updateDoneStatus(sourceId, nodeId, ResourceType.SHARED, false);
|
|
984
1063
|
if (this.options.slpk) {
|
|
985
1064
|
const slpkSharedPath = join(childPath, 'shared');
|
|
986
1065
|
await this.writeQueue.enqueue({
|
|
987
1066
|
archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
|
|
1067
|
+
sourceId,
|
|
1068
|
+
outputId: nodeId,
|
|
1069
|
+
resourceType: ResourceType.SHARED,
|
|
988
1070
|
writePromise: () => writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
|
|
989
1071
|
});
|
|
990
1072
|
} else {
|
|
991
1073
|
const sharedPath = join(childPath, 'shared/');
|
|
992
|
-
await this.writeQueue.enqueue({
|
|
1074
|
+
await this.writeQueue.enqueue({
|
|
1075
|
+
sourceId,
|
|
1076
|
+
outputId: nodeId,
|
|
1077
|
+
resourceType: ResourceType.SHARED,
|
|
1078
|
+
writePromise: () => writeFile(sharedPath, sharedDataStr)
|
|
1079
|
+
});
|
|
993
1080
|
}
|
|
994
1081
|
}
|
|
995
1082
|
|
|
@@ -998,11 +1085,15 @@ export default class I3SConverter {
|
|
|
998
1085
|
* @param texture - the texture image
|
|
999
1086
|
* @param childPath - a child path to write resources
|
|
1000
1087
|
* @param slpkChildPath - the resource path inside *slpk file
|
|
1088
|
+
* @param sourceId - source filename
|
|
1089
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
1001
1090
|
*/
|
|
1002
1091
|
private async _writeTexture(
|
|
1003
1092
|
texture: GLTFImagePostprocessed,
|
|
1004
1093
|
childPath: string,
|
|
1005
|
-
slpkChildPath: string
|
|
1094
|
+
slpkChildPath: string,
|
|
1095
|
+
sourceId: string,
|
|
1096
|
+
nodeId: number
|
|
1006
1097
|
): Promise<void> {
|
|
1007
1098
|
if (texture) {
|
|
1008
1099
|
const format = this._getFormatByMimeType(texture?.mimeType);
|
|
@@ -1013,7 +1104,21 @@ export default class I3SConverter {
|
|
|
1013
1104
|
case 'jpg':
|
|
1014
1105
|
case 'png': {
|
|
1015
1106
|
formats.push({name: '0', format});
|
|
1016
|
-
|
|
1107
|
+
this.conversionDump.updateDoneStatus(
|
|
1108
|
+
sourceId,
|
|
1109
|
+
nodeId,
|
|
1110
|
+
`${ResourceType.TEXTURE}/${format}`,
|
|
1111
|
+
false
|
|
1112
|
+
);
|
|
1113
|
+
await this.writeTextureFile(
|
|
1114
|
+
textureData,
|
|
1115
|
+
'0',
|
|
1116
|
+
format,
|
|
1117
|
+
childPath,
|
|
1118
|
+
slpkChildPath,
|
|
1119
|
+
sourceId,
|
|
1120
|
+
nodeId
|
|
1121
|
+
);
|
|
1017
1122
|
|
|
1018
1123
|
if (this.generateTextures) {
|
|
1019
1124
|
formats.push({name: '1', format: 'ktx2'});
|
|
@@ -1022,6 +1127,7 @@ export default class I3SConverter {
|
|
|
1022
1127
|
const arrayToEncode = new Uint8Array(copyArrayBuffer);
|
|
1023
1128
|
const ktx2TextureData = encode(
|
|
1024
1129
|
{...texture.image, data: arrayToEncode},
|
|
1130
|
+
// @ts-expect-error - Worker encoder typing is still WIP
|
|
1025
1131
|
KTX2BasisWriterWorker,
|
|
1026
1132
|
{
|
|
1027
1133
|
...KTX2BasisWriterWorker.options,
|
|
@@ -1035,7 +1141,22 @@ export default class I3SConverter {
|
|
|
1035
1141
|
}
|
|
1036
1142
|
);
|
|
1037
1143
|
|
|
1038
|
-
|
|
1144
|
+
this.conversionDump.updateDoneStatus(
|
|
1145
|
+
sourceId,
|
|
1146
|
+
nodeId,
|
|
1147
|
+
`${ResourceType.TEXTURE}/ktx2`,
|
|
1148
|
+
false
|
|
1149
|
+
);
|
|
1150
|
+
|
|
1151
|
+
await this.writeTextureFile(
|
|
1152
|
+
ktx2TextureData,
|
|
1153
|
+
'1',
|
|
1154
|
+
'ktx2',
|
|
1155
|
+
childPath,
|
|
1156
|
+
slpkChildPath,
|
|
1157
|
+
sourceId,
|
|
1158
|
+
nodeId
|
|
1159
|
+
);
|
|
1039
1160
|
}
|
|
1040
1161
|
|
|
1041
1162
|
break;
|
|
@@ -1043,17 +1164,39 @@ export default class I3SConverter {
|
|
|
1043
1164
|
|
|
1044
1165
|
case 'ktx2': {
|
|
1045
1166
|
formats.push({name: '1', format});
|
|
1046
|
-
|
|
1167
|
+
this.conversionDump.updateDoneStatus(
|
|
1168
|
+
sourceId,
|
|
1169
|
+
nodeId,
|
|
1170
|
+
`${ResourceType.TEXTURE}/${format}`,
|
|
1171
|
+
false
|
|
1172
|
+
);
|
|
1173
|
+
await this.writeTextureFile(
|
|
1174
|
+
textureData,
|
|
1175
|
+
'1',
|
|
1176
|
+
format,
|
|
1177
|
+
childPath,
|
|
1178
|
+
slpkChildPath,
|
|
1179
|
+
sourceId,
|
|
1180
|
+
nodeId
|
|
1181
|
+
);
|
|
1047
1182
|
|
|
1048
1183
|
if (this.generateTextures) {
|
|
1049
1184
|
formats.push({name: '0', format: 'jpg'});
|
|
1050
1185
|
const decodedFromKTX2TextureData = encode(texture.image!.data[0], ImageWriter);
|
|
1186
|
+
this.conversionDump.updateDoneStatus(
|
|
1187
|
+
sourceId,
|
|
1188
|
+
nodeId,
|
|
1189
|
+
`${ResourceType.TEXTURE}/jpg`,
|
|
1190
|
+
false
|
|
1191
|
+
);
|
|
1051
1192
|
await this.writeTextureFile(
|
|
1052
1193
|
decodedFromKTX2TextureData,
|
|
1053
1194
|
'0',
|
|
1054
1195
|
'jpg',
|
|
1055
1196
|
childPath,
|
|
1056
|
-
slpkChildPath
|
|
1197
|
+
slpkChildPath,
|
|
1198
|
+
sourceId,
|
|
1199
|
+
nodeId
|
|
1057
1200
|
);
|
|
1058
1201
|
}
|
|
1059
1202
|
}
|
|
@@ -1073,13 +1216,17 @@ export default class I3SConverter {
|
|
|
1073
1216
|
* @param format
|
|
1074
1217
|
* @param childPath
|
|
1075
1218
|
* @param slpkChildPath
|
|
1219
|
+
* @param sourceId
|
|
1220
|
+
* @param nodeId
|
|
1076
1221
|
*/
|
|
1077
1222
|
private async writeTextureFile(
|
|
1078
1223
|
textureData: Uint8Array | Promise<ArrayBuffer>,
|
|
1079
1224
|
name: string,
|
|
1080
1225
|
format: 'jpg' | 'png' | 'ktx2',
|
|
1081
1226
|
childPath: string,
|
|
1082
|
-
slpkChildPath: string
|
|
1227
|
+
slpkChildPath: string,
|
|
1228
|
+
sourceId: string,
|
|
1229
|
+
nodeId: number
|
|
1083
1230
|
): Promise<void> {
|
|
1084
1231
|
if (this.options.slpk) {
|
|
1085
1232
|
const slpkTexturePath = join(childPath, 'textures');
|
|
@@ -1087,12 +1234,18 @@ export default class I3SConverter {
|
|
|
1087
1234
|
|
|
1088
1235
|
await this.writeQueue.enqueue({
|
|
1089
1236
|
archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
|
|
1237
|
+
sourceId,
|
|
1238
|
+
outputId: nodeId,
|
|
1239
|
+
resourceType: `${ResourceType.TEXTURE}/${format}`,
|
|
1090
1240
|
writePromise: () =>
|
|
1091
1241
|
writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
|
|
1092
1242
|
});
|
|
1093
1243
|
} else {
|
|
1094
1244
|
const texturePath = join(childPath, `textures/${name}/`);
|
|
1095
1245
|
await this.writeQueue.enqueue({
|
|
1246
|
+
sourceId,
|
|
1247
|
+
outputId: nodeId,
|
|
1248
|
+
resourceType: `${ResourceType.TEXTURE}/${format}`,
|
|
1096
1249
|
writePromise: () => writeFile(texturePath, textureData, `index.${format}`)
|
|
1097
1250
|
});
|
|
1098
1251
|
}
|
|
@@ -1103,11 +1256,15 @@ export default class I3SConverter {
|
|
|
1103
1256
|
* @param attributes - feature attributes
|
|
1104
1257
|
* @param childPath - a child path to write resources
|
|
1105
1258
|
* @param slpkChildPath - the resource path inside *slpk file
|
|
1259
|
+
* @param sourceId - source filename
|
|
1260
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
1106
1261
|
*/
|
|
1107
1262
|
private async _writeAttributes(
|
|
1108
1263
|
attributes: ArrayBuffer[] | null = [],
|
|
1109
1264
|
childPath: string,
|
|
1110
|
-
slpkChildPath: string
|
|
1265
|
+
slpkChildPath: string,
|
|
1266
|
+
sourceId: string,
|
|
1267
|
+
nodeId: number
|
|
1111
1268
|
): Promise<void> {
|
|
1112
1269
|
if (attributes?.length && this.attributeMetadataInfo.attributeStorageInfo.length) {
|
|
1113
1270
|
const minimumLength =
|
|
@@ -1118,16 +1275,27 @@ export default class I3SConverter {
|
|
|
1118
1275
|
for (let index = 0; index < minimumLength; index++) {
|
|
1119
1276
|
const folderName = this.attributeMetadataInfo.attributeStorageInfo[index].key;
|
|
1120
1277
|
const fileBuffer = new Uint8Array(attributes[index]);
|
|
1121
|
-
|
|
1278
|
+
this.conversionDump.updateDoneStatus(
|
|
1279
|
+
sourceId,
|
|
1280
|
+
nodeId,
|
|
1281
|
+
`${ResourceType.ATTRIBUTES}/${folderName}`,
|
|
1282
|
+
false
|
|
1283
|
+
);
|
|
1122
1284
|
if (this.options.slpk) {
|
|
1123
1285
|
const slpkAttributesPath = join(childPath, 'attributes', folderName);
|
|
1124
1286
|
await this.writeQueue.enqueue({
|
|
1125
1287
|
archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
|
|
1288
|
+
sourceId,
|
|
1289
|
+
outputId: nodeId,
|
|
1290
|
+
resourceType: `${ResourceType.ATTRIBUTES}/${folderName}`,
|
|
1126
1291
|
writePromise: () => writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
|
|
1127
1292
|
});
|
|
1128
1293
|
} else {
|
|
1129
1294
|
const attributesPath = join(childPath, `attributes/${folderName}/0`);
|
|
1130
1295
|
await this.writeQueue.enqueue({
|
|
1296
|
+
sourceId,
|
|
1297
|
+
outputId: nodeId,
|
|
1298
|
+
resourceType: `${ResourceType.ATTRIBUTES}/${folderName}`,
|
|
1131
1299
|
writePromise: () => writeFile(attributesPath, fileBuffer, 'index.bin')
|
|
1132
1300
|
});
|
|
1133
1301
|
}
|
|
@@ -241,3 +241,11 @@ export const AttributeType = {
|
|
|
241
241
|
/** Integer data type name for feature attributes */
|
|
242
242
|
SHORT_INT_TYPE: 'Int32'
|
|
243
243
|
} as const;
|
|
244
|
+
|
|
245
|
+
export enum ResourceType {
|
|
246
|
+
ATTRIBUTES = 'ATTRIBUTES',
|
|
247
|
+
DRACO_GEOMETRY = 'DRACO_GEOMETRY',
|
|
248
|
+
GEOMETRY = 'GEOMETRY',
|
|
249
|
+
SHARED = 'SHARED',
|
|
250
|
+
TEXTURE = 'TEXTURE'
|
|
251
|
+
}
|