@loaders.gl/tile-converter 3.2.12 → 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 +43 -8
- 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 +58405 -61237
- 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 +50 -60
- 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 +124 -0
- package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
- package/dist/es5/i3s-converter/helpers/coordinate-converter.js +2 -19
- 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 +516 -356
- package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/es5/i3s-converter/helpers/gltf-attributes.js +57 -43
- 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 +462 -208
- package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
- package/dist/es5/i3s-converter/i3s-converter.js +722 -1153
- 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 +41 -82
- 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 +46 -40
- 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 +113 -0
- package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
- package/dist/esm/i3s-converter/helpers/coordinate-converter.js +5 -6
- 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 +295 -196
- package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
- package/dist/esm/i3s-converter/helpers/gltf-attributes.js +59 -34
- 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 +216 -491
- 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 +27 -38
- 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 +11 -0
- package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -0
- package/dist/i3s-converter/helpers/batch-ids-extensions.js +141 -0
- 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/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 +349 -99
- package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
- package/dist/i3s-converter/helpers/gltf-attributes.js +53 -21
- 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 +218 -403
- 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 +38 -8
- 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 -3
- package/dist/lib/utils/write-queue.d.ts.map +1 -1
- package/dist/lib/utils/write-queue.js +21 -16
- 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 +54 -8
- 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 +206 -0
- package/src/i3s-converter/helpers/coordinate-converter.ts +2 -2
- 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 +423 -111
- package/src/i3s-converter/helpers/gltf-attributes.ts +59 -24
- 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 +264 -487
- 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 +33 -2
- package/src/lib/utils/file-utils.ts +62 -7
- package/src/lib/utils/write-queue.ts +42 -19
- 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,3 +1,15 @@
|
|
|
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';
|
|
12
|
+
|
|
1
13
|
import {Vector3, Matrix4, Vector4} from '@math.gl/core';
|
|
2
14
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
3
15
|
|
|
@@ -5,16 +17,16 @@ import {DracoWriterWorker} from '@loaders.gl/draco';
|
|
|
5
17
|
import {assert, encode} from '@loaders.gl/core';
|
|
6
18
|
import {concatenateArrayBuffers, concatenateTypedArrays} from '@loaders.gl/loader-utils';
|
|
7
19
|
import md5 from 'md5';
|
|
20
|
+
import {v4 as uuidv4} from 'uuid';
|
|
8
21
|
import {generateAttributes} from './geometry-attributes';
|
|
9
22
|
import {createBoundingVolumesFromGeometry} from './coordinate-converter';
|
|
10
23
|
import {
|
|
11
24
|
ConvertedAttributes,
|
|
12
25
|
I3SConvertedResources,
|
|
13
26
|
I3SMaterialWithTexture,
|
|
27
|
+
MergedMaterial,
|
|
14
28
|
SharedResourcesArrays
|
|
15
29
|
} from '../types';
|
|
16
|
-
import {B3DMContent} from '@loaders.gl/3d-tiles';
|
|
17
|
-
import {GLTFMaterialPostprocessed, GLTFNodePostprocessed} from '@loaders.gl/gltf';
|
|
18
30
|
import {
|
|
19
31
|
AttributeStorageInfo,
|
|
20
32
|
I3SMaterialDefinition,
|
|
@@ -23,13 +35,11 @@ import {
|
|
|
23
35
|
} from '@loaders.gl/i3s';
|
|
24
36
|
import {TypedArray} from '@loaders.gl/schema';
|
|
25
37
|
import {Geoid} from '@math.gl/geoid';
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
GLTFMeshPostprocessed,
|
|
29
|
-
GLTFTexturePostprocessed
|
|
30
|
-
} from 'modules/gltf/src/lib/types/gltf-types';
|
|
31
|
-
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';
|
|
32
40
|
import {prepareDataForAttributesConversion} from './gltf-attributes';
|
|
41
|
+
import {handleBatchIdsExtensions} from './batch-ids-extensions';
|
|
42
|
+
import {checkPropertiesLength, flattenPropertyTableByFeatureIds} from './feature-attributes';
|
|
33
43
|
|
|
34
44
|
// Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
|
|
35
45
|
const DEFAULT_ROUGHNESS_FACTOR = 1;
|
|
@@ -50,90 +60,89 @@ const OBJECT_ID_TYPE = 'Oid32';
|
|
|
50
60
|
*/
|
|
51
61
|
const BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES = ['CUSTOM_ATTRIBUTE_2', '_BATCHID', 'BATCHID'];
|
|
52
62
|
|
|
63
|
+
const EXT_FEATURE_METADATA = 'EXT_feature_metadata';
|
|
64
|
+
const EXT_MESH_FEATURES = 'EXT_mesh_features';
|
|
65
|
+
|
|
53
66
|
let scratchVector = new Vector3();
|
|
54
67
|
|
|
55
68
|
/**
|
|
56
69
|
* Convert binary data from b3dm file to i3s resources
|
|
57
70
|
*
|
|
58
71
|
* @param tileContent - 3d tile content
|
|
59
|
-
* @param
|
|
72
|
+
* @param addNodeToNodePage - function to add new node to node pages
|
|
73
|
+
* @param propertyTable - batch table (corresponding to feature attributes data)
|
|
60
74
|
* @param featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
|
|
61
75
|
* @param attributeStorageInfo - attributes metadata from 3DSceneLayer json
|
|
62
76
|
* @param draco - is converter should create draco compressed geometry
|
|
63
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
|
|
64
79
|
* @param geoidHeightModel - model to convert elevation from elipsoidal to geoid
|
|
80
|
+
* @param workerSource - source code of used workers
|
|
65
81
|
* @returns Array of node resources to create one or more i3s nodes
|
|
66
82
|
*/
|
|
67
83
|
export default async function convertB3dmToI3sGeometry(
|
|
68
84
|
tileContent: B3DMContent,
|
|
69
|
-
|
|
85
|
+
addNodeToNodePage: () => Promise<number>,
|
|
86
|
+
propertyTable: FeatureTableJson | null,
|
|
70
87
|
featuresHashArray: string[],
|
|
71
88
|
attributeStorageInfo: AttributeStorageInfo[] | undefined,
|
|
72
89
|
draco: boolean,
|
|
73
90
|
generateBoundingVolumes: boolean,
|
|
91
|
+
shouldMergeMaterials: boolean,
|
|
74
92
|
geoidHeightModel: Geoid,
|
|
75
93
|
workerSource: {[key: string]: string}
|
|
76
|
-
) {
|
|
94
|
+
): Promise<I3SConvertedResources[] | null> {
|
|
77
95
|
const useCartesianPositions = generateBoundingVolumes;
|
|
78
|
-
const materialAndTextureList: I3SMaterialWithTexture[] = convertMaterials(
|
|
79
|
-
tileContent.gltf?.materials
|
|
96
|
+
const materialAndTextureList: I3SMaterialWithTexture[] = await convertMaterials(
|
|
97
|
+
tileContent.gltf?.materials,
|
|
98
|
+
shouldMergeMaterials
|
|
80
99
|
);
|
|
81
100
|
|
|
82
101
|
const dataForAttributesConversion = prepareDataForAttributesConversion(tileContent);
|
|
83
|
-
|
|
84
102
|
const convertedAttributesMap: Map<string, ConvertedAttributes> = await convertAttributes(
|
|
85
103
|
dataForAttributesConversion,
|
|
104
|
+
materialAndTextureList,
|
|
86
105
|
useCartesianPositions
|
|
87
106
|
);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
+
// });
|
|
96
115
|
|
|
97
116
|
if (generateBoundingVolumes) {
|
|
98
117
|
_generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeightModel);
|
|
99
118
|
}
|
|
100
119
|
|
|
101
|
-
if (convertedAttributesMap.has('default')) {
|
|
102
|
-
materialAndTextureList.push({
|
|
103
|
-
material: getDefaultMaterial()
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
120
|
const result: I3SConvertedResources[] = [];
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
materials.push({id: 'default'});
|
|
112
|
-
}
|
|
113
|
-
for (let i = 0; i < materials.length; i++) {
|
|
114
|
-
const sourceMaterial = materials[i];
|
|
115
|
-
if (!convertedAttributesMap.has(sourceMaterial.id)) {
|
|
121
|
+
for (const materialAndTexture of materialAndTextureList) {
|
|
122
|
+
const originarMaterialId = materialAndTexture.mergedMaterials[0].originalMaterialId;
|
|
123
|
+
if (!convertedAttributesMap.has(originarMaterialId)) {
|
|
116
124
|
continue; // eslint-disable-line no-continue
|
|
117
125
|
}
|
|
118
|
-
const convertedAttributes = convertedAttributesMap.get(
|
|
126
|
+
const convertedAttributes = convertedAttributesMap.get(originarMaterialId);
|
|
119
127
|
if (!convertedAttributes) {
|
|
120
128
|
continue;
|
|
121
129
|
}
|
|
122
|
-
const {material, texture} =
|
|
130
|
+
const {material, texture} = materialAndTexture;
|
|
131
|
+
const nodeId = await addNodeToNodePage();
|
|
123
132
|
result.push(
|
|
124
133
|
await _makeNodeResources({
|
|
125
134
|
convertedAttributes,
|
|
126
135
|
material,
|
|
127
136
|
texture,
|
|
128
137
|
tileContent,
|
|
129
|
-
nodeId
|
|
138
|
+
nodeId,
|
|
130
139
|
featuresHashArray,
|
|
140
|
+
propertyTable,
|
|
131
141
|
attributeStorageInfo,
|
|
132
142
|
draco,
|
|
133
143
|
workerSource
|
|
134
144
|
})
|
|
135
145
|
);
|
|
136
|
-
nodesCounter++;
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
if (!result.length) {
|
|
@@ -180,8 +189,10 @@ function _generateBoundingVolumesFromGeometry(
|
|
|
180
189
|
* @param params.tileContent - B3DM decoded content
|
|
181
190
|
* @param params.nodeId - new node ID
|
|
182
191
|
* @param params.featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
|
|
183
|
-
* @param params.
|
|
192
|
+
* @param params.propertyTable - batch table (corresponding to feature attributes data)
|
|
193
|
+
* @param params.attributeStorageInfo - attributes metadata from 3DSceneLayer json
|
|
184
194
|
* @param params.draco - is converter should create draco compressed geometry
|
|
195
|
+
* @param params.workerSource - source code of used workers
|
|
185
196
|
* @returns Array of I3S node resources
|
|
186
197
|
*/
|
|
187
198
|
async function _makeNodeResources({
|
|
@@ -191,6 +202,7 @@ async function _makeNodeResources({
|
|
|
191
202
|
tileContent,
|
|
192
203
|
nodeId,
|
|
193
204
|
featuresHashArray,
|
|
205
|
+
propertyTable,
|
|
194
206
|
attributeStorageInfo,
|
|
195
207
|
draco,
|
|
196
208
|
workerSource
|
|
@@ -201,13 +213,14 @@ async function _makeNodeResources({
|
|
|
201
213
|
tileContent: B3DMContent;
|
|
202
214
|
nodeId: number;
|
|
203
215
|
featuresHashArray: string[];
|
|
216
|
+
propertyTable: FeatureTableJson | null;
|
|
204
217
|
attributeStorageInfo?: AttributeStorageInfo[];
|
|
205
218
|
draco: boolean;
|
|
206
219
|
workerSource: {[key: string]: string};
|
|
207
220
|
}): Promise<I3SConvertedResources> {
|
|
208
221
|
const boundingVolumes = convertedAttributes.boundingVolumes;
|
|
209
222
|
const vertexCount = convertedAttributes.positions.length / VALUES_PER_VERTEX;
|
|
210
|
-
const {faceRange, featureIds, positions, normals, colors, texCoords, featureCount} =
|
|
223
|
+
const {faceRange, featureIds, positions, normals, colors, uvRegions, texCoords, featureCount} =
|
|
211
224
|
generateAttributes(convertedAttributes);
|
|
212
225
|
|
|
213
226
|
if (tileContent.batchTableJson) {
|
|
@@ -230,6 +243,7 @@ async function _makeNodeResources({
|
|
|
230
243
|
normals.buffer,
|
|
231
244
|
texture ? texCoords.buffer : new ArrayBuffer(0),
|
|
232
245
|
colors.buffer,
|
|
246
|
+
uvRegions,
|
|
233
247
|
typedFeatureIds.buffer,
|
|
234
248
|
faceRange.buffer
|
|
235
249
|
)
|
|
@@ -243,6 +257,7 @@ async function _makeNodeResources({
|
|
|
243
257
|
normals,
|
|
244
258
|
texCoords: texture ? texCoords : new Float32Array(0),
|
|
245
259
|
colors,
|
|
260
|
+
uvRegions,
|
|
246
261
|
featureIds,
|
|
247
262
|
faceRange
|
|
248
263
|
},
|
|
@@ -250,16 +265,22 @@ async function _makeNodeResources({
|
|
|
250
265
|
)
|
|
251
266
|
: null;
|
|
252
267
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
268
|
+
let attributes: ArrayBuffer[] = [];
|
|
269
|
+
|
|
270
|
+
if (attributeStorageInfo && propertyTable) {
|
|
271
|
+
attributes = convertPropertyTableToAttributeBuffers(
|
|
272
|
+
featureIds,
|
|
273
|
+
propertyTable,
|
|
274
|
+
attributeStorageInfo
|
|
275
|
+
);
|
|
276
|
+
}
|
|
258
277
|
|
|
259
278
|
return {
|
|
279
|
+
nodeId,
|
|
260
280
|
geometry: fileBuffer,
|
|
261
281
|
compressedGeometry,
|
|
262
282
|
texture,
|
|
283
|
+
hasUvRegions: Boolean(uvRegions.length),
|
|
263
284
|
sharedResources: getSharedResources(tileContent.gltf?.materials || [], nodeId),
|
|
264
285
|
meshMaterial: material,
|
|
265
286
|
vertexCount,
|
|
@@ -271,32 +292,40 @@ async function _makeNodeResources({
|
|
|
271
292
|
|
|
272
293
|
/**
|
|
273
294
|
* Convert attributes from the gltf nodes tree to i3s plain geometry
|
|
274
|
-
* @param
|
|
295
|
+
* @param attributesData - geometry attributes from gltf
|
|
296
|
+
* @param materialAndTextureList - array of data about materials and textures of the content
|
|
275
297
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
276
298
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
277
299
|
* @returns map of converted geometry attributes
|
|
278
300
|
*/
|
|
279
301
|
export async function convertAttributes(
|
|
280
302
|
attributesData: B3DMAttributesData,
|
|
303
|
+
materialAndTextureList: I3SMaterialWithTexture[],
|
|
281
304
|
useCartesianPositions: boolean
|
|
282
305
|
): Promise<Map<string, ConvertedAttributes>> {
|
|
283
|
-
const {
|
|
306
|
+
const {nodes, images, cartographicOrigin, cartesianModelMatrix} = attributesData;
|
|
284
307
|
const attributesMap = new Map<string, ConvertedAttributes>();
|
|
285
308
|
|
|
286
|
-
for (const
|
|
287
|
-
|
|
309
|
+
for (const materialAndTexture of materialAndTextureList) {
|
|
310
|
+
const attributes = {
|
|
288
311
|
positions: new Float32Array(0),
|
|
289
312
|
normals: new Float32Array(0),
|
|
290
313
|
texCoords: new Float32Array(0),
|
|
291
314
|
colors: new Uint8Array(0),
|
|
315
|
+
uvRegions: new Uint16Array(0),
|
|
292
316
|
featureIndicesGroups: [],
|
|
293
317
|
featureIndices: [],
|
|
294
|
-
boundingVolumes: null
|
|
295
|
-
|
|
318
|
+
boundingVolumes: null,
|
|
319
|
+
mergedMaterials: materialAndTexture.mergedMaterials
|
|
320
|
+
};
|
|
321
|
+
for (const mergedMaterial of materialAndTexture.mergedMaterials) {
|
|
322
|
+
attributesMap.set(mergedMaterial.originalMaterialId, attributes);
|
|
323
|
+
}
|
|
296
324
|
}
|
|
297
325
|
|
|
298
326
|
convertNodes(
|
|
299
327
|
nodes,
|
|
328
|
+
images,
|
|
300
329
|
cartographicOrigin,
|
|
301
330
|
cartesianModelMatrix,
|
|
302
331
|
attributesMap,
|
|
@@ -327,7 +356,9 @@ export async function convertAttributes(
|
|
|
327
356
|
* Gltf has hierarchical structure of nodes. This function converts nodes starting from those which are in gltf scene object.
|
|
328
357
|
* The goal is applying tranformation matrix for all children. Functions "convertNodes" and "convertNode" work together recursively.
|
|
329
358
|
* @param nodes - gltf nodes array
|
|
330
|
-
* @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
|
|
331
362
|
* @param attributesMap - for recursive concatenation of attributes
|
|
332
363
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
333
364
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
@@ -336,6 +367,7 @@ export async function convertAttributes(
|
|
|
336
367
|
*/
|
|
337
368
|
function convertNodes(
|
|
338
369
|
nodes: GLTFNodePostprocessed[],
|
|
370
|
+
images: GLTFImagePostprocessed[],
|
|
339
371
|
cartographicOrigin: Vector3,
|
|
340
372
|
cartesianModelMatrix: Matrix4,
|
|
341
373
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
@@ -346,6 +378,7 @@ function convertNodes(
|
|
|
346
378
|
for (const node of nodes) {
|
|
347
379
|
convertNode(
|
|
348
380
|
node,
|
|
381
|
+
images,
|
|
349
382
|
cartographicOrigin,
|
|
350
383
|
cartesianModelMatrix,
|
|
351
384
|
attributesMap,
|
|
@@ -362,7 +395,7 @@ function convertNodes(
|
|
|
362
395
|
* @param node
|
|
363
396
|
* @param matrix
|
|
364
397
|
*/
|
|
365
|
-
function getCompositeTransformationMatrix(node, matrix) {
|
|
398
|
+
function getCompositeTransformationMatrix(node: GLTFNodePostprocessed, matrix: Matrix4) {
|
|
366
399
|
let transformationMatrix = matrix;
|
|
367
400
|
|
|
368
401
|
const {matrix: nodeMatrix, rotation, scale, translation} = node;
|
|
@@ -389,7 +422,9 @@ function getCompositeTransformationMatrix(node, matrix) {
|
|
|
389
422
|
/**
|
|
390
423
|
* Convert all primitives of node and all children nodes
|
|
391
424
|
* @param node - gltf node
|
|
392
|
-
* @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
|
|
393
428
|
* @param {Map} attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
394
429
|
* attributes
|
|
395
430
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
@@ -398,6 +433,7 @@ function getCompositeTransformationMatrix(node, matrix) {
|
|
|
398
433
|
*/
|
|
399
434
|
function convertNode(
|
|
400
435
|
node: GLTFNodePostprocessed,
|
|
436
|
+
images: GLTFImagePostprocessed[],
|
|
401
437
|
cartographicOrigin: Vector3,
|
|
402
438
|
cartesianModelMatrix: Matrix4,
|
|
403
439
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
@@ -407,9 +443,11 @@ function convertNode(
|
|
|
407
443
|
const transformationMatrix = getCompositeTransformationMatrix(node, matrix);
|
|
408
444
|
|
|
409
445
|
const mesh = node.mesh;
|
|
446
|
+
|
|
410
447
|
if (mesh) {
|
|
411
448
|
convertMesh(
|
|
412
449
|
mesh,
|
|
450
|
+
images,
|
|
413
451
|
cartographicOrigin,
|
|
414
452
|
cartesianModelMatrix,
|
|
415
453
|
attributesMap,
|
|
@@ -420,6 +458,7 @@ function convertNode(
|
|
|
420
458
|
|
|
421
459
|
convertNodes(
|
|
422
460
|
node.children || [],
|
|
461
|
+
images,
|
|
423
462
|
cartographicOrigin,
|
|
424
463
|
cartesianModelMatrix,
|
|
425
464
|
attributesMap,
|
|
@@ -429,9 +468,13 @@ function convertNode(
|
|
|
429
468
|
}
|
|
430
469
|
|
|
431
470
|
/**
|
|
432
|
-
* Convert all primitives of
|
|
433
|
-
* @param mesh - gltf
|
|
434
|
-
* @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
|
|
435
478
|
* @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
|
|
436
479
|
* Cartesian coordinates will be required for creating bounding voulmest from geometry positions
|
|
437
480
|
* @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
|
|
@@ -441,6 +484,7 @@ function convertNode(
|
|
|
441
484
|
*/
|
|
442
485
|
function convertMesh(
|
|
443
486
|
mesh: GLTFMeshPostprocessed,
|
|
487
|
+
images: GLTFImagePostprocessed[],
|
|
444
488
|
cartographicOrigin: Vector3,
|
|
445
489
|
cartesianModelMatrix: Matrix4,
|
|
446
490
|
attributesMap: Map<string, ConvertedAttributes>,
|
|
@@ -449,8 +493,12 @@ function convertMesh(
|
|
|
449
493
|
) {
|
|
450
494
|
for (const primitive of mesh.primitives) {
|
|
451
495
|
let outputAttributes: ConvertedAttributes | null | undefined = null;
|
|
496
|
+
let materialUvRegion: Uint16Array | undefined;
|
|
452
497
|
if (primitive.material) {
|
|
453
|
-
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;
|
|
454
502
|
} else if (attributesMap.has('default')) {
|
|
455
503
|
outputAttributes = attributesMap.get('default');
|
|
456
504
|
}
|
|
@@ -496,9 +544,16 @@ function convertMesh(
|
|
|
496
544
|
flattenColors(attributes.COLOR_0, primitive.indices?.value)
|
|
497
545
|
);
|
|
498
546
|
|
|
547
|
+
if (materialUvRegion) {
|
|
548
|
+
outputAttributes.uvRegions = concatenateTypedArrays(
|
|
549
|
+
outputAttributes.uvRegions,
|
|
550
|
+
createUvRegion(materialUvRegion, primitive.indices?.value)
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
499
554
|
outputAttributes.featureIndicesGroups = outputAttributes.featureIndicesGroups || [];
|
|
500
555
|
outputAttributes.featureIndicesGroups.push(
|
|
501
|
-
flattenBatchIds(
|
|
556
|
+
flattenBatchIds(getBatchIds(attributes, primitive, images), primitive.indices?.value)
|
|
502
557
|
);
|
|
503
558
|
}
|
|
504
559
|
}
|
|
@@ -646,6 +701,20 @@ function flattenColors(
|
|
|
646
701
|
return newColors;
|
|
647
702
|
}
|
|
648
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
|
+
|
|
649
718
|
/**
|
|
650
719
|
* Flatten batchedIds list based on indices to right ordered array, compatible with i3s
|
|
651
720
|
* @param batchedIds - gltf primitive
|
|
@@ -665,14 +734,23 @@ function flattenBatchIds(batchedIds: number[], indices: Uint8Array): number[] {
|
|
|
665
734
|
}
|
|
666
735
|
|
|
667
736
|
/**
|
|
668
|
-
*
|
|
669
|
-
* @param attributes -
|
|
670
|
-
* @
|
|
737
|
+
* Get batchIds for featureIds creation
|
|
738
|
+
* @param attributes - gltf accessors
|
|
739
|
+
* @param primitive - gltf primitive data
|
|
740
|
+
* @param images - gltf texture images
|
|
671
741
|
*/
|
|
672
|
-
function
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
742
|
+
function getBatchIds(
|
|
743
|
+
attributes: {
|
|
744
|
+
[key: string]: GLTFAccessorPostprocessed;
|
|
745
|
+
},
|
|
746
|
+
primitive: GLTFMeshPrimitivePostprocessed,
|
|
747
|
+
images: GLTFImagePostprocessed[]
|
|
748
|
+
): number[] {
|
|
749
|
+
const batchIds: number[] = handleBatchIdsExtensions(attributes, primitive, images);
|
|
750
|
+
|
|
751
|
+
if (batchIds.length) {
|
|
752
|
+
return batchIds;
|
|
753
|
+
}
|
|
676
754
|
|
|
677
755
|
for (let index = 0; index < BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES.length; index++) {
|
|
678
756
|
const possibleBatchIdAttributeName = BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES[index];
|
|
@@ -680,29 +758,137 @@ function getBatchIdsByAttributeName(attributes: {
|
|
|
680
758
|
attributes[possibleBatchIdAttributeName] &&
|
|
681
759
|
attributes[possibleBatchIdAttributeName].value
|
|
682
760
|
) {
|
|
683
|
-
|
|
684
|
-
break;
|
|
761
|
+
return attributes[possibleBatchIdAttributeName].value;
|
|
685
762
|
}
|
|
686
763
|
}
|
|
687
764
|
|
|
688
|
-
return
|
|
765
|
+
return [];
|
|
689
766
|
}
|
|
690
767
|
|
|
691
768
|
/**
|
|
692
769
|
* Convert GLTF material to I3S material definitions and textures
|
|
693
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
|
|
694
773
|
* @returns Array of Couples I3SMaterialDefinition + texture content
|
|
695
774
|
*/
|
|
696
|
-
function convertMaterials(
|
|
697
|
-
sourceMaterials: GLTFMaterialPostprocessed[] = []
|
|
698
|
-
|
|
699
|
-
|
|
775
|
+
async function convertMaterials(
|
|
776
|
+
sourceMaterials: GLTFMaterialPostprocessed[] = [],
|
|
777
|
+
shouldMergeMaterials: boolean
|
|
778
|
+
): Promise<I3SMaterialWithTexture[]> {
|
|
779
|
+
let materials: I3SMaterialWithTexture[] = [];
|
|
700
780
|
for (const sourceMaterial of sourceMaterials) {
|
|
701
|
-
|
|
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
|
+
});
|
|
702
857
|
}
|
|
703
858
|
return result;
|
|
704
859
|
}
|
|
705
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
|
+
|
|
706
892
|
/**
|
|
707
893
|
* Convert texture and material from gltf 2.0 material object
|
|
708
894
|
* @param sourceMaterial - material object
|
|
@@ -741,6 +927,9 @@ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterial
|
|
|
741
927
|
};
|
|
742
928
|
}
|
|
743
929
|
|
|
930
|
+
const uniqueId = uuidv4();
|
|
931
|
+
sourceMaterial.uniqueId = uniqueId;
|
|
932
|
+
let mergedMaterials: MergedMaterial[] = [{originalMaterialId: uniqueId}];
|
|
744
933
|
if (!texture) {
|
|
745
934
|
// Should use default baseColorFactor if it is not present in source material
|
|
746
935
|
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-pbrmetallicroughness
|
|
@@ -752,9 +941,11 @@ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterial
|
|
|
752
941
|
number,
|
|
753
942
|
number
|
|
754
943
|
]) || undefined;
|
|
944
|
+
} else {
|
|
945
|
+
mergedMaterials[0].textureSize = {width: texture.image.width, height: texture.image.height};
|
|
755
946
|
}
|
|
756
947
|
|
|
757
|
-
return {material, texture};
|
|
948
|
+
return {material, texture, mergedMaterials};
|
|
758
949
|
}
|
|
759
950
|
|
|
760
951
|
/**
|
|
@@ -897,7 +1088,9 @@ function extractSharedResourcesMaterialInfo(
|
|
|
897
1088
|
const specular = dielectricSpecular.lerp(dielectricSpecular, baseColorVector, metallicFactor);
|
|
898
1089
|
return {
|
|
899
1090
|
params: {
|
|
1091
|
+
// @ts-expect-error NumericArray
|
|
900
1092
|
diffuse: diffuse.toArray(),
|
|
1093
|
+
// @ts-expect-error NumericArray
|
|
901
1094
|
specular: specular.toArray(),
|
|
902
1095
|
renderMode: 'solid'
|
|
903
1096
|
}
|
|
@@ -929,13 +1122,13 @@ function extractSharedResourcesTextureInfo(
|
|
|
929
1122
|
}
|
|
930
1123
|
|
|
931
1124
|
/**
|
|
932
|
-
* Formula for
|
|
1125
|
+
* Formula for calculating imageId:
|
|
933
1126
|
* https://github.com/Esri/i3s-spec/blob/0a6366a9249b831db8436c322f8d27521e86cf07/format/Indexed%203d%20Scene%20Layer%20Format%20Specification.md#generating-image-ids
|
|
934
1127
|
* @param texture - texture image info
|
|
935
1128
|
* @param nodeId - I3S node ID
|
|
936
1129
|
* @returns calculate image ID according to the spec
|
|
937
1130
|
*/
|
|
938
|
-
function generateImageId(texture: GLTFTexturePostprocessed, nodeId) {
|
|
1131
|
+
function generateImageId(texture: GLTFTexturePostprocessed, nodeId: number) {
|
|
939
1132
|
const {width, height} = texture.source?.image;
|
|
940
1133
|
const levelCountOfTexture = 1;
|
|
941
1134
|
const indexOfLevel = 0;
|
|
@@ -1036,49 +1229,66 @@ function replaceIndicesByUnique(indicesArray, featureMap) {
|
|
|
1036
1229
|
}
|
|
1037
1230
|
|
|
1038
1231
|
/**
|
|
1039
|
-
* Convert
|
|
1040
|
-
* @param {Object} batchTable - table with metadata for particular feature.
|
|
1232
|
+
* Convert property table data to attribute buffers.
|
|
1041
1233
|
* @param {Array} featureIds
|
|
1234
|
+
* @param {Object} propertyTable - table with metadata for particular feature.
|
|
1042
1235
|
* @param {Array} attributeStorageInfo
|
|
1043
1236
|
* @returns {Array} - Array of file buffers.
|
|
1044
1237
|
*/
|
|
1045
|
-
function
|
|
1238
|
+
function convertPropertyTableToAttributeBuffers(
|
|
1239
|
+
featureIds: number[],
|
|
1240
|
+
propertyTable: FeatureTableJson,
|
|
1241
|
+
attributeStorageInfo: AttributeStorageInfo[]
|
|
1242
|
+
) {
|
|
1046
1243
|
const attributeBuffers: ArrayBuffer[] = [];
|
|
1047
1244
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
};
|
|
1245
|
+
const needFlattenPropertyTable = checkPropertiesLength(featureIds, propertyTable);
|
|
1246
|
+
const properties = needFlattenPropertyTable
|
|
1247
|
+
? flattenPropertyTableByFeatureIds(featureIds, propertyTable)
|
|
1248
|
+
: propertyTable;
|
|
1053
1249
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
switch (type) {
|
|
1060
|
-
case OBJECT_ID_TYPE:
|
|
1061
|
-
case SHORT_INT_TYPE:
|
|
1062
|
-
attributeBuffer = generateShortIntegerAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1063
|
-
break;
|
|
1064
|
-
case DOUBLE_TYPE:
|
|
1065
|
-
attributeBuffer = generateDoubleAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1066
|
-
break;
|
|
1067
|
-
case STRING_TYPE:
|
|
1068
|
-
attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1069
|
-
break;
|
|
1070
|
-
default:
|
|
1071
|
-
attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
|
|
1072
|
-
}
|
|
1250
|
+
const propertyTableWithObjectIds = {
|
|
1251
|
+
OBJECTID: featureIds,
|
|
1252
|
+
...properties
|
|
1253
|
+
};
|
|
1073
1254
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
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);
|
|
1078
1261
|
}
|
|
1079
1262
|
|
|
1080
1263
|
return attributeBuffers;
|
|
1081
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
|
+
|
|
1082
1292
|
/**
|
|
1083
1293
|
* Return attribute type.
|
|
1084
1294
|
* @param {String} key
|
|
@@ -1171,7 +1381,7 @@ async function generateCompressedGeometry(
|
|
|
1171
1381
|
attributes,
|
|
1172
1382
|
dracoWorkerSoure
|
|
1173
1383
|
) {
|
|
1174
|
-
const {positions, normals, texCoords, colors, featureIds, faceRange} = attributes;
|
|
1384
|
+
const {positions, normals, texCoords, colors, uvRegions, featureIds, faceRange} = attributes;
|
|
1175
1385
|
const indices = new Uint32Array(vertexCount);
|
|
1176
1386
|
|
|
1177
1387
|
for (let index = 0; index < indices.length; index++) {
|
|
@@ -1190,6 +1400,7 @@ async function generateCompressedGeometry(
|
|
|
1190
1400
|
colors: TypedArray;
|
|
1191
1401
|
'feature-index': TypedArray;
|
|
1192
1402
|
texCoords?: TypedArray;
|
|
1403
|
+
'uv-region'?: TypedArray;
|
|
1193
1404
|
} = {
|
|
1194
1405
|
positions,
|
|
1195
1406
|
normals,
|
|
@@ -1208,6 +1419,13 @@ async function generateCompressedGeometry(
|
|
|
1208
1419
|
}
|
|
1209
1420
|
};
|
|
1210
1421
|
|
|
1422
|
+
if (uvRegions.length) {
|
|
1423
|
+
compressedAttributes['uv-region'] = uvRegions;
|
|
1424
|
+
attributesMetadata['uv-region'] = {
|
|
1425
|
+
'i3s-attribute-type': 'uv-region'
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1211
1429
|
return encode({attributes: compressedAttributes, indices}, DracoWriterWorker, {
|
|
1212
1430
|
...DracoWriterWorker.options,
|
|
1213
1431
|
source: dracoWorkerSoure,
|
|
@@ -1242,3 +1460,97 @@ function generateFeatureIndexAttribute(featureIndex, faceRange) {
|
|
|
1242
1460
|
|
|
1243
1461
|
return orderedFeatureIndices;
|
|
1244
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
|
+
}
|