@loaders.gl/tile-converter 4.2.0-alpha.4 → 4.2.0-alpha.5
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 +3 -3
- package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
- package/dist/3d-tiles-converter/3d-tiles-converter.js +329 -293
- package/dist/3d-tiles-converter/helpers/b3dm-converter.js +257 -200
- package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +14 -5
- package/dist/3d-tiles-converter/helpers/load-i3s.js +106 -75
- package/dist/3d-tiles-converter/helpers/texture-atlas.js +44 -21
- package/dist/3d-tiles-converter/json-templates/tileset.js +32 -33
- package/dist/constants.js +0 -1
- package/dist/converter-cli.js +255 -234
- package/dist/converter.min.cjs +80 -90
- package/dist/deps-installer/deps-installer.js +72 -58
- package/dist/i3s-converter/helpers/attribute-metadata-info.js +207 -153
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +1 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.js +145 -103
- package/dist/i3s-converter/helpers/coordinate-converter.js +100 -65
- package/dist/i3s-converter/helpers/create-scene-server-path.js +14 -9
- package/dist/i3s-converter/helpers/feature-attributes.js +168 -105
- package/dist/i3s-converter/helpers/geometry-attributes.d.ts +1 -1
- package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/geometry-attributes.js +204 -212
- package/dist/i3s-converter/helpers/geometry-converter.d.ts +2 -2
- package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/geometry-converter.js +1148 -829
- 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 +111 -97
- package/dist/i3s-converter/helpers/load-3d-tiles.js +103 -66
- package/dist/i3s-converter/helpers/node-debug.js +98 -54
- package/dist/i3s-converter/helpers/node-index-document.d.ts +3 -3
- package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/node-index-document.js +248 -177
- package/dist/i3s-converter/helpers/node-pages.d.ts +1 -1
- package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/node-pages.js +299 -194
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts +1 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.js +92 -60
- package/dist/i3s-converter/helpers/progress.js +134 -83
- package/dist/i3s-converter/helpers/tileset-traversal.d.ts +1 -1
- package/dist/i3s-converter/helpers/tileset-traversal.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/tileset-traversal.js +24 -13
- package/dist/i3s-converter/i3s-converter.d.ts +7 -7
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.js +1044 -898
- package/dist/i3s-converter/json-templates/geometry-definitions.js +70 -79
- package/dist/i3s-converter/json-templates/layers.js +120 -121
- package/dist/i3s-converter/json-templates/metadata.js +19 -20
- package/dist/i3s-converter/json-templates/node.js +73 -71
- package/dist/i3s-converter/json-templates/scene-server.js +25 -26
- package/dist/i3s-converter/json-templates/shared-resources.js +107 -108
- package/dist/i3s-converter/json-templates/store.js +96 -94
- package/dist/i3s-converter/types.js +35 -23
- package/dist/i3s-server/app.js +15 -12
- package/dist/i3s-server/bin/www.js +14 -7
- package/dist/i3s-server/controllers/index-controller.js +18 -15
- package/dist/i3s-server/controllers/slpk-controller.js +22 -11
- package/dist/i3s-server/routes/index.js +9 -8
- package/dist/i3s-server/routes/slpk-router.js +18 -17
- package/dist/i3s-server/utils/create-scene-server.js +15 -10
- package/dist/i3s-server/utils/server-utils.js +49 -32
- package/dist/index.cjs +292 -851
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/lib/json-schemas/conversion-dump-json-schema.js +243 -421
- package/dist/lib/utils/cli-utils.js +63 -36
- package/dist/lib/utils/compress-util.js +20 -15
- package/dist/lib/utils/conversion-dump.d.ts +1 -1
- package/dist/lib/utils/conversion-dump.d.ts.map +1 -1
- package/dist/lib/utils/conversion-dump.js +209 -187
- package/dist/lib/utils/file-utils.js +122 -74
- package/dist/lib/utils/geometry-utils.js +13 -7
- package/dist/lib/utils/lod-conversion-utils.js +65 -33
- package/dist/lib/utils/queue.js +12 -13
- package/dist/lib/utils/statistic-utills.d.ts +6 -23
- package/dist/lib/utils/statistic-utills.js +64 -59
- package/dist/lib/utils/write-queue.d.ts +2 -2
- package/dist/lib/utils/write-queue.d.ts.map +1 -1
- package/dist/lib/utils/write-queue.js +68 -86
- package/dist/pgm-loader.js +16 -12
- package/dist/slpk-extractor/slpk-extractor.js +59 -50
- package/dist/slpk-extractor-cli.js +82 -59
- package/package.json +18 -18
- package/dist/3d-tiles-converter/3d-tiles-converter.js.map +0 -1
- package/dist/3d-tiles-converter/helpers/b3dm-converter.js.map +0 -1
- package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +0 -1
- package/dist/3d-tiles-converter/helpers/load-i3s.js.map +0 -1
- package/dist/3d-tiles-converter/helpers/texture-atlas.js.map +0 -1
- package/dist/3d-tiles-converter/json-templates/tileset.js.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/converter-cli.js.map +0 -1
- package/dist/deps-installer/deps-installer.js.map +0 -1
- package/dist/i3s-converter/helpers/attribute-metadata-info.js.map +0 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.js.map +0 -1
- package/dist/i3s-converter/helpers/coordinate-converter.js.map +0 -1
- package/dist/i3s-converter/helpers/create-scene-server-path.js.map +0 -1
- package/dist/i3s-converter/helpers/feature-attributes.js.map +0 -1
- package/dist/i3s-converter/helpers/geometry-attributes.js.map +0 -1
- package/dist/i3s-converter/helpers/geometry-converter.js.map +0 -1
- package/dist/i3s-converter/helpers/gltf-attributes.js.map +0 -1
- package/dist/i3s-converter/helpers/load-3d-tiles.js.map +0 -1
- package/dist/i3s-converter/helpers/node-debug.js.map +0 -1
- package/dist/i3s-converter/helpers/node-index-document.js.map +0 -1
- package/dist/i3s-converter/helpers/node-pages.js.map +0 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.js.map +0 -1
- package/dist/i3s-converter/helpers/progress.js.map +0 -1
- package/dist/i3s-converter/helpers/tileset-traversal.js.map +0 -1
- package/dist/i3s-converter/i3s-converter.js.map +0 -1
- package/dist/i3s-converter/json-templates/geometry-definitions.js.map +0 -1
- package/dist/i3s-converter/json-templates/layers.js.map +0 -1
- package/dist/i3s-converter/json-templates/metadata.js.map +0 -1
- package/dist/i3s-converter/json-templates/node.js.map +0 -1
- package/dist/i3s-converter/json-templates/scene-server.js.map +0 -1
- package/dist/i3s-converter/json-templates/shared-resources.js.map +0 -1
- package/dist/i3s-converter/json-templates/store.js.map +0 -1
- package/dist/i3s-converter/types.js.map +0 -1
- package/dist/i3s-server/README.md +0 -63
- package/dist/i3s-server/app.js.map +0 -1
- package/dist/i3s-server/bin/www.js.map +0 -1
- package/dist/i3s-server/certs/cert.pem +0 -19
- package/dist/i3s-server/certs/key.pem +0 -27
- package/dist/i3s-server/controllers/index-controller.js.map +0 -1
- package/dist/i3s-server/controllers/slpk-controller.js.map +0 -1
- package/dist/i3s-server/routes/index.js.map +0 -1
- package/dist/i3s-server/routes/slpk-router.js.map +0 -1
- package/dist/i3s-server/utils/create-scene-server.js.map +0 -1
- package/dist/i3s-server/utils/server-utils.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/json-schemas/conversion-dump-json-schema.js.map +0 -1
- package/dist/lib/utils/cli-utils.js.map +0 -1
- package/dist/lib/utils/compress-util.js.map +0 -1
- package/dist/lib/utils/conversion-dump.js.map +0 -1
- package/dist/lib/utils/file-utils.js.map +0 -1
- package/dist/lib/utils/geometry-utils.js.map +0 -1
- package/dist/lib/utils/lod-conversion-utils.js.map +0 -1
- package/dist/lib/utils/queue.js.map +0 -1
- package/dist/lib/utils/statistic-utills.js.map +0 -1
- package/dist/lib/utils/write-queue.js.map +0 -1
- package/dist/pgm-loader.js.map +0 -1
- package/dist/slpk-extractor/slpk-extractor.js.map +0 -1
- package/dist/slpk-extractor-cli.js.map +0 -1
|
@@ -2,204 +2,309 @@ import { join } from 'path';
|
|
|
2
2
|
import transform from 'json-map-transform';
|
|
3
3
|
import { METADATA as metadataTemplate } from "../json-templates/metadata.js";
|
|
4
4
|
import { isFileExists, openJson } from "../../lib/utils/file-utils.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.length = 0;
|
|
20
|
-
}
|
|
21
|
-
useWriteFunction(func) {
|
|
22
|
-
this.writeFile = func;
|
|
23
|
-
}
|
|
24
|
-
getNodePageFileName(nodePageId) {
|
|
25
|
-
let filePath;
|
|
26
|
-
let fileName;
|
|
27
|
-
if (this.converter.options.slpk) {
|
|
28
|
-
filePath = join(this.converter.layers0Path, 'nodepages');
|
|
29
|
-
fileName = `${nodePageId.toString()}.json`;
|
|
30
|
-
} else {
|
|
31
|
-
filePath = join(this.converter.layers0Path, 'nodepages', nodePageId.toString());
|
|
32
|
-
fileName = 'index.json';
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
filePath,
|
|
36
|
-
fileName
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
async loadNodePage(nodePageId) {
|
|
40
|
-
const {
|
|
41
|
-
filePath,
|
|
42
|
-
fileName
|
|
43
|
-
} = this.getNodePageFileName(nodePageId);
|
|
44
|
-
const fullName = join(filePath, fileName);
|
|
45
|
-
if (await isFileExists(fullName)) {
|
|
46
|
-
console.log(`load ${fullName}.`);
|
|
47
|
-
return await openJson(filePath, fileName);
|
|
48
|
-
} else {
|
|
49
|
-
return {
|
|
50
|
-
nodes: []
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
getPageIndexByNodeId(id) {
|
|
55
|
-
return Math.floor(id / this.nodesPerPage);
|
|
56
|
-
}
|
|
57
|
-
async getPageByNodeId(id) {
|
|
58
|
-
const pageIndex = this.getPageIndexByNodeId(id);
|
|
59
|
-
if (this.converter.options.instantNodeWriting) {
|
|
60
|
-
return await this.loadNodePage(pageIndex);
|
|
61
|
-
}
|
|
62
|
-
return this.nodePages[pageIndex];
|
|
63
|
-
}
|
|
64
|
-
async getNodeById(id, nodePage) {
|
|
65
|
-
const nodeIndex = id % this.nodesPerPage;
|
|
66
|
-
nodePage = nodePage || (await this.getPageByNodeId(id));
|
|
67
|
-
return nodePage.nodes[nodeIndex];
|
|
68
|
-
}
|
|
69
|
-
async addChildRelation(parentId, childId) {
|
|
70
|
-
var _parentNode$children;
|
|
71
|
-
if (parentId === null || parentId === undefined) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const parentNode = await this.getNodeById(parentId);
|
|
75
|
-
(_parentNode$children = parentNode.children) === null || _parentNode$children === void 0 ? void 0 : _parentNode$children.push(childId);
|
|
76
|
-
await this.saveNode(parentNode);
|
|
77
|
-
}
|
|
78
|
-
async push(node, parentId) {
|
|
79
|
-
node.index = this.nodesCounter++;
|
|
80
|
-
if (!this.converter.options.instantNodeWriting) {
|
|
81
|
-
let currentNodePage = this.nodePages[this.nodePages.length - 1];
|
|
82
|
-
if (currentNodePage.nodes.length === this.nodesPerPage) {
|
|
83
|
-
currentNodePage = {
|
|
84
|
-
nodes: []
|
|
85
|
-
};
|
|
86
|
-
this.nodePages.push(currentNodePage);
|
|
87
|
-
}
|
|
88
|
-
currentNodePage.nodes.push(node);
|
|
89
|
-
}
|
|
90
|
-
await this.addChildRelation(parentId, node.index);
|
|
91
|
-
NodePages.updateResourceInMesh(node);
|
|
92
|
-
await this.saveNode(node);
|
|
93
|
-
return node;
|
|
94
|
-
}
|
|
95
|
-
async saveNode(node) {
|
|
96
|
-
if (!this.converter.options.instantNodeWriting) {
|
|
97
|
-
return;
|
|
98
|
-
} else {
|
|
99
|
-
const nodePageIndex = this.getPageIndexByNodeId(node.index);
|
|
100
|
-
const nodePage = await this.getPageByNodeId(node.index);
|
|
101
|
-
const {
|
|
102
|
-
filePath,
|
|
103
|
-
fileName
|
|
104
|
-
} = this.getNodePageFileName(nodePageIndex);
|
|
105
|
-
const nodeToUpdate = await this.getNodeById(node.index, nodePage);
|
|
106
|
-
if (nodeToUpdate) {
|
|
107
|
-
NodePages.updateAll(nodeToUpdate, node);
|
|
108
|
-
} else {
|
|
109
|
-
nodePage.nodes.push(node);
|
|
110
|
-
}
|
|
111
|
-
const nodePageStr = JSON.stringify(nodePage);
|
|
112
|
-
if (this.converter.options.slpk) {
|
|
113
|
-
await this.converter.writeQueue.enqueue({
|
|
114
|
-
archiveKey: `nodePages/${nodePageIndex.toString()}.json.gz`,
|
|
115
|
-
writePromise: () => this.writeFile(filePath, nodePageStr, fileName, true, this.converter.compressList)
|
|
116
|
-
}, true);
|
|
117
|
-
} else {
|
|
118
|
-
await this.converter.writeQueue.enqueue({
|
|
119
|
-
writePromise: () => this.writeFile(filePath, nodePageStr)
|
|
120
|
-
}, true);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
async saveMetadata() {
|
|
125
|
-
const metadata = transform({
|
|
126
|
-
nodeCount: this.nodesCounter
|
|
127
|
-
}, metadataTemplate());
|
|
128
|
-
const compress = false;
|
|
129
|
-
await this.converter.writeQueue.enqueue({
|
|
130
|
-
archiveKey: 'metadata.json',
|
|
131
|
-
writePromise: () => this.writeFile(this.converter.layers0Path, JSON.stringify(metadata), 'metadata.json', compress)
|
|
5
|
+
/**
|
|
6
|
+
* class NodePages - wrapper of nodePages array
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import {writeFile} from './helpers/write-file';
|
|
10
|
+
*
|
|
11
|
+
* // create an instance of the class
|
|
12
|
+
* const nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE);
|
|
13
|
+
* ...
|
|
14
|
+
* // push root node
|
|
15
|
+
* const parent = await nodePages.push({
|
|
16
|
+
lodThreshold: HARDCODED_MAX_SCREEN_THRESHOLD_SQ,
|
|
17
|
+
obb: coordinates.obb,
|
|
18
|
+
children: []
|
|
132
19
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
await this.converter.writeQueue.enqueue({
|
|
144
|
-
archiveKey: `nodePages/${index.toString()}.json.gz`,
|
|
145
|
-
writePromise: () => this.writeFile(slpkPath, nodePageStr, `${index.toString()}.json`)
|
|
146
|
-
});
|
|
20
|
+
* ...
|
|
21
|
+
* // push node with parent relation
|
|
22
|
+
* const nodeInPage = {
|
|
23
|
+
lodThreshold: HARDCODED_MAX_SCREEN_THRESHOLD_SQ,
|
|
24
|
+
obb: coordinates.obb,
|
|
25
|
+
children: [],
|
|
26
|
+
mesh: {
|
|
27
|
+
geometry: {
|
|
28
|
+
definition: 0
|
|
29
|
+
}
|
|
147
30
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
31
|
+
};
|
|
32
|
+
* const node = await this.nodePages.push(nodeInPage, parent.index);
|
|
33
|
+
* ...
|
|
34
|
+
* // save all the nodePages in the end of pushing all the nodes
|
|
35
|
+
* await this.nodePages.save(layers0path);
|
|
36
|
+
*/
|
|
37
|
+
export default class NodePages {
|
|
38
|
+
/**
|
|
39
|
+
* @constructs
|
|
40
|
+
* Create a nodePages instance.
|
|
41
|
+
* @param writeFileFunc - function to save one nodePage into a file
|
|
42
|
+
* @param nodesPerPage - length limit for one nodePage. An additional nodePage is created when this limit is met
|
|
43
|
+
*/
|
|
44
|
+
constructor(writeFileFunc, nodesPerPage, converter) {
|
|
45
|
+
this.length = 0;
|
|
46
|
+
this.nodesPerPage = nodesPerPage;
|
|
47
|
+
this.nodesCounter = 0;
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
this.nodePages = [{}];
|
|
50
|
+
this.nodePages[0].nodes = [];
|
|
51
|
+
this.writeFile = writeFileFunc;
|
|
52
|
+
this.converter = converter;
|
|
53
|
+
this.length = 0;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Setup function to save node pages
|
|
57
|
+
* @param func - function which should be used to save node pages
|
|
58
|
+
*/
|
|
59
|
+
useWriteFunction(func) {
|
|
60
|
+
this.writeFile = func;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get file path and file name of the node page with the particular id
|
|
64
|
+
* @param nodePageId - node page id
|
|
65
|
+
* @returns file path and file name
|
|
66
|
+
*/
|
|
67
|
+
getNodePageFileName(nodePageId) {
|
|
68
|
+
let filePath;
|
|
69
|
+
let fileName;
|
|
70
|
+
if (this.converter.options.slpk) {
|
|
71
|
+
filePath = join(this.converter.layers0Path, 'nodepages');
|
|
72
|
+
fileName = `${nodePageId.toString()}.json`;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
filePath = join(this.converter.layers0Path, 'nodepages', nodePageId.toString());
|
|
76
|
+
fileName = 'index.json';
|
|
77
|
+
}
|
|
78
|
+
return { filePath, fileName };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Load node page from a file on the disk
|
|
82
|
+
* @param nodePageId - node page id
|
|
83
|
+
* @returns - node page data
|
|
84
|
+
*/
|
|
85
|
+
async loadNodePage(nodePageId) {
|
|
86
|
+
const { filePath, fileName } = this.getNodePageFileName(nodePageId);
|
|
87
|
+
const fullName = join(filePath, fileName);
|
|
88
|
+
if (await isFileExists(fullName)) {
|
|
89
|
+
console.log(`load ${fullName}.`); // eslint-disable-line
|
|
90
|
+
return (await openJson(filePath, fileName));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return { nodes: [] };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get nodepage id by node id
|
|
98
|
+
* @param id node id
|
|
99
|
+
* @returns node page id
|
|
100
|
+
*/
|
|
101
|
+
getPageIndexByNodeId(id) {
|
|
102
|
+
return Math.floor(id / this.nodesPerPage);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get node page data by node id
|
|
106
|
+
* @param id node id
|
|
107
|
+
* @returns node page data
|
|
108
|
+
*/
|
|
109
|
+
async getPageByNodeId(id) {
|
|
110
|
+
const pageIndex = this.getPageIndexByNodeId(id);
|
|
111
|
+
if (this.converter.options.instantNodeWriting) {
|
|
112
|
+
return await this.loadNodePage(pageIndex);
|
|
113
|
+
}
|
|
114
|
+
return this.nodePages[pageIndex];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get the node by its end-to-end index
|
|
118
|
+
* @param id - end-to-end index of the node
|
|
119
|
+
* @return the node object
|
|
120
|
+
*/
|
|
121
|
+
async getNodeById(id, nodePage) {
|
|
122
|
+
const nodeIndex = id % this.nodesPerPage;
|
|
123
|
+
nodePage = nodePage || (await this.getPageByNodeId(id));
|
|
124
|
+
return nodePage.nodes[nodeIndex];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Add a child id into the parent node.children array
|
|
128
|
+
* @param parentId - end-to-end parent node index
|
|
129
|
+
* @param childId - end-to-end child node index
|
|
130
|
+
*/
|
|
131
|
+
async addChildRelation(parentId, childId) {
|
|
132
|
+
if (parentId === null || parentId === undefined) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const parentNode = await this.getNodeById(parentId);
|
|
136
|
+
parentNode.children?.push(childId);
|
|
137
|
+
await this.saveNode(parentNode);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Put new node in nodePages array
|
|
141
|
+
* @param node - node object
|
|
142
|
+
* @param parentId - index of parent node
|
|
143
|
+
* @return
|
|
144
|
+
*/
|
|
145
|
+
async push(node, parentId) {
|
|
146
|
+
node.index = this.nodesCounter++;
|
|
147
|
+
if (!this.converter.options.instantNodeWriting) {
|
|
148
|
+
let currentNodePage = this.nodePages[this.nodePages.length - 1];
|
|
149
|
+
if (currentNodePage.nodes.length === this.nodesPerPage) {
|
|
150
|
+
currentNodePage = { nodes: [] };
|
|
151
|
+
this.nodePages.push(currentNodePage);
|
|
152
|
+
}
|
|
153
|
+
currentNodePage.nodes.push(node);
|
|
154
|
+
}
|
|
155
|
+
await this.addChildRelation(parentId, node.index);
|
|
156
|
+
NodePages.updateResourceInMesh(node);
|
|
157
|
+
await this.saveNode(node);
|
|
158
|
+
return node;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Save node to the file on the disk
|
|
162
|
+
* @param node - node data
|
|
163
|
+
*/
|
|
164
|
+
async saveNode(node) {
|
|
165
|
+
if (!this.converter.options.instantNodeWriting) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
const nodePageIndex = this.getPageIndexByNodeId(node.index);
|
|
170
|
+
const nodePage = await this.getPageByNodeId(node.index);
|
|
171
|
+
const { filePath, fileName } = this.getNodePageFileName(nodePageIndex);
|
|
172
|
+
const nodeToUpdate = await this.getNodeById(node.index, nodePage);
|
|
173
|
+
if (nodeToUpdate) {
|
|
174
|
+
NodePages.updateAll(nodeToUpdate, node);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
nodePage.nodes.push(node);
|
|
178
|
+
}
|
|
179
|
+
const nodePageStr = JSON.stringify(nodePage);
|
|
180
|
+
if (this.converter.options.slpk) {
|
|
181
|
+
await this.converter.writeQueue.enqueue({
|
|
182
|
+
archiveKey: `nodePages/${nodePageIndex.toString()}.json.gz`,
|
|
183
|
+
writePromise: () => this.writeFile(filePath, nodePageStr, fileName, true, this.converter.compressList)
|
|
184
|
+
}, true);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
await this.converter.writeQueue.enqueue({
|
|
188
|
+
writePromise: () => this.writeFile(filePath, nodePageStr)
|
|
189
|
+
}, true);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Save metadata file (for slpk only)
|
|
195
|
+
*/
|
|
196
|
+
async saveMetadata() {
|
|
197
|
+
const metadata = transform({ nodeCount: this.nodesCounter }, metadataTemplate());
|
|
198
|
+
const compress = false;
|
|
153
199
|
await this.converter.writeQueue.enqueue({
|
|
154
|
-
|
|
200
|
+
archiveKey: 'metadata.json',
|
|
201
|
+
writePromise: () => this.writeFile(this.converter.layers0Path, JSON.stringify(metadata), 'metadata.json', compress)
|
|
155
202
|
});
|
|
156
|
-
}
|
|
157
203
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Save all the node pages
|
|
206
|
+
* Run this method when all nodes is pushed in nodePages
|
|
207
|
+
*/
|
|
208
|
+
async save() {
|
|
209
|
+
if (this.converter.options.instantNodeWriting) {
|
|
210
|
+
await this.saveMetadata();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (this.converter.options.slpk) {
|
|
214
|
+
for (const [index, nodePage] of this.nodePages.entries()) {
|
|
215
|
+
const nodePageStr = JSON.stringify(nodePage);
|
|
216
|
+
const slpkPath = join(this.converter.layers0Path, 'nodepages');
|
|
217
|
+
await this.converter.writeQueue.enqueue({
|
|
218
|
+
archiveKey: `nodePages/${index.toString()}.json.gz`,
|
|
219
|
+
writePromise: () => this.writeFile(slpkPath, nodePageStr, `${index.toString()}.json`)
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
await this.saveMetadata();
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
for (const [index, nodePage] of this.nodePages.entries()) {
|
|
226
|
+
const nodePageStr = JSON.stringify(nodePage);
|
|
227
|
+
const nodePagePath = join(this.converter.layers0Path, 'nodepages', index.toString());
|
|
228
|
+
await this.converter.writeQueue.enqueue({
|
|
229
|
+
writePromise: () => this.writeFile(nodePagePath, nodePageStr)
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Update resource index in node.mesh object
|
|
236
|
+
* @param node - node object
|
|
237
|
+
*/
|
|
238
|
+
static updateResourceInMesh(node) {
|
|
239
|
+
if (node.mesh && isFinite(node.index)) {
|
|
240
|
+
node.mesh.geometry.resource = node.index;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Update all fields in the node excluding id
|
|
245
|
+
* @param node - node object
|
|
246
|
+
* @param data - NodeInPage data to replace original data
|
|
247
|
+
*/
|
|
248
|
+
static updateAll(node, data) {
|
|
249
|
+
Object.assign(node, data, { index: node.index });
|
|
250
|
+
NodePages.updateResourceInMesh(node);
|
|
251
|
+
return node;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Update material in node.mesh object by node id
|
|
255
|
+
* @param id - end-to-end index of the node
|
|
256
|
+
* @param materialId - id from scene layer materialDefinitions
|
|
257
|
+
*/
|
|
258
|
+
static updateMaterialByNodeId(node, materialId) {
|
|
259
|
+
if (!node.mesh) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
node.mesh.material = {
|
|
263
|
+
definition: materialId,
|
|
264
|
+
resource: node.index
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Update vertexCount in node.mesh.geometry object by node id
|
|
269
|
+
* @param id - end-to-end index of the node
|
|
270
|
+
* @param vertexCount - vertex count for particular node
|
|
271
|
+
*/
|
|
272
|
+
static updateVertexCountByNodeId(node, vertexCount) {
|
|
273
|
+
if (!node.mesh) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
node.mesh.geometry.vertexCount = vertexCount;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Update resource in node.mesh.attribute object by node id
|
|
280
|
+
* @param node - node object
|
|
281
|
+
*/
|
|
282
|
+
static updateNodeAttributeByNodeId(node) {
|
|
283
|
+
if (!node.mesh || !node.index) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
node.mesh.attribute.resource = node.index;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Update featureCount in node.mesh.geometry object by node id
|
|
290
|
+
* @param node - node object
|
|
291
|
+
* @param featureCount - features count of the node
|
|
292
|
+
*/
|
|
293
|
+
static updateFeatureCountByNodeId(node, featureCount) {
|
|
294
|
+
if (!node.mesh) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
node.mesh.geometry.featureCount = featureCount;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Update texelCountHint in node.mesh.material object by node id
|
|
301
|
+
* @param node - node object
|
|
302
|
+
* @param texelCountHint - texelCountHint of particular node
|
|
303
|
+
*/
|
|
304
|
+
static updateTexelCountHintByNodeId(node, texelCountHint) {
|
|
305
|
+
if (!node.mesh || !node.mesh.material) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
node.mesh.material.texelCountHint = texelCountHint;
|
|
162
309
|
}
|
|
163
|
-
}
|
|
164
|
-
static updateAll(node, data) {
|
|
165
|
-
Object.assign(node, data, {
|
|
166
|
-
index: node.index
|
|
167
|
-
});
|
|
168
|
-
NodePages.updateResourceInMesh(node);
|
|
169
|
-
return node;
|
|
170
|
-
}
|
|
171
|
-
static updateMaterialByNodeId(node, materialId) {
|
|
172
|
-
if (!node.mesh) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
node.mesh.material = {
|
|
176
|
-
definition: materialId,
|
|
177
|
-
resource: node.index
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
static updateVertexCountByNodeId(node, vertexCount) {
|
|
181
|
-
if (!node.mesh) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
node.mesh.geometry.vertexCount = vertexCount;
|
|
185
|
-
}
|
|
186
|
-
static updateNodeAttributeByNodeId(node) {
|
|
187
|
-
if (!node.mesh || !node.index) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
node.mesh.attribute.resource = node.index;
|
|
191
|
-
}
|
|
192
|
-
static updateFeatureCountByNodeId(node, featureCount) {
|
|
193
|
-
if (!node.mesh) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
node.mesh.geometry.featureCount = featureCount;
|
|
197
|
-
}
|
|
198
|
-
static updateTexelCountHintByNodeId(node, texelCountHint) {
|
|
199
|
-
if (!node.mesh || !node.mesh.material) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
node.mesh.material.texelCountHint = texelCountHint;
|
|
203
|
-
}
|
|
204
310
|
}
|
|
205
|
-
//# sourceMappingURL=node-pages.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tiles3DTileContent } from '@loaders.gl/3d-tiles';
|
|
2
|
-
import { GLTFPrimitiveModeString, PreprocessData } from
|
|
2
|
+
import { GLTFPrimitiveModeString, PreprocessData } from "../types.js";
|
|
3
3
|
/**
|
|
4
4
|
* glTF primitive modes
|
|
5
5
|
* @see https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preprocess-3d-tiles.d.ts","sourceRoot":"","sources":["../../../src/i3s-converter/helpers/preprocess-3d-tiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAC,uBAAuB,EAAE,cAAc,EAAC,
|
|
1
|
+
{"version":3,"file":"preprocess-3d-tiles.d.ts","sourceRoot":"","sources":["../../../src/i3s-converter/helpers/preprocess-3d-tiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAC,uBAAuB,EAAE,cAAc,EAAC,oBAAiB;AAWjE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,2BAQhC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,gBAChB,kBAAkB,GAAG,IAAI,KACrC,QAAQ,cAAc,CAuBxB,CAAC;AAwDF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,YAAa,cAAc,WAAW,cAAc,KAAG,IAUtF,CAAC"}
|
|
@@ -2,72 +2,104 @@ import { GLTFPrimitiveModeString } from "../types.js";
|
|
|
2
2
|
import { EXT_STRUCTURAL_METADATA, GLTFLoader } from '@loaders.gl/gltf';
|
|
3
3
|
import { parse } from '@loaders.gl/core';
|
|
4
4
|
import { EXT_FEATURE_METADATA } from '@loaders.gl/gltf';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
/**
|
|
6
|
+
* glTF primitive modes
|
|
7
|
+
* @see https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode
|
|
8
|
+
*/
|
|
9
|
+
export const GLTF_PRIMITIVE_MODES = [
|
|
10
|
+
GLTFPrimitiveModeString.POINTS, // 0
|
|
11
|
+
GLTFPrimitiveModeString.LINES, // 1
|
|
12
|
+
GLTFPrimitiveModeString.LINE_LOOP, // 2
|
|
13
|
+
GLTFPrimitiveModeString.LINE_STRIP, // 3
|
|
14
|
+
GLTFPrimitiveModeString.TRIANGLES, // 4
|
|
15
|
+
GLTFPrimitiveModeString.TRIANGLE_STRIP, // 5
|
|
16
|
+
GLTFPrimitiveModeString.TRIANGLE_FAN // 6
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Analyze tile content. This function is used during preprocess stage of
|
|
20
|
+
* conversion
|
|
21
|
+
* @param tileContent - 3DTiles tile content ArrayBuffer
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
export const analyzeTileContent = async (tileContent) => {
|
|
25
|
+
const defaultResult = {
|
|
26
|
+
meshTopologyTypes: new Set(),
|
|
27
|
+
metadataClasses: new Set()
|
|
28
|
+
};
|
|
29
|
+
if (!tileContent?.gltfArrayBuffer) {
|
|
30
|
+
return defaultResult;
|
|
20
31
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
const gltfData = await parse(tileContent.gltfArrayBuffer, GLTFLoader, {
|
|
33
|
+
gltf: { normalize: false, loadBuffers: false, loadImages: false, decompressMeshes: false }
|
|
34
|
+
});
|
|
35
|
+
const gltf = gltfData.json;
|
|
36
|
+
if (!gltf) {
|
|
37
|
+
return defaultResult;
|
|
38
|
+
}
|
|
39
|
+
const meshTopologyTypes = getMeshTypesFromGLTF(gltf);
|
|
40
|
+
const metadataClasses = getMetadataClassesFromGLTF(gltf);
|
|
41
|
+
return {
|
|
42
|
+
meshTopologyTypes,
|
|
43
|
+
metadataClasses
|
|
44
|
+
};
|
|
32
45
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Get mesh topology types that the glb content has
|
|
48
|
+
* @param gltfJson - JSON part of GLB content
|
|
49
|
+
* @returns array of mesh types found
|
|
50
|
+
*/
|
|
51
|
+
const getMeshTypesFromGLTF = (gltfJson) => {
|
|
52
|
+
const result = new Set();
|
|
53
|
+
for (const mesh of gltfJson.meshes || []) {
|
|
54
|
+
for (const primitive of mesh.primitives) {
|
|
55
|
+
let { mode } = primitive;
|
|
56
|
+
if (typeof mode !== 'number') {
|
|
57
|
+
mode = 4; // Default is 4 - TRIANGLES
|
|
58
|
+
}
|
|
59
|
+
result.add(GLTF_PRIMITIVE_MODES[mode]);
|
|
60
|
+
}
|
|
44
61
|
}
|
|
45
|
-
|
|
46
|
-
return result;
|
|
62
|
+
return result;
|
|
47
63
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Get feature metadata classes from glTF
|
|
66
|
+
* The tileset might contain multiple metadata classes provided by EXT_feature_metadata and EXT_structural_metadata extensions.
|
|
67
|
+
* Every class is a set of properties. But I3S can consume only one set of properties.
|
|
68
|
+
* On the pre-process we collect all classes from the tileset in order to show the prompt to select one class for conversion to I3S.
|
|
69
|
+
* @param gltfJson - JSON part of GLB content
|
|
70
|
+
* @returns array of classes
|
|
71
|
+
*/
|
|
72
|
+
const getMetadataClassesFromGLTF = (gltfJson) => {
|
|
73
|
+
const result = new Set();
|
|
74
|
+
// Try to parse from EXT_feature_metadata
|
|
75
|
+
const extFeatureMetadataClasses = gltfJson.extensions?.[EXT_FEATURE_METADATA]?.schema?.classes;
|
|
76
|
+
if (extFeatureMetadataClasses) {
|
|
77
|
+
for (const classKey of Object.keys(extFeatureMetadataClasses)) {
|
|
78
|
+
result.add(classKey);
|
|
79
|
+
}
|
|
55
80
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
81
|
+
// Try to parse from EXT_structural_metadata
|
|
82
|
+
const extStructuralMetadataClasses = gltfJson.extensions?.[EXT_STRUCTURAL_METADATA]?.schema?.classes;
|
|
83
|
+
if (extStructuralMetadataClasses) {
|
|
84
|
+
for (const classKey of Object.keys(extStructuralMetadataClasses)) {
|
|
85
|
+
result.add(classKey);
|
|
86
|
+
}
|
|
61
87
|
}
|
|
62
|
-
|
|
63
|
-
return result;
|
|
88
|
+
return result;
|
|
64
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* Merge object2 into object1
|
|
92
|
+
* @param object1
|
|
93
|
+
* @param object2
|
|
94
|
+
* @returns nothing
|
|
95
|
+
*/
|
|
65
96
|
export const mergePreprocessData = (object1, object2) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
97
|
+
// Merge topology mesh types info
|
|
98
|
+
for (const type of object2.meshTopologyTypes) {
|
|
99
|
+
object1.meshTopologyTypes.add(type);
|
|
100
|
+
}
|
|
101
|
+
// Merge feature metadata classes
|
|
102
|
+
for (const metadataClass of object2.metadataClasses) {
|
|
103
|
+
object1.metadataClasses.add(metadataClass);
|
|
104
|
+
}
|
|
72
105
|
};
|
|
73
|
-
//# sourceMappingURL=preprocess-3d-tiles.js.map
|