@loaders.gl/tile-converter 4.0.0-alpha.24 → 4.0.0-alpha.25
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/helpers/b3dm-converter.d.ts +4 -4
- package/dist/converter.min.js +106 -106
- package/dist/dist.min.js +507 -489
- package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +18 -18
- package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
- package/dist/es5/deps-installer/deps-installer.js +1 -1
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +16 -14
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/geometry-converter.js +4 -76
- package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js +15 -8
- package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
- package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/es5/i3s-converter/types.js.map +1 -1
- package/dist/es5/pgm-loader.js +1 -1
- package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +8 -8
- package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
- package/dist/esm/deps-installer/deps-installer.js +1 -1
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +5 -15
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/geometry-converter.js +3 -75
- package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js +15 -9
- package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -1
- package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/esm/i3s-converter/types.js.map +1 -1
- package/dist/esm/i3s-server/bin/i3s-server.min.js +75 -75
- package/dist/esm/pgm-loader.js +1 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +4 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/geometry-converter.d.ts +1 -1
- package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/types.d.ts +6 -1
- package/dist/i3s-converter/types.d.ts.map +1 -1
- package/dist/slpk-extractor.min.js +42 -42
- package/package.json +14 -14
- package/src/3d-tiles-converter/helpers/b3dm-converter.ts +8 -8
- package/src/i3s-converter/helpers/batch-ids-extensions.ts +14 -35
- package/src/i3s-converter/helpers/geometry-converter.ts +23 -168
- package/src/i3s-converter/helpers/preprocess-3d-tiles.ts +30 -9
- package/src/i3s-converter/i3s-converter.ts +0 -2
- package/src/i3s-converter/types.ts +6 -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.25",
|
|
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.25",
|
|
49
|
+
"@loaders.gl/crypto": "4.0.0-alpha.25",
|
|
50
|
+
"@loaders.gl/draco": "4.0.0-alpha.25",
|
|
51
|
+
"@loaders.gl/gltf": "4.0.0-alpha.25",
|
|
52
|
+
"@loaders.gl/i3s": "4.0.0-alpha.25",
|
|
53
|
+
"@loaders.gl/images": "4.0.0-alpha.25",
|
|
54
|
+
"@loaders.gl/loader-utils": "4.0.0-alpha.25",
|
|
55
|
+
"@loaders.gl/polyfills": "4.0.0-alpha.25",
|
|
56
|
+
"@loaders.gl/textures": "4.0.0-alpha.25",
|
|
57
|
+
"@loaders.gl/tiles": "4.0.0-alpha.25",
|
|
58
|
+
"@loaders.gl/worker-utils": "4.0.0-alpha.25",
|
|
59
|
+
"@loaders.gl/zip": "4.0.0-alpha.25",
|
|
60
60
|
"@math.gl/core": "^3.5.1",
|
|
61
61
|
"@math.gl/culling": "^3.5.1",
|
|
62
62
|
"@math.gl/geoid": "^3.5.1",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"join-images": "^1.1.3",
|
|
81
81
|
"sharp": "^0.31.3"
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "40135f391b869388dbbcd615bbe51178d0c370be",
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@types/express": "^4.17.17",
|
|
86
86
|
"@types/node": "^20.4.2"
|
|
@@ -33,7 +33,7 @@ export default class B3dmConverter {
|
|
|
33
33
|
i3sAttributesData: I3SAttributesData,
|
|
34
34
|
featureAttributes: any = null
|
|
35
35
|
): Promise<ArrayBuffer> {
|
|
36
|
-
const gltf = await this.
|
|
36
|
+
const gltf = await this.buildGLTF(i3sAttributesData, featureAttributes);
|
|
37
37
|
const b3dm = encodeSync(
|
|
38
38
|
{
|
|
39
39
|
gltfEncoded: new Uint8Array(gltf),
|
|
@@ -51,7 +51,7 @@ export default class B3dmConverter {
|
|
|
51
51
|
* @param i3sTile - Tile3D instance for I3S node
|
|
52
52
|
* @returns - encoded glb content
|
|
53
53
|
*/
|
|
54
|
-
async
|
|
54
|
+
async buildGLTF(
|
|
55
55
|
i3sAttributesData: I3SAttributesData,
|
|
56
56
|
featureAttributes: any
|
|
57
57
|
): Promise<ArrayBuffer> {
|
|
@@ -59,8 +59,8 @@ export default class B3dmConverter {
|
|
|
59
59
|
const {material, attributes, indices: originalIndices, modelMatrix} = tileContent;
|
|
60
60
|
const gltfBuilder = new GLTFScenegraph();
|
|
61
61
|
|
|
62
|
-
const textureIndex = await this.
|
|
63
|
-
const pbrMaterialInfo = this.
|
|
62
|
+
const textureIndex = await this._addI3sTextureToGLTF(tileContent, textureFormat, gltfBuilder);
|
|
63
|
+
const pbrMaterialInfo = this._convertI3sMaterialToGLTFMaterial(material, textureIndex);
|
|
64
64
|
const materialIndex = gltfBuilder.addMaterial(pbrMaterialInfo);
|
|
65
65
|
|
|
66
66
|
const positions = attributes.positions;
|
|
@@ -115,7 +115,7 @@ export default class B3dmConverter {
|
|
|
115
115
|
* @param {GLTFScenegraph} gltfBuilder - gltfScenegraph instance to construct GLTF
|
|
116
116
|
* @returns {Promise<number | null>} - GLTF texture index
|
|
117
117
|
*/
|
|
118
|
-
async
|
|
118
|
+
async _addI3sTextureToGLTF(tileContent, textureFormat, gltfBuilder) {
|
|
119
119
|
const {texture, material, attributes} = tileContent;
|
|
120
120
|
let textureIndex = null;
|
|
121
121
|
let selectedTexture = texture;
|
|
@@ -222,7 +222,7 @@ export default class B3dmConverter {
|
|
|
222
222
|
* @param {number | null} textureIndex - texture index in GLTF
|
|
223
223
|
* @returns {object} GLTF material
|
|
224
224
|
*/
|
|
225
|
-
|
|
225
|
+
_convertI3sMaterialToGLTFMaterial(material, textureIndex) {
|
|
226
226
|
const isTextureIndexExists = textureIndex !== null;
|
|
227
227
|
|
|
228
228
|
if (!material) {
|
|
@@ -248,7 +248,7 @@ export default class B3dmConverter {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
if (textureIndex !== null) {
|
|
251
|
-
material = this.
|
|
251
|
+
material = this._setGLTFTexture(material, textureIndex);
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
return material;
|
|
@@ -260,7 +260,7 @@ export default class B3dmConverter {
|
|
|
260
260
|
* @param {number} textureIndex - texture index in GLTF
|
|
261
261
|
* @returns {void}
|
|
262
262
|
*/
|
|
263
|
-
|
|
263
|
+
_setGLTFTexture(materialDefinition, textureIndex) {
|
|
264
264
|
const material = {
|
|
265
265
|
...materialDefinition,
|
|
266
266
|
pbrMetallicRoughness: {...materialDefinition.pbrMetallicRoughness}
|
|
@@ -3,8 +3,7 @@ import type {NumericArray} from '@loaders.gl/loader-utils';
|
|
|
3
3
|
import type {
|
|
4
4
|
GLTF_EXT_feature_metadata_FeatureIdTexture,
|
|
5
5
|
GLTF_EXT_feature_metadata_GLTF,
|
|
6
|
-
GLTF_EXT_feature_metadata_Primitive
|
|
7
|
-
GLTF_EXT_structural_metadata
|
|
6
|
+
GLTF_EXT_feature_metadata_Primitive
|
|
8
7
|
} from '@loaders.gl/gltf';
|
|
9
8
|
|
|
10
9
|
import type {GLTF_EXT_mesh_features} from '@loaders.gl/gltf';
|
|
@@ -12,11 +11,14 @@ import type {GLTF_EXT_mesh_features} from '@loaders.gl/gltf';
|
|
|
12
11
|
import {TypedArray} from '@math.gl/core';
|
|
13
12
|
import {TextureImageProperties} from '../types';
|
|
14
13
|
import {emod} from '@loaders.gl/math';
|
|
15
|
-
import {
|
|
14
|
+
import {EXT_MESH_FEATURES, EXT_FEATURE_METADATA} from '@loaders.gl/gltf';
|
|
16
15
|
import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
|
-
* Get featureTexture by
|
|
18
|
+
* Get featureTexture by a metadata class.
|
|
19
|
+
* Metadata classes come from a structural metadata extesion (EXT_feature_metadata or EXT_structural_metadata).
|
|
20
|
+
* The glTF might contain multiple texel-level metadata textures related to different classes. Having only one metadata class
|
|
21
|
+
* selected to convert to I3S, we have to pick only one texture to convert to per-vertex property.
|
|
20
22
|
* @param tileContent - 3d tile content
|
|
21
23
|
* @param metadataClass - user selected feature metadata class name
|
|
22
24
|
* @returns featureTexture key
|
|
@@ -72,12 +74,6 @@ export function handleBatchIdsExtensions(
|
|
|
72
74
|
);
|
|
73
75
|
case EXT_MESH_FEATURES:
|
|
74
76
|
return handleExtMeshFeaturesExtension(attributes, extensionData as GLTF_EXT_mesh_features);
|
|
75
|
-
case EXT_STRUCTURAL_METADATA:
|
|
76
|
-
return handleExtStructuralMetadataExtension(
|
|
77
|
-
attributes,
|
|
78
|
-
extensionData as GLTF_EXT_structural_metadata
|
|
79
|
-
);
|
|
80
|
-
|
|
81
77
|
default:
|
|
82
78
|
return [];
|
|
83
79
|
}
|
|
@@ -86,23 +82,6 @@ export function handleBatchIdsExtensions(
|
|
|
86
82
|
return [];
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
function handleExtStructuralMetadataExtension(
|
|
90
|
-
attributes: {
|
|
91
|
-
[key: string]: GLTFAccessorPostprocessed;
|
|
92
|
-
},
|
|
93
|
-
extStructuralMetadata: GLTF_EXT_structural_metadata
|
|
94
|
-
): NumericArray {
|
|
95
|
-
// Take only first extension object to get batchIds attribute name.
|
|
96
|
-
const dataAttributeNames = extStructuralMetadata?.dataAttributeNames;
|
|
97
|
-
if (dataAttributeNames?.length) {
|
|
98
|
-
// Let's use the first element of the array
|
|
99
|
-
// TODO: What to do with others if any?
|
|
100
|
-
const batchIdsAttribute = attributes[dataAttributeNames[0]];
|
|
101
|
-
return batchIdsAttribute.value;
|
|
102
|
-
}
|
|
103
|
-
return [];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
85
|
/**
|
|
107
86
|
* Getting batchIds from EXT_mesh_features extensions.
|
|
108
87
|
* @param attributes - gltf accessors
|
|
@@ -115,19 +94,19 @@ function handleExtMeshFeaturesExtension(
|
|
|
115
94
|
},
|
|
116
95
|
extMeshFeatures: GLTF_EXT_mesh_features
|
|
117
96
|
): NumericArray {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
97
|
+
for (let ids of extMeshFeatures.featureIds) {
|
|
98
|
+
if (typeof ids.propertyTable !== 'undefined') {
|
|
99
|
+
// propertyTable is an index that can be 0
|
|
100
|
+
// return the first featureID set that corresponts to property table.
|
|
101
|
+
return ids.data as NumericArray;
|
|
102
|
+
}
|
|
124
103
|
}
|
|
125
104
|
return [];
|
|
126
105
|
}
|
|
127
106
|
|
|
128
107
|
/**
|
|
129
108
|
* Get batchIds from EXT_feature_metadata extension.
|
|
130
|
-
*
|
|
109
|
+
* @see - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata
|
|
131
110
|
* @param attributes - glTF attributes
|
|
132
111
|
* @param extFeatureMetadata - primitive-level EXT_FEATURE_METADATA extension data
|
|
133
112
|
* @param textures - texture images
|
|
@@ -182,7 +161,7 @@ function handleExtFeatureMetadataExtension(
|
|
|
182
161
|
|
|
183
162
|
/**
|
|
184
163
|
* Generates implicit feature ids
|
|
185
|
-
*
|
|
164
|
+
* @see - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata#implicit-feature-ids
|
|
186
165
|
* @param featuresCount
|
|
187
166
|
* @param constant
|
|
188
167
|
* @param devisor
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type {FeatureTableJson, Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
2
2
|
import type {
|
|
3
|
-
GLTF_EXT_mesh_features,
|
|
4
|
-
GLTF_EXT_structural_metadata,
|
|
5
3
|
GLTFAccessorPostprocessed,
|
|
6
4
|
GLTFMaterialPostprocessed,
|
|
7
5
|
GLTFNodePostprocessed,
|
|
8
6
|
GLTFMeshPrimitivePostprocessed,
|
|
9
7
|
GLTFMeshPostprocessed,
|
|
10
8
|
GLTFTexturePostprocessed,
|
|
11
|
-
GLTF_EXT_feature_metadata_GLTF
|
|
9
|
+
GLTF_EXT_feature_metadata_GLTF,
|
|
10
|
+
GLTF_EXT_structural_metadata_GLTF
|
|
12
11
|
} from '@loaders.gl/gltf';
|
|
13
12
|
|
|
14
13
|
import {Vector3, Matrix4, Vector4} from '@math.gl/core';
|
|
@@ -50,7 +49,12 @@ import type {GLTFAttributesData, TextureImageProperties, TypedArrayConstructor}
|
|
|
50
49
|
import {generateSyntheticIndices} from '../../lib/utils/geometry-utils';
|
|
51
50
|
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
|
|
52
51
|
|
|
53
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
EXT_FEATURE_METADATA,
|
|
54
|
+
EXT_STRUCTURAL_METADATA,
|
|
55
|
+
getPropertyTableFromExtFeatureMetadata,
|
|
56
|
+
getPropertyTableFromExtStructuralMetadata
|
|
57
|
+
} from '@loaders.gl/gltf';
|
|
54
58
|
|
|
55
59
|
// Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
|
|
56
60
|
const DEFAULT_ROUGHNESS_FACTOR = 1;
|
|
@@ -385,7 +389,7 @@ export async function convertAttributes(
|
|
|
385
389
|
}
|
|
386
390
|
|
|
387
391
|
/**
|
|
388
|
-
*
|
|
392
|
+
* glTF has hierarchical structure of nodes. This function converts nodes starting from those which are in gltf scene object.
|
|
389
393
|
* The goal is applying tranformation matrix for all children. Functions "convertNodes" and "convertNode" work together recursively.
|
|
390
394
|
* @param nodes - gltf nodes array
|
|
391
395
|
* @param images - gltf images array
|
|
@@ -1053,7 +1057,7 @@ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterial
|
|
|
1053
1057
|
|
|
1054
1058
|
/**
|
|
1055
1059
|
* Converts from `alphaMode` material property from GLTF to I3S format
|
|
1056
|
-
* @param gltfAlphaMode
|
|
1060
|
+
* @param gltfAlphaMode glTF material `alphaMode` property
|
|
1057
1061
|
* @returns I3SMaterialDefinition.alphaMode property
|
|
1058
1062
|
*/
|
|
1059
1063
|
function convertAlphaMode(
|
|
@@ -1606,7 +1610,7 @@ function generateFeatureIndexAttribute(
|
|
|
1606
1610
|
* For example it can be batchTable for b3dm files or property table in gLTF extension.
|
|
1607
1611
|
* @param tileContent - 3DTiles tile content
|
|
1608
1612
|
* @param metadataClass - user selected feature metadata class name
|
|
1609
|
-
* @return batch table from b3dm / feature properties from EXT_FEATURE_METADATA
|
|
1613
|
+
* @return batch table from b3dm / feature properties from EXT_FEATURE_METADATA or EXT_STRUCTURAL_METADATA.
|
|
1610
1614
|
*/
|
|
1611
1615
|
export function getPropertyTable(
|
|
1612
1616
|
tileContent: Tiles3DTileContent | null,
|
|
@@ -1616,7 +1620,7 @@ export function getPropertyTable(
|
|
|
1616
1620
|
return null;
|
|
1617
1621
|
}
|
|
1618
1622
|
let propertyTable: FeatureTableJson | null;
|
|
1619
|
-
const batchTableJson = tileContent
|
|
1623
|
+
const batchTableJson = tileContent.batchTableJson;
|
|
1620
1624
|
|
|
1621
1625
|
if (batchTableJson) {
|
|
1622
1626
|
return batchTableJson;
|
|
@@ -1625,16 +1629,9 @@ export function getPropertyTable(
|
|
|
1625
1629
|
const {extensionName, extension} = getPropertyTableExtension(tileContent);
|
|
1626
1630
|
|
|
1627
1631
|
switch (extensionName) {
|
|
1628
|
-
case EXT_MESH_FEATURES: {
|
|
1629
|
-
propertyTable = getPropertyTableFromExtMeshFeatures(
|
|
1630
|
-
extension as GLTF_EXT_mesh_features,
|
|
1631
|
-
metadataClass
|
|
1632
|
-
);
|
|
1633
|
-
return propertyTable;
|
|
1634
|
-
}
|
|
1635
1632
|
case EXT_STRUCTURAL_METADATA: {
|
|
1636
1633
|
propertyTable = getPropertyTableFromExtStructuralMetadata(
|
|
1637
|
-
extension as
|
|
1634
|
+
extension as GLTF_EXT_structural_metadata_GLTF,
|
|
1638
1635
|
metadataClass
|
|
1639
1636
|
);
|
|
1640
1637
|
return propertyTable;
|
|
@@ -1657,18 +1654,9 @@ export function getPropertyTable(
|
|
|
1657
1654
|
*/
|
|
1658
1655
|
function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
|
|
1659
1656
|
extensionName: null | string;
|
|
1660
|
-
extension:
|
|
1661
|
-
| string
|
|
1662
|
-
| GLTF_EXT_feature_metadata_GLTF
|
|
1663
|
-
| GLTF_EXT_structural_metadata
|
|
1664
|
-
| GLTF_EXT_mesh_features
|
|
1665
|
-
| null;
|
|
1657
|
+
extension: string | GLTF_EXT_feature_metadata_GLTF | GLTF_EXT_structural_metadata_GLTF | null;
|
|
1666
1658
|
} {
|
|
1667
|
-
const extensionsWithPropertyTables = [
|
|
1668
|
-
EXT_FEATURE_METADATA,
|
|
1669
|
-
EXT_STRUCTURAL_METADATA,
|
|
1670
|
-
EXT_MESH_FEATURES
|
|
1671
|
-
];
|
|
1659
|
+
const extensionsWithPropertyTables = [EXT_FEATURE_METADATA, EXT_STRUCTURAL_METADATA];
|
|
1672
1660
|
const extensionsUsed = tileContent?.gltf?.extensionsUsed;
|
|
1673
1661
|
|
|
1674
1662
|
if (!extensionsUsed) {
|
|
@@ -1679,6 +1667,12 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
|
|
|
1679
1667
|
for (const extensionItem of tileContent?.gltf?.extensionsUsed || []) {
|
|
1680
1668
|
if (extensionsWithPropertyTables.includes(extensionItem)) {
|
|
1681
1669
|
extensionName = extensionItem;
|
|
1670
|
+
/*
|
|
1671
|
+
It returns the first extension containing the property table.
|
|
1672
|
+
We assume that there can be only one extension containing the property table:
|
|
1673
|
+
either EXT_FEATURE_METADATA, which is a depricated extension,
|
|
1674
|
+
or EXT_STRUCTURAL_METADATA.
|
|
1675
|
+
*/
|
|
1682
1676
|
break;
|
|
1683
1677
|
}
|
|
1684
1678
|
}
|
|
@@ -1689,147 +1683,8 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
|
|
|
1689
1683
|
|
|
1690
1684
|
const extension = tileContent?.gltf?.extensions?.[extensionName] as
|
|
1691
1685
|
| string // EXT_mesh_features doesn't have global metadata
|
|
1692
|
-
| GLTF_EXT_feature_metadata_GLTF
|
|
1686
|
+
| GLTF_EXT_feature_metadata_GLTF
|
|
1687
|
+
| GLTF_EXT_structural_metadata_GLTF;
|
|
1693
1688
|
|
|
1694
1689
|
return {extensionName, extension};
|
|
1695
1690
|
}
|
|
1696
|
-
|
|
1697
|
-
/**
|
|
1698
|
-
* Handle EXT_feature_metadata to get property table
|
|
1699
|
-
* @param extension - global level of EXT_FEATURE_METADATA extension
|
|
1700
|
-
* @param metadataClass - user selected feature metadata class name
|
|
1701
|
-
* @returns {FeatureTableJson | null} Property table or null if the extension can't be handled properly.
|
|
1702
|
-
*/
|
|
1703
|
-
function getPropertyTableFromExtFeatureMetadata(
|
|
1704
|
-
extension: GLTF_EXT_feature_metadata_GLTF,
|
|
1705
|
-
metadataClass?: string
|
|
1706
|
-
): FeatureTableJson | null {
|
|
1707
|
-
if (extension?.featureTables) {
|
|
1708
|
-
/**
|
|
1709
|
-
* Take only first feature table to generate attributes storage info object.
|
|
1710
|
-
* TODO: Think about getting data from all feature tables?
|
|
1711
|
-
* It can be tricky just because 3dTiles is able to have multiple featureId attributes and multiple feature tables.
|
|
1712
|
-
* In I3S we should decide which featureIds attribute will be passed to geometry data.
|
|
1713
|
-
*/
|
|
1714
|
-
const firstFeatureTableName = Object.keys(extension.featureTables)?.[0];
|
|
1715
|
-
|
|
1716
|
-
if (firstFeatureTableName) {
|
|
1717
|
-
const featureTable = extension?.featureTables[firstFeatureTableName];
|
|
1718
|
-
const propertyTable = {};
|
|
1719
|
-
|
|
1720
|
-
for (const propertyName in featureTable.properties) {
|
|
1721
|
-
propertyTable[propertyName] = featureTable.properties[propertyName].data;
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
return propertyTable;
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
|
|
1728
|
-
if (extension?.featureTextures) {
|
|
1729
|
-
let featureTexture: string | undefined;
|
|
1730
|
-
for (const textureKey in extension.featureTextures) {
|
|
1731
|
-
const texture = extension.featureTextures[textureKey];
|
|
1732
|
-
if (texture.class === metadataClass) {
|
|
1733
|
-
featureTexture = textureKey;
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
if (typeof featureTexture === 'string') {
|
|
1738
|
-
const featureTable = extension?.featureTextures[featureTexture];
|
|
1739
|
-
const propertyTable = {};
|
|
1740
|
-
|
|
1741
|
-
for (const propertyName in featureTable.properties) {
|
|
1742
|
-
propertyTable[propertyName] = featureTable.properties[propertyName].data;
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
return propertyTable;
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
console.warn(
|
|
1750
|
-
"The I3S converter couldn't handle EXT_feature_metadata extension: There is neither featureTables, no featureTextures in the extension."
|
|
1751
|
-
);
|
|
1752
|
-
return null;
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
|
-
/**
|
|
1756
|
-
* Handle EXT_structural_metadata to get property table
|
|
1757
|
-
* @param extension - global level of EXT_STRUCTURAL_METADATA extension
|
|
1758
|
-
* @param metadataClass - user selected feature metadata class name
|
|
1759
|
-
* @returns {FeatureTableJson | null} Property table or null if the extension can't be handled properly.
|
|
1760
|
-
*/
|
|
1761
|
-
function getPropertyTableFromExtStructuralMetadata(
|
|
1762
|
-
extension: GLTF_EXT_structural_metadata,
|
|
1763
|
-
metadataClass?: string
|
|
1764
|
-
): FeatureTableJson | null {
|
|
1765
|
-
if (extension?.propertyTables) {
|
|
1766
|
-
/**
|
|
1767
|
-
* Take only first feature table to generate attributes storage info object.
|
|
1768
|
-
* TODO: Think about getting data from all feature tables?
|
|
1769
|
-
* It can be tricky just because 3dTiles is able to have multiple featureId attributes and multiple feature tables.
|
|
1770
|
-
* In I3S we should decide which featureIds attribute will be passed to geometry data.
|
|
1771
|
-
*/
|
|
1772
|
-
const firstPropertyTable = extension?.propertyTables[0];
|
|
1773
|
-
const propertyTableWithData = {};
|
|
1774
|
-
|
|
1775
|
-
for (const propertyName in firstPropertyTable.properties) {
|
|
1776
|
-
propertyTableWithData[propertyName] = firstPropertyTable.properties[propertyName].data;
|
|
1777
|
-
}
|
|
1778
|
-
|
|
1779
|
-
return propertyTableWithData;
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
if (extension?.propertyTextures) {
|
|
1783
|
-
/**
|
|
1784
|
-
* Take only first feature table to generate attributes storage info object.
|
|
1785
|
-
* TODO: Think about getting data from all feature tables?
|
|
1786
|
-
* It can be tricky just because 3dTiles is able to have multiple featureId attributes and multiple feature tables.
|
|
1787
|
-
* In I3S we should decide which featureIds attribute will be passed to geometry data.
|
|
1788
|
-
*/
|
|
1789
|
-
if (extension?.propertyTextures) {
|
|
1790
|
-
const firstPropertyTexture = extension?.propertyTextures[0];
|
|
1791
|
-
const propertyTableWithData = {};
|
|
1792
|
-
|
|
1793
|
-
for (const propertyName in firstPropertyTexture.properties) {
|
|
1794
|
-
propertyTableWithData[propertyName] = firstPropertyTexture.properties[propertyName].data;
|
|
1795
|
-
}
|
|
1796
|
-
|
|
1797
|
-
return propertyTableWithData;
|
|
1798
|
-
}
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
console.warn(
|
|
1802
|
-
"The I3S converter couldn't handle EXT_structural_metadata extension: There is neither propertyTables, no propertyTextures in the extension."
|
|
1803
|
-
);
|
|
1804
|
-
return null;
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
|
-
/**
|
|
1808
|
-
* Handle EXT_mesh_features to get property table
|
|
1809
|
-
* @param extension - global level of EXT_MESH_FEATURES extension
|
|
1810
|
-
* @param metadataClass - user selected feature metadata class name
|
|
1811
|
-
* @returns {FeatureTableJson | null} Property table or null if the extension can't be handled properly.
|
|
1812
|
-
*/
|
|
1813
|
-
function getPropertyTableFromExtMeshFeatures(
|
|
1814
|
-
extension: GLTF_EXT_mesh_features,
|
|
1815
|
-
metadataClass?: string
|
|
1816
|
-
): FeatureTableJson | null {
|
|
1817
|
-
if (extension?.featureIds) {
|
|
1818
|
-
const firstFeatureId = extension?.featureIds[0];
|
|
1819
|
-
const propertyTableWithData = {};
|
|
1820
|
-
|
|
1821
|
-
// When firstFeatureId.propertyTable is defined, the property data will be taken from EXT_structural_metadata extension
|
|
1822
|
-
if (!firstFeatureId.propertyTable) {
|
|
1823
|
-
console.warn(
|
|
1824
|
-
'Should be implemented as we have the tileset with Ext_mesh_features not linked with EXT_structural_metadata extension'
|
|
1825
|
-
);
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
return propertyTableWithData;
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
console.warn(
|
|
1832
|
-
"The I3S converter couldn't handle EXT_mesh_features extension: There is no featureIds in the extension."
|
|
1833
|
-
);
|
|
1834
|
-
return null;
|
|
1835
|
-
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
|
|
2
2
|
import {GLTFPrimitiveModeString, PreprocessData} from '../types';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
EXT_STRUCTURAL_METADATA,
|
|
5
|
+
GLTF,
|
|
6
|
+
GLTFLoader,
|
|
7
|
+
GLTF_EXT_feature_metadata_GLTF,
|
|
8
|
+
GLTF_EXT_structural_metadata_GLTF
|
|
9
|
+
} from '@loaders.gl/gltf';
|
|
4
10
|
import {parse} from '@loaders.gl/core';
|
|
5
11
|
import {EXT_FEATURE_METADATA} from '@loaders.gl/gltf';
|
|
6
12
|
|
|
@@ -43,8 +49,8 @@ export const analyzeTileContent = async (
|
|
|
43
49
|
if (!gltf) {
|
|
44
50
|
return defaultResult;
|
|
45
51
|
}
|
|
46
|
-
const meshTopologyTypes =
|
|
47
|
-
const metadataClasses =
|
|
52
|
+
const meshTopologyTypes = getMeshTypesFromGLTF(gltf);
|
|
53
|
+
const metadataClasses = getMetadataClassesFromGLTF(gltf);
|
|
48
54
|
return {
|
|
49
55
|
meshTopologyTypes,
|
|
50
56
|
metadataClasses
|
|
@@ -56,7 +62,7 @@ export const analyzeTileContent = async (
|
|
|
56
62
|
* @param gltfJson - JSON part of GLB content
|
|
57
63
|
* @returns array of mesh types found
|
|
58
64
|
*/
|
|
59
|
-
const
|
|
65
|
+
const getMeshTypesFromGLTF = (gltfJson: GLTF): Set<GLTFPrimitiveModeString> => {
|
|
60
66
|
const result: Set<GLTFPrimitiveModeString> = new Set();
|
|
61
67
|
for (const mesh of gltfJson.meshes || []) {
|
|
62
68
|
for (const primitive of mesh.primitives) {
|
|
@@ -72,17 +78,32 @@ const getMeshTypesFromGltf = (gltfJson: GLTF): Set<GLTFPrimitiveModeString> => {
|
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
80
|
* Get feature metadata classes from glTF
|
|
81
|
+
* The tileset might contain multiple metadata classes provided by EXT_feature_metadata and EXT_structural_metadata extensions.
|
|
82
|
+
* Every class is a set of properties. But I3S can consume only one set of properties.
|
|
83
|
+
* 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.
|
|
75
84
|
* @param gltfJson - JSON part of GLB content
|
|
76
85
|
* @returns array of classes
|
|
77
86
|
*/
|
|
78
|
-
const
|
|
87
|
+
const getMetadataClassesFromGLTF = (gltfJson: GLTF): Set<string> => {
|
|
79
88
|
const result: Set<string> = new Set();
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
90
|
+
// Try to parse from EXT_feature_metadata
|
|
91
|
+
const extFeatureMetadataClasses = (
|
|
92
|
+
gltfJson.extensions?.[EXT_FEATURE_METADATA] as GLTF_EXT_feature_metadata_GLTF
|
|
93
|
+
)?.schema?.classes;
|
|
83
94
|
|
|
84
|
-
if (
|
|
85
|
-
for (const classKey of Object.keys(
|
|
95
|
+
if (extFeatureMetadataClasses) {
|
|
96
|
+
for (const classKey of Object.keys(extFeatureMetadataClasses)) {
|
|
97
|
+
result.add(classKey);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Try to parse from EXT_structural_metadata
|
|
102
|
+
const extStructuralMetadataClasses = (
|
|
103
|
+
gltfJson.extensions?.[EXT_STRUCTURAL_METADATA] as GLTF_EXT_structural_metadata_GLTF
|
|
104
|
+
)?.schema?.classes;
|
|
105
|
+
if (extStructuralMetadataClasses) {
|
|
106
|
+
for (const classKey of Object.keys(extStructuralMetadataClasses)) {
|
|
86
107
|
result.add(classKey);
|
|
87
108
|
}
|
|
88
109
|
}
|
|
@@ -656,7 +656,6 @@ export default class I3SConverter {
|
|
|
656
656
|
We will append new attributes only in case the property table is updated.
|
|
657
657
|
According to ver 1.9 (see https://github.com/Esri/i3s-spec/blob/master/docs/1.9/attributeStorageInfo.cmn.md):
|
|
658
658
|
"The attributeStorageInfo object describes the structure of the binary attribute data resource of a layer, which is the same for every node in the layer."
|
|
659
|
-
But the specification of ver 2.1 doesn't have such a requirement ("...the same for every node...")
|
|
660
659
|
*/
|
|
661
660
|
this._convertPropertyTableToNodeAttributes(propertyTable);
|
|
662
661
|
}
|
|
@@ -1167,7 +1166,6 @@ export default class I3SConverter {
|
|
|
1167
1166
|
We will append new attributes only in case the property table is updated.
|
|
1168
1167
|
According to ver 1.9 (see https://github.com/Esri/i3s-spec/blob/master/docs/1.9/attributeStorageInfo.cmn.md):
|
|
1169
1168
|
"The attributeStorageInfo object describes the structure of the binary attribute data resource of a layer, which is the same for every node in the layer."
|
|
1170
|
-
But the specification of ver 2.1 doesn't have such a requirement ("...the same for every node...")
|
|
1171
1169
|
*/
|
|
1172
1170
|
const found = this.layers0!.attributeStorageInfo!.find((element) => element.name === key);
|
|
1173
1171
|
if (!found) {
|
|
@@ -187,7 +187,12 @@ export enum GLTFPrimitiveModeString {
|
|
|
187
187
|
export type PreprocessData = {
|
|
188
188
|
/** Mesh topology types used in gltf primitives of the tileset */
|
|
189
189
|
meshTopologyTypes: Set<GLTFPrimitiveModeString>;
|
|
190
|
-
/**
|
|
190
|
+
/**
|
|
191
|
+
* Featrue metadata classes found in glTF extensions
|
|
192
|
+
* The tileset might contain multiple metadata classes provided by EXT_feature_metadata and EXT_structural_metadata extensions.
|
|
193
|
+
* Every class is a set of properties. But I3S can consume only one set of properties.
|
|
194
|
+
* 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.
|
|
195
|
+
*/
|
|
191
196
|
metadataClasses: Set<string>;
|
|
192
197
|
};
|
|
193
198
|
|