@loaders.gl/tile-converter 4.0.0-alpha.10 → 4.0.0-alpha.12
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/bin/slpk-extractor.js +4 -0
- package/dist/3d-tiles-attributes-worker.js +1 -1
- package/dist/converter-cli.js +18 -84
- package/dist/converter.min.js +50 -50
- package/dist/dist.min.js +21 -18
- package/dist/es5/3d-tiles-attributes-worker.js +1 -1
- package/dist/es5/converter-cli.js +18 -63
- package/dist/es5/converter-cli.js.map +1 -1
- package/dist/es5/deps-installer/deps-installer.js +1 -1
- package/dist/es5/i3s-attributes-worker.js +1 -1
- package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js +2 -2
- package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
- package/dist/es5/i3s-converter/i3s-converter.js +59 -38
- package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/es5/lib/utils/cli-utils.js +57 -0
- package/dist/es5/lib/utils/cli-utils.js.map +1 -0
- package/dist/es5/pgm-loader.js +1 -1
- package/dist/es5/slpk-extractor/helpers/file-handle-provider.js +181 -0
- package/dist/es5/slpk-extractor/helpers/file-handle-provider.js.map +1 -0
- package/dist/es5/slpk-extractor/slpk-extractor.js +172 -0
- package/dist/es5/slpk-extractor/slpk-extractor.js.map +1 -0
- package/dist/es5/slpk-extractor-cli.js +117 -0
- package/dist/es5/slpk-extractor-cli.js.map +1 -0
- package/dist/esm/3d-tiles-attributes-worker.js +1 -1
- package/dist/esm/converter-cli.js +1 -46
- package/dist/esm/converter-cli.js.map +1 -1
- package/dist/esm/deps-installer/deps-installer.js +1 -1
- package/dist/esm/i3s-attributes-worker.js +1 -1
- package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js +1 -1
- package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
- package/dist/esm/i3s-converter/i3s-converter.js +22 -9
- package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/esm/lib/utils/cli-utils.js +47 -0
- package/dist/esm/lib/utils/cli-utils.js.map +1 -0
- package/dist/esm/pgm-loader.js +1 -1
- package/dist/esm/slpk-extractor/helpers/file-handle-provider.js +43 -0
- package/dist/esm/slpk-extractor/helpers/file-handle-provider.js.map +1 -0
- package/dist/esm/slpk-extractor/slpk-extractor.js +63 -0
- package/dist/esm/slpk-extractor/slpk-extractor.js.map +1 -0
- package/dist/esm/slpk-extractor-cli.js +74 -0
- package/dist/esm/slpk-extractor-cli.js.map +1 -0
- package/dist/i3s-converter/helpers/coordinate-converter.d.ts +1 -2
- package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/coordinate-converter.js +1 -2
- package/dist/i3s-converter/helpers/gltf-attributes.d.ts +1 -1
- package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/gltf-attributes.js +2 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts +2 -3
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.js +1 -2
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.js +21 -6
- package/dist/lib/utils/cli-utils.d.ts +34 -0
- package/dist/lib/utils/cli-utils.d.ts.map +1 -0
- package/dist/lib/utils/cli-utils.js +82 -0
- package/dist/slpk-extractor/helpers/file-handle-provider.d.ts +48 -0
- package/dist/slpk-extractor/helpers/file-handle-provider.d.ts.map +1 -0
- package/dist/slpk-extractor/helpers/file-handle-provider.js +71 -0
- package/dist/slpk-extractor/slpk-extractor.d.ts +23 -0
- package/dist/slpk-extractor/slpk-extractor.d.ts.map +1 -0
- package/dist/slpk-extractor/slpk-extractor.js +78 -0
- package/dist/slpk-extractor-cli.d.ts +17 -0
- package/dist/slpk-extractor-cli.d.ts.map +1 -0
- package/dist/slpk-extractor-cli.js +102 -0
- package/dist/slpk-extractor.min.js +189 -0
- package/package.json +17 -15
- package/src/converter-cli.ts +7 -72
- package/src/i3s-converter/helpers/coordinate-converter.ts +1 -2
- package/src/i3s-converter/helpers/gltf-attributes.ts +7 -8
- package/src/i3s-converter/helpers/preprocess-3d-tiles.ts +1 -3
- package/src/i3s-converter/i3s-converter.ts +24 -7
- package/src/lib/utils/cli-utils.ts +78 -0
- package/src/slpk-extractor/helpers/file-handle-provider.ts +91 -0
- package/src/slpk-extractor/slpk-extractor.ts +102 -0
- package/src/slpk-extractor-cli.ts +128 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loaders.gl/tile-converter",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.12",
|
|
4
4
|
"description": "Converter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"sideEffects": false,
|
|
22
22
|
"bin": {
|
|
23
23
|
"tile-converter": "./bin/converter.js",
|
|
24
|
+
"slpk-extractor": "./bin/slpk-extractor.js",
|
|
24
25
|
"i3s-server": "./src/i3s-server/bin/www"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
@@ -37,25 +38,26 @@
|
|
|
37
38
|
"join-images": false
|
|
38
39
|
},
|
|
39
40
|
"scripts": {
|
|
40
|
-
"pre-build": "npm run build-bundle && npm run build-converter-bundle && npm run build-i3s-attributes-worker && npm run build-3d-tiles-attributes-worker",
|
|
41
|
+
"pre-build": "npm run build-bundle && npm run build-converter-bundle && npm run build-i3s-attributes-worker && npm run build-slpk-extractor-bundle && npm run build-3d-tiles-attributes-worker",
|
|
41
42
|
"build-bundle": "esbuild ./src/index.ts --bundle --outfile=dist/dist.min.js --platform=node --external:join-images",
|
|
42
43
|
"build-converter-bundle": "esbuild src/converter-cli.ts --outfile=dist/converter.min.js --platform=node --target=esnext,node14 --external:join-images --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
|
|
44
|
+
"build-slpk-extractor-bundle": "esbuild src/slpk-extractor-cli.ts --outfile=dist/slpk-extractor.min.js --platform=node --target=esnext,node14 --external:join-images --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
|
|
43
45
|
"build-i3s-attributes-worker": "esbuild src/workers/i3s-attributes-worker.ts --outfile=dist/i3s-attributes-worker.js --platform=node --target=esnext,node14 --external:join-images --minify --bundle --sourcemap --define:__VERSION__=\\\"$npm_package_version\\\"",
|
|
44
46
|
"build-3d-tiles-attributes-worker": "esbuild src/workers/3d-tiles-attributes-worker.ts --outfile=dist/3d-tiles-attributes-worker.js --platform=node --target=esnext,node14 --external:join-images --minify --bundle --sourcemap --define:__VERSION__=\\\"$npm_package_version\\\""
|
|
45
47
|
},
|
|
46
48
|
"dependencies": {
|
|
47
|
-
"@loaders.gl/3d-tiles": "4.0.0-alpha.
|
|
48
|
-
"@loaders.gl/crypto": "4.0.0-alpha.
|
|
49
|
-
"@loaders.gl/draco": "4.0.0-alpha.
|
|
50
|
-
"@loaders.gl/gltf": "4.0.0-alpha.
|
|
51
|
-
"@loaders.gl/i3s": "4.0.0-alpha.
|
|
52
|
-
"@loaders.gl/images": "4.0.0-alpha.
|
|
53
|
-
"@loaders.gl/loader-utils": "4.0.0-alpha.
|
|
54
|
-
"@loaders.gl/polyfills": "4.0.0-alpha.
|
|
55
|
-
"@loaders.gl/textures": "4.0.0-alpha.
|
|
56
|
-
"@loaders.gl/tiles": "4.0.0-alpha.
|
|
57
|
-
"@loaders.gl/worker-utils": "4.0.0-alpha.
|
|
58
|
-
"@loaders.gl/zip": "4.0.0-alpha.
|
|
49
|
+
"@loaders.gl/3d-tiles": "4.0.0-alpha.12",
|
|
50
|
+
"@loaders.gl/crypto": "4.0.0-alpha.12",
|
|
51
|
+
"@loaders.gl/draco": "4.0.0-alpha.12",
|
|
52
|
+
"@loaders.gl/gltf": "4.0.0-alpha.12",
|
|
53
|
+
"@loaders.gl/i3s": "4.0.0-alpha.12",
|
|
54
|
+
"@loaders.gl/images": "4.0.0-alpha.12",
|
|
55
|
+
"@loaders.gl/loader-utils": "4.0.0-alpha.12",
|
|
56
|
+
"@loaders.gl/polyfills": "4.0.0-alpha.12",
|
|
57
|
+
"@loaders.gl/textures": "4.0.0-alpha.12",
|
|
58
|
+
"@loaders.gl/tiles": "4.0.0-alpha.12",
|
|
59
|
+
"@loaders.gl/worker-utils": "4.0.0-alpha.12",
|
|
60
|
+
"@loaders.gl/zip": "4.0.0-alpha.12",
|
|
59
61
|
"@math.gl/core": "^3.5.1",
|
|
60
62
|
"@math.gl/culling": "^3.5.1",
|
|
61
63
|
"@math.gl/geoid": "^3.5.1",
|
|
@@ -78,5 +80,5 @@
|
|
|
78
80
|
"join-images": "^1.1.3",
|
|
79
81
|
"sharp": "^0.31.3"
|
|
80
82
|
},
|
|
81
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "42dfc47a41e3e6089eec22a1e1d4f3387e0cb6e9"
|
|
82
84
|
}
|
package/src/converter-cli.ts
CHANGED
|
@@ -3,6 +3,13 @@ import '@loaders.gl/polyfills';
|
|
|
3
3
|
import {join} from 'path';
|
|
4
4
|
import {I3SConverter, Tiles3DConverter} from '@loaders.gl/tile-converter';
|
|
5
5
|
import {DepsInstaller} from './deps-installer/deps-installer';
|
|
6
|
+
import {
|
|
7
|
+
getBooleanValue,
|
|
8
|
+
getIntegerValue,
|
|
9
|
+
getStringValue,
|
|
10
|
+
getURLValue,
|
|
11
|
+
validateOptionsWithEqual
|
|
12
|
+
} from './lib/utils/cli-utils';
|
|
6
13
|
|
|
7
14
|
type TileConversionOptions = {
|
|
8
15
|
/** "I3S" - for I3S to 3DTiles conversion, "3DTILES" for 3DTiles to I3S conversion */
|
|
@@ -213,19 +220,6 @@ function validateOptions(options: TileConversionOptions): ValidatedTileConversio
|
|
|
213
220
|
return <ValidatedTileConversionOptions>options;
|
|
214
221
|
}
|
|
215
222
|
|
|
216
|
-
function validateOptionsWithEqual(args: string[]): string[] {
|
|
217
|
-
return args.reduce((acc: string[], curr) => {
|
|
218
|
-
const equalSignIndex = curr.indexOf('=');
|
|
219
|
-
const beforeEqual = curr.slice(0, equalSignIndex);
|
|
220
|
-
const afterEqual = curr.slice(equalSignIndex + 1, curr.length);
|
|
221
|
-
const condition = curr.includes('=') && curr.startsWith('--') && afterEqual;
|
|
222
|
-
if (condition) {
|
|
223
|
-
return acc.concat(beforeEqual, afterEqual);
|
|
224
|
-
}
|
|
225
|
-
return acc.concat(curr);
|
|
226
|
-
}, []);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
223
|
/**
|
|
230
224
|
* Parse option from the cli arguments array
|
|
231
225
|
* @param args
|
|
@@ -309,62 +303,3 @@ function parseOptions(args: string[]): TileConversionOptions {
|
|
|
309
303
|
});
|
|
310
304
|
return opts;
|
|
311
305
|
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Get string option value from cli arguments
|
|
315
|
-
* @param index - option's name index in the argument's array.
|
|
316
|
-
* The value of the option should be next to name of the option.
|
|
317
|
-
* @param args - cli arguments array
|
|
318
|
-
* @returns - string value of the option
|
|
319
|
-
*/
|
|
320
|
-
function getStringValue(index: number, args: string[]): string {
|
|
321
|
-
if (index + 1 >= args.length) {
|
|
322
|
-
return '';
|
|
323
|
-
}
|
|
324
|
-
const value = args[index + 1];
|
|
325
|
-
if (value.indexOf('--') === 0) {
|
|
326
|
-
return '';
|
|
327
|
-
}
|
|
328
|
-
return value;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Modyfy URL path to be compatible with fetch
|
|
333
|
-
* @param index - option's name index in the argument's array.
|
|
334
|
-
* The value of the option should be next to name of the option.
|
|
335
|
-
* @param args - cli arguments array
|
|
336
|
-
* @returns - string value of the option
|
|
337
|
-
*/
|
|
338
|
-
function getURLValue(index: number, args: string[]): string {
|
|
339
|
-
const value = getStringValue(index, args);
|
|
340
|
-
console.log(`Input tileset value: ${value}`);
|
|
341
|
-
console.log(`Modified tileset value: ${value.replace(/\\/g, '/')}`);
|
|
342
|
-
return value.replace(/\\/g, '/');
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Get integer option value from cli arguments
|
|
347
|
-
* @param index - option's name index in the argument's array
|
|
348
|
-
* The value of the option should be next to name of the option.
|
|
349
|
-
* @param args - cli arguments array
|
|
350
|
-
* @returns - number value of the option
|
|
351
|
-
*/
|
|
352
|
-
function getIntegerValue(index: number, args: string[]): number {
|
|
353
|
-
const stringValue: string = getStringValue(index, args);
|
|
354
|
-
const result: number = Number.parseInt(stringValue);
|
|
355
|
-
if (isFinite(result)) {
|
|
356
|
-
return result;
|
|
357
|
-
}
|
|
358
|
-
return NaN;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function getBooleanValue(index: number, args: string[]): boolean {
|
|
362
|
-
const stringValue: string = getStringValue(index, args).toLowerCase().trim();
|
|
363
|
-
if (['--no-draco', '--split-nodes'].includes(args[index]) && !stringValue) {
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
if (!stringValue || stringValue === 'true') {
|
|
367
|
-
return true;
|
|
368
|
-
}
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
@@ -103,7 +103,6 @@ export function convertPositionsToVectors(positions: Float32Array): Vector3[] {
|
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
105
|
* Convert common coordinate to fullExtent https://github.com/Esri/i3s-spec/blob/master/docs/1.8/fullExtent.cmn.md
|
|
106
|
-
* @param
|
|
107
106
|
* @param boundingVolume
|
|
108
107
|
* @returns - fullExtent object
|
|
109
108
|
*/
|
|
@@ -142,7 +141,7 @@ export function convertBoundingVolumeToI3SFullExtent(
|
|
|
142
141
|
/**
|
|
143
142
|
* Creates oriented boundinb box from mbs.
|
|
144
143
|
* @param mbs - Minimum Bounding Sphere
|
|
145
|
-
* @returns - Oriented
|
|
144
|
+
* @returns - Oriented Bounding Box
|
|
146
145
|
*/
|
|
147
146
|
export function createObbFromMbs(mbs: Mbs): Obb {
|
|
148
147
|
const radius = mbs[3];
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import type {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
2
2
|
import type {GLTFAccessorPostprocessed, GLTFNodePostprocessed} from '@loaders.gl/gltf';
|
|
3
3
|
import type {B3DMAttributesData} from '../../i3s-attributes-worker';
|
|
4
|
-
import {Matrix4, Vector3} from '@math.gl/core';
|
|
4
|
+
import {Matrix4, TypedArray, Vector3} from '@math.gl/core';
|
|
5
5
|
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
|
|
6
6
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
7
7
|
|
|
8
|
-
type AttributesObject = {
|
|
9
|
-
[k: string]: GLTFAccessorPostprocessed;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
8
|
/**
|
|
13
9
|
* Prepare attributes for conversion to avoid binary data breaking in worker thread.
|
|
14
10
|
* @param tileContent - 3DTiles tile content
|
|
15
11
|
* @param tileTransform - transformation matrix of the tile, calculated recursively multiplying
|
|
16
12
|
* transform of all parent tiles and transform of the current tile
|
|
17
13
|
* @param boundingVolume - initialized bounding volume of the source tile
|
|
18
|
-
* @returns
|
|
14
|
+
* @returns 3DTiles content data, prepared for conversion
|
|
19
15
|
*/
|
|
20
16
|
export function prepareDataForAttributesConversion(
|
|
21
17
|
tileContent: Tiles3DTileContent,
|
|
@@ -67,9 +63,12 @@ export function prepareDataForAttributesConversion(
|
|
|
67
63
|
/**
|
|
68
64
|
* Keep only values for glTF attributes to pass data to worker thread.
|
|
69
65
|
* @param attributes - geometry attributes
|
|
66
|
+
* @returns attributes with only `value` item
|
|
70
67
|
*/
|
|
71
|
-
function getB3DMAttributesWithoutBufferView(
|
|
72
|
-
|
|
68
|
+
function getB3DMAttributesWithoutBufferView(
|
|
69
|
+
attributes: Record<string, GLTFAccessorPostprocessed>
|
|
70
|
+
): Record<string, {value: TypedArray}> {
|
|
71
|
+
const attributesWithoutBufferView: Record<string, {value: TypedArray}> = {};
|
|
73
72
|
|
|
74
73
|
for (const attributeName in attributes) {
|
|
75
74
|
attributesWithoutBufferView[attributeName] = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Tiles3DTileContent
|
|
1
|
+
import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
2
2
|
import {GltfPrimitiveModeString, PreprocessData} from '../types';
|
|
3
3
|
import {GLTF, GLTFLoader} from '@loaders.gl/gltf';
|
|
4
4
|
import {parse} from '@loaders.gl/core';
|
|
@@ -20,12 +20,10 @@ export const GLTF_PRIMITIVE_MODES = [
|
|
|
20
20
|
/**
|
|
21
21
|
* Analyze tile content. This function is used during preprocess stage of
|
|
22
22
|
* conversion
|
|
23
|
-
* @param tile - 3DTiles tile JSON metadata
|
|
24
23
|
* @param tileContent - 3DTiles tile content ArrayBuffer
|
|
25
24
|
* @returns
|
|
26
25
|
*/
|
|
27
26
|
export const analyzeTileContent = async (
|
|
28
|
-
tile: Tiles3DTileJSONPostprocessed,
|
|
29
27
|
tileContent: Tiles3DTileContent | null
|
|
30
28
|
): Promise<PreprocessData> => {
|
|
31
29
|
const result: PreprocessData = {
|
|
@@ -313,11 +313,19 @@ export default class I3SConverter {
|
|
|
313
313
|
if (sourceTile.id) {
|
|
314
314
|
console.log(`[analyze]: ${sourceTile.id}`); // eslint-disable-line
|
|
315
315
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
316
|
+
|
|
317
|
+
let tileContent: Tiles3DTileContent | null = null;
|
|
318
|
+
try {
|
|
319
|
+
tileContent = await loadTile3DContent(this.sourceTileset, sourceTile, {
|
|
320
|
+
...this.loadOptions,
|
|
321
|
+
'3d-tiles': {...this.loadOptions['3d-tiles'], loadGLTF: false}
|
|
322
|
+
});
|
|
323
|
+
} catch (error) {
|
|
324
|
+
console.log(
|
|
325
|
+
`[warning]: Failed to load ${sourceTile.contentUrl}. An I3S tile with empty content will be added to the output tileset`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
const tilePreprocessData = await analyzeTileContent(tileContent);
|
|
321
329
|
mergePreprocessData(this.preprocessData, tilePreprocessData);
|
|
322
330
|
|
|
323
331
|
return null;
|
|
@@ -576,7 +584,12 @@ export default class I3SConverter {
|
|
|
576
584
|
|
|
577
585
|
await this._updateTilesetOptions();
|
|
578
586
|
|
|
579
|
-
|
|
587
|
+
let tileContent: Tiles3DTileContent | null = null;
|
|
588
|
+
try {
|
|
589
|
+
tileContent = await loadTile3DContent(this.sourceTileset, sourceTile, this.loadOptions);
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.log(`[warning]: Failed to load ${sourceTile.contentUrl}`);
|
|
592
|
+
}
|
|
580
593
|
const sourceBoundingVolume = createBoundingVolume(
|
|
581
594
|
sourceTile.boundingVolume,
|
|
582
595
|
transformationMatrix,
|
|
@@ -753,13 +766,17 @@ export default class I3SConverter {
|
|
|
753
766
|
}
|
|
754
767
|
|
|
755
768
|
let nodeId = resources.nodeId;
|
|
756
|
-
let node;
|
|
769
|
+
let node: NodeInPage;
|
|
757
770
|
if (!nodeId) {
|
|
758
771
|
node = await this.nodePages.push(nodeInPage, parentId);
|
|
759
772
|
} else {
|
|
760
773
|
node = await this.nodePages.getNodeById(nodeId);
|
|
761
774
|
}
|
|
762
775
|
|
|
776
|
+
if (!nodeInPage.mesh) {
|
|
777
|
+
console.log(`[warning]: node ${node.index} is created with empty content`);
|
|
778
|
+
}
|
|
779
|
+
|
|
763
780
|
NodePages.updateAll(node, nodeInPage);
|
|
764
781
|
if (meshMaterial) {
|
|
765
782
|
NodePages.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get string option value from cli arguments
|
|
3
|
+
* @param index - option's name index in the argument's array.
|
|
4
|
+
* The value of the option should be next to name of the option.
|
|
5
|
+
* @param args - cli arguments array
|
|
6
|
+
* @returns - string value of the option
|
|
7
|
+
*/
|
|
8
|
+
export function getStringValue(index: number, args: string[]): string {
|
|
9
|
+
if (index + 1 >= args.length) {
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
const value = args[index + 1];
|
|
13
|
+
if (value.indexOf('--') === 0) {
|
|
14
|
+
return '';
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Modyfy URL path to be compatible with fetch
|
|
21
|
+
* @param index - option's name index in the argument's array.
|
|
22
|
+
* The value of the option should be next to name of the option.
|
|
23
|
+
* @param args - cli arguments array
|
|
24
|
+
* @returns - string value of the option
|
|
25
|
+
*/
|
|
26
|
+
export function getURLValue(index: number, args: string[]): string {
|
|
27
|
+
const value = getStringValue(index, args);
|
|
28
|
+
console.log(`Input tileset value: ${value}`);
|
|
29
|
+
console.log(`Modified tileset value: ${value.replace(/\\/g, '/')}`);
|
|
30
|
+
return value.replace(/\\/g, '/');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function validateOptionsWithEqual(args: string[]): string[] {
|
|
34
|
+
return args.reduce((acc: string[], curr) => {
|
|
35
|
+
const equalSignIndex = curr.indexOf('=');
|
|
36
|
+
const beforeEqual = curr.slice(0, equalSignIndex);
|
|
37
|
+
const afterEqual = curr.slice(equalSignIndex + 1, curr.length);
|
|
38
|
+
const condition = curr.includes('=') && curr.startsWith('--') && afterEqual;
|
|
39
|
+
if (condition) {
|
|
40
|
+
return acc.concat(beforeEqual, afterEqual);
|
|
41
|
+
}
|
|
42
|
+
return acc.concat(curr);
|
|
43
|
+
}, []);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get integer option value from cli arguments
|
|
48
|
+
* @param index - option's name index in the argument's array
|
|
49
|
+
* The value of the option should be next to name of the option.
|
|
50
|
+
* @param args - cli arguments array
|
|
51
|
+
* @returns - number value of the option
|
|
52
|
+
*/
|
|
53
|
+
export function getIntegerValue(index: number, args: string[]): number {
|
|
54
|
+
const stringValue: string = getStringValue(index, args);
|
|
55
|
+
const result: number = Number.parseInt(stringValue);
|
|
56
|
+
if (isFinite(result)) {
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
return NaN;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get boolean option value from cli arguments
|
|
64
|
+
* @param index - option's name index in the argument's array
|
|
65
|
+
* The value of the option should be next to name of the option.
|
|
66
|
+
* @param args - cli arguments array
|
|
67
|
+
* @returns - boolean value of the option
|
|
68
|
+
*/
|
|
69
|
+
export function getBooleanValue(index: number, args: string[]): boolean {
|
|
70
|
+
const stringValue: string = getStringValue(index, args).toLowerCase().trim();
|
|
71
|
+
if (['--no-draco', '--split-nodes'].includes(args[index]) && !stringValue) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (!stringValue || stringValue === 'true') {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {FileProvider} from '@loaders.gl/i3s';
|
|
2
|
+
import {promises as fsPromises, PathLike} from 'fs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Provides file data using node fs library
|
|
6
|
+
*/
|
|
7
|
+
export class FileHandleProvider implements FileProvider {
|
|
8
|
+
/**
|
|
9
|
+
* Returns a new copy of FileHandleProvider
|
|
10
|
+
* @param path The path to the file in file system
|
|
11
|
+
*/
|
|
12
|
+
static async from(path: PathLike): Promise<FileHandleProvider> {
|
|
13
|
+
const fileDescriptor = await fsPromises.open(path);
|
|
14
|
+
return new FileHandleProvider(fileDescriptor, (await fileDescriptor.stat()).size);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The FileHandle from which data is provided
|
|
19
|
+
*/
|
|
20
|
+
private fileDescriptor: fsPromises.FileHandle;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The file length in bytes
|
|
24
|
+
*/
|
|
25
|
+
private size: number;
|
|
26
|
+
|
|
27
|
+
private constructor(fileDescriptor: fsPromises.FileHandle, size: number) {
|
|
28
|
+
this.fileDescriptor = fileDescriptor;
|
|
29
|
+
this.size = size;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Gets an unsigned 8-bit integer (unsigned byte) at the specified byte offset from the start of the file.
|
|
34
|
+
* @param offset The offset, in bytes, from the start of the file where to read the data.
|
|
35
|
+
*/
|
|
36
|
+
async getUint8(offset: number): Promise<number> {
|
|
37
|
+
const val = new Uint8Array(
|
|
38
|
+
(await this.fileDescriptor.read(Buffer.alloc(1), 0, 1, offset)).buffer.buffer
|
|
39
|
+
).at(0);
|
|
40
|
+
if (val === undefined) {
|
|
41
|
+
throw new Error('something went wrong');
|
|
42
|
+
}
|
|
43
|
+
return val;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Gets an unsigned 16-bit integer (unsigned byte) at the specified byte offset from the start of the file.
|
|
48
|
+
* @param offset The offset, in bytes, from the start of the file where to read the data.
|
|
49
|
+
*/
|
|
50
|
+
async getUint16(offset: number): Promise<number> {
|
|
51
|
+
const val = new Uint16Array(
|
|
52
|
+
(await this.fileDescriptor.read(Buffer.alloc(2), 0, 2, offset)).buffer.buffer
|
|
53
|
+
).at(0);
|
|
54
|
+
if (val === undefined) {
|
|
55
|
+
throw new Error('something went wrong');
|
|
56
|
+
}
|
|
57
|
+
return val;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Gets an unsigned 32-bit integer (unsigned byte) at the specified byte offset from the start of the file.
|
|
62
|
+
* @param offset The offset, in bytes, from the start of the file where to read the data.
|
|
63
|
+
*/
|
|
64
|
+
async getUint32(offset: number): Promise<number> {
|
|
65
|
+
const val = new Uint32Array(
|
|
66
|
+
(await this.fileDescriptor.read(Buffer.alloc(4), 0, 4, offset)).buffer.buffer
|
|
67
|
+
).at(0);
|
|
68
|
+
if (val === undefined) {
|
|
69
|
+
throw new Error('something went wrong');
|
|
70
|
+
}
|
|
71
|
+
return val;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* returns an ArrayBuffer whose contents are a copy of this file bytes from startOffset, inclusive, up to endOffset, exclusive.
|
|
76
|
+
* @param startOffset The offset, in bytes, from the start of the file where to start reading the data.
|
|
77
|
+
* @param endOffset The offset, in bytes, from the start of the file where to end reading the data.
|
|
78
|
+
*/
|
|
79
|
+
async slice(startOffset: number, endOffset: number): Promise<ArrayBuffer> {
|
|
80
|
+
const length = endOffset - startOffset;
|
|
81
|
+
return (await this.fileDescriptor.read(Buffer.alloc(length), 0, length, startOffset)).buffer
|
|
82
|
+
.buffer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* the length (in bytes) of the data.
|
|
87
|
+
*/
|
|
88
|
+
get length(): number {
|
|
89
|
+
return this.size;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {isBrowser} from '@loaders.gl/core';
|
|
2
|
+
|
|
3
|
+
import {BROWSER_ERROR_MESSAGE} from '../constants';
|
|
4
|
+
import {FileHandleProvider} from './helpers/file-handle-provider';
|
|
5
|
+
import {parseZipLocalFileHeader} from '@loaders.gl/i3s';
|
|
6
|
+
import {path} from '@loaders.gl/loader-utils';
|
|
7
|
+
import {GZipCompression} from '@loaders.gl/compression';
|
|
8
|
+
import {writeFile} from '../lib/utils/file-utils';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* names of files that should be changed to index
|
|
12
|
+
*/
|
|
13
|
+
const indexNames = [
|
|
14
|
+
'3dSceneLayer.json.gz',
|
|
15
|
+
'3dNodeIndexDocument.json.gz',
|
|
16
|
+
'sharedResource.json.gz'
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Description of the file in the SLPK
|
|
21
|
+
*/
|
|
22
|
+
type File = {
|
|
23
|
+
name: string | null;
|
|
24
|
+
data: ArrayBuffer;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Converter from slpk to i3s
|
|
29
|
+
*/
|
|
30
|
+
export default class SLPKExtractor {
|
|
31
|
+
/**
|
|
32
|
+
* extract slpk to i3s
|
|
33
|
+
* @param options
|
|
34
|
+
* @param options.inputUrl the url to read SLPK file
|
|
35
|
+
* @param options.outputPath the output filename
|
|
36
|
+
*/
|
|
37
|
+
public async extract(options: {inputUrl: string; outputPath: string}): Promise<string> {
|
|
38
|
+
if (isBrowser) {
|
|
39
|
+
console.log(BROWSER_ERROR_MESSAGE);
|
|
40
|
+
return BROWSER_ERROR_MESSAGE;
|
|
41
|
+
}
|
|
42
|
+
const {inputUrl} = options;
|
|
43
|
+
|
|
44
|
+
const provider = await FileHandleProvider.from(inputUrl);
|
|
45
|
+
|
|
46
|
+
let localHeader = await parseZipLocalFileHeader(0, provider);
|
|
47
|
+
while (localHeader) {
|
|
48
|
+
await this.writeFile(
|
|
49
|
+
await this.unGzip({
|
|
50
|
+
name: this.correctIndexNames(localHeader.fileName),
|
|
51
|
+
data: await provider.slice(
|
|
52
|
+
localHeader.fileDataOffset,
|
|
53
|
+
localHeader.fileDataOffset + localHeader.compressedSize
|
|
54
|
+
)
|
|
55
|
+
}),
|
|
56
|
+
options.outputPath
|
|
57
|
+
);
|
|
58
|
+
localHeader = await parseZipLocalFileHeader(
|
|
59
|
+
localHeader?.fileDataOffset + localHeader?.compressedSize,
|
|
60
|
+
provider
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return 'success';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Defines file name and path for i3s format
|
|
69
|
+
* @param fileName initial file name and path
|
|
70
|
+
*/
|
|
71
|
+
private correctIndexNames(fileName: string): string | null {
|
|
72
|
+
if (indexNames.includes(path.filename(path.join('/', fileName)))) {
|
|
73
|
+
return path.join(path.dirname(fileName), 'index.json.gz');
|
|
74
|
+
}
|
|
75
|
+
// finds path with name part and extention part
|
|
76
|
+
let parts = /^(.*\/[^\/\.]*)(\..+)$/.exec(fileName);
|
|
77
|
+
if (!parts) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return `${parts?.at(1)}/index${parts?.at(2)}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private async unGzip(file: File): Promise<File> {
|
|
84
|
+
if (/\.gz$/.test(file.name ?? '')) {
|
|
85
|
+
const compression = new GZipCompression();
|
|
86
|
+
|
|
87
|
+
const decompressedData = await compression.decompress(file.data);
|
|
88
|
+
return {data: decompressedData, name: (file.name ?? '').slice(0, -3)};
|
|
89
|
+
}
|
|
90
|
+
return Promise.resolve(file);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private async writeFile(options: File, outputPath: string): Promise<void> {
|
|
94
|
+
if (!options.name) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const finalPath = path.join(outputPath, options.name);
|
|
98
|
+
const dirName = path.dirname(finalPath);
|
|
99
|
+
const fileName = path.filename(finalPath);
|
|
100
|
+
await writeFile(dirName, options.data, fileName);
|
|
101
|
+
}
|
|
102
|
+
}
|