@loaders.gl/tile-converter 4.1.0-alpha.9 → 4.2.0-alpha.1
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/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
- package/dist/3d-tiles-converter/3d-tiles-converter.js +4 -4
- package/dist/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
- package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
- package/dist/3d-tiles-converter/helpers/b3dm-converter.js +8 -0
- package/dist/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
- package/dist/3d-tiles-converter/json-templates/tileset.d.ts.map +1 -1
- package/dist/3d-tiles-converter/json-templates/tileset.js +3 -0
- package/dist/3d-tiles-converter/json-templates/tileset.js.map +1 -1
- 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 +3 -3
- package/dist/converter-cli.js.map +1 -1
- package/dist/converter.min.cjs +131 -220
- package/dist/deps-installer/deps-installer.js +1 -1
- package/dist/i3s-converter/helpers/attribute-metadata-info.d.ts +10 -0
- package/dist/i3s-converter/helpers/attribute-metadata-info.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/attribute-metadata-info.js +5 -0
- package/dist/i3s-converter/helpers/attribute-metadata-info.js.map +1 -1
- package/dist/i3s-converter/helpers/node-index-document.d.ts +2 -1
- package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/node-index-document.js +6 -8
- package/dist/i3s-converter/helpers/node-index-document.js.map +1 -1
- package/dist/i3s-converter/helpers/progress.js +1 -1
- package/dist/i3s-converter/helpers/progress.js.map +1 -1
- package/dist/i3s-converter/i3s-converter.d.ts +32 -0
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.js +195 -47
- 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 +76 -76
- package/dist/index.cjs +638 -139
- package/dist/lib/utils/compress-util.d.ts +0 -37
- package/dist/lib/utils/compress-util.d.ts.map +1 -1
- package/dist/lib/utils/compress-util.js +1 -149
- package/dist/lib/utils/compress-util.js.map +1 -1
- package/dist/lib/utils/conversion-dump.d.ts +131 -0
- package/dist/lib/utils/conversion-dump.d.ts.map +1 -0
- package/dist/lib/utils/conversion-dump.js +191 -0
- package/dist/lib/utils/conversion-dump.js.map +1 -0
- package/dist/lib/utils/statistic-utills.js +1 -1
- package/dist/lib/utils/statistic-utills.js.map +1 -1
- 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/slpk-extractor.min.cjs +31 -31
- package/package.json +16 -16
- package/src/3d-tiles-converter/3d-tiles-converter.ts +5 -4
- package/src/3d-tiles-converter/helpers/b3dm-converter.ts +19 -0
- package/src/3d-tiles-converter/json-templates/tileset.ts +3 -0
- package/src/constants.ts +1 -0
- package/src/converter-cli.ts +3 -3
- package/src/i3s-converter/helpers/attribute-metadata-info.ts +16 -0
- package/src/i3s-converter/helpers/node-index-document.ts +18 -8
- package/src/i3s-converter/helpers/progress.ts +1 -1
- package/src/i3s-converter/i3s-converter.ts +385 -93
- package/src/i3s-converter/types.ts +8 -0
- package/src/lib/utils/compress-util.ts +1 -264
- package/src/lib/utils/conversion-dump.ts +325 -0
- package/src/lib/utils/statistic-utills.ts +1 -1
- package/src/lib/utils/write-queue.ts +15 -2
|
@@ -17,7 +17,8 @@ import type {
|
|
|
17
17
|
BoundingVolumes,
|
|
18
18
|
MaxScreenThresholdSQ,
|
|
19
19
|
NodeInPage,
|
|
20
|
-
Attribute
|
|
20
|
+
Attribute,
|
|
21
|
+
Node3DIndexDocument
|
|
21
22
|
} from '@loaders.gl/i3s';
|
|
22
23
|
import {load, encode, isBrowser} from '@loaders.gl/core';
|
|
23
24
|
import {CesiumIonLoader, Tiles3DLoader} from '@loaders.gl/3d-tiles';
|
|
@@ -30,12 +31,7 @@ import md5 from 'md5';
|
|
|
30
31
|
|
|
31
32
|
import NodePages from './helpers/node-pages';
|
|
32
33
|
import {writeFile, removeDir, writeFileForSlpk, removeFile} from '../lib/utils/file-utils';
|
|
33
|
-
import {
|
|
34
|
-
compressFileWithGzip,
|
|
35
|
-
compressWithChildProcess
|
|
36
|
-
// generateHash128FromZip,
|
|
37
|
-
// addFileToZip
|
|
38
|
-
} from '../lib/utils/compress-util';
|
|
34
|
+
import {compressFileWithGzip} from '../lib/utils/compress-util';
|
|
39
35
|
import {calculateFilesSize, timeConverter} from '../lib/utils/statistic-utills';
|
|
40
36
|
import convertB3dmToI3sGeometry, {getPropertyTable} from './helpers/geometry-converter';
|
|
41
37
|
import {
|
|
@@ -51,7 +47,7 @@ import {GEOMETRY_DEFINITION as geometryDefinitionTemlate} from './json-templates
|
|
|
51
47
|
import {SHARED_RESOURCES as sharedResourcesTemplate} from './json-templates/shared-resources';
|
|
52
48
|
import {validateNodeBoundingVolumes} from './helpers/node-debug';
|
|
53
49
|
import {KTX2BasisWriterWorker} from '@loaders.gl/textures';
|
|
54
|
-
import {
|
|
50
|
+
import {LoaderWithParser} from '@loaders.gl/loader-utils';
|
|
55
51
|
import {I3SMaterialDefinition, TextureSetDefinitionFormats} from '@loaders.gl/i3s';
|
|
56
52
|
import {ImageWriter} from '@loaders.gl/images';
|
|
57
53
|
import {GLTFImagePostprocessed} from '@loaders.gl/gltf';
|
|
@@ -59,6 +55,7 @@ import {
|
|
|
59
55
|
GLTFPrimitiveModeString,
|
|
60
56
|
I3SConvertedResources,
|
|
61
57
|
PreprocessData,
|
|
58
|
+
ResourceType,
|
|
62
59
|
SharedResourcesArrays
|
|
63
60
|
} from './types';
|
|
64
61
|
import {WorkerFarm} from '@loaders.gl/worker-utils';
|
|
@@ -81,7 +78,8 @@ import {createBoundingVolume} from '@loaders.gl/tiles';
|
|
|
81
78
|
import {TraversalConversionProps, traverseDatasetWith} from './helpers/tileset-traversal';
|
|
82
79
|
import {analyzeTileContent, mergePreprocessData} from './helpers/preprocess-3d-tiles';
|
|
83
80
|
import {Progress} from './helpers/progress';
|
|
84
|
-
import {
|
|
81
|
+
import {composeHashFile, createZip} from '@loaders.gl/zip';
|
|
82
|
+
import {ConversionDump, ConversionDumpOptions, DumpMetadata} from '../lib/utils/conversion-dump';
|
|
85
83
|
|
|
86
84
|
const ION_DEFAULT_TOKEN = process.env?.IonToken;
|
|
87
85
|
const HARDCODED_NODES_PER_PAGE = 64;
|
|
@@ -136,13 +134,14 @@ export default class I3SConverter {
|
|
|
136
134
|
generateBoundingVolumes: boolean;
|
|
137
135
|
layersHasTexture: boolean;
|
|
138
136
|
workerSource: {[key: string]: string} = {};
|
|
139
|
-
writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue();
|
|
137
|
+
writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue(new ConversionDump());
|
|
140
138
|
compressList: string[] | null = null;
|
|
141
139
|
preprocessData: PreprocessData = {
|
|
142
140
|
meshTopologyTypes: new Set(),
|
|
143
141
|
metadataClasses: new Set()
|
|
144
142
|
};
|
|
145
143
|
progresses: Record<string, Progress> = {};
|
|
144
|
+
conversionDump: ConversionDump;
|
|
146
145
|
|
|
147
146
|
constructor() {
|
|
148
147
|
this.attributeMetadataInfo = new AttributeMetadataInfo();
|
|
@@ -165,6 +164,7 @@ export default class I3SConverter {
|
|
|
165
164
|
this.generateBoundingVolumes = false;
|
|
166
165
|
this.layersHasTexture = false;
|
|
167
166
|
this.compressList = null;
|
|
167
|
+
this.conversionDump = new ConversionDump();
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
/**
|
|
@@ -228,6 +228,8 @@ export default class I3SConverter {
|
|
|
228
228
|
analyze = false
|
|
229
229
|
} = options;
|
|
230
230
|
this.options = {
|
|
231
|
+
outputPath,
|
|
232
|
+
tilesetName,
|
|
231
233
|
maxDepth,
|
|
232
234
|
slpk,
|
|
233
235
|
sevenZipExe,
|
|
@@ -247,7 +249,7 @@ export default class I3SConverter {
|
|
|
247
249
|
this.generateTextures = Boolean(generateTextures);
|
|
248
250
|
this.generateBoundingVolumes = Boolean(generateBoundingVolumes);
|
|
249
251
|
|
|
250
|
-
this.writeQueue = new WriteQueue();
|
|
252
|
+
this.writeQueue = new WriteQueue(this.conversionDump);
|
|
251
253
|
this.writeQueue.startListening();
|
|
252
254
|
|
|
253
255
|
console.log('Loading egm file...'); // eslint-disable-line
|
|
@@ -411,18 +413,49 @@ export default class I3SConverter {
|
|
|
411
413
|
*/
|
|
412
414
|
private async _createAndSaveTileset(outputPath: string, tilesetName: string): Promise<void> {
|
|
413
415
|
const tilesetPath = join(`${outputPath}`, `${tilesetName}`);
|
|
416
|
+
|
|
417
|
+
await this.conversionDump.createDump(this.options as ConversionDumpOptions);
|
|
418
|
+
if (this.conversionDump.restored && this.options.inquirer) {
|
|
419
|
+
const result = await this.options.inquirer.prompt([
|
|
420
|
+
{
|
|
421
|
+
name: 'resumeConversion',
|
|
422
|
+
type: 'confirm',
|
|
423
|
+
message:
|
|
424
|
+
'Dump file of the previous conversion exists, do you want to resume that conversion?'
|
|
425
|
+
}
|
|
426
|
+
]);
|
|
427
|
+
if (!result.resumeConversion) {
|
|
428
|
+
this.conversionDump.reset();
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
this.layers0Path = join(tilesetPath, 'SceneServer', 'layers', '0');
|
|
433
|
+
|
|
414
434
|
// Removing the tilesetPath needed to exclude erroneous files after conversion
|
|
435
|
+
const removePath = this.conversionDump.restored
|
|
436
|
+
? join(this.layers0Path, 'nodepages')
|
|
437
|
+
: tilesetPath;
|
|
415
438
|
try {
|
|
416
|
-
await removeDir(
|
|
439
|
+
await removeDir(removePath);
|
|
417
440
|
} catch (e) {
|
|
418
441
|
// do nothing
|
|
419
442
|
}
|
|
420
443
|
|
|
421
|
-
this.
|
|
444
|
+
if (this.conversionDump.restored && this.conversionDump.attributeMetadataInfo) {
|
|
445
|
+
this.attributeMetadataInfo.fromObject(this.conversionDump.attributeMetadataInfo);
|
|
446
|
+
}
|
|
422
447
|
|
|
423
448
|
this.materialDefinitions = [];
|
|
424
449
|
this.materialMap = new Map();
|
|
425
450
|
|
|
451
|
+
if (this.conversionDump.restored && this.conversionDump.materialDefinitions) {
|
|
452
|
+
for (let i = 0; i < this.conversionDump.materialDefinitions.length; i++) {
|
|
453
|
+
const hash = md5(JSON.stringify(this.conversionDump.materialDefinitions[i]));
|
|
454
|
+
this.materialMap.set(hash, i);
|
|
455
|
+
}
|
|
456
|
+
this.materialDefinitions = this.conversionDump.materialDefinitions;
|
|
457
|
+
}
|
|
458
|
+
|
|
426
459
|
const sourceRootTile: Tiles3DTileJSONPostprocessed = this.sourceTileset!.root!;
|
|
427
460
|
const sourceBoundingVolume = createBoundingVolume(
|
|
428
461
|
sourceRootTile.boundingVolume,
|
|
@@ -467,6 +500,10 @@ export default class I3SConverter {
|
|
|
467
500
|
this.layers0!.layerType = _3D_OBJECT_LAYER_TYPE;
|
|
468
501
|
}
|
|
469
502
|
|
|
503
|
+
if (this.conversionDump.restored && this.conversionDump.textureSetDefinitions) {
|
|
504
|
+
this.layers0!.textureSetDefinitions = this.conversionDump.textureSetDefinitions;
|
|
505
|
+
}
|
|
506
|
+
|
|
470
507
|
this.layers0!.materialDefinitions = this.materialDefinitions;
|
|
471
508
|
// @ts-ignore
|
|
472
509
|
this.layers0.geometryDefinitions = transform(
|
|
@@ -554,38 +591,16 @@ export default class I3SConverter {
|
|
|
554
591
|
* @param tilesetPath - Path to save file
|
|
555
592
|
*/
|
|
556
593
|
private async _createSlpk(tilesetPath: string): Promise<void> {
|
|
594
|
+
await this.conversionDump.deleteDumpFile();
|
|
557
595
|
if (this.options.slpk) {
|
|
558
596
|
const slpkTilesetPath = join(tilesetPath, 'SceneServer', 'layers', '0');
|
|
559
597
|
const slpkFileName = `${tilesetPath}.slpk`;
|
|
560
|
-
await compressWithChildProcess(
|
|
561
|
-
slpkTilesetPath,
|
|
562
|
-
slpkFileName,
|
|
563
|
-
0,
|
|
564
|
-
'.',
|
|
565
|
-
this.options.sevenZipExe
|
|
566
|
-
);
|
|
567
598
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
// try {
|
|
574
|
-
// await generateHash128FromZip(slpkFileName, fileHash128Path);
|
|
575
|
-
// await addFileToZip(
|
|
576
|
-
// tilesetPath,
|
|
577
|
-
// '@specialIndexFileHASH128@',
|
|
578
|
-
// slpkFileName,
|
|
579
|
-
// this.options.sevenZipExe
|
|
580
|
-
// );
|
|
581
|
-
// } catch (error) {
|
|
582
|
-
// if (error.code === FS_FILE_TOO_LARGE) {
|
|
583
|
-
// console.warn(`${slpkFileName} file is too big to generate a hash`); // eslint-disable-line
|
|
584
|
-
// } else {
|
|
585
|
-
// console.error(error); // eslint-disable-line
|
|
586
|
-
// }
|
|
587
|
-
// }
|
|
588
|
-
// All converted files are contained in slpk now they can be deleted
|
|
599
|
+
await createZip(slpkTilesetPath, slpkFileName, async (fileList) => ({
|
|
600
|
+
path: '@specialIndexFileHASH128@',
|
|
601
|
+
file: await composeHashFile(fileList)
|
|
602
|
+
}));
|
|
603
|
+
|
|
589
604
|
try {
|
|
590
605
|
await removeDir(tilesetPath);
|
|
591
606
|
} catch (e) {
|
|
@@ -618,13 +633,20 @@ export default class I3SConverter {
|
|
|
618
633
|
if (sourceTile.id) {
|
|
619
634
|
console.log(`[convert]: ${sourceTile.id}`); // eslint-disable-line
|
|
620
635
|
}
|
|
636
|
+
|
|
621
637
|
const {parentNodes, transform} = traversalProps;
|
|
622
638
|
let transformationMatrix: Matrix4 = transform.clone();
|
|
623
639
|
if (sourceTile.transform) {
|
|
624
640
|
transformationMatrix = transformationMatrix.multiplyRight(sourceTile.transform);
|
|
625
641
|
}
|
|
626
642
|
const parentNode = parentNodes[0];
|
|
627
|
-
const
|
|
643
|
+
const restoreResult = await this._restoreNode(parentNode, sourceTile, transformationMatrix);
|
|
644
|
+
let childNodes;
|
|
645
|
+
if (restoreResult === null) {
|
|
646
|
+
childNodes = await this._createNode(parentNode, sourceTile, transformationMatrix);
|
|
647
|
+
} else {
|
|
648
|
+
childNodes = restoreResult;
|
|
649
|
+
}
|
|
628
650
|
await parentNode.addChildren(childNodes);
|
|
629
651
|
|
|
630
652
|
const newTraversalProps: TraversalConversionProps = {
|
|
@@ -642,8 +664,9 @@ export default class I3SConverter {
|
|
|
642
664
|
timeRemainingString = `${timeRemainingStringBasedOnCount} left`;
|
|
643
665
|
}
|
|
644
666
|
|
|
645
|
-
|
|
646
|
-
|
|
667
|
+
const percentString = this.progresses[PROGRESS_PHASE1_COUNT].getPercentString();
|
|
668
|
+
const progressString = percentString ? ` ${percentString}%, ${timeRemainingString}` : '';
|
|
669
|
+
console.log(`[converted${progressString}]: ${sourceTile.id}`); // eslint-disable-line
|
|
647
670
|
}
|
|
648
671
|
return newTraversalProps;
|
|
649
672
|
}
|
|
@@ -667,6 +690,114 @@ export default class I3SConverter {
|
|
|
667
690
|
}
|
|
668
691
|
}
|
|
669
692
|
|
|
693
|
+
/**
|
|
694
|
+
* Generate NodeIndexDocument
|
|
695
|
+
* @param boundingVolumes - Bounding volumes
|
|
696
|
+
* @param resources - converted or dumped node resources data
|
|
697
|
+
* @param parentNode - 3DNodeIndexDocument of parent node
|
|
698
|
+
* @param sourceTile - source 3DTile data
|
|
699
|
+
* @param isDumped - indicator if the node is dumped
|
|
700
|
+
* @return NodeIndexDocument, nodeInPage and node data
|
|
701
|
+
*/
|
|
702
|
+
private async _generateNodeIndexDocument(
|
|
703
|
+
boundingVolumes: BoundingVolumes,
|
|
704
|
+
resources: I3SConvertedResources | DumpMetadata,
|
|
705
|
+
parentNode: NodeIndexDocument,
|
|
706
|
+
sourceTile: Tiles3DTileJSONPostprocessed,
|
|
707
|
+
isDumped: boolean
|
|
708
|
+
): Promise<{node: NodeIndexDocument; nodeInPage: NodeInPage; nodeData: Node3DIndexDocument}> {
|
|
709
|
+
this.layersHasTexture =
|
|
710
|
+
this.layersHasTexture ||
|
|
711
|
+
Boolean(
|
|
712
|
+
('texture' in resources && resources.texture) ||
|
|
713
|
+
('texelCountHint' in resources && resources.texelCountHint)
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
if (this.generateBoundingVolumes && resources.boundingVolumes) {
|
|
717
|
+
boundingVolumes = resources.boundingVolumes;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const lodSelection = convertGeometricErrorToScreenThreshold(sourceTile, boundingVolumes);
|
|
721
|
+
const maxScreenThresholdSQ = lodSelection.find(
|
|
722
|
+
(val) => val.metricType === 'maxScreenThresholdSQ'
|
|
723
|
+
) || {maxError: 0};
|
|
724
|
+
|
|
725
|
+
if (isDumped) {
|
|
726
|
+
const draftObb = {
|
|
727
|
+
center: [],
|
|
728
|
+
halfSize: [],
|
|
729
|
+
quaternion: []
|
|
730
|
+
};
|
|
731
|
+
await this.nodePages.push({index: 0, obb: draftObb}, parentNode.inPageId);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const nodeInPage = await this._updateNodeInNodePages(
|
|
735
|
+
maxScreenThresholdSQ,
|
|
736
|
+
boundingVolumes,
|
|
737
|
+
sourceTile,
|
|
738
|
+
parentNode.inPageId,
|
|
739
|
+
resources
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
const nodeData = await NodeIndexDocument.createNodeIndexDocument(
|
|
743
|
+
parentNode,
|
|
744
|
+
boundingVolumes,
|
|
745
|
+
lodSelection,
|
|
746
|
+
nodeInPage,
|
|
747
|
+
resources
|
|
748
|
+
);
|
|
749
|
+
|
|
750
|
+
const node = await new NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
|
|
751
|
+
return {node, nodeInPage, nodeData};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Restore 3DNodeIndexDocument from a comversion dump file
|
|
756
|
+
* @param parentNode - 3DNodeIndexDocument of parent node
|
|
757
|
+
* @param sourceTile - source 3DTile data
|
|
758
|
+
* @param transformationMatrix - transformation matrix of the current tile, calculated recursively multiplying
|
|
759
|
+
* transform of all parent tiles and transform of the current tile
|
|
760
|
+
*/
|
|
761
|
+
private async _restoreNode(
|
|
762
|
+
parentNode: NodeIndexDocument,
|
|
763
|
+
sourceTile: Tiles3DTileJSONPostprocessed,
|
|
764
|
+
transformationMatrix: Matrix4
|
|
765
|
+
): Promise<null | NodeIndexDocument[]> {
|
|
766
|
+
this._checkAddRefinementTypeForTile(sourceTile);
|
|
767
|
+
await this._updateTilesetOptions();
|
|
768
|
+
if (
|
|
769
|
+
this.conversionDump.restored &&
|
|
770
|
+
sourceTile.id &&
|
|
771
|
+
this.conversionDump.isFileConversionComplete(sourceTile.id)
|
|
772
|
+
) {
|
|
773
|
+
const sourceBoundingVolume = createBoundingVolume(
|
|
774
|
+
sourceTile.boundingVolume,
|
|
775
|
+
transformationMatrix,
|
|
776
|
+
null
|
|
777
|
+
);
|
|
778
|
+
let boundingVolumes = createBoundingVolumes(sourceBoundingVolume, this.geoidHeightModel!);
|
|
779
|
+
const nodes: NodeIndexDocument[] = [];
|
|
780
|
+
for (const convertedNode of this.conversionDump.tilesConverted[sourceTile.id].nodes) {
|
|
781
|
+
const {node} = await this._generateNodeIndexDocument(
|
|
782
|
+
boundingVolumes,
|
|
783
|
+
{
|
|
784
|
+
...(convertedNode.dumpMetadata as DumpMetadata),
|
|
785
|
+
nodeId: convertedNode.nodeId
|
|
786
|
+
} as I3SConvertedResources | DumpMetadata,
|
|
787
|
+
parentNode,
|
|
788
|
+
sourceTile,
|
|
789
|
+
true
|
|
790
|
+
);
|
|
791
|
+
nodes.push(node);
|
|
792
|
+
}
|
|
793
|
+
return nodes;
|
|
794
|
+
} else if (this.conversionDump.restored && sourceTile.id) {
|
|
795
|
+
//clear existing record in a dump
|
|
796
|
+
this.conversionDump.clearDumpRecord(sourceTile.id);
|
|
797
|
+
}
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
800
|
+
|
|
670
801
|
/**
|
|
671
802
|
* Convert tile to one or more I3S nodes
|
|
672
803
|
* @param parentNode - 3DNodeIndexDocument of parent node
|
|
@@ -700,6 +831,12 @@ export default class I3SConverter {
|
|
|
700
831
|
const propertyTable = getPropertyTable(tileContent, this.options.metadataClass);
|
|
701
832
|
this.createAttributeStorageInfo(tileContent, propertyTable);
|
|
702
833
|
|
|
834
|
+
this.conversionDump.attributeMetadataInfo = {
|
|
835
|
+
attributeStorageInfo: this.attributeMetadataInfo.attributeStorageInfo,
|
|
836
|
+
fields: this.attributeMetadataInfo.fields,
|
|
837
|
+
popupInfo: this.attributeMetadataInfo.popupInfo
|
|
838
|
+
};
|
|
839
|
+
|
|
703
840
|
const resourcesData = await this._convertResources(
|
|
704
841
|
sourceTile,
|
|
705
842
|
transformationMatrix,
|
|
@@ -726,37 +863,34 @@ export default class I3SConverter {
|
|
|
726
863
|
};
|
|
727
864
|
|
|
728
865
|
for (const resources of resourcesData || [emptyResources]) {
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
if (this.generateBoundingVolumes && resources.boundingVolumes) {
|
|
732
|
-
boundingVolumes = resources.boundingVolumes;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
const lodSelection = convertGeometricErrorToScreenThreshold(sourceTile, boundingVolumes);
|
|
736
|
-
const maxScreenThresholdSQ = lodSelection.find(
|
|
737
|
-
(val) => val.metricType === 'maxScreenThresholdSQ'
|
|
738
|
-
) || {maxError: 0};
|
|
739
|
-
|
|
740
|
-
const nodeInPage = await this._updateNodeInNodePages(
|
|
741
|
-
maxScreenThresholdSQ,
|
|
866
|
+
const {node, nodeInPage, nodeData} = await this._generateNodeIndexDocument(
|
|
742
867
|
boundingVolumes,
|
|
743
|
-
|
|
744
|
-
parentNode.inPageId,
|
|
745
|
-
resources
|
|
746
|
-
);
|
|
747
|
-
|
|
748
|
-
const nodeData = await NodeIndexDocument.createNodeIndexDocument(
|
|
868
|
+
resources,
|
|
749
869
|
parentNode,
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
nodeInPage,
|
|
753
|
-
resources
|
|
870
|
+
sourceTile,
|
|
871
|
+
false
|
|
754
872
|
);
|
|
755
|
-
const node = await new NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
|
|
756
873
|
nodes.push(node);
|
|
757
874
|
|
|
758
875
|
if (nodeInPage.mesh) {
|
|
759
|
-
|
|
876
|
+
//update a record in a dump file
|
|
877
|
+
if (sourceTile.id) {
|
|
878
|
+
const dumpMetadata = {
|
|
879
|
+
boundingVolumes: resources.boundingVolumes,
|
|
880
|
+
attributesCount: resources.attributes?.length,
|
|
881
|
+
featureCount: resources.featureCount,
|
|
882
|
+
geometry: Boolean(resources.geometry),
|
|
883
|
+
hasUvRegions: resources.hasUvRegions,
|
|
884
|
+
materialId: nodeInPage.mesh.material.definition,
|
|
885
|
+
texelCountHint: nodeInPage.mesh.material.texelCountHint,
|
|
886
|
+
vertexCount: resources.vertexCount
|
|
887
|
+
};
|
|
888
|
+
this.conversionDump.setMaterialsDefinitions(this.materialDefinitions);
|
|
889
|
+
await this.conversionDump.addNode(sourceTile.id, nodeInPage.index, dumpMetadata);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
//write resources
|
|
893
|
+
await this._writeResources(resources, node.id, sourceTile);
|
|
760
894
|
}
|
|
761
895
|
|
|
762
896
|
if (this.validate) {
|
|
@@ -839,9 +973,9 @@ export default class I3SConverter {
|
|
|
839
973
|
boundingVolumes: BoundingVolumes,
|
|
840
974
|
sourceTile: Tiles3DTileJSONPostprocessed,
|
|
841
975
|
parentId: number,
|
|
842
|
-
resources: I3SConvertedResources
|
|
976
|
+
resources: I3SConvertedResources | DumpMetadata
|
|
843
977
|
): Promise<NodeInPage> {
|
|
844
|
-
const {
|
|
978
|
+
const {vertexCount, featureCount, geometry, hasUvRegions} = resources;
|
|
845
979
|
const nodeInPage: NodeInPage = {
|
|
846
980
|
index: 0,
|
|
847
981
|
lodThreshold: maxScreenThresholdSQ.maxError,
|
|
@@ -851,7 +985,13 @@ export default class I3SConverter {
|
|
|
851
985
|
if (geometry && this.isContentSupported(sourceTile)) {
|
|
852
986
|
nodeInPage.mesh = {
|
|
853
987
|
geometry: {
|
|
854
|
-
definition: this.findOrCreateGeometryDefinition(
|
|
988
|
+
definition: this.findOrCreateGeometryDefinition(
|
|
989
|
+
Boolean(
|
|
990
|
+
('texture' in resources && resources.texture) ||
|
|
991
|
+
('texelCountHint' in resources && resources.texelCountHint)
|
|
992
|
+
),
|
|
993
|
+
hasUvRegions
|
|
994
|
+
),
|
|
855
995
|
resource: 0
|
|
856
996
|
},
|
|
857
997
|
attribute: {
|
|
@@ -863,7 +1003,7 @@ export default class I3SConverter {
|
|
|
863
1003
|
};
|
|
864
1004
|
}
|
|
865
1005
|
|
|
866
|
-
let nodeId = resources.nodeId;
|
|
1006
|
+
let nodeId = 'nodeId' in resources ? resources.nodeId : undefined;
|
|
867
1007
|
let node: NodeInPage;
|
|
868
1008
|
if (!nodeId) {
|
|
869
1009
|
node = await this.nodePages.push(nodeInPage, parentId);
|
|
@@ -876,12 +1016,16 @@ export default class I3SConverter {
|
|
|
876
1016
|
}
|
|
877
1017
|
|
|
878
1018
|
NodePages.updateAll(node, nodeInPage);
|
|
879
|
-
if (meshMaterial) {
|
|
880
|
-
NodePages.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
|
|
1019
|
+
if ('meshMaterial' in resources && resources.meshMaterial) {
|
|
1020
|
+
NodePages.updateMaterialByNodeId(node, this._findOrCreateMaterial(resources.meshMaterial));
|
|
1021
|
+
} else if ('materialId' in resources && resources.materialId !== null) {
|
|
1022
|
+
NodePages.updateMaterialByNodeId(node, resources.materialId);
|
|
881
1023
|
}
|
|
882
|
-
if (texture) {
|
|
883
|
-
const texelCountHint = texture.image.height * texture.image.width;
|
|
1024
|
+
if ('texture' in resources && resources.texture) {
|
|
1025
|
+
const texelCountHint = resources.texture.image.height * resources.texture.image.width;
|
|
884
1026
|
NodePages.updateTexelCountHintByNodeId(node, texelCountHint);
|
|
1027
|
+
} else if ('texelCountHint' in resources && resources.texelCountHint) {
|
|
1028
|
+
NodePages.updateTexelCountHintByNodeId(node, resources.texelCountHint);
|
|
885
1029
|
}
|
|
886
1030
|
if (vertexCount) {
|
|
887
1031
|
this.vertexCounter += vertexCount;
|
|
@@ -905,9 +1049,15 @@ export default class I3SConverter {
|
|
|
905
1049
|
* @param resources.texture - texture image
|
|
906
1050
|
* @param resources.sharedResources - shared resource data object
|
|
907
1051
|
* @param resources.attributes - feature attributes
|
|
1052
|
+
* @param nodePath - node path
|
|
1053
|
+
* @param sourceTile - source tile (3DTile)
|
|
908
1054
|
* @return {Promise<void>}
|
|
909
1055
|
*/
|
|
910
|
-
private async _writeResources(
|
|
1056
|
+
private async _writeResources(
|
|
1057
|
+
resources: I3SConvertedResources,
|
|
1058
|
+
nodePath: string,
|
|
1059
|
+
sourceTile: Tiles3DTileJSONPostprocessed
|
|
1060
|
+
): Promise<void> {
|
|
911
1061
|
const {
|
|
912
1062
|
geometry: geometryBuffer,
|
|
913
1063
|
compressedGeometry,
|
|
@@ -918,10 +1068,36 @@ export default class I3SConverter {
|
|
|
918
1068
|
const childPath = join(this.layers0Path, 'nodes', nodePath);
|
|
919
1069
|
const slpkChildPath = join('nodes', nodePath);
|
|
920
1070
|
|
|
921
|
-
await this._writeGeometries(
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1071
|
+
await this._writeGeometries(
|
|
1072
|
+
geometryBuffer!,
|
|
1073
|
+
compressedGeometry!,
|
|
1074
|
+
childPath,
|
|
1075
|
+
slpkChildPath,
|
|
1076
|
+
sourceTile.id || '',
|
|
1077
|
+
parseInt(nodePath)
|
|
1078
|
+
);
|
|
1079
|
+
await this._writeShared(
|
|
1080
|
+
sharedResources,
|
|
1081
|
+
childPath,
|
|
1082
|
+
slpkChildPath,
|
|
1083
|
+
nodePath,
|
|
1084
|
+
sourceTile.id || '',
|
|
1085
|
+
parseInt(nodePath)
|
|
1086
|
+
);
|
|
1087
|
+
await this._writeTexture(
|
|
1088
|
+
texture,
|
|
1089
|
+
childPath,
|
|
1090
|
+
slpkChildPath,
|
|
1091
|
+
sourceTile.id || '',
|
|
1092
|
+
parseInt(nodePath)
|
|
1093
|
+
);
|
|
1094
|
+
await this._writeAttributes(
|
|
1095
|
+
attributes,
|
|
1096
|
+
childPath,
|
|
1097
|
+
slpkChildPath,
|
|
1098
|
+
sourceTile.id || '',
|
|
1099
|
+
parseInt(nodePath)
|
|
1100
|
+
);
|
|
925
1101
|
}
|
|
926
1102
|
|
|
927
1103
|
/**
|
|
@@ -930,37 +1106,57 @@ export default class I3SConverter {
|
|
|
930
1106
|
* @param compressedGeometry - Uint8Array with compressed (draco) geometry
|
|
931
1107
|
* @param childPath - a child path to write resources
|
|
932
1108
|
* @param slpkChildPath - resource path inside *slpk file
|
|
1109
|
+
* @param sourceId - source filename
|
|
1110
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
933
1111
|
*/
|
|
934
1112
|
private async _writeGeometries(
|
|
935
1113
|
geometryBuffer: ArrayBuffer,
|
|
936
1114
|
compressedGeometry: Promise<ArrayBuffer>,
|
|
937
1115
|
childPath: string,
|
|
938
|
-
slpkChildPath: string
|
|
1116
|
+
slpkChildPath: string,
|
|
1117
|
+
sourceId: string,
|
|
1118
|
+
nodeId: number
|
|
939
1119
|
): Promise<void> {
|
|
1120
|
+
this.conversionDump.updateDoneStatus(sourceId, nodeId, ResourceType.GEOMETRY, false);
|
|
1121
|
+
|
|
940
1122
|
if (this.options.slpk) {
|
|
941
1123
|
const slpkGeometryPath = join(childPath, 'geometries');
|
|
942
1124
|
await this.writeQueue.enqueue({
|
|
943
1125
|
archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
|
|
1126
|
+
sourceId,
|
|
1127
|
+
outputId: nodeId,
|
|
1128
|
+
resourceType: ResourceType.GEOMETRY,
|
|
944
1129
|
writePromise: () => writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
|
|
945
1130
|
});
|
|
946
1131
|
} else {
|
|
947
1132
|
const geometryPath = join(childPath, 'geometries/0/');
|
|
948
1133
|
await this.writeQueue.enqueue({
|
|
1134
|
+
sourceId,
|
|
1135
|
+
outputId: nodeId,
|
|
1136
|
+
resourceType: ResourceType.GEOMETRY,
|
|
949
1137
|
writePromise: () => writeFile(geometryPath, geometryBuffer, 'index.bin')
|
|
950
1138
|
});
|
|
951
1139
|
}
|
|
952
1140
|
|
|
953
1141
|
if (this.options.draco) {
|
|
1142
|
+
this.conversionDump.updateDoneStatus(sourceId, nodeId, ResourceType.DRACO_GEOMETRY, false);
|
|
1143
|
+
|
|
954
1144
|
if (this.options.slpk) {
|
|
955
1145
|
const slpkCompressedGeometryPath = join(childPath, 'geometries');
|
|
956
1146
|
await this.writeQueue.enqueue({
|
|
957
1147
|
archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
|
|
1148
|
+
sourceId,
|
|
1149
|
+
outputId: nodeId,
|
|
1150
|
+
resourceType: ResourceType.DRACO_GEOMETRY,
|
|
958
1151
|
writePromise: () =>
|
|
959
1152
|
writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
|
|
960
1153
|
});
|
|
961
1154
|
} else {
|
|
962
1155
|
const compressedGeometryPath = join(childPath, 'geometries/1/');
|
|
963
1156
|
await this.writeQueue.enqueue({
|
|
1157
|
+
sourceId,
|
|
1158
|
+
outputId: nodeId,
|
|
1159
|
+
resourceType: ResourceType.DRACO_GEOMETRY,
|
|
964
1160
|
writePromise: () => writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
|
|
965
1161
|
});
|
|
966
1162
|
}
|
|
@@ -973,12 +1169,16 @@ export default class I3SConverter {
|
|
|
973
1169
|
* @param childPath - a child path to write resources
|
|
974
1170
|
* @param slpkChildPath - resource path inside *slpk file
|
|
975
1171
|
* @param nodePath - a node path
|
|
1172
|
+
* @param sourceId - source filename
|
|
1173
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
976
1174
|
*/
|
|
977
1175
|
private async _writeShared(
|
|
978
1176
|
sharedResources: SharedResourcesArrays | null,
|
|
979
1177
|
childPath: string,
|
|
980
1178
|
slpkChildPath: string,
|
|
981
|
-
nodePath: string
|
|
1179
|
+
nodePath: string,
|
|
1180
|
+
sourceId: string,
|
|
1181
|
+
nodeId: number
|
|
982
1182
|
): Promise<void> {
|
|
983
1183
|
if (!sharedResources) {
|
|
984
1184
|
return;
|
|
@@ -986,15 +1186,24 @@ export default class I3SConverter {
|
|
|
986
1186
|
sharedResources.nodePath = nodePath;
|
|
987
1187
|
const sharedData = transform(sharedResources, sharedResourcesTemplate());
|
|
988
1188
|
const sharedDataStr = JSON.stringify(sharedData);
|
|
1189
|
+
this.conversionDump.updateDoneStatus(sourceId, nodeId, ResourceType.SHARED, false);
|
|
989
1190
|
if (this.options.slpk) {
|
|
990
1191
|
const slpkSharedPath = join(childPath, 'shared');
|
|
991
1192
|
await this.writeQueue.enqueue({
|
|
992
1193
|
archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
|
|
1194
|
+
sourceId,
|
|
1195
|
+
outputId: nodeId,
|
|
1196
|
+
resourceType: ResourceType.SHARED,
|
|
993
1197
|
writePromise: () => writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
|
|
994
1198
|
});
|
|
995
1199
|
} else {
|
|
996
1200
|
const sharedPath = join(childPath, 'shared/');
|
|
997
|
-
await this.writeQueue.enqueue({
|
|
1201
|
+
await this.writeQueue.enqueue({
|
|
1202
|
+
sourceId,
|
|
1203
|
+
outputId: nodeId,
|
|
1204
|
+
resourceType: ResourceType.SHARED,
|
|
1205
|
+
writePromise: () => writeFile(sharedPath, sharedDataStr)
|
|
1206
|
+
});
|
|
998
1207
|
}
|
|
999
1208
|
}
|
|
1000
1209
|
|
|
@@ -1003,11 +1212,15 @@ export default class I3SConverter {
|
|
|
1003
1212
|
* @param texture - the texture image
|
|
1004
1213
|
* @param childPath - a child path to write resources
|
|
1005
1214
|
* @param slpkChildPath - the resource path inside *slpk file
|
|
1215
|
+
* @param sourceId - source filename
|
|
1216
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
1006
1217
|
*/
|
|
1007
1218
|
private async _writeTexture(
|
|
1008
1219
|
texture: GLTFImagePostprocessed,
|
|
1009
1220
|
childPath: string,
|
|
1010
|
-
slpkChildPath: string
|
|
1221
|
+
slpkChildPath: string,
|
|
1222
|
+
sourceId: string,
|
|
1223
|
+
nodeId: number
|
|
1011
1224
|
): Promise<void> {
|
|
1012
1225
|
if (texture) {
|
|
1013
1226
|
const format = this._getFormatByMimeType(texture?.mimeType);
|
|
@@ -1018,7 +1231,21 @@ export default class I3SConverter {
|
|
|
1018
1231
|
case 'jpg':
|
|
1019
1232
|
case 'png': {
|
|
1020
1233
|
formats.push({name: '0', format});
|
|
1021
|
-
|
|
1234
|
+
this.conversionDump.updateDoneStatus(
|
|
1235
|
+
sourceId,
|
|
1236
|
+
nodeId,
|
|
1237
|
+
`${ResourceType.TEXTURE}/${format}`,
|
|
1238
|
+
false
|
|
1239
|
+
);
|
|
1240
|
+
await this.writeTextureFile(
|
|
1241
|
+
textureData,
|
|
1242
|
+
'0',
|
|
1243
|
+
format,
|
|
1244
|
+
childPath,
|
|
1245
|
+
slpkChildPath,
|
|
1246
|
+
sourceId,
|
|
1247
|
+
nodeId
|
|
1248
|
+
);
|
|
1022
1249
|
|
|
1023
1250
|
if (this.generateTextures) {
|
|
1024
1251
|
formats.push({name: '1', format: 'ktx2'});
|
|
@@ -1041,7 +1268,22 @@ export default class I3SConverter {
|
|
|
1041
1268
|
}
|
|
1042
1269
|
);
|
|
1043
1270
|
|
|
1044
|
-
|
|
1271
|
+
this.conversionDump.updateDoneStatus(
|
|
1272
|
+
sourceId,
|
|
1273
|
+
nodeId,
|
|
1274
|
+
`${ResourceType.TEXTURE}/ktx2`,
|
|
1275
|
+
false
|
|
1276
|
+
);
|
|
1277
|
+
|
|
1278
|
+
await this.writeTextureFile(
|
|
1279
|
+
ktx2TextureData,
|
|
1280
|
+
'1',
|
|
1281
|
+
'ktx2',
|
|
1282
|
+
childPath,
|
|
1283
|
+
slpkChildPath,
|
|
1284
|
+
sourceId,
|
|
1285
|
+
nodeId
|
|
1286
|
+
);
|
|
1045
1287
|
}
|
|
1046
1288
|
|
|
1047
1289
|
break;
|
|
@@ -1049,17 +1291,39 @@ export default class I3SConverter {
|
|
|
1049
1291
|
|
|
1050
1292
|
case 'ktx2': {
|
|
1051
1293
|
formats.push({name: '1', format});
|
|
1052
|
-
|
|
1294
|
+
this.conversionDump.updateDoneStatus(
|
|
1295
|
+
sourceId,
|
|
1296
|
+
nodeId,
|
|
1297
|
+
`${ResourceType.TEXTURE}/${format}`,
|
|
1298
|
+
false
|
|
1299
|
+
);
|
|
1300
|
+
await this.writeTextureFile(
|
|
1301
|
+
textureData,
|
|
1302
|
+
'1',
|
|
1303
|
+
format,
|
|
1304
|
+
childPath,
|
|
1305
|
+
slpkChildPath,
|
|
1306
|
+
sourceId,
|
|
1307
|
+
nodeId
|
|
1308
|
+
);
|
|
1053
1309
|
|
|
1054
1310
|
if (this.generateTextures) {
|
|
1055
1311
|
formats.push({name: '0', format: 'jpg'});
|
|
1056
1312
|
const decodedFromKTX2TextureData = encode(texture.image!.data[0], ImageWriter);
|
|
1313
|
+
this.conversionDump.updateDoneStatus(
|
|
1314
|
+
sourceId,
|
|
1315
|
+
nodeId,
|
|
1316
|
+
`${ResourceType.TEXTURE}/jpg`,
|
|
1317
|
+
false
|
|
1318
|
+
);
|
|
1057
1319
|
await this.writeTextureFile(
|
|
1058
1320
|
decodedFromKTX2TextureData,
|
|
1059
1321
|
'0',
|
|
1060
1322
|
'jpg',
|
|
1061
1323
|
childPath,
|
|
1062
|
-
slpkChildPath
|
|
1324
|
+
slpkChildPath,
|
|
1325
|
+
sourceId,
|
|
1326
|
+
nodeId
|
|
1063
1327
|
);
|
|
1064
1328
|
}
|
|
1065
1329
|
}
|
|
@@ -1068,6 +1332,9 @@ export default class I3SConverter {
|
|
|
1068
1332
|
if (!this.layers0!.textureSetDefinitions!.length) {
|
|
1069
1333
|
this.layers0!.textureSetDefinitions!.push({formats});
|
|
1070
1334
|
this.layers0!.textureSetDefinitions!.push({formats, atlas: true});
|
|
1335
|
+
if (this.layers0!.textureSetDefinitions) {
|
|
1336
|
+
this.conversionDump.addTexturesDefinitions(this.layers0!.textureSetDefinitions);
|
|
1337
|
+
}
|
|
1071
1338
|
}
|
|
1072
1339
|
}
|
|
1073
1340
|
}
|
|
@@ -1079,13 +1346,17 @@ export default class I3SConverter {
|
|
|
1079
1346
|
* @param format
|
|
1080
1347
|
* @param childPath
|
|
1081
1348
|
* @param slpkChildPath
|
|
1349
|
+
* @param sourceId
|
|
1350
|
+
* @param nodeId
|
|
1082
1351
|
*/
|
|
1083
1352
|
private async writeTextureFile(
|
|
1084
1353
|
textureData: Uint8Array | Promise<ArrayBuffer>,
|
|
1085
1354
|
name: string,
|
|
1086
1355
|
format: 'jpg' | 'png' | 'ktx2',
|
|
1087
1356
|
childPath: string,
|
|
1088
|
-
slpkChildPath: string
|
|
1357
|
+
slpkChildPath: string,
|
|
1358
|
+
sourceId: string,
|
|
1359
|
+
nodeId: number
|
|
1089
1360
|
): Promise<void> {
|
|
1090
1361
|
if (this.options.slpk) {
|
|
1091
1362
|
const slpkTexturePath = join(childPath, 'textures');
|
|
@@ -1093,12 +1364,18 @@ export default class I3SConverter {
|
|
|
1093
1364
|
|
|
1094
1365
|
await this.writeQueue.enqueue({
|
|
1095
1366
|
archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
|
|
1367
|
+
sourceId,
|
|
1368
|
+
outputId: nodeId,
|
|
1369
|
+
resourceType: `${ResourceType.TEXTURE}/${format}`,
|
|
1096
1370
|
writePromise: () =>
|
|
1097
1371
|
writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
|
|
1098
1372
|
});
|
|
1099
1373
|
} else {
|
|
1100
1374
|
const texturePath = join(childPath, `textures/${name}/`);
|
|
1101
1375
|
await this.writeQueue.enqueue({
|
|
1376
|
+
sourceId,
|
|
1377
|
+
outputId: nodeId,
|
|
1378
|
+
resourceType: `${ResourceType.TEXTURE}/${format}`,
|
|
1102
1379
|
writePromise: () => writeFile(texturePath, textureData, `index.${format}`)
|
|
1103
1380
|
});
|
|
1104
1381
|
}
|
|
@@ -1109,11 +1386,15 @@ export default class I3SConverter {
|
|
|
1109
1386
|
* @param attributes - feature attributes
|
|
1110
1387
|
* @param childPath - a child path to write resources
|
|
1111
1388
|
* @param slpkChildPath - the resource path inside *slpk file
|
|
1389
|
+
* @param sourceId - source filename
|
|
1390
|
+
* @param nodeId - nodeId of a converted node for the writing
|
|
1112
1391
|
*/
|
|
1113
1392
|
private async _writeAttributes(
|
|
1114
1393
|
attributes: ArrayBuffer[] | null = [],
|
|
1115
1394
|
childPath: string,
|
|
1116
|
-
slpkChildPath: string
|
|
1395
|
+
slpkChildPath: string,
|
|
1396
|
+
sourceId: string,
|
|
1397
|
+
nodeId: number
|
|
1117
1398
|
): Promise<void> {
|
|
1118
1399
|
if (attributes?.length && this.attributeMetadataInfo.attributeStorageInfo.length) {
|
|
1119
1400
|
const minimumLength =
|
|
@@ -1124,16 +1405,27 @@ export default class I3SConverter {
|
|
|
1124
1405
|
for (let index = 0; index < minimumLength; index++) {
|
|
1125
1406
|
const folderName = this.attributeMetadataInfo.attributeStorageInfo[index].key;
|
|
1126
1407
|
const fileBuffer = new Uint8Array(attributes[index]);
|
|
1127
|
-
|
|
1408
|
+
this.conversionDump.updateDoneStatus(
|
|
1409
|
+
sourceId,
|
|
1410
|
+
nodeId,
|
|
1411
|
+
`${ResourceType.ATTRIBUTES}/${folderName}`,
|
|
1412
|
+
false
|
|
1413
|
+
);
|
|
1128
1414
|
if (this.options.slpk) {
|
|
1129
1415
|
const slpkAttributesPath = join(childPath, 'attributes', folderName);
|
|
1130
1416
|
await this.writeQueue.enqueue({
|
|
1131
1417
|
archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
|
|
1418
|
+
sourceId,
|
|
1419
|
+
outputId: nodeId,
|
|
1420
|
+
resourceType: `${ResourceType.ATTRIBUTES}/${folderName}`,
|
|
1132
1421
|
writePromise: () => writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
|
|
1133
1422
|
});
|
|
1134
1423
|
} else {
|
|
1135
1424
|
const attributesPath = join(childPath, `attributes/${folderName}/0`);
|
|
1136
1425
|
await this.writeQueue.enqueue({
|
|
1426
|
+
sourceId,
|
|
1427
|
+
outputId: nodeId,
|
|
1428
|
+
resourceType: `${ResourceType.ATTRIBUTES}/${folderName}`,
|
|
1137
1429
|
writePromise: () => writeFile(attributesPath, fileBuffer, 'index.bin')
|
|
1138
1430
|
});
|
|
1139
1431
|
}
|