@loaders.gl/tile-converter 3.3.0-alpha.1 → 3.3.0-alpha.10
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-attributes-worker.d.ts +3 -3
- package/dist/3d-tiles-attributes-worker.d.ts.map +1 -1
- package/dist/3d-tiles-attributes-worker.js +2 -3
- package/dist/3d-tiles-attributes-worker.js.map +3 -3
- package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +8 -0
- package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
- package/dist/3d-tiles-converter/3d-tiles-converter.js +57 -43
- package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +5 -5
- package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
- package/dist/3d-tiles-converter/helpers/b3dm-converter.js +21 -17
- package/dist/converter-cli.js +29 -4
- package/dist/converter.min.js +24 -21
- package/dist/deps-installer/deps-installer.d.ts +5 -1
- package/dist/deps-installer/deps-installer.d.ts.map +1 -1
- package/dist/deps-installer/deps-installer.js +29 -1
- package/dist/dist.min.js +61034 -64112
- package/dist/es5/3d-tiles-attributes-worker.js +4 -7
- package/dist/es5/3d-tiles-attributes-worker.js.map +1 -1
- package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +125 -210
- package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
- package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +53 -85
- package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
- package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +0 -8
- package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
- package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js +0 -5
- package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
- package/dist/es5/3d-tiles-converter/json-templates/tileset.js +0 -6
- package/dist/es5/3d-tiles-converter/json-templates/tileset.js.map +1 -1
- package/dist/es5/bundle.js +0 -1
- package/dist/es5/bundle.js.map +1 -1
- package/dist/es5/constants.js.map +1 -1
- package/dist/es5/converter-cli.js +25 -58
- package/dist/es5/converter-cli.js.map +1 -1
- package/dist/es5/deps-installer/deps-installer.js +73 -28
- package/dist/es5/deps-installer/deps-installer.js.map +1 -1
- package/dist/es5/i3s-attributes-worker.js +3 -6
- package/dist/es5/i3s-attributes-worker.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +18 -29
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/coordinate-converter.js +8 -25
- package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/create-scene-server-path.js +0 -11
- package/dist/es5/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/feature-attributes.js +184 -0
- package/dist/es5/i3s-converter/helpers/feature-attributes.js.map +1 -0
- package/dist/es5/i3s-converter/helpers/geometry-attributes.js +60 -51
- package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/geometry-converter.js +504 -350
- package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/gltf-attributes.js +57 -57
- package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/node-debug.js +4 -23
- package/dist/es5/i3s-converter/helpers/node-debug.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/node-index-document.js +507 -0
- package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -0
- package/dist/es5/i3s-converter/helpers/node-pages.js +478 -168
- package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
- package/dist/es5/i3s-converter/i3s-converter.js +794 -1125
- package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/es5/i3s-converter/json-templates/geometry-definitions.js +107 -0
- package/dist/es5/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
- package/dist/es5/i3s-converter/json-templates/layers.js +2 -107
- package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -1
- package/dist/es5/i3s-converter/json-templates/metadata.js +0 -2
- package/dist/es5/i3s-converter/json-templates/metadata.js.map +1 -1
- package/dist/es5/i3s-converter/json-templates/node.js +2 -12
- package/dist/es5/i3s-converter/json-templates/node.js.map +1 -1
- package/dist/es5/i3s-converter/json-templates/scene-server.js +0 -2
- package/dist/es5/i3s-converter/json-templates/scene-server.js.map +1 -1
- package/dist/es5/i3s-converter/json-templates/shared-resources.js +9 -32
- package/dist/es5/i3s-converter/json-templates/shared-resources.js.map +1 -1
- package/dist/es5/i3s-converter/json-templates/store.js.map +1 -1
- package/dist/es5/i3s-converter/types.js.map +1 -1
- package/dist/es5/i3s-server/app.js +0 -5
- package/dist/es5/i3s-server/app.js.map +1 -1
- package/dist/es5/i3s-server/controllers/index-controller.js +0 -16
- package/dist/es5/i3s-server/controllers/index-controller.js.map +1 -1
- package/dist/es5/i3s-server/routes/index.js +1 -10
- package/dist/es5/i3s-server/routes/index.js.map +1 -1
- package/dist/es5/index.js +0 -3
- package/dist/es5/index.js.map +1 -1
- package/dist/es5/lib/utils/compress-util.js +19 -74
- package/dist/es5/lib/utils/compress-util.js.map +1 -1
- package/dist/es5/lib/utils/file-utils.js +103 -47
- package/dist/es5/lib/utils/file-utils.js.map +1 -1
- package/dist/es5/lib/utils/lod-conversion-utils.js +0 -7
- package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
- package/dist/es5/lib/utils/queue.js +0 -14
- package/dist/es5/lib/utils/queue.js.map +1 -1
- package/dist/es5/lib/utils/statistic-utills.js +1 -46
- package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
- package/dist/es5/lib/utils/write-queue.js +86 -87
- package/dist/es5/lib/utils/write-queue.js.map +1 -1
- package/dist/es5/pgm-loader.js +1 -8
- package/dist/es5/pgm-loader.js.map +1 -1
- package/dist/es5/workers/3d-tiles-attributes-worker.js +2 -9
- package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -1
- package/dist/es5/workers/i3s-attributes-worker.js +2 -10
- package/dist/es5/workers/i3s-attributes-worker.js.map +1 -1
- package/dist/esm/3d-tiles-attributes-worker.js +4 -2
- package/dist/esm/3d-tiles-attributes-worker.js.map +1 -1
- package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +60 -77
- package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
- package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +29 -50
- package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
- package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +1 -0
- package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
- package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js +1 -4
- package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
- package/dist/esm/3d-tiles-converter/json-templates/tileset.js +0 -3
- package/dist/esm/3d-tiles-converter/json-templates/tileset.js.map +1 -1
- package/dist/esm/bundle.js +1 -1
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/converter-cli.js +26 -43
- package/dist/esm/converter-cli.js.map +1 -1
- package/dist/esm/deps-installer/deps-installer.js +30 -4
- package/dist/esm/deps-installer/deps-installer.js.map +1 -1
- package/dist/esm/i3s-attributes-worker.js +3 -1
- package/dist/esm/i3s-attributes-worker.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +20 -24
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/coordinate-converter.js +11 -12
- package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/create-scene-server-path.js +1 -0
- package/dist/esm/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/feature-attributes.js +158 -0
- package/dist/esm/i3s-converter/helpers/feature-attributes.js.map +1 -0
- package/dist/esm/i3s-converter/helpers/geometry-attributes.js +39 -33
- package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/geometry-converter.js +286 -192
- package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/gltf-attributes.js +59 -48
- package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/node-debug.js +3 -13
- package/dist/esm/i3s-converter/helpers/node-debug.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/node-index-document.js +197 -0
- package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -0
- package/dist/esm/i3s-converter/helpers/node-pages.js +161 -87
- package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
- package/dist/esm/i3s-converter/i3s-converter.js +235 -508
- package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
- package/dist/esm/i3s-converter/json-templates/geometry-definitions.js +89 -0
- package/dist/esm/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
- package/dist/esm/i3s-converter/json-templates/layers.js +2 -95
- package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -1
- package/dist/esm/i3s-converter/json-templates/metadata.js.map +1 -1
- package/dist/esm/i3s-converter/json-templates/node.js +0 -4
- package/dist/esm/i3s-converter/json-templates/node.js.map +1 -1
- package/dist/esm/i3s-converter/json-templates/scene-server.js.map +1 -1
- package/dist/esm/i3s-converter/json-templates/shared-resources.js +3 -15
- package/dist/esm/i3s-converter/json-templates/shared-resources.js.map +1 -1
- package/dist/esm/i3s-converter/json-templates/store.js.map +1 -1
- package/dist/esm/i3s-converter/types.js.map +1 -1
- package/dist/esm/i3s-server/app.js +0 -5
- package/dist/esm/i3s-server/app.js.map +1 -1
- package/dist/esm/i3s-server/controllers/index-controller.js +0 -5
- package/dist/esm/i3s-server/controllers/index-controller.js.map +1 -1
- package/dist/esm/i3s-server/routes/index.js +0 -3
- package/dist/esm/i3s-server/routes/index.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/utils/compress-util.js +19 -12
- package/dist/esm/lib/utils/compress-util.js.map +1 -1
- package/dist/esm/lib/utils/file-utils.js +54 -11
- package/dist/esm/lib/utils/file-utils.js.map +1 -1
- package/dist/esm/lib/utils/lod-conversion-utils.js +2 -6
- package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
- package/dist/esm/lib/utils/queue.js +0 -4
- package/dist/esm/lib/utils/queue.js.map +1 -1
- package/dist/esm/lib/utils/statistic-utills.js +0 -11
- package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
- package/dist/esm/lib/utils/write-queue.js +29 -28
- package/dist/esm/lib/utils/write-queue.js.map +1 -1
- package/dist/esm/pgm-loader.js +3 -1
- package/dist/esm/pgm-loader.js.map +1 -1
- package/dist/esm/workers/3d-tiles-attributes-worker.js +4 -1
- package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -1
- package/dist/esm/workers/i3s-attributes-worker.js +4 -1
- package/dist/esm/workers/i3s-attributes-worker.js.map +1 -1
- package/dist/i3s-attributes-worker.d.ts +7 -3
- package/dist/i3s-attributes-worker.d.ts.map +1 -1
- package/dist/i3s-attributes-worker.js +2 -3
- package/dist/i3s-attributes-worker.js.map +3 -3
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +5 -6
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/batch-ids-extensions.js +18 -4
- package/dist/i3s-converter/helpers/coordinate-converter.d.ts +2 -2
- package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/coordinate-converter.js +8 -6
- package/dist/i3s-converter/helpers/feature-attributes.d.ts +56 -0
- package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -0
- package/dist/i3s-converter/helpers/feature-attributes.js +216 -0
- package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/geometry-attributes.js +42 -17
- package/dist/i3s-converter/helpers/geometry-converter.d.ts +18 -6
- package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/geometry-converter.js +337 -92
- package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/gltf-attributes.js +51 -32
- package/dist/i3s-converter/helpers/node-index-document.d.ts +91 -0
- package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -0
- package/dist/i3s-converter/helpers/node-index-document.js +242 -0
- package/dist/i3s-converter/helpers/node-pages.d.ts +81 -42
- package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/node-pages.js +200 -92
- package/dist/i3s-converter/i3s-converter.d.ts +52 -108
- package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
- package/dist/i3s-converter/i3s-converter.js +234 -420
- package/dist/i3s-converter/json-templates/geometry-definitions.d.ts +7 -0
- package/dist/i3s-converter/json-templates/geometry-definitions.d.ts.map +1 -0
- package/dist/i3s-converter/json-templates/geometry-definitions.js +87 -0
- package/dist/i3s-converter/json-templates/layers.d.ts +1 -30
- package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -1
- package/dist/i3s-converter/json-templates/layers.js +2 -86
- package/dist/i3s-converter/json-templates/shared-resources.js +3 -3
- package/dist/i3s-converter/types.d.ts +37 -55
- package/dist/i3s-converter/types.d.ts.map +1 -1
- package/dist/lib/utils/file-utils.d.ts +17 -1
- package/dist/lib/utils/file-utils.d.ts.map +1 -1
- package/dist/lib/utils/file-utils.js +64 -7
- package/dist/lib/utils/write-queue.d.ts +19 -2
- package/dist/lib/utils/write-queue.d.ts.map +1 -1
- package/dist/lib/utils/write-queue.js +26 -7
- package/dist/pgm-loader.d.ts.map +1 -1
- package/dist/pgm-loader.js +2 -1
- package/dist/workers/3d-tiles-attributes-worker.js +1 -1
- package/dist/workers/i3s-attributes-worker.js +1 -1
- package/package.json +18 -16
- package/src/3d-tiles-attributes-worker.ts +1 -1
- package/src/3d-tiles-converter/3d-tiles-converter.ts +71 -55
- package/src/3d-tiles-converter/helpers/b3dm-converter.ts +25 -18
- package/src/converter-cli.ts +38 -4
- package/src/deps-installer/deps-installer.ts +38 -2
- package/src/i3s-attributes-worker.ts +5 -1
- package/src/i3s-converter/helpers/batch-ids-extensions.ts +38 -14
- package/src/i3s-converter/helpers/coordinate-converter.ts +10 -8
- package/src/i3s-converter/helpers/feature-attributes.ts +247 -0
- package/src/i3s-converter/helpers/geometry-attributes.ts +46 -18
- package/src/i3s-converter/helpers/geometry-converter.ts +405 -108
- package/src/i3s-converter/helpers/gltf-attributes.ts +55 -35
- package/src/i3s-converter/helpers/node-index-document.ts +306 -0
- package/src/i3s-converter/helpers/node-pages.ts +222 -109
- package/src/i3s-converter/i3s-converter.ts +279 -499
- package/src/i3s-converter/json-templates/geometry-definitions.ts +83 -0
- package/src/i3s-converter/json-templates/layers.ts +2 -91
- package/src/i3s-converter/json-templates/shared-resources.ts +3 -3
- package/src/i3s-converter/types.ts +31 -51
- package/src/lib/utils/file-utils.ts +62 -7
- package/src/lib/utils/write-queue.ts +43 -10
- package/src/pgm-loader.ts +2 -2
- package/src/workers/3d-tiles-attributes-worker.ts +1 -1
- package/src/workers/i3s-attributes-worker.ts +2 -1
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {B3DMContent, FeatureTableJson} from '@loaders.gl/3d-tiles';
|
|
2
|
+
import type {
|
|
3
|
+
GLTF_EXT_feature_metadata,
|
|
4
|
+
GLTFAccessorPostprocessed,
|
|
5
|
+
GLTFMaterialPostprocessed,
|
|
6
|
+
GLTFNodePostprocessed,
|
|
7
|
+
GLTFImagePostprocessed,
|
|
8
|
+
GLTFMeshPrimitivePostprocessed,
|
|
9
|
+
GLTFMeshPostprocessed,
|
|
10
|
+
GLTFTexturePostprocessed
|
|
11
|
+
} from '@loaders.gl/gltf';
|
|
2
12
|
|
|
3
13
|
import {Vector3, Matrix4, Vector4} from '@math.gl/core';
|
|
4
14
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
@@ -7,16 +17,16 @@ import {DracoWriterWorker} from '@loaders.gl/draco';
|
|
|
7
17
|
import {assert, encode} from '@loaders.gl/core';
|
|
8
18
|
import {concatenateArrayBuffers, concatenateTypedArrays} from '@loaders.gl/loader-utils';
|
|
9
19
|
import md5 from 'md5';
|
|
20
|
+
import {v4 as uuidv4} from 'uuid';
|
|
10
21
|
import {generateAttributes} from './geometry-attributes';
|
|
11
22
|
import {createBoundingVolumesFromGeometry} from './coordinate-converter';
|
|
12
23
|
import {
|
|
13
24
|
ConvertedAttributes,
|
|
14
25
|
I3SConvertedResources,
|
|
15
26
|
I3SMaterialWithTexture,
|
|
27
|
+
MergedMaterial,
|
|
16
28
|
SharedResourcesArrays
|
|
17
29
|
} from '../types';
|
|
18
|
-
import {B3DMContent} from '@loaders.gl/3d-tiles';
|
|
19
|
-
import {GLTFMaterialPostprocessed, GLTFNodePostprocessed} from '@loaders.gl/gltf';
|
|
20
30
|
import {
|
|
21
31
|
AttributeStorageInfo,
|
|
22
32
|
I3SMaterialDefinition,
|
|
@@ -25,14 +35,11 @@ import {
|
|
|
25
35
|
} from '@loaders.gl/i3s';
|
|
26
36
|
import {TypedArray} from '@loaders.gl/schema';
|
|
27
37
|
import {Geoid} from '@math.gl/geoid';
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
GLTFMeshPostprocessed,
|
|
31
|
-
GLTFTexturePostprocessed
|
|
32
|
-
} from 'modules/gltf/src/lib/types/gltf-types';
|
|
33
|
-
import {B3DMAttributesData /*transformI3SAttributesOnWorker */} from '../../i3s-attributes-worker';
|
|
38
|
+
/** Usage of worker here brings more overhead than advantage */
|
|
39
|
+
import {B3DMAttributesData /*, transformI3SAttributesOnWorker*/} from '../../i3s-attributes-worker';
|
|
34
40
|
import {prepareDataForAttributesConversion} from './gltf-attributes';
|
|
35
41
|
import {handleBatchIdsExtensions} from './batch-ids-extensions';
|
|
42
|
+
import {checkPropertiesLength, flattenPropertyTableByFeatureIds} from './feature-attributes';
|
|
36
43
|
|
|
37
44
|
// Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
|
|
38
45
|
const DEFAULT_ROUGHNESS_FACTOR = 1;
|
|
@@ -53,90 +60,89 @@ const OBJECT_ID_TYPE = 'Oid32';
|
|
|
53
60
|
*/
|
|
54
61
|
const BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES = ['CUSTOM_ATTRIBUTE_2', '_BATCHID', 'BATCHID'];
|
|
55
62
|
|
|
63
|
+
const EXT_FEATURE_METADATA = 'EXT_feature_metadata';
|
|
64
|
+
const EXT_MESH_FEATURES = 'EXT_mesh_features';
|
|
65
|
+
|
|
56
66
|
let scratchVector = new Vector3();
|
|
57
67
|
|
|
58
68
|
/**
|
|
59
69
|
* Convert binary data from b3dm file to i3s resources
|
|
60
70
|
*
|
|
61
71
|
* @param tileContent - 3d tile content
|
|
62
|
-
* @param
|
|
72
|
+
* @param addNodeToNodePage - function to add new node to node pages
|
|
73
|
+
* @param propertyTable - batch table (corresponding to feature attributes data)
|
|
63
74
|
* @param featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
|
|
64
75
|
* @param attributeStorageInfo - attributes metadata from 3DSceneLayer json
|
|
65
76
|
* @param draco - is converter should create draco compressed geometry
|
|
66
77
|
* @param generateBoundingVolumes - is converter should create accurate bounding voulmes from geometry attributes
|
|
78
|
+
* @param shouldMergeMaterials - Try to merge similar materials to be able to merge meshes into one node
|
|
67
79
|
* @param geoidHeightModel - model to convert elevation from elipsoidal to geoid
|
|
80
|
+
* @param workerSource - source code of used workers
|
|
68
81
|
* @returns Array of node resources to create one or more i3s nodes
|
|
69
82
|
*/
|
|
70
83
|
export default async function convertB3dmToI3sGeometry(
|
|
71
84
|
tileContent: B3DMContent,
|
|
72
|
-
|
|
85
|
+
addNodeToNodePage: () => Promise<number>,
|
|
86
|
+
propertyTable: FeatureTableJson | null,
|
|
73
87
|
featuresHashArray: string[],
|
|
74
88
|
attributeStorageInfo: AttributeStorageInfo[] | undefined,
|
|
75
89
|
draco: boolean,
|
|
76
90
|
generateBoundingVolumes: boolean,
|
|
91
|
+
shouldMergeMaterials: boolean,
|
|
77
92
|
geoidHeightModel: Geoid,
|
|
78
93
|
workerSource: {[key: string]: string}
|
|
79
|
-
) {
|
|
94
|
+
): Promise<I3SConvertedResources[] | null> {
|
|
80
95
|
const useCartesianPositions = generateBoundingVolumes;
|
|
81
|
-
const materialAndTextureList: I3SMaterialWithTexture[] = convertMaterials(
|
|
82
|
-
tileContent.gltf?.materials
|
|
96
|
+
const materialAndTextureList: I3SMaterialWithTexture[] = await convertMaterials(
|
|
97
|
+
tileContent.gltf?.materials,
|
|
98
|
+
shouldMergeMaterials
|
|
83
99
|
);
|
|
84
100
|
|
|
85
101
|
const dataForAttributesConversion = prepareDataForAttributesConversion(tileContent);
|
|
86
|
-
|
|
87
102
|
const convertedAttributesMap: Map<string, ConvertedAttributes> = await convertAttributes(
|
|
88
103
|
dataForAttributesConversion,
|
|
104
|
+
materialAndTextureList,
|
|
89
105
|
useCartesianPositions
|
|
90
106
|
);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
/** Usage of worker here brings more overhead than advantage */
|
|
108
|
+
// const convertedAttributesMap: Map<string, ConvertedAttributes> =
|
|
109
|
+
// await transformI3SAttributesOnWorker(dataForAttributesConversion, {
|
|
110
|
+
// reuseWorkers: true,
|
|
111
|
+
// _nodeWorkers: true,
|
|
112
|
+
// useCartesianPositions,
|
|
113
|
+
// source: workerSource.I3SAttributes
|
|
114
|
+
// });
|
|
99
115
|
|
|
100
116
|
if (generateBoundingVolumes) {
|
|
101
117
|
_generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeightModel);
|
|
102
118
|
}
|
|
103
119
|
|
|
104
|
-
if (convertedAttributesMap.has('default')) {
|
|
105
|
-
materialAndTextureList.push({
|
|
106
|
-
material: getDefaultMaterial()
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
120
|
const result: I3SConvertedResources[] = [];
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
materials.push({id: 'default'});
|
|
115
|
-
}
|
|
116
|
-
for (let i = 0; i < materials.length; i++) {
|
|
117
|
-
const sourceMaterial = materials[i];
|
|
118
|
-
if (!convertedAttributesMap.has(sourceMaterial.id)) {
|
|
121
|
+
for (const materialAndTexture of materialAndTextureList) {
|
|
122
|
+
const originarMaterialId = materialAndTexture.mergedMaterials[0].originalMaterialId;
|
|
123
|
+
if (!convertedAttributesMap.has(originarMaterialId)) {
|
|
119
124
|
continue; // eslint-disable-line no-continue
|
|
120
125
|
}
|
|
121
|
-
const convertedAttributes = convertedAttributesMap.get(
|
|
126
|
+
const convertedAttributes = convertedAttributesMap.get(originarMaterialId);
|
|
122
127
|
if (!convertedAttributes) {
|
|
123
128
|
continue;
|
|
124
129
|
}
|
|
125
|
-
const {material, texture} =
|
|
130
|
+
const {material, texture} = materialAndTexture;
|
|
131
|
+
const nodeId = await addNodeToNodePage();
|
|
126
132
|
result.push(
|
|
127
133
|
await _makeNodeResources({
|
|
128
134
|
convertedAttributes,
|
|
129
135
|
material,
|
|
130
136
|
texture,
|
|
131
137
|
tileContent,
|
|
132
|
-
nodeId
|
|
138
|
+
nodeId,
|
|
133
139
|
featuresHashArray,
|
|
140
|
+
propertyTable,
|
|
134
141
|
attributeStorageInfo,
|
|
135
142
|
draco,
|
|
136
143
|
workerSource
|
|
137
144
|
})
|
|
138
145
|
);
|
|
139
|
-
nodesCounter++;
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
if (!result.length) {
|
|
@@ -183,8 +189,10 @@ function _generateBoundingVolumesFromGeometry(
|
|
|
183
189
|
* @param params.tileContent - B3DM decoded content
|
|
184
190
|
* @param params.nodeId - new node ID
|
|
185
191
|
* @param params.featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
|
|
186
|
-
* @param params.
|
|
192
|
+
* @param params.propertyTable - batch table (corresponding to feature attributes data)
|
|
193
|
+
* @param params.attributeStorageInfo - attributes metadata from 3DSceneLayer json
|
|
187
194
|
* @param params.draco - is converter should create draco compressed geometry
|
|
195
|
+
* @param params.workerSource - source code of used workers
|
|
188
196
|
* @returns Array of I3S node resources
|
|
189
197
|
*/
|
|
190
198
|
async function _makeNodeResources({
|
|
@@ -194,6 +202,7 @@ async function _makeNodeResources({
|
|
|
194
202
|
tileContent,
|
|
195
203
|
nodeId,
|
|
196
204
|
featuresHashArray,
|
|
205
|
+
propertyTable,
|
|
197
206
|
attributeStorageInfo,
|
|
198
207
|
draco,
|
|
199
208
|
workerSource
|
|
@@ -204,13 +213,14 @@ async function _makeNodeResources({
|
|
|
204
213
|
tileContent: B3DMContent;
|
|
205
214
|
nodeId: number;
|
|
206
215
|
featuresHashArray: string[];
|
|
216
|
+
propertyTable: FeatureTableJson | null;
|
|
207
217
|
attributeStorageInfo?: AttributeStorageInfo[];
|
|
208
218
|
draco: boolean;
|
|
209
219
|
workerSource: {[key: string]: string};
|
|
210
220
|
}): Promise<I3SConvertedResources> {
|
|
211
221
|
const boundingVolumes = convertedAttributes.boundingVolumes;
|
|
212
222
|
const vertexCount = convertedAttributes.positions.length / VALUES_PER_VERTEX;
|
|
213
|
-
const {faceRange, featureIds, positions, normals, colors, texCoords, featureCount} =
|
|
223
|
+
const {faceRange, featureIds, positions, normals, colors, uvRegions, texCoords, featureCount} =
|
|
214
224
|
generateAttributes(convertedAttributes);
|
|
215
225
|
|
|
216
226
|
if (tileContent.batchTableJson) {
|
|
@@ -233,6 +243,7 @@ async function _makeNodeResources({
|
|
|
233
243
|
normals.buffer,
|
|
234
244
|
texture ? texCoords.buffer : new ArrayBuffer(0),
|
|
235
245
|
colors.buffer,
|
|
246
|
+
uvRegions,
|
|
236
247
|
typedFeatureIds.buffer,
|
|
237
248
|
faceRange.buffer
|
|
238
249
|
)
|
|
@@ -246,6 +257,7 @@ async function _makeNodeResources({
|
|
|
246
257
|
normals,
|
|
247
258
|
texCoords: texture ? texCoords : new Float32Array(0),
|
|
248
259
|
colors,
|
|
260
|
+
uvRegions,
|
|
249
261
|
featureIds,
|
|
250
262
|
faceRange
|
|
251
263
|
},
|
|
@@ -253,16 +265,22 @@ async function _makeNodeResources({
|
|
|
253
265
|
)
|
|
254
266
|
: null;
|
|
255
267
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
268
|
+
let attributes: ArrayBuffer[] = [];
|
|
269
|
+
|
|
270
|
+
if (attributeStorageInfo && propertyTable) {
|
|
271
|
+
attributes = convertPropertyTableToAttributeBuffers(
|
|
272
|
+
featureIds,
|
|
273
|
+
propertyTable,
|
|
274
|
+
attributeStorageInfo
|
|
275
|
+
);
|
|
276
|
+
}
|
|
261
277
|
|
|
262
278
|
return {
|
|
279
|
+
nodeId,
|
|
263
280
|
geometry: fileBuffer,
|
|
264
281
|
compressedGeometry,
|
|
265
282
|
texture,
|
|
283
|
+
hasUvRegions: Boolean(uvRegions.length),
|
|
266
284
|
sharedResources: getSharedResources(tileContent.gltf?.materials || [], nodeId),
|
|
267
285
|
meshMaterial: material,
|
|
268
286
|
vertexCount,
|
|
@@ -274,32 +292,40 @@ async function _makeNodeResources({
|
|
|
274
292
|
|
|
275
293
|
/**
|
|
276
294
|
* Convert attributes from the gltf nodes tree to i3s plain geometry
|
|
277
|
-
* @param
|
|
295
|
+
* @param attributesData - geometry attributes from gltf
|
|
296
|
+
* @param materialAndTextureList - array of data about materials and textures of the content
|
|
278
297
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
279
298
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
280
299
|
* @returns map of converted geometry attributes
|
|
281
300
|
*/
|
|
282
301
|
export async function convertAttributes(
|
|
283
302
|
attributesData: B3DMAttributesData,
|
|
303
|
+
materialAndTextureList: I3SMaterialWithTexture[],
|
|
284
304
|
useCartesianPositions: boolean
|
|
285
305
|
): Promise<Map<string, ConvertedAttributes>> {
|
|
286
|
-
const {
|
|
306
|
+
const {nodes, images, cartographicOrigin, cartesianModelMatrix} = attributesData;
|
|
287
307
|
const attributesMap = new Map<string, ConvertedAttributes>();
|
|
288
308
|
|
|
289
|
-
for (const
|
|
290
|
-
|
|
309
|
+
for (const materialAndTexture of materialAndTextureList) {
|
|
310
|
+
const attributes = {
|
|
291
311
|
positions: new Float32Array(0),
|
|
292
312
|
normals: new Float32Array(0),
|
|
293
313
|
texCoords: new Float32Array(0),
|
|
294
314
|
colors: new Uint8Array(0),
|
|
315
|
+
uvRegions: new Uint16Array(0),
|
|
295
316
|
featureIndicesGroups: [],
|
|
296
317
|
featureIndices: [],
|
|
297
|
-
boundingVolumes: null
|
|
298
|
-
|
|
318
|
+
boundingVolumes: null,
|
|
319
|
+
mergedMaterials: materialAndTexture.mergedMaterials
|
|
320
|
+
};
|
|
321
|
+
for (const mergedMaterial of materialAndTexture.mergedMaterials) {
|
|
322
|
+
attributesMap.set(mergedMaterial.originalMaterialId, attributes);
|
|
323
|
+
}
|
|
299
324
|
}
|
|
300
325
|
|
|
301
326
|
convertNodes(
|
|
302
327
|
nodes,
|
|
328
|
+
images,
|
|
303
329
|
cartographicOrigin,
|
|
304
330
|
cartesianModelMatrix,
|
|
305
331
|
attributesMap,
|
|
@@ -330,7 +356,9 @@ export async function convertAttributes(
|
|
|
330
356
|
* Gltf has hierarchical structure of nodes. This function converts nodes starting from those which are in gltf scene object.
|
|
331
357
|
* The goal is applying tranformation matrix for all children. Functions "convertNodes" and "convertNode" work together recursively.
|
|
332
358
|
* @param nodes - gltf nodes array
|
|
333
|
-
* @param
|
|
359
|
+
* @param images - gltf images array
|
|
360
|
+
* @param cartographicOrigin - cartographic origin of bounding volume
|
|
361
|
+
* @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
|
|
334
362
|
* @param attributesMap - for recursive concatenation of attributes
|
|
335
363
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
336
364
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
@@ -339,6 +367,7 @@ export async function convertAttributes(
|
|
|
339
367
|
*/
|
|
340
368
|
function convertNodes(
|
|
341
369
|
nodes: GLTFNodePostprocessed[],
|
|
370
|
+
images: GLTFImagePostprocessed[],
|
|
342
371
|
cartographicOrigin: Vector3,
|
|
343
372
|
cartesianModelMatrix: Matrix4,
|
|
344
373
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
@@ -349,6 +378,7 @@ function convertNodes(
|
|
|
349
378
|
for (const node of nodes) {
|
|
350
379
|
convertNode(
|
|
351
380
|
node,
|
|
381
|
+
images,
|
|
352
382
|
cartographicOrigin,
|
|
353
383
|
cartesianModelMatrix,
|
|
354
384
|
attributesMap,
|
|
@@ -365,7 +395,7 @@ function convertNodes(
|
|
|
365
395
|
* @param node
|
|
366
396
|
* @param matrix
|
|
367
397
|
*/
|
|
368
|
-
function getCompositeTransformationMatrix(node, matrix) {
|
|
398
|
+
function getCompositeTransformationMatrix(node: GLTFNodePostprocessed, matrix: Matrix4) {
|
|
369
399
|
let transformationMatrix = matrix;
|
|
370
400
|
|
|
371
401
|
const {matrix: nodeMatrix, rotation, scale, translation} = node;
|
|
@@ -392,7 +422,9 @@ function getCompositeTransformationMatrix(node, matrix) {
|
|
|
392
422
|
/**
|
|
393
423
|
* Convert all primitives of node and all children nodes
|
|
394
424
|
* @param node - gltf node
|
|
395
|
-
* @param
|
|
425
|
+
* @param images - gltf images array
|
|
426
|
+
* @param cartographicOrigin - cartographic origin of bounding volume
|
|
427
|
+
* @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
|
|
396
428
|
* @param {Map} attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
397
429
|
* attributes
|
|
398
430
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
@@ -401,6 +433,7 @@ function getCompositeTransformationMatrix(node, matrix) {
|
|
|
401
433
|
*/
|
|
402
434
|
function convertNode(
|
|
403
435
|
node: GLTFNodePostprocessed,
|
|
436
|
+
images: GLTFImagePostprocessed[],
|
|
404
437
|
cartographicOrigin: Vector3,
|
|
405
438
|
cartesianModelMatrix: Matrix4,
|
|
406
439
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
@@ -410,7 +443,6 @@ function convertNode(
|
|
|
410
443
|
const transformationMatrix = getCompositeTransformationMatrix(node, matrix);
|
|
411
444
|
|
|
412
445
|
const mesh = node.mesh;
|
|
413
|
-
const images = node.images;
|
|
414
446
|
|
|
415
447
|
if (mesh) {
|
|
416
448
|
convertMesh(
|
|
@@ -426,6 +458,7 @@ function convertNode(
|
|
|
426
458
|
|
|
427
459
|
convertNodes(
|
|
428
460
|
node.children || [],
|
|
461
|
+
images,
|
|
429
462
|
cartographicOrigin,
|
|
430
463
|
cartesianModelMatrix,
|
|
431
464
|
attributesMap,
|
|
@@ -435,9 +468,13 @@ function convertNode(
|
|
|
435
468
|
}
|
|
436
469
|
|
|
437
470
|
/**
|
|
438
|
-
* Convert all primitives of
|
|
439
|
-
* @param mesh - gltf
|
|
440
|
-
* @param
|
|
471
|
+
* Convert all primitives of the mesh
|
|
472
|
+
* @param mesh - gltf mesh data
|
|
473
|
+
* @param images - gltf images array
|
|
474
|
+
* @param cartographicOrigin - cartographic origin of bounding volume
|
|
475
|
+
* @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
|
|
476
|
+
* @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
477
|
+
* attributes
|
|
441
478
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
442
479
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
443
480
|
* @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
@@ -447,7 +484,7 @@ function convertNode(
|
|
|
447
484
|
*/
|
|
448
485
|
function convertMesh(
|
|
449
486
|
mesh: GLTFMeshPostprocessed,
|
|
450
|
-
images:
|
|
487
|
+
images: GLTFImagePostprocessed[],
|
|
451
488
|
cartographicOrigin: Vector3,
|
|
452
489
|
cartesianModelMatrix: Matrix4,
|
|
453
490
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
@@ -456,8 +493,12 @@ function convertMesh(
|
|
|
456
493
|
) {
|
|
457
494
|
for (const primitive of mesh.primitives) {
|
|
458
495
|
let outputAttributes: ConvertedAttributes | null | undefined = null;
|
|
496
|
+
let materialUvRegion: Uint16Array | undefined;
|
|
459
497
|
if (primitive.material) {
|
|
460
|
-
outputAttributes = attributesMap.get(primitive.material.
|
|
498
|
+
outputAttributes = attributesMap.get(primitive.material.uniqueId);
|
|
499
|
+
materialUvRegion = outputAttributes?.mergedMaterials.find(
|
|
500
|
+
({originalMaterialId}) => originalMaterialId === primitive.material?.uniqueId
|
|
501
|
+
)?.uvRegion;
|
|
461
502
|
} else if (attributesMap.has('default')) {
|
|
462
503
|
outputAttributes = attributesMap.get('default');
|
|
463
504
|
}
|
|
@@ -503,6 +544,13 @@ function convertMesh(
|
|
|
503
544
|
flattenColors(attributes.COLOR_0, primitive.indices?.value)
|
|
504
545
|
);
|
|
505
546
|
|
|
547
|
+
if (materialUvRegion) {
|
|
548
|
+
outputAttributes.uvRegions = concatenateTypedArrays(
|
|
549
|
+
outputAttributes.uvRegions,
|
|
550
|
+
createUvRegion(materialUvRegion, primitive.indices?.value)
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
506
554
|
outputAttributes.featureIndicesGroups = outputAttributes.featureIndicesGroups || [];
|
|
507
555
|
outputAttributes.featureIndicesGroups.push(
|
|
508
556
|
flattenBatchIds(getBatchIds(attributes, primitive, images), primitive.indices?.value)
|
|
@@ -653,6 +701,20 @@ function flattenColors(
|
|
|
653
701
|
return newColors;
|
|
654
702
|
}
|
|
655
703
|
|
|
704
|
+
/**
|
|
705
|
+
* Create per-vertex uv-region array
|
|
706
|
+
* @param materialUvRegion - uv-region fragment for a single vertex
|
|
707
|
+
* @param indices - geometry indices data
|
|
708
|
+
* @returns - uv-region array
|
|
709
|
+
*/
|
|
710
|
+
function createUvRegion(materialUvRegion: Uint16Array, indices: Uint8Array): Uint16Array {
|
|
711
|
+
const result = new Uint16Array(indices.length * 4);
|
|
712
|
+
for (let i = 0; i < result.length; i += 4) {
|
|
713
|
+
result.set(materialUvRegion, i);
|
|
714
|
+
}
|
|
715
|
+
return result;
|
|
716
|
+
}
|
|
717
|
+
|
|
656
718
|
/**
|
|
657
719
|
* Flatten batchedIds list based on indices to right ordered array, compatible with i3s
|
|
658
720
|
* @param batchedIds - gltf primitive
|
|
@@ -673,16 +735,16 @@ function flattenBatchIds(batchedIds: number[], indices: Uint8Array): number[] {
|
|
|
673
735
|
|
|
674
736
|
/**
|
|
675
737
|
* Get batchIds for featureIds creation
|
|
676
|
-
* @param attributes
|
|
677
|
-
* @param primitive
|
|
678
|
-
* @param
|
|
738
|
+
* @param attributes - gltf accessors
|
|
739
|
+
* @param primitive - gltf primitive data
|
|
740
|
+
* @param images - gltf texture images
|
|
679
741
|
*/
|
|
680
742
|
function getBatchIds(
|
|
681
743
|
attributes: {
|
|
682
744
|
[key: string]: GLTFAccessorPostprocessed;
|
|
683
745
|
},
|
|
684
|
-
primitive:
|
|
685
|
-
images:
|
|
746
|
+
primitive: GLTFMeshPrimitivePostprocessed,
|
|
747
|
+
images: GLTFImagePostprocessed[]
|
|
686
748
|
): number[] {
|
|
687
749
|
const batchIds: number[] = handleBatchIdsExtensions(attributes, primitive, images);
|
|
688
750
|
|
|
@@ -706,18 +768,127 @@ function getBatchIds(
|
|
|
706
768
|
/**
|
|
707
769
|
* Convert GLTF material to I3S material definitions and textures
|
|
708
770
|
* @param sourceMaterials Source GLTF materials
|
|
771
|
+
* @param shouldMergeMaterials - if true - the converter will try to merge similar materials
|
|
772
|
+
* to be able to merge primitives having those materials
|
|
709
773
|
* @returns Array of Couples I3SMaterialDefinition + texture content
|
|
710
774
|
*/
|
|
711
|
-
function convertMaterials(
|
|
712
|
-
sourceMaterials: GLTFMaterialPostprocessed[] = []
|
|
713
|
-
|
|
714
|
-
|
|
775
|
+
async function convertMaterials(
|
|
776
|
+
sourceMaterials: GLTFMaterialPostprocessed[] = [],
|
|
777
|
+
shouldMergeMaterials: boolean
|
|
778
|
+
): Promise<I3SMaterialWithTexture[]> {
|
|
779
|
+
let materials: I3SMaterialWithTexture[] = [];
|
|
715
780
|
for (const sourceMaterial of sourceMaterials) {
|
|
716
|
-
|
|
781
|
+
materials.push(convertMaterial(sourceMaterial));
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
if (shouldMergeMaterials) {
|
|
785
|
+
materials = await mergeAllMaterials(materials);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return materials;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Merge materials when possible
|
|
793
|
+
* @param materials materials array
|
|
794
|
+
* @returns merged materials array
|
|
795
|
+
*/
|
|
796
|
+
async function mergeAllMaterials(
|
|
797
|
+
materials: I3SMaterialWithTexture[]
|
|
798
|
+
): Promise<I3SMaterialWithTexture[]> {
|
|
799
|
+
const result: I3SMaterialWithTexture[] = [];
|
|
800
|
+
while (materials.length > 0) {
|
|
801
|
+
let newMaterial = materials.splice(0, 1)[0];
|
|
802
|
+
const mergedIndices: number[] = [];
|
|
803
|
+
for (let i = 0; i < materials.length; i++) {
|
|
804
|
+
const material = materials[i];
|
|
805
|
+
if (
|
|
806
|
+
(newMaterial.texture && material.texture) ||
|
|
807
|
+
(!newMaterial.texture && !material.texture)
|
|
808
|
+
) {
|
|
809
|
+
newMaterial = await mergeMaterials(newMaterial, material);
|
|
810
|
+
mergedIndices.push(i);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
if (newMaterial.texture && mergedIndices.length) {
|
|
814
|
+
const newWidth = newMaterial.mergedMaterials?.reduce(
|
|
815
|
+
(accum, {textureSize}) => accum + (textureSize?.width || 0),
|
|
816
|
+
0
|
|
817
|
+
);
|
|
818
|
+
const newHeight = newMaterial.mergedMaterials?.reduce(
|
|
819
|
+
(accum, {textureSize}) => Math.max(accum, textureSize?.height || 0),
|
|
820
|
+
0
|
|
821
|
+
);
|
|
822
|
+
let currentX = -1;
|
|
823
|
+
for (const aTextureMetadata of newMaterial.mergedMaterials) {
|
|
824
|
+
if (aTextureMetadata.textureSize) {
|
|
825
|
+
const newX =
|
|
826
|
+
currentX +
|
|
827
|
+
1 +
|
|
828
|
+
(aTextureMetadata.textureSize.width / newWidth) *
|
|
829
|
+
2 ** (Uint16Array.BYTES_PER_ELEMENT * 8) -
|
|
830
|
+
1;
|
|
831
|
+
aTextureMetadata.uvRegion = new Uint16Array([
|
|
832
|
+
currentX + 1,
|
|
833
|
+
0,
|
|
834
|
+
newX,
|
|
835
|
+
(aTextureMetadata.textureSize.height / newHeight) *
|
|
836
|
+
2 ** (Uint16Array.BYTES_PER_ELEMENT * 8) -
|
|
837
|
+
1
|
|
838
|
+
]);
|
|
839
|
+
currentX = newX;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
newMaterial.texture.image.width = newWidth;
|
|
844
|
+
newMaterial.texture.image.height = newHeight;
|
|
845
|
+
}
|
|
846
|
+
for (const index of mergedIndices.reverse()) {
|
|
847
|
+
materials.splice(index, 1);
|
|
848
|
+
}
|
|
849
|
+
result.push(newMaterial);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (!result.length) {
|
|
853
|
+
result.push({
|
|
854
|
+
material: getDefaultMaterial(),
|
|
855
|
+
mergedMaterials: [{originalMaterialId: 'default'}]
|
|
856
|
+
});
|
|
717
857
|
}
|
|
718
858
|
return result;
|
|
719
859
|
}
|
|
720
860
|
|
|
861
|
+
/**
|
|
862
|
+
* Merge 2 materials including texture
|
|
863
|
+
* @param material1
|
|
864
|
+
* @param material2
|
|
865
|
+
* @returns
|
|
866
|
+
*/
|
|
867
|
+
async function mergeMaterials(
|
|
868
|
+
material1: I3SMaterialWithTexture,
|
|
869
|
+
material2: I3SMaterialWithTexture
|
|
870
|
+
): Promise<I3SMaterialWithTexture> {
|
|
871
|
+
if (
|
|
872
|
+
material1.texture?.bufferView &&
|
|
873
|
+
material2.texture?.bufferView &&
|
|
874
|
+
material1.mergedMaterials &&
|
|
875
|
+
material2.mergedMaterials
|
|
876
|
+
) {
|
|
877
|
+
const buffer1 = Buffer.from(material1.texture.bufferView.data);
|
|
878
|
+
const buffer2 = Buffer.from(material2.texture.bufferView.data);
|
|
879
|
+
// @ts-ignore
|
|
880
|
+
const {joinImages} = await import('join-images');
|
|
881
|
+
const sharpData = await joinImages([buffer1, buffer2], {direction: 'horizontal'});
|
|
882
|
+
material1.texture.bufferView.data = await sharpData
|
|
883
|
+
.toFormat(material1.texture.mimeType === 'image/png' ? 'png' : 'jpeg')
|
|
884
|
+
.toBuffer();
|
|
885
|
+
// @ts-ignore
|
|
886
|
+
material1.material.pbrMetallicRoughness.baseColorTexture.textureSetDefinitionId = 1;
|
|
887
|
+
}
|
|
888
|
+
material1.mergedMaterials = material1.mergedMaterials.concat(material2.mergedMaterials);
|
|
889
|
+
return material1;
|
|
890
|
+
}
|
|
891
|
+
|
|
721
892
|
/**
|
|
722
893
|
* Convert texture and material from gltf 2.0 material object
|
|
723
894
|
* @param sourceMaterial - material object
|
|
@@ -756,6 +927,9 @@ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterial
|
|
|
756
927
|
};
|
|
757
928
|
}
|
|
758
929
|
|
|
930
|
+
const uniqueId = uuidv4();
|
|
931
|
+
sourceMaterial.uniqueId = uniqueId;
|
|
932
|
+
let mergedMaterials: MergedMaterial[] = [{originalMaterialId: uniqueId}];
|
|
759
933
|
if (!texture) {
|
|
760
934
|
// Should use default baseColorFactor if it is not present in source material
|
|
761
935
|
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-pbrmetallicroughness
|
|
@@ -767,9 +941,11 @@ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterial
|
|
|
767
941
|
number,
|
|
768
942
|
number
|
|
769
943
|
]) || undefined;
|
|
944
|
+
} else {
|
|
945
|
+
mergedMaterials[0].textureSize = {width: texture.image.width, height: texture.image.height};
|
|
770
946
|
}
|
|
771
947
|
|
|
772
|
-
return {material, texture};
|
|
948
|
+
return {material, texture, mergedMaterials};
|
|
773
949
|
}
|
|
774
950
|
|
|
775
951
|
/**
|
|
@@ -912,7 +1088,9 @@ function extractSharedResourcesMaterialInfo(
|
|
|
912
1088
|
const specular = dielectricSpecular.lerp(dielectricSpecular, baseColorVector, metallicFactor);
|
|
913
1089
|
return {
|
|
914
1090
|
params: {
|
|
1091
|
+
// @ts-expect-error NumericArray
|
|
915
1092
|
diffuse: diffuse.toArray(),
|
|
1093
|
+
// @ts-expect-error NumericArray
|
|
916
1094
|
specular: specular.toArray(),
|
|
917
1095
|
renderMode: 'solid'
|
|
918
1096
|
}
|
|
@@ -944,13 +1122,13 @@ function extractSharedResourcesTextureInfo(
|
|
|
944
1122
|
}
|
|
945
1123
|
|
|
946
1124
|
/**
|
|
947
|
-
* Formula for
|
|
1125
|
+
* Formula for calculating imageId:
|
|
948
1126
|
* https://github.com/Esri/i3s-spec/blob/0a6366a9249b831db8436c322f8d27521e86cf07/format/Indexed%203d%20Scene%20Layer%20Format%20Specification.md#generating-image-ids
|
|
949
1127
|
* @param texture - texture image info
|
|
950
1128
|
* @param nodeId - I3S node ID
|
|
951
1129
|
* @returns calculate image ID according to the spec
|
|
952
1130
|
*/
|
|
953
|
-
function generateImageId(texture: GLTFTexturePostprocessed, nodeId) {
|
|
1131
|
+
function generateImageId(texture: GLTFTexturePostprocessed, nodeId: number) {
|
|
954
1132
|
const {width, height} = texture.source?.image;
|
|
955
1133
|
const levelCountOfTexture = 1;
|
|
956
1134
|
const indexOfLevel = 0;
|
|
@@ -1051,49 +1229,66 @@ function replaceIndicesByUnique(indicesArray, featureMap) {
|
|
|
1051
1229
|
}
|
|
1052
1230
|
|
|
1053
1231
|
/**
|
|
1054
|
-
* Convert
|
|
1055
|
-
* @param {Object} batchTable - table with metadata for particular feature.
|
|
1232
|
+
* Convert property table data to attribute buffers.
|
|
1056
1233
|
* @param {Array} featureIds
|
|
1234
|
+
* @param {Object} propertyTable - table with metadata for particular feature.
|
|
1057
1235
|
* @param {Array} attributeStorageInfo
|
|
1058
1236
|
* @returns {Array} - Array of file buffers.
|
|
1059
1237
|
*/
|
|
1060
|
-
function
|
|
1238
|
+
function convertPropertyTableToAttributeBuffers(
|
|
1239
|
+
featureIds: number[],
|
|
1240
|
+
propertyTable: FeatureTableJson,
|
|
1241
|
+
attributeStorageInfo: AttributeStorageInfo[]
|
|
1242
|
+
) {
|
|
1061
1243
|
const attributeBuffers: ArrayBuffer[] = [];
|
|
1062
1244
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
};
|
|
1245
|
+
const needFlattenPropertyTable = checkPropertiesLength(featureIds, propertyTable);
|
|
1246
|
+
const properties = needFlattenPropertyTable
|
|
1247
|
+
? flattenPropertyTableByFeatureIds(featureIds, propertyTable)
|
|
1248
|
+
: propertyTable;
|
|
1068
1249
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
switch (type) {
|
|
1075
|
-
case OBJECT_ID_TYPE:
|
|
1076
|
-
case SHORT_INT_TYPE:
|
|
1077
|
-
attributeBuffer = generateShortIntegerAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1078
|
-
break;
|
|
1079
|
-
case DOUBLE_TYPE:
|
|
1080
|
-
attributeBuffer = generateDoubleAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1081
|
-
break;
|
|
1082
|
-
case STRING_TYPE:
|
|
1083
|
-
attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1084
|
-
break;
|
|
1085
|
-
default:
|
|
1086
|
-
attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1087
|
-
}
|
|
1250
|
+
const propertyTableWithObjectIds = {
|
|
1251
|
+
OBJECTID: featureIds,
|
|
1252
|
+
...properties
|
|
1253
|
+
};
|
|
1088
1254
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1255
|
+
for (const propertyName in propertyTableWithObjectIds) {
|
|
1256
|
+
const type = getAttributeType(propertyName, attributeStorageInfo);
|
|
1257
|
+
const value = propertyTableWithObjectIds[propertyName];
|
|
1258
|
+
const attributeBuffer = generateAttributeBuffer(type, value);
|
|
1259
|
+
|
|
1260
|
+
attributeBuffers.push(attributeBuffer);
|
|
1093
1261
|
}
|
|
1094
1262
|
|
|
1095
1263
|
return attributeBuffers;
|
|
1096
1264
|
}
|
|
1265
|
+
|
|
1266
|
+
/**
|
|
1267
|
+
* Generates attribute buffer based on attribute type
|
|
1268
|
+
* @param type
|
|
1269
|
+
* @param value
|
|
1270
|
+
*/
|
|
1271
|
+
function generateAttributeBuffer(type: string, value: any): ArrayBuffer {
|
|
1272
|
+
let attributeBuffer: ArrayBuffer;
|
|
1273
|
+
|
|
1274
|
+
switch (type) {
|
|
1275
|
+
case OBJECT_ID_TYPE:
|
|
1276
|
+
case SHORT_INT_TYPE:
|
|
1277
|
+
attributeBuffer = generateShortIntegerAttributeBuffer(value);
|
|
1278
|
+
break;
|
|
1279
|
+
case DOUBLE_TYPE:
|
|
1280
|
+
attributeBuffer = generateDoubleAttributeBuffer(value);
|
|
1281
|
+
break;
|
|
1282
|
+
case STRING_TYPE:
|
|
1283
|
+
attributeBuffer = generateStringAttributeBuffer(value);
|
|
1284
|
+
break;
|
|
1285
|
+
default:
|
|
1286
|
+
attributeBuffer = generateStringAttributeBuffer(value);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
return attributeBuffer;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1097
1292
|
/**
|
|
1098
1293
|
* Return attribute type.
|
|
1099
1294
|
* @param {String} key
|
|
@@ -1186,7 +1381,7 @@ async function generateCompressedGeometry(
|
|
|
1186
1381
|
attributes,
|
|
1187
1382
|
dracoWorkerSoure
|
|
1188
1383
|
) {
|
|
1189
|
-
const {positions, normals, texCoords, colors, featureIds, faceRange} = attributes;
|
|
1384
|
+
const {positions, normals, texCoords, colors, uvRegions, featureIds, faceRange} = attributes;
|
|
1190
1385
|
const indices = new Uint32Array(vertexCount);
|
|
1191
1386
|
|
|
1192
1387
|
for (let index = 0; index < indices.length; index++) {
|
|
@@ -1205,6 +1400,7 @@ async function generateCompressedGeometry(
|
|
|
1205
1400
|
colors: TypedArray;
|
|
1206
1401
|
'feature-index': TypedArray;
|
|
1207
1402
|
texCoords?: TypedArray;
|
|
1403
|
+
'uv-region'?: TypedArray;
|
|
1208
1404
|
} = {
|
|
1209
1405
|
positions,
|
|
1210
1406
|
normals,
|
|
@@ -1223,6 +1419,13 @@ async function generateCompressedGeometry(
|
|
|
1223
1419
|
}
|
|
1224
1420
|
};
|
|
1225
1421
|
|
|
1422
|
+
if (uvRegions.length) {
|
|
1423
|
+
compressedAttributes['uv-region'] = uvRegions;
|
|
1424
|
+
attributesMetadata['uv-region'] = {
|
|
1425
|
+
'i3s-attribute-type': 'uv-region'
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1226
1429
|
return encode({attributes: compressedAttributes, indices}, DracoWriterWorker, {
|
|
1227
1430
|
...DracoWriterWorker.options,
|
|
1228
1431
|
source: dracoWorkerSoure,
|
|
@@ -1257,3 +1460,97 @@ function generateFeatureIndexAttribute(featureIndex, faceRange) {
|
|
|
1257
1460
|
|
|
1258
1461
|
return orderedFeatureIndices;
|
|
1259
1462
|
}
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Find property table in tile
|
|
1466
|
+
* For example it can be batchTable for b3dm files or property table in gLTF extension.
|
|
1467
|
+
* @param sourceTile
|
|
1468
|
+
* @return batch table from b3dm / feature properties from EXT_FEATURE_METADATA
|
|
1469
|
+
*/
|
|
1470
|
+
export function getPropertyTable(tileContent: B3DMContent): FeatureTableJson | null {
|
|
1471
|
+
const batchTableJson = tileContent?.batchTableJson;
|
|
1472
|
+
|
|
1473
|
+
if (batchTableJson) {
|
|
1474
|
+
return batchTableJson;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
const {extensionName, extension} = getPropertyTableExtension(tileContent);
|
|
1478
|
+
|
|
1479
|
+
switch (extensionName) {
|
|
1480
|
+
case EXT_MESH_FEATURES: {
|
|
1481
|
+
console.warn('The I3S converter does not yet support the EXT_mesh_features extension');
|
|
1482
|
+
return null;
|
|
1483
|
+
}
|
|
1484
|
+
case EXT_FEATURE_METADATA: {
|
|
1485
|
+
return getPropertyTableFromExtFeatureMetadata(extension);
|
|
1486
|
+
}
|
|
1487
|
+
default:
|
|
1488
|
+
return null;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
* Check extensions which can be with property table inside.
|
|
1494
|
+
* @param sourceTile
|
|
1495
|
+
*/
|
|
1496
|
+
function getPropertyTableExtension(tileContent: B3DMContent) {
|
|
1497
|
+
const extensionsWithPropertyTables = [EXT_FEATURE_METADATA, EXT_MESH_FEATURES];
|
|
1498
|
+
const extensionsUsed = tileContent?.gltf?.extensionsUsed;
|
|
1499
|
+
|
|
1500
|
+
if (!extensionsUsed) {
|
|
1501
|
+
return {extensionName: null, extension: null};
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
let extensionName: string = '';
|
|
1505
|
+
|
|
1506
|
+
for (const extensionItem of tileContent?.gltf?.extensionsUsed || []) {
|
|
1507
|
+
if (extensionsWithPropertyTables.includes(extensionItem)) {
|
|
1508
|
+
extensionName = extensionItem;
|
|
1509
|
+
break;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
const extension = tileContent?.gltf?.extensions?.[extensionName];
|
|
1514
|
+
|
|
1515
|
+
return {extensionName, extension};
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* Handle EXT_feature_metadata to get property table
|
|
1520
|
+
* @param extension
|
|
1521
|
+
* TODO add EXT_feature_metadata feature textures support.
|
|
1522
|
+
*/
|
|
1523
|
+
function getPropertyTableFromExtFeatureMetadata(
|
|
1524
|
+
extension: GLTF_EXT_feature_metadata
|
|
1525
|
+
): FeatureTableJson | null {
|
|
1526
|
+
if (extension?.featureTextures) {
|
|
1527
|
+
console.warn(
|
|
1528
|
+
'The I3S converter does not yet support the EXT_feature_metadata feature textures'
|
|
1529
|
+
);
|
|
1530
|
+
return null;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
if (extension?.featureTables) {
|
|
1534
|
+
/**
|
|
1535
|
+
* Take only first feature table to generate attributes storage info object.
|
|
1536
|
+
* TODO: Think about getting data from all feature tables?
|
|
1537
|
+
* It can be tricky just because 3dTiles is able to have multiple featureId attributes and multiple feature tables.
|
|
1538
|
+
* In I3S we should decide which featureIds attribute will be passed to geometry data.
|
|
1539
|
+
*/
|
|
1540
|
+
const firstFeatureTableName = Object.keys(extension.featureTables)?.[0];
|
|
1541
|
+
|
|
1542
|
+
if (firstFeatureTableName) {
|
|
1543
|
+
const featureTable = extension?.featureTables[firstFeatureTableName];
|
|
1544
|
+
const propertyTable = {};
|
|
1545
|
+
|
|
1546
|
+
for (const propertyName in featureTable.properties) {
|
|
1547
|
+
propertyTable[propertyName] = featureTable.properties[propertyName].data;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
return propertyTable;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
console.warn("The I3S converter couldn't handle EXT_feature_metadata extension");
|
|
1555
|
+
return null;
|
|
1556
|
+
}
|