@loaders.gl/tile-converter 4.0.0-alpha.19 → 4.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/converter-cli.js +10 -2
- package/dist/converter.min.js +172 -103
- package/dist/dist.min.js +151 -86
- package/dist/es5/constants.js +5 -1
- package/dist/es5/constants.js.map +1 -1
- package/dist/es5/converter-cli.js +7 -2
- package/dist/es5/converter-cli.js.map +1 -1
- package/dist/es5/deps-installer/deps-installer.js +1 -1
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +21 -8
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/geometry-attributes.js +7 -6
- package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/geometry-converter.js +67 -59
- package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js +38 -9
- package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
- package/dist/es5/i3s-converter/i3s-converter.js +55 -13
- package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/es5/i3s-converter/types.js +11 -11
- package/dist/es5/i3s-converter/types.js.map +1 -1
- package/dist/es5/i3s-server/controllers/slpk-controller.js +1 -1
- package/dist/es5/i3s-server/controllers/slpk-controller.js.map +1 -1
- package/dist/es5/index.js +3 -3
- package/dist/es5/index.js.map +1 -1
- package/dist/es5/pgm-loader.js +1 -1
- package/dist/es5/slpk-extractor/helpers/{file-handle-provider.js → file-handle-file.js} +9 -9
- package/dist/es5/slpk-extractor/helpers/file-handle-file.js.map +1 -0
- package/dist/es5/slpk-extractor/slpk-extractor.js +5 -5
- package/dist/es5/slpk-extractor/slpk-extractor.js.map +1 -1
- package/dist/esm/constants.js +2 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/converter-cli.js +7 -2
- package/dist/esm/converter-cli.js.map +1 -1
- package/dist/esm/deps-installer/deps-installer.js +1 -1
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +18 -6
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/geometry-attributes.js +7 -6
- package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/geometry-converter.js +28 -20
- package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js +28 -9
- package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
- package/dist/esm/i3s-converter/i3s-converter.js +39 -9
- package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/esm/i3s-converter/types.js +9 -9
- package/dist/esm/i3s-converter/types.js.map +1 -1
- package/dist/esm/i3s-server/bin/i3s-server.min.js +71 -71
- package/dist/esm/i3s-server/controllers/slpk-controller.js +2 -2
- package/dist/esm/i3s-server/controllers/slpk-controller.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pgm-loader.js +1 -1
- package/dist/esm/slpk-extractor/helpers/{file-handle-provider.js → file-handle-file.js} +3 -3
- package/dist/esm/slpk-extractor/helpers/file-handle-file.js.map +1 -0
- package/dist/esm/slpk-extractor/slpk-extractor.js +3 -3
- package/dist/esm/slpk-extractor/slpk-extractor.js.map +1 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +11 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.js +33 -13
- package/dist/i3s-converter/helpers/geometry-attributes.js +7 -6
- package/dist/i3s-converter/helpers/geometry-converter.d.ts +6 -3
- package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/geometry-converter.js +42 -35
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts +2 -2
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.js +39 -14
- package/dist/i3s-converter/i3s-converter.d.ts +2 -0
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.js +40 -10
- package/dist/i3s-converter/types.d.ts +4 -2
- package/dist/i3s-converter/types.d.ts.map +1 -1
- package/dist/i3s-converter/types.js +11 -11
- package/dist/i3s-server/controllers/slpk-controller.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/slpk-extractor/helpers/{file-handle-provider.d.ts → file-handle-file.d.ts} +5 -5
- package/dist/slpk-extractor/helpers/file-handle-file.d.ts.map +1 -0
- package/dist/slpk-extractor/helpers/{file-handle-provider.js → file-handle-file.js} +5 -5
- package/dist/slpk-extractor/slpk-extractor.js +5 -5
- package/dist/slpk-extractor.min.js +32 -32
- package/package.json +15 -14
- package/src/constants.ts +3 -0
- package/src/converter-cli.ts +9 -2
- package/src/i3s-converter/helpers/batch-ids-extensions.ts +39 -12
- package/src/i3s-converter/helpers/geometry-attributes.ts +15 -8
- package/src/i3s-converter/helpers/geometry-converter.ts +66 -35
- package/src/i3s-converter/helpers/preprocess-3d-tiles.ts +48 -18
- package/src/i3s-converter/i3s-converter.ts +54 -12
- package/src/i3s-converter/types.ts +4 -2
- package/src/i3s-server/controllers/slpk-controller.ts +2 -2
- package/src/index.ts +1 -1
- package/src/slpk-extractor/helpers/{file-handle-provider.ts → file-handle-file.ts} +5 -5
- package/src/slpk-extractor/slpk-extractor.ts +3 -3
- package/dist/es5/slpk-extractor/helpers/file-handle-provider.js.map +0 -1
- package/dist/esm/slpk-extractor/helpers/file-handle-provider.js.map +0 -1
- package/dist/slpk-extractor/helpers/file-handle-provider.d.ts.map +0 -1
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.20",
|
|
4
4
|
"description": "Converter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -45,18 +45,18 @@
|
|
|
45
45
|
"build-i3s-server-bundle": "esbuild src/i3s-server/bin/www.ts --outfile=dist/esm/i3s-server/bin/i3s-server.min.js --platform=node --target=esnext,node14 --external:join-images --minify --bundle --define:__VERSION__=\\\"$npm_package_version\\\""
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@loaders.gl/3d-tiles": "4.0.0-alpha.
|
|
49
|
-
"@loaders.gl/crypto": "4.0.0-alpha.
|
|
50
|
-
"@loaders.gl/draco": "4.0.0-alpha.
|
|
51
|
-
"@loaders.gl/gltf": "4.0.0-alpha.
|
|
52
|
-
"@loaders.gl/i3s": "4.0.0-alpha.
|
|
53
|
-
"@loaders.gl/images": "4.0.0-alpha.
|
|
54
|
-
"@loaders.gl/loader-utils": "4.0.0-alpha.
|
|
55
|
-
"@loaders.gl/polyfills": "4.0.0-alpha.
|
|
56
|
-
"@loaders.gl/textures": "4.0.0-alpha.
|
|
57
|
-
"@loaders.gl/tiles": "4.0.0-alpha.
|
|
58
|
-
"@loaders.gl/worker-utils": "4.0.0-alpha.
|
|
59
|
-
"@loaders.gl/zip": "4.0.0-alpha.
|
|
48
|
+
"@loaders.gl/3d-tiles": "4.0.0-alpha.20",
|
|
49
|
+
"@loaders.gl/crypto": "4.0.0-alpha.20",
|
|
50
|
+
"@loaders.gl/draco": "4.0.0-alpha.20",
|
|
51
|
+
"@loaders.gl/gltf": "4.0.0-alpha.20",
|
|
52
|
+
"@loaders.gl/i3s": "4.0.0-alpha.20",
|
|
53
|
+
"@loaders.gl/images": "4.0.0-alpha.20",
|
|
54
|
+
"@loaders.gl/loader-utils": "4.0.0-alpha.20",
|
|
55
|
+
"@loaders.gl/polyfills": "4.0.0-alpha.20",
|
|
56
|
+
"@loaders.gl/textures": "4.0.0-alpha.20",
|
|
57
|
+
"@loaders.gl/tiles": "4.0.0-alpha.20",
|
|
58
|
+
"@loaders.gl/worker-utils": "4.0.0-alpha.20",
|
|
59
|
+
"@loaders.gl/zip": "4.0.0-alpha.20",
|
|
60
60
|
"@math.gl/core": "^3.5.1",
|
|
61
61
|
"@math.gl/culling": "^3.5.1",
|
|
62
62
|
"@math.gl/geoid": "^3.5.1",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"crypt": "^0.0.2",
|
|
67
67
|
"debug": "~4.3.4",
|
|
68
68
|
"express": "~4.18.2",
|
|
69
|
+
"inquirer": "^8.0.0",
|
|
69
70
|
"json-map-transform": "^1.2.6",
|
|
70
71
|
"jszip": "^3.5.0",
|
|
71
72
|
"md5": "^2.3.0",
|
|
@@ -79,7 +80,7 @@
|
|
|
79
80
|
"join-images": "^1.1.3",
|
|
80
81
|
"sharp": "^0.31.3"
|
|
81
82
|
},
|
|
82
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "ac122e83102657c38207d59c631a5ce4e7aa46bd",
|
|
83
84
|
"devDependencies": {
|
|
84
85
|
"@types/express": "^4.17.17",
|
|
85
86
|
"@types/node": "^20.4.2"
|
package/src/constants.ts
CHANGED
package/src/converter-cli.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import '@loaders.gl/polyfills';
|
|
3
3
|
import {join} from 'path';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
4
5
|
import {I3SConverter, Tiles3DConverter} from '@loaders.gl/tile-converter';
|
|
5
6
|
import {DepsInstaller} from './deps-installer/deps-installer';
|
|
6
7
|
import {
|
|
@@ -49,6 +50,8 @@ type TileConversionOptions = {
|
|
|
49
50
|
maxDepth?: number;
|
|
50
51
|
/** 3DTiles->I3S only. Whether the converter generates *.slpk (Scene Layer Package) I3S output file */
|
|
51
52
|
slpk: boolean;
|
|
53
|
+
/** Feature metadata class from EXT_FEATURE_METADATA or EXT_STRUCTURAL_METADATA extensions */
|
|
54
|
+
metadataClass?: string;
|
|
52
55
|
};
|
|
53
56
|
|
|
54
57
|
/* During validation we check that particular options are defined so they can't be undefined */
|
|
@@ -132,8 +135,9 @@ function printHelp(): void {
|
|
|
132
135
|
console.log(
|
|
133
136
|
'--generate-textures [Enable KTX2 textures generation if only one of (JPG, PNG) texture is provided or generate JPG texture if only KTX2 is provided]'
|
|
134
137
|
);
|
|
138
|
+
console.log('--generate-bounding-volumes [Generate obb and mbs bounding volumes from geometry]');
|
|
135
139
|
console.log(
|
|
136
|
-
'--
|
|
140
|
+
'--metadata-class [One of the list of feature metadata classes, detected by converter on "analyze" stage, default: not set]'
|
|
137
141
|
);
|
|
138
142
|
console.log('--validate [Enable validation]');
|
|
139
143
|
process.exit(0); // eslint-disable-line
|
|
@@ -175,7 +179,8 @@ async function convert(options: ValidatedTileConversionOptions) {
|
|
|
175
179
|
generateTextures: options.generateTextures,
|
|
176
180
|
generateBoundingVolumes: options.generateBoundingVolumes,
|
|
177
181
|
validate: options.validate,
|
|
178
|
-
instantNodeWriting: options.instantNodeWriting
|
|
182
|
+
instantNodeWriting: options.instantNodeWriting,
|
|
183
|
+
inquirer
|
|
179
184
|
});
|
|
180
185
|
break;
|
|
181
186
|
default:
|
|
@@ -292,6 +297,8 @@ function parseOptions(args: string[]): TileConversionOptions {
|
|
|
292
297
|
case '--generate-bounding-volumes':
|
|
293
298
|
opts.generateBoundingVolumes = getBooleanValue(index, args);
|
|
294
299
|
break;
|
|
300
|
+
case '--metadata-class':
|
|
301
|
+
opts.metadataClass = getStringValue(index, args);
|
|
295
302
|
case '--help':
|
|
296
303
|
printHelp();
|
|
297
304
|
break;
|
|
@@ -2,26 +2,54 @@ import {GLTFAccessorPostprocessed, GLTFMeshPrimitivePostprocessed} from '@loader
|
|
|
2
2
|
import type {NumericArray} from '@loaders.gl/loader-utils';
|
|
3
3
|
import type {
|
|
4
4
|
GLTF_EXT_feature_metadata_FeatureIdTexture,
|
|
5
|
+
GLTF_EXT_feature_metadata_GLTF,
|
|
5
6
|
GLTF_EXT_feature_metadata_Primitive
|
|
6
7
|
} from '@loaders.gl/gltf';
|
|
7
8
|
import {TypedArray} from '@math.gl/core';
|
|
8
9
|
import {TextureImageProperties} from '../types';
|
|
10
|
+
import {EXT_FEATURE_METADATA, EXT_MESH_FEATURES} from '../../constants';
|
|
11
|
+
import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Get featureTexture by metadataClass
|
|
15
|
+
* @param tileContent - 3d tile content
|
|
16
|
+
* @param metadataClass - user selected feature metadata class name
|
|
17
|
+
* @returns featureTexture key
|
|
18
|
+
*/
|
|
19
|
+
export function getTextureByMetadataClass(
|
|
20
|
+
tileContent: Tiles3DTileContent,
|
|
21
|
+
metadataClass?: string
|
|
22
|
+
): string | null {
|
|
23
|
+
const extFeatureMetadata = tileContent.gltf?.extensions?.[
|
|
24
|
+
EXT_FEATURE_METADATA
|
|
25
|
+
] as GLTF_EXT_feature_metadata_GLTF;
|
|
26
|
+
if (!extFeatureMetadata?.featureTextures) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
for (const textureKey in extFeatureMetadata.featureTextures) {
|
|
30
|
+
const texture = extFeatureMetadata.featureTextures[textureKey];
|
|
31
|
+
if (texture.class === metadataClass) {
|
|
32
|
+
return textureKey;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
12
37
|
|
|
13
38
|
/**
|
|
14
39
|
* Getting batchIds from 3DTilesNext extensions.
|
|
15
40
|
* @param attributes - gltf accessors
|
|
16
41
|
* @param primitive - gltf primitive data
|
|
17
42
|
* @param images - gltf texture images
|
|
43
|
+
* @param featureTexture - feature texture key
|
|
44
|
+
* @return array of batch IDs
|
|
18
45
|
*/
|
|
19
46
|
export function handleBatchIdsExtensions(
|
|
20
47
|
attributes: {
|
|
21
48
|
[key: string]: GLTFAccessorPostprocessed;
|
|
22
49
|
},
|
|
23
50
|
primitive: GLTFMeshPrimitivePostprocessed,
|
|
24
|
-
images: (TextureImageProperties | null)[]
|
|
51
|
+
images: (TextureImageProperties | null)[],
|
|
52
|
+
featureTexture: string | null
|
|
25
53
|
): NumericArray {
|
|
26
54
|
const extensions = primitive?.extensions;
|
|
27
55
|
|
|
@@ -35,7 +63,8 @@ export function handleBatchIdsExtensions(
|
|
|
35
63
|
return handleExtFeatureMetadataExtension(
|
|
36
64
|
attributes,
|
|
37
65
|
extensionData as GLTF_EXT_feature_metadata_Primitive,
|
|
38
|
-
images
|
|
66
|
+
images,
|
|
67
|
+
featureTexture
|
|
39
68
|
);
|
|
40
69
|
case EXT_MESH_FEATURES:
|
|
41
70
|
console.warn('EXT_mesh_features extension is not supported yet');
|
|
@@ -51,16 +80,18 @@ export function handleBatchIdsExtensions(
|
|
|
51
80
|
/**
|
|
52
81
|
* Get batchIds from EXT_feature_metadata extension.
|
|
53
82
|
* Docs - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata
|
|
54
|
-
* @param attributes
|
|
55
|
-
* @param extFeatureMetadata
|
|
56
|
-
* @param textures
|
|
83
|
+
* @param attributes - glTF attributes
|
|
84
|
+
* @param extFeatureMetadata - primitive-level EXT_FEATURE_METADATA extension data
|
|
85
|
+
* @param textures - texture images
|
|
86
|
+
* @param featureTexture - feature texture key
|
|
57
87
|
*/
|
|
58
88
|
function handleExtFeatureMetadataExtension(
|
|
59
89
|
attributes: {
|
|
60
90
|
[key: string]: GLTFAccessorPostprocessed;
|
|
61
91
|
},
|
|
62
92
|
extFeatureMetadata: GLTF_EXT_feature_metadata_Primitive,
|
|
63
|
-
images: (TextureImageProperties | null)[]
|
|
93
|
+
images: (TextureImageProperties | null)[],
|
|
94
|
+
featureTexture: string | null
|
|
64
95
|
): NumericArray {
|
|
65
96
|
// Take only first extension object to get batchIds attribute name.
|
|
66
97
|
const featureIdAttribute = extFeatureMetadata?.featureIdAttributes?.[0];
|
|
@@ -93,10 +124,6 @@ function handleExtFeatureMetadataExtension(
|
|
|
93
124
|
return generateBatchIdsFromTexture(featureIdTexture, textureCoordinates, images);
|
|
94
125
|
}
|
|
95
126
|
|
|
96
|
-
// Take only first extension texture to get batchIds from the root EXT_feature_metadata object.
|
|
97
|
-
const featureTexture =
|
|
98
|
-
extFeatureMetadata?.featureTextures && extFeatureMetadata?.featureTextures[0];
|
|
99
|
-
|
|
100
127
|
if (featureTexture) {
|
|
101
128
|
const batchIdsAttribute = attributes[featureTexture];
|
|
102
129
|
return batchIdsAttribute.value;
|
|
@@ -199,19 +199,26 @@ function unifyObjectsByFeatureId(
|
|
|
199
199
|
|
|
200
200
|
for (let index = 0; index < sortedData.length; index++) {
|
|
201
201
|
const currentObject = sortedData[index];
|
|
202
|
-
const
|
|
202
|
+
const existingObject = uniqueObjects.find((obj) => obj.featureId === currentObject.featureId);
|
|
203
203
|
|
|
204
|
-
if (
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
if (existingObject) {
|
|
205
|
+
existingObject.positions = concatenateTypedArrays(
|
|
206
|
+
existingObject.positions,
|
|
207
207
|
currentObject.positions
|
|
208
208
|
);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
existingObject.normals = concatenateTypedArrays(
|
|
210
|
+
existingObject.normals,
|
|
211
|
+
currentObject.normals
|
|
212
|
+
);
|
|
213
|
+
existingObject.colors = concatenateTypedArrays(existingObject.colors, currentObject.colors);
|
|
214
|
+
existingObject.texCoords = concatenateTypedArrays(
|
|
215
|
+
existingObject.texCoords,
|
|
213
216
|
currentObject.texCoords
|
|
214
217
|
);
|
|
218
|
+
existingObject.uvRegions = concatenateTypedArrays(
|
|
219
|
+
existingObject.uvRegions,
|
|
220
|
+
currentObject.uvRegions
|
|
221
|
+
);
|
|
215
222
|
} else {
|
|
216
223
|
uniqueObjects.push(currentObject);
|
|
217
224
|
}
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
import {NumberArray, TypedArray} from '@loaders.gl/loader-utils';
|
|
36
36
|
import {Geoid} from '@math.gl/geoid';
|
|
37
37
|
import {prepareDataForAttributesConversion} from './gltf-attributes';
|
|
38
|
-
import {handleBatchIdsExtensions} from './batch-ids-extensions';
|
|
38
|
+
import {getTextureByMetadataClass, handleBatchIdsExtensions} from './batch-ids-extensions';
|
|
39
39
|
import {checkPropertiesLength, flattenPropertyTableByFeatureIds} from './feature-attributes';
|
|
40
40
|
import {GL} from '@loaders.gl/math';
|
|
41
41
|
|
|
@@ -47,6 +47,7 @@ import {GL} from '@loaders.gl/math';
|
|
|
47
47
|
import type {GLTFAttributesData, TextureImageProperties, TypedArrayConstructor} from '../types';
|
|
48
48
|
import {generateSyntheticIndices} from '../../lib/utils/geometry-utils';
|
|
49
49
|
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
|
|
50
|
+
import {EXT_FEATURE_METADATA, EXT_MESH_FEATURES} from '../../constants';
|
|
50
51
|
|
|
51
52
|
// Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
|
|
52
53
|
const DEFAULT_ROUGHNESS_FACTOR = 1;
|
|
@@ -67,9 +68,6 @@ const OBJECT_ID_TYPE = 'Oid32';
|
|
|
67
68
|
*/
|
|
68
69
|
const BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES = ['CUSTOM_ATTRIBUTE_2', '_BATCHID', 'BATCHID'];
|
|
69
70
|
|
|
70
|
-
const EXT_FEATURE_METADATA = 'EXT_feature_metadata';
|
|
71
|
-
const EXT_MESH_FEATURES = 'EXT_mesh_features';
|
|
72
|
-
|
|
73
71
|
let scratchVector = new Vector3();
|
|
74
72
|
|
|
75
73
|
/**
|
|
@@ -88,6 +86,7 @@ let scratchVector = new Vector3();
|
|
|
88
86
|
* @param shouldMergeMaterials - Try to merge similar materials to be able to merge meshes into one node
|
|
89
87
|
* @param geoidHeightModel - model to convert elevation from elipsoidal to geoid
|
|
90
88
|
* @param libraries - dynamicaly loaded 3rd-party libraries
|
|
89
|
+
* @param metadataClass `- user selected feature metadata class name`
|
|
91
90
|
* @returns Array of node resources to create one or more i3s nodes
|
|
92
91
|
*/
|
|
93
92
|
export default async function convertB3dmToI3sGeometry(
|
|
@@ -102,7 +101,8 @@ export default async function convertB3dmToI3sGeometry(
|
|
|
102
101
|
generateBoundingVolumes: boolean,
|
|
103
102
|
shouldMergeMaterials: boolean,
|
|
104
103
|
geoidHeightModel: Geoid,
|
|
105
|
-
libraries: Record<string, string
|
|
104
|
+
libraries: Record<string, string>,
|
|
105
|
+
metadataClass?: string
|
|
106
106
|
): Promise<I3SConvertedResources[] | null> {
|
|
107
107
|
const useCartesianPositions = generateBoundingVolumes;
|
|
108
108
|
const materialAndTextureList: I3SMaterialWithTexture[] = await convertMaterials(
|
|
@@ -115,10 +115,12 @@ export default async function convertB3dmToI3sGeometry(
|
|
|
115
115
|
tileTransform,
|
|
116
116
|
tileBoundingVolume
|
|
117
117
|
);
|
|
118
|
+
const featureTexture = getTextureByMetadataClass(tileContent, metadataClass);
|
|
118
119
|
const convertedAttributesMap: Map<string, ConvertedAttributes> = await convertAttributes(
|
|
119
120
|
dataForAttributesConversion,
|
|
120
121
|
materialAndTextureList,
|
|
121
|
-
useCartesianPositions
|
|
122
|
+
useCartesianPositions,
|
|
123
|
+
featureTexture
|
|
122
124
|
);
|
|
123
125
|
/** Usage of worker here brings more overhead than advantage */
|
|
124
126
|
// const convertedAttributesMap: Map<string, ConvertedAttributes> =
|
|
@@ -312,12 +314,14 @@ async function _makeNodeResources({
|
|
|
312
314
|
* @param materialAndTextureList - array of data about materials and textures of the content
|
|
313
315
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
314
316
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
317
|
+
* @param featureTexture - feature texture key
|
|
315
318
|
* @returns map of converted geometry attributes
|
|
316
319
|
*/
|
|
317
320
|
export async function convertAttributes(
|
|
318
321
|
attributesData: GLTFAttributesData,
|
|
319
322
|
materialAndTextureList: I3SMaterialWithTexture[],
|
|
320
|
-
useCartesianPositions: boolean
|
|
323
|
+
useCartesianPositions: boolean,
|
|
324
|
+
featureTexture: string | null
|
|
321
325
|
): Promise<Map<string, ConvertedAttributes>> {
|
|
322
326
|
const {nodes, images, cartographicOrigin, cartesianModelMatrix} = attributesData;
|
|
323
327
|
const attributesMap = new Map<string, ConvertedAttributes>();
|
|
@@ -345,7 +349,9 @@ export async function convertAttributes(
|
|
|
345
349
|
cartographicOrigin,
|
|
346
350
|
cartesianModelMatrix,
|
|
347
351
|
attributesMap,
|
|
348
|
-
useCartesianPositions
|
|
352
|
+
useCartesianPositions,
|
|
353
|
+
undefined,
|
|
354
|
+
featureTexture
|
|
349
355
|
);
|
|
350
356
|
|
|
351
357
|
for (const attrKey of attributesMap.keys()) {
|
|
@@ -379,6 +385,7 @@ export async function convertAttributes(
|
|
|
379
385
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
380
386
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
381
387
|
* @param matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
|
|
388
|
+
* @param featureTexture - feature texture key
|
|
382
389
|
* @returns {void}
|
|
383
390
|
*/
|
|
384
391
|
function convertNodes(
|
|
@@ -388,7 +395,8 @@ function convertNodes(
|
|
|
388
395
|
cartesianModelMatrix: Matrix4,
|
|
389
396
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
390
397
|
useCartesianPositions: boolean,
|
|
391
|
-
matrix: Matrix4 = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
|
|
398
|
+
matrix: Matrix4 = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
|
399
|
+
featureTexture: string | null
|
|
392
400
|
) {
|
|
393
401
|
if (nodes) {
|
|
394
402
|
for (const node of nodes) {
|
|
@@ -399,7 +407,8 @@ function convertNodes(
|
|
|
399
407
|
cartesianModelMatrix,
|
|
400
408
|
attributesMap,
|
|
401
409
|
useCartesianPositions,
|
|
402
|
-
matrix
|
|
410
|
+
matrix,
|
|
411
|
+
featureTexture
|
|
403
412
|
);
|
|
404
413
|
}
|
|
405
414
|
}
|
|
@@ -441,11 +450,12 @@ function getCompositeTransformationMatrix(node: GLTFNodePostprocessed, matrix: M
|
|
|
441
450
|
* @param images - gltf images array
|
|
442
451
|
* @param cartographicOrigin - cartographic origin of bounding volume
|
|
443
452
|
* @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
|
|
444
|
-
* @param
|
|
453
|
+
* @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
445
454
|
* attributes
|
|
446
455
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
447
456
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
448
|
-
* @param
|
|
457
|
+
* @param matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
|
|
458
|
+
* @param featureTexture - feature texture key
|
|
449
459
|
*/
|
|
450
460
|
function convertNode(
|
|
451
461
|
node: GLTFNodePostprocessed,
|
|
@@ -454,7 +464,8 @@ function convertNode(
|
|
|
454
464
|
cartesianModelMatrix: Matrix4,
|
|
455
465
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
456
466
|
useCartesianPositions,
|
|
457
|
-
matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
|
|
467
|
+
matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
|
468
|
+
featureTexture: string | null
|
|
458
469
|
) {
|
|
459
470
|
const transformationMatrix = getCompositeTransformationMatrix(node, matrix);
|
|
460
471
|
|
|
@@ -468,7 +479,8 @@ function convertNode(
|
|
|
468
479
|
cartesianModelMatrix,
|
|
469
480
|
attributesMap,
|
|
470
481
|
useCartesianPositions,
|
|
471
|
-
transformationMatrix
|
|
482
|
+
transformationMatrix,
|
|
483
|
+
featureTexture
|
|
472
484
|
);
|
|
473
485
|
}
|
|
474
486
|
|
|
@@ -479,7 +491,8 @@ function convertNode(
|
|
|
479
491
|
cartesianModelMatrix,
|
|
480
492
|
attributesMap,
|
|
481
493
|
useCartesianPositions,
|
|
482
|
-
transformationMatrix
|
|
494
|
+
transformationMatrix,
|
|
495
|
+
featureTexture
|
|
483
496
|
);
|
|
484
497
|
}
|
|
485
498
|
|
|
@@ -491,12 +504,12 @@ function convertNode(
|
|
|
491
504
|
* @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
|
|
492
505
|
* @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
493
506
|
* attributes
|
|
494
|
-
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
507
|
+
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
495
508
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
496
509
|
* @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
497
510
|
* attributes
|
|
498
|
-
|
|
499
|
-
* @param
|
|
511
|
+
* @param matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
|
|
512
|
+
* @param featureTexture - feature texture key
|
|
500
513
|
*/
|
|
501
514
|
function convertMesh(
|
|
502
515
|
mesh: GLTFMeshPostprocessed,
|
|
@@ -505,7 +518,8 @@ function convertMesh(
|
|
|
505
518
|
cartesianModelMatrix: Matrix4,
|
|
506
519
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
507
520
|
useCartesianPositions = false,
|
|
508
|
-
matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
|
|
521
|
+
matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
|
522
|
+
featureTexture: string | null
|
|
509
523
|
) {
|
|
510
524
|
for (const primitive of mesh.primitives) {
|
|
511
525
|
let outputAttributes: ConvertedAttributes | null | undefined = null;
|
|
@@ -576,7 +590,7 @@ function convertMesh(
|
|
|
576
590
|
|
|
577
591
|
outputAttributes.featureIndicesGroups = outputAttributes.featureIndicesGroups || [];
|
|
578
592
|
outputAttributes.featureIndicesGroups.push(
|
|
579
|
-
flattenBatchIds(getBatchIds(attributes, primitive, images), indices)
|
|
593
|
+
flattenBatchIds(getBatchIds(attributes, primitive, images, featureTexture), indices)
|
|
580
594
|
);
|
|
581
595
|
}
|
|
582
596
|
}
|
|
@@ -803,15 +817,23 @@ function flattenBatchIds(batchedIds: NumberArray, indices: TypedArray): number[]
|
|
|
803
817
|
* @param attributes - gltf accessors
|
|
804
818
|
* @param primitive - gltf primitive data
|
|
805
819
|
* @param images - gltf texture images
|
|
820
|
+
* @param featureTexture - feature texture key
|
|
821
|
+
* @return batch IDs
|
|
806
822
|
*/
|
|
807
823
|
function getBatchIds(
|
|
808
824
|
attributes: {
|
|
809
825
|
[key: string]: GLTFAccessorPostprocessed;
|
|
810
826
|
},
|
|
811
827
|
primitive: GLTFMeshPrimitivePostprocessed,
|
|
812
|
-
images: (TextureImageProperties | null)[]
|
|
828
|
+
images: (TextureImageProperties | null)[],
|
|
829
|
+
featureTexture: string | null
|
|
813
830
|
): NumberArray {
|
|
814
|
-
const batchIds: NumberArray = handleBatchIdsExtensions(
|
|
831
|
+
const batchIds: NumberArray = handleBatchIdsExtensions(
|
|
832
|
+
attributes,
|
|
833
|
+
primitive,
|
|
834
|
+
images,
|
|
835
|
+
featureTexture
|
|
836
|
+
);
|
|
815
837
|
|
|
816
838
|
if (batchIds.length) {
|
|
817
839
|
return batchIds;
|
|
@@ -1555,9 +1577,13 @@ function generateFeatureIndexAttribute(
|
|
|
1555
1577
|
* Find property table in tile
|
|
1556
1578
|
* For example it can be batchTable for b3dm files or property table in gLTF extension.
|
|
1557
1579
|
* @param tileContent - 3DTiles tile content
|
|
1580
|
+
* @param metadataClass - - user selected feature metadata class name
|
|
1558
1581
|
* @return batch table from b3dm / feature properties from EXT_FEATURE_METADATA
|
|
1559
1582
|
*/
|
|
1560
|
-
export function getPropertyTable(
|
|
1583
|
+
export function getPropertyTable(
|
|
1584
|
+
tileContent: Tiles3DTileContent | null,
|
|
1585
|
+
metadataClass?: string
|
|
1586
|
+
): FeatureTableJson | null {
|
|
1561
1587
|
if (!tileContent) {
|
|
1562
1588
|
return null;
|
|
1563
1589
|
}
|
|
@@ -1576,7 +1602,10 @@ export function getPropertyTable(tileContent: Tiles3DTileContent | null): Featur
|
|
|
1576
1602
|
return null;
|
|
1577
1603
|
}
|
|
1578
1604
|
case EXT_FEATURE_METADATA: {
|
|
1579
|
-
return getPropertyTableFromExtFeatureMetadata(
|
|
1605
|
+
return getPropertyTableFromExtFeatureMetadata(
|
|
1606
|
+
extension as GLTF_EXT_feature_metadata_GLTF,
|
|
1607
|
+
metadataClass
|
|
1608
|
+
);
|
|
1580
1609
|
}
|
|
1581
1610
|
default:
|
|
1582
1611
|
return null;
|
|
@@ -1619,10 +1648,11 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
|
|
|
1619
1648
|
|
|
1620
1649
|
/**
|
|
1621
1650
|
* Handle EXT_feature_metadata to get property table
|
|
1622
|
-
* @param extension
|
|
1651
|
+
* @param extension - global level of EXT_FEATURE_METADATA extension
|
|
1623
1652
|
*/
|
|
1624
1653
|
function getPropertyTableFromExtFeatureMetadata(
|
|
1625
|
-
extension: GLTF_EXT_feature_metadata_GLTF
|
|
1654
|
+
extension: GLTF_EXT_feature_metadata_GLTF,
|
|
1655
|
+
metadataClass?: string
|
|
1626
1656
|
): FeatureTableJson | null {
|
|
1627
1657
|
if (extension?.featureTables) {
|
|
1628
1658
|
/**
|
|
@@ -1646,15 +1676,16 @@ function getPropertyTableFromExtFeatureMetadata(
|
|
|
1646
1676
|
}
|
|
1647
1677
|
|
|
1648
1678
|
if (extension?.featureTextures) {
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1679
|
+
let featureTexture: string | undefined;
|
|
1680
|
+
for (const textureKey in extension.featureTextures) {
|
|
1681
|
+
const texture = extension.featureTextures[textureKey];
|
|
1682
|
+
if (texture.class === metadataClass) {
|
|
1683
|
+
featureTexture = textureKey;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
if (typeof featureTexture === 'string') {
|
|
1688
|
+
const featureTable = extension?.featureTextures[featureTexture];
|
|
1658
1689
|
const propertyTable = {};
|
|
1659
1690
|
|
|
1660
1691
|
for (const propertyName in featureTable.properties) {
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
2
|
-
import {
|
|
3
|
-
import {GLTF, GLTFLoader} from '@loaders.gl/gltf';
|
|
2
|
+
import {GLTFPrimitiveModeString, PreprocessData} from '../types';
|
|
3
|
+
import {GLTF, GLTFLoader, GLTF_EXT_feature_metadata_GLTF} from '@loaders.gl/gltf';
|
|
4
4
|
import {parse} from '@loaders.gl/core';
|
|
5
|
+
import {EXT_FEATURE_METADATA} from '../../constants';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* glTF primitive modes
|
|
8
9
|
* @see https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode
|
|
9
10
|
*/
|
|
10
11
|
export const GLTF_PRIMITIVE_MODES = [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
GLTFPrimitiveModeString.POINTS, // 0
|
|
13
|
+
GLTFPrimitiveModeString.LINES, // 1
|
|
14
|
+
GLTFPrimitiveModeString.LINE_LOOP, // 2
|
|
15
|
+
GLTFPrimitiveModeString.LINE_STRIP, // 3
|
|
16
|
+
GLTFPrimitiveModeString.TRIANGLES, // 4
|
|
17
|
+
GLTFPrimitiveModeString.TRIANGLE_STRIP, // 5
|
|
18
|
+
GLTFPrimitiveModeString.TRIANGLE_FAN // 6
|
|
18
19
|
];
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -26,11 +27,12 @@ export const GLTF_PRIMITIVE_MODES = [
|
|
|
26
27
|
export const analyzeTileContent = async (
|
|
27
28
|
tileContent: Tiles3DTileContent | null
|
|
28
29
|
): Promise<PreprocessData> => {
|
|
29
|
-
const
|
|
30
|
-
meshTopologyTypes: new Set()
|
|
30
|
+
const defaultResult = {
|
|
31
|
+
meshTopologyTypes: new Set<GLTFPrimitiveModeString>(),
|
|
32
|
+
metadataClasses: new Set<string>()
|
|
31
33
|
};
|
|
32
34
|
if (!tileContent?.gltfArrayBuffer) {
|
|
33
|
-
return
|
|
35
|
+
return defaultResult;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
const gltfData = await parse(tileContent.gltfArrayBuffer, GLTFLoader, {
|
|
@@ -39,11 +41,14 @@ export const analyzeTileContent = async (
|
|
|
39
41
|
const gltf = gltfData.json;
|
|
40
42
|
|
|
41
43
|
if (!gltf) {
|
|
42
|
-
return
|
|
44
|
+
return defaultResult;
|
|
43
45
|
}
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
return
|
|
46
|
+
const meshTopologyTypes = getMeshTypesFromGltf(gltf);
|
|
47
|
+
const metadataClasses = getMetadataClassesFromGltf(gltf);
|
|
48
|
+
return {
|
|
49
|
+
meshTopologyTypes,
|
|
50
|
+
metadataClasses
|
|
51
|
+
};
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
/**
|
|
@@ -51,8 +56,8 @@ export const analyzeTileContent = async (
|
|
|
51
56
|
* @param gltfJson - JSON part of GLB content
|
|
52
57
|
* @returns array of mesh types found
|
|
53
58
|
*/
|
|
54
|
-
const getMeshTypesFromGltf = (gltfJson: GLTF): Set<
|
|
55
|
-
const result: Set<
|
|
59
|
+
const getMeshTypesFromGltf = (gltfJson: GLTF): Set<GLTFPrimitiveModeString> => {
|
|
60
|
+
const result: Set<GLTFPrimitiveModeString> = new Set();
|
|
56
61
|
for (const mesh of gltfJson.meshes || []) {
|
|
57
62
|
for (const primitive of mesh.primitives) {
|
|
58
63
|
let {mode} = primitive;
|
|
@@ -65,6 +70,26 @@ const getMeshTypesFromGltf = (gltfJson: GLTF): Set<GltfPrimitiveModeString> => {
|
|
|
65
70
|
return result;
|
|
66
71
|
};
|
|
67
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Get feature metadata classes from glTF
|
|
75
|
+
* @param gltfJson - JSON part of GLB content
|
|
76
|
+
* @returns array of classes
|
|
77
|
+
*/
|
|
78
|
+
const getMetadataClassesFromGltf = (gltfJson: GLTF): Set<string> => {
|
|
79
|
+
const result: Set<string> = new Set();
|
|
80
|
+
|
|
81
|
+
const classes = (gltfJson.extensions?.[EXT_FEATURE_METADATA] as GLTF_EXT_feature_metadata_GLTF)
|
|
82
|
+
?.schema?.classes;
|
|
83
|
+
|
|
84
|
+
if (classes) {
|
|
85
|
+
for (const classKey of Object.keys(classes)) {
|
|
86
|
+
result.add(classKey);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return result;
|
|
91
|
+
};
|
|
92
|
+
|
|
68
93
|
/**
|
|
69
94
|
* Merge object2 into object1
|
|
70
95
|
* @param object1
|
|
@@ -76,4 +101,9 @@ export const mergePreprocessData = (object1: PreprocessData, object2: Preprocess
|
|
|
76
101
|
for (const type of object2.meshTopologyTypes) {
|
|
77
102
|
object1.meshTopologyTypes.add(type);
|
|
78
103
|
}
|
|
104
|
+
|
|
105
|
+
// Merge feature metadata classes
|
|
106
|
+
for (const metadataClass of object2.metadataClasses) {
|
|
107
|
+
object1.metadataClasses.add(metadataClass);
|
|
108
|
+
}
|
|
79
109
|
};
|