@loaders.gl/tile-converter 4.0.0-alpha.6 → 4.0.0-alpha.8

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.
Files changed (176) hide show
  1. package/bin/converter.js +1 -1
  2. package/dist/3d-tiles-attributes-worker.js +2 -2
  3. package/dist/3d-tiles-attributes-worker.js.map +3 -3
  4. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  5. package/dist/3d-tiles-converter/3d-tiles-converter.js +4 -3
  6. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +0 -8
  7. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +2 -15
  9. package/dist/converter.min.js +75 -76
  10. package/dist/deps-installer/deps-installer.js +4 -4
  11. package/dist/dist.min.js +2529 -1884
  12. package/dist/es5/3d-tiles-attributes-worker.js +1 -1
  13. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +0 -3
  14. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  15. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +2 -10
  16. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  17. package/dist/es5/deps-installer/deps-installer.js +5 -5
  18. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  19. package/dist/es5/i3s-attributes-worker.js +1 -1
  20. package/dist/es5/i3s-attributes-worker.js.map +1 -1
  21. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +4 -4
  22. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  23. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +6 -7
  24. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  25. package/dist/es5/i3s-converter/helpers/geometry-converter.js +49 -30
  26. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  27. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +46 -16
  28. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  29. package/dist/es5/i3s-converter/helpers/load-3d-tiles.js +82 -0
  30. package/dist/es5/i3s-converter/helpers/load-3d-tiles.js.map +1 -0
  31. package/dist/es5/i3s-converter/helpers/node-index-document.js +74 -45
  32. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -1
  33. package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js +111 -0
  34. package/dist/es5/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -0
  35. package/dist/es5/i3s-converter/helpers/tileset-traversal.js +82 -0
  36. package/dist/es5/i3s-converter/helpers/tileset-traversal.js.map +1 -0
  37. package/dist/es5/i3s-converter/i3s-converter.js +545 -523
  38. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  39. package/dist/es5/i3s-converter/types.js +16 -0
  40. package/dist/es5/i3s-converter/types.js.map +1 -1
  41. package/dist/es5/i3s-server/README.md +19 -0
  42. package/dist/es5/i3s-server/app.js +10 -1
  43. package/dist/es5/i3s-server/app.js.map +1 -1
  44. package/dist/es5/i3s-server/controllers/slpk-controller.js +84 -0
  45. package/dist/es5/i3s-server/controllers/slpk-controller.js.map +1 -0
  46. package/dist/es5/i3s-server/routes/slpk-router.js +71 -0
  47. package/dist/es5/i3s-server/routes/slpk-router.js.map +1 -0
  48. package/dist/es5/i3s-server/utils/create-scene-server.js +17 -0
  49. package/dist/es5/i3s-server/utils/create-scene-server.js.map +1 -0
  50. package/dist/es5/lib/utils/file-utils.js +1 -1
  51. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  52. package/dist/es5/lib/utils/geometry-utils.js +15 -0
  53. package/dist/es5/lib/utils/geometry-utils.js.map +1 -0
  54. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  55. package/dist/es5/pgm-loader.js +1 -1
  56. package/dist/esm/3d-tiles-attributes-worker.js +1 -1
  57. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +0 -3
  58. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  59. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +2 -8
  60. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  61. package/dist/esm/deps-installer/deps-installer.js +5 -5
  62. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  63. package/dist/esm/i3s-attributes-worker.js +1 -1
  64. package/dist/esm/i3s-attributes-worker.js.map +1 -1
  65. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +4 -4
  66. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  67. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +6 -7
  68. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  69. package/dist/esm/i3s-converter/helpers/geometry-converter.js +37 -18
  70. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  71. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +50 -16
  72. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  73. package/dist/esm/i3s-converter/helpers/load-3d-tiles.js +35 -0
  74. package/dist/esm/i3s-converter/helpers/load-3d-tiles.js.map +1 -0
  75. package/dist/esm/i3s-converter/helpers/node-index-document.js +14 -1
  76. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -1
  77. package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js +48 -0
  78. package/dist/esm/i3s-converter/helpers/preprocess-3d-tiles.js.map +1 -0
  79. package/dist/esm/i3s-converter/helpers/tileset-traversal.js +14 -0
  80. package/dist/esm/i3s-converter/helpers/tileset-traversal.js.map +1 -0
  81. package/dist/esm/i3s-converter/i3s-converter.js +134 -127
  82. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  83. package/dist/esm/i3s-converter/types.js +10 -1
  84. package/dist/esm/i3s-converter/types.js.map +1 -1
  85. package/dist/esm/i3s-server/README.md +19 -0
  86. package/dist/esm/i3s-server/app.js +11 -1
  87. package/dist/esm/i3s-server/app.js.map +1 -1
  88. package/dist/esm/i3s-server/controllers/slpk-controller.js +36 -0
  89. package/dist/esm/i3s-server/controllers/slpk-controller.js.map +1 -0
  90. package/dist/esm/i3s-server/routes/slpk-router.js +33 -0
  91. package/dist/esm/i3s-server/routes/slpk-router.js.map +1 -0
  92. package/dist/esm/i3s-server/utils/create-scene-server.js +16 -0
  93. package/dist/esm/i3s-server/utils/create-scene-server.js.map +1 -0
  94. package/dist/esm/lib/utils/file-utils.js +1 -1
  95. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  96. package/dist/esm/lib/utils/geometry-utils.js +8 -0
  97. package/dist/esm/lib/utils/geometry-utils.js.map +1 -0
  98. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  99. package/dist/esm/pgm-loader.js +1 -1
  100. package/dist/i3s-attributes-worker.d.ts +10 -2
  101. package/dist/i3s-attributes-worker.d.ts.map +1 -1
  102. package/dist/i3s-attributes-worker.js +2 -2
  103. package/dist/i3s-attributes-worker.js.map +3 -3
  104. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +4 -2
  105. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
  106. package/dist/i3s-converter/helpers/batch-ids-extensions.js +4 -7
  107. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +3 -4
  108. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
  109. package/dist/i3s-converter/helpers/coordinate-converter.js +8 -9
  110. package/dist/i3s-converter/helpers/geometry-converter.d.ts +9 -4
  111. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  112. package/dist/i3s-converter/helpers/geometry-converter.js +84 -54
  113. package/dist/i3s-converter/helpers/gltf-attributes.d.ts +22 -3
  114. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
  115. package/dist/i3s-converter/helpers/gltf-attributes.js +62 -22
  116. package/dist/i3s-converter/helpers/load-3d-tiles.d.ts +18 -0
  117. package/dist/i3s-converter/helpers/load-3d-tiles.d.ts.map +1 -0
  118. package/dist/i3s-converter/helpers/load-3d-tiles.js +53 -0
  119. package/dist/i3s-converter/helpers/node-index-document.d.ts +8 -0
  120. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -1
  121. package/dist/i3s-converter/helpers/node-index-document.js +20 -2
  122. package/dist/i3s-converter/helpers/node-pages.js +1 -1
  123. package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts +23 -0
  124. package/dist/i3s-converter/helpers/preprocess-3d-tiles.d.ts.map +1 -0
  125. package/dist/i3s-converter/helpers/preprocess-3d-tiles.js +76 -0
  126. package/dist/i3s-converter/helpers/tileset-traversal.d.ts +25 -0
  127. package/dist/i3s-converter/helpers/tileset-traversal.d.ts.map +1 -0
  128. package/dist/i3s-converter/helpers/tileset-traversal.js +29 -0
  129. package/dist/i3s-converter/i3s-converter.d.ts +40 -40
  130. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  131. package/dist/i3s-converter/i3s-converter.js +150 -125
  132. package/dist/i3s-converter/types.d.ts +18 -0
  133. package/dist/i3s-converter/types.d.ts.map +1 -1
  134. package/dist/i3s-converter/types.js +15 -0
  135. package/dist/i3s-server/app.d.ts.map +1 -1
  136. package/dist/i3s-server/app.js +9 -1
  137. package/dist/i3s-server/controllers/slpk-controller.d.ts +3 -0
  138. package/dist/i3s-server/controllers/slpk-controller.d.ts.map +1 -0
  139. package/dist/i3s-server/controllers/slpk-controller.js +32 -0
  140. package/dist/i3s-server/routes/slpk-router.d.ts +3 -0
  141. package/dist/i3s-server/routes/slpk-router.d.ts.map +1 -0
  142. package/dist/i3s-server/routes/slpk-router.js +33 -0
  143. package/dist/i3s-server/utils/create-scene-server.d.ts +11 -0
  144. package/dist/i3s-server/utils/create-scene-server.d.ts.map +1 -0
  145. package/dist/i3s-server/utils/create-scene-server.js +14 -0
  146. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  147. package/dist/lib/utils/file-utils.js +2 -1
  148. package/dist/lib/utils/geometry-utils.d.ts +9 -0
  149. package/dist/lib/utils/geometry-utils.d.ts.map +1 -0
  150. package/dist/lib/utils/geometry-utils.js +18 -0
  151. package/dist/lib/utils/lod-conversion-utils.d.ts +3 -2
  152. package/dist/lib/utils/lod-conversion-utils.d.ts.map +1 -1
  153. package/dist/lib/utils/lod-conversion-utils.js +1 -1
  154. package/package.json +15 -16
  155. package/src/3d-tiles-converter/3d-tiles-converter.ts +9 -8
  156. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +2 -16
  157. package/src/deps-installer/deps-installer.ts +4 -4
  158. package/src/i3s-attributes-worker.ts +11 -2
  159. package/src/i3s-converter/helpers/batch-ids-extensions.ts +15 -19
  160. package/src/i3s-converter/helpers/coordinate-converter.ts +11 -10
  161. package/src/i3s-converter/helpers/geometry-converter.ts +154 -95
  162. package/src/i3s-converter/helpers/gltf-attributes.ts +85 -25
  163. package/src/i3s-converter/helpers/load-3d-tiles.ts +68 -0
  164. package/src/i3s-converter/helpers/node-index-document.ts +22 -2
  165. package/src/i3s-converter/helpers/preprocess-3d-tiles.ts +81 -0
  166. package/src/i3s-converter/helpers/tileset-traversal.ts +51 -0
  167. package/src/i3s-converter/i3s-converter.ts +229 -178
  168. package/src/i3s-converter/types.ts +20 -0
  169. package/src/i3s-server/README.md +19 -0
  170. package/src/i3s-server/app.js +8 -1
  171. package/src/i3s-server/controllers/slpk-controller.js +38 -0
  172. package/src/i3s-server/routes/slpk-router.js +33 -0
  173. package/src/i3s-server/utils/create-scene-server.js +15 -0
  174. package/src/lib/utils/file-utils.ts +2 -1
  175. package/src/lib/utils/geometry-utils.ts +14 -0
  176. package/src/lib/utils/lod-conversion-utils.ts +6 -2
@@ -1,10 +1,10 @@
1
- import type {B3DMContent, FeatureTableJson} from '@loaders.gl/3d-tiles';
1
+ import type {FeatureTableJson, Tiles3DTileContent} from '@loaders.gl/3d-tiles';
2
2
  import type {
3
3
  GLTF_EXT_feature_metadata,
4
+ GLTF_EXT_mesh_features,
4
5
  GLTFAccessorPostprocessed,
5
6
  GLTFMaterialPostprocessed,
6
7
  GLTFNodePostprocessed,
7
- GLTFImagePostprocessed,
8
8
  GLTFMeshPrimitivePostprocessed,
9
9
  GLTFMeshPostprocessed,
10
10
  GLTFTexturePostprocessed
@@ -33,14 +33,16 @@ import {
33
33
  MaterialDefinitionInfo,
34
34
  TextureDefinitionInfo
35
35
  } from '@loaders.gl/i3s';
36
- import {TypedArray} from '@loaders.gl/schema';
36
+ import {NumberArray, TypedArray} from '@loaders.gl/loader-utils';
37
37
  import {Geoid} from '@math.gl/geoid';
38
38
  /** Usage of worker here brings more overhead than advantage */
39
- import {B3DMAttributesData /*, transformI3SAttributesOnWorker*/} from '../../i3s-attributes-worker';
39
+ import {
40
+ B3DMAttributesData /*, transformI3SAttributesOnWorker*/,
41
+ TextureImageProperties
42
+ } from '../../i3s-attributes-worker';
40
43
  import {prepareDataForAttributesConversion} from './gltf-attributes';
41
44
  import {handleBatchIdsExtensions} from './batch-ids-extensions';
42
45
  import {checkPropertiesLength, flattenPropertyTableByFeatureIds} from './feature-attributes';
43
- import {MeshPrimitive} from 'modules/gltf/src/lib/types/gltf-postprocessed-schema';
44
46
  import {GL} from '@loaders.gl/math';
45
47
 
46
48
  /*
@@ -49,6 +51,8 @@ import {GL} from '@loaders.gl/math';
49
51
  import type {TypedArrayConstructor} from '@math.gl/types';
50
52
  */
51
53
  import type {TypedArrayConstructor} from '../types';
54
+ import {generateSyntheticIndices} from '../../lib/utils/geometry-utils';
55
+ import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
52
56
 
53
57
  // Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
54
58
  const DEFAULT_ROUGHNESS_FACTOR = 1;
@@ -78,6 +82,9 @@ let scratchVector = new Vector3();
78
82
  * Convert binary data from b3dm file to i3s resources
79
83
  *
80
84
  * @param tileContent - 3d tile content
85
+ * @param tileTransform - transformation matrix of the tile, calculated recursively multiplying
86
+ * transform of all parent tiles and transform of the current tile
87
+ * @param tileBoundingVolume - initialized bounding volume of the source tile
81
88
  * @param addNodeToNodePage - function to add new node to node pages
82
89
  * @param propertyTable - batch table (corresponding to feature attributes data)
83
90
  * @param featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
@@ -90,7 +97,9 @@ let scratchVector = new Vector3();
90
97
  * @returns Array of node resources to create one or more i3s nodes
91
98
  */
92
99
  export default async function convertB3dmToI3sGeometry(
93
- tileContent: B3DMContent,
100
+ tileContent: Tiles3DTileContent,
101
+ tileTransform: Matrix4,
102
+ tileBoundingVolume: OrientedBoundingBox | BoundingSphere,
94
103
  addNodeToNodePage: () => Promise<number>,
95
104
  propertyTable: FeatureTableJson | null,
96
105
  featuresHashArray: string[],
@@ -107,7 +116,11 @@ export default async function convertB3dmToI3sGeometry(
107
116
  shouldMergeMaterials
108
117
  );
109
118
 
110
- const dataForAttributesConversion = prepareDataForAttributesConversion(tileContent);
119
+ const dataForAttributesConversion = prepareDataForAttributesConversion(
120
+ tileContent,
121
+ tileTransform,
122
+ tileBoundingVolume
123
+ );
111
124
  const convertedAttributesMap: Map<string, ConvertedAttributes> = await convertAttributes(
112
125
  dataForAttributesConversion,
113
126
  materialAndTextureList,
@@ -195,7 +208,7 @@ function _generateBoundingVolumesFromGeometry(
195
208
  * @param params.convertedAttributes - Converted geometry attributes
196
209
  * @param params.material - I3S PBR-like material definition
197
210
  * @param params.texture - texture content
198
- * @param params.tileContent - B3DM decoded content
211
+ * @param params.tileContent - 3DTiles decoded content
199
212
  * @param params.nodeId - new node ID
200
213
  * @param params.featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
201
214
  * @param params.propertyTable - batch table (corresponding to feature attributes data)
@@ -219,7 +232,7 @@ async function _makeNodeResources({
219
232
  convertedAttributes: ConvertedAttributes;
220
233
  material: I3SMaterialDefinition;
221
234
  texture?: {};
222
- tileContent: B3DMContent;
235
+ tileContent: Tiles3DTileContent;
223
236
  nodeId: number;
224
237
  featuresHashArray: string[];
225
238
  propertyTable: FeatureTableJson | null;
@@ -376,7 +389,7 @@ export async function convertAttributes(
376
389
  */
377
390
  function convertNodes(
378
391
  nodes: GLTFNodePostprocessed[],
379
- images: GLTFImagePostprocessed[],
392
+ images: (TextureImageProperties | null)[],
380
393
  cartographicOrigin: Vector3,
381
394
  cartesianModelMatrix: Matrix4,
382
395
  attributesMap: Map<string, ConvertedAttributes>,
@@ -442,7 +455,7 @@ function getCompositeTransformationMatrix(node: GLTFNodePostprocessed, matrix: M
442
455
  */
443
456
  function convertNode(
444
457
  node: GLTFNodePostprocessed,
445
- images: GLTFImagePostprocessed[],
458
+ images: (TextureImageProperties | null)[],
446
459
  cartographicOrigin: Vector3,
447
460
  cartesianModelMatrix: Matrix4,
448
461
  attributesMap: Map<string, ConvertedAttributes>,
@@ -493,7 +506,7 @@ function convertNode(
493
506
  */
494
507
  function convertMesh(
495
508
  mesh: GLTFMeshPostprocessed,
496
- images: GLTFImagePostprocessed[],
509
+ images: (TextureImageProperties | null)[],
497
510
  cartographicOrigin: Vector3,
498
511
  cartesianModelMatrix: Matrix4,
499
512
  attributesMap: Map<string, ConvertedAttributes>,
@@ -504,20 +517,28 @@ function convertMesh(
504
517
  let outputAttributes: ConvertedAttributes | null | undefined = null;
505
518
  let materialUvRegion: Uint16Array | undefined;
506
519
  if (primitive.material) {
507
- outputAttributes = attributesMap.get(primitive.material.uniqueId);
520
+ outputAttributes = attributesMap.get(primitive.material.id);
508
521
  materialUvRegion = outputAttributes?.mergedMaterials.find(
509
- ({originalMaterialId}) => originalMaterialId === primitive.material?.uniqueId
522
+ ({originalMaterialId}) => originalMaterialId === primitive.material?.id
510
523
  )?.uvRegion;
511
524
  } else if (attributesMap.has('default')) {
512
525
  outputAttributes = attributesMap.get('default');
513
526
  }
514
527
  assert(outputAttributes !== null, 'Primitive - material mapping failed');
528
+ // Per the spec https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode
529
+ // GL.TRIANGLES is default. So in case `mode` is `undefined`, it is 'TRIANGLES'
530
+ assert(
531
+ primitive.mode === undefined ||
532
+ primitive.mode === GL.TRIANGLES ||
533
+ primitive.mode === GL.TRIANGLE_STRIP,
534
+ `Primitive - unsupported mode ${primitive.mode}`
535
+ );
515
536
  const attributes = primitive.attributes;
516
537
  if (!outputAttributes) {
517
538
  continue;
518
539
  }
519
540
 
520
- const indices = getIndices(primitive);
541
+ const indices = normalizeIndices(primitive);
521
542
  outputAttributes.positions = concatenateTypedArrays(
522
543
  outputAttributes.positions,
523
544
  transformVertexArray({
@@ -567,11 +588,16 @@ function convertMesh(
567
588
  }
568
589
  /**
569
590
  * Converts TRIANGLE-STRIPS to independent TRIANGLES
570
- * @param {MeshPrimitive} primitive - the primitive to get the indices from
591
+ * @param primitive - the primitive to get the indices from
571
592
  * @returns indices of vertices of the independent triangles
572
593
  */
573
- function getIndices(primitive: MeshPrimitive): TypedArray {
574
- let indices: TypedArray = primitive.indices?.value;
594
+ function normalizeIndices(primitive: GLTFMeshPrimitivePostprocessed): TypedArray {
595
+ let indices: TypedArray | undefined = primitive.indices?.value;
596
+ if (!indices) {
597
+ const positions = primitive.attributes.POSITION.value;
598
+ return generateSyntheticIndices(positions.length / VALUES_PER_VERTEX);
599
+ }
600
+
575
601
  if (indices && primitive.mode === GL.TRIANGLE_STRIP) {
576
602
  /*
577
603
  TRIANGLE_STRIP geometry contains n+2 vertices for n triangles;
@@ -600,7 +626,7 @@ function getIndices(primitive: MeshPrimitive): TypedArray {
600
626
  }
601
627
  indices = newIndices;
602
628
  }
603
- return indices;
629
+ return indices as TypedArray;
604
630
  }
605
631
 
606
632
  /**
@@ -613,17 +639,17 @@ function getIndices(primitive: MeshPrimitive): TypedArray {
613
639
  * @param args.indices - gltf primitive indices
614
640
  * @param args.attributeSpecificTransformation - function to do attribute - specific transformations
615
641
  * @param args.useCartesianPositions - use coordinates as it is.
616
- * @returns {Float32Array}
642
+ * @returns
617
643
  */
618
644
  function transformVertexArray(args: {
619
- vertices: Float32Array;
645
+ vertices: TypedArray;
620
646
  cartographicOrigin: number[];
621
647
  cartesianModelMatrix: number[];
622
648
  nodeMatrix: Matrix4;
623
649
  indices: TypedArray;
624
650
  attributeSpecificTransformation: Function;
625
651
  useCartesianPositions: boolean;
626
- }) {
652
+ }): Float32Array {
627
653
  const {vertices, indices, attributeSpecificTransformation} = args;
628
654
  const newVertices = new Float32Array(indices.length * VALUES_PER_VERTEX);
629
655
  if (!vertices) {
@@ -699,7 +725,7 @@ function transformVertexNormals(vertexVector, calleeArgs): number[] {
699
725
  * @param indices - gltf primitive indices
700
726
  * @returns flattened texture coordinates
701
727
  */
702
- function flattenTexCoords(texCoords: Float32Array, indices: TypedArray): Float32Array {
728
+ function flattenTexCoords(texCoords: TypedArray, indices: TypedArray): Float32Array {
703
729
  const newTexCoords = new Float32Array(indices.length * VALUES_PER_TEX_COORD);
704
730
  if (!texCoords) {
705
731
  // We need dummy UV0s because it is required in 1.6
@@ -766,7 +792,7 @@ function createUvRegion(materialUvRegion: Uint16Array, indices: TypedArray): Uin
766
792
  * @param indices - gltf primitive indices
767
793
  * @returns flattened batch ids
768
794
  */
769
- function flattenBatchIds(batchedIds: number[], indices: TypedArray): number[] {
795
+ function flattenBatchIds(batchedIds: NumberArray, indices: TypedArray): number[] {
770
796
  if (!batchedIds.length || !indices.length) {
771
797
  return [];
772
798
  }
@@ -789,9 +815,9 @@ function getBatchIds(
789
815
  [key: string]: GLTFAccessorPostprocessed;
790
816
  },
791
817
  primitive: GLTFMeshPrimitivePostprocessed,
792
- images: GLTFImagePostprocessed[]
793
- ): number[] {
794
- const batchIds: number[] = handleBatchIdsExtensions(attributes, primitive, images);
818
+ images: (TextureImageProperties | null)[]
819
+ ): NumberArray {
820
+ const batchIds: NumberArray = handleBatchIdsExtensions(attributes, primitive, images);
795
821
 
796
822
  if (batchIds.length) {
797
823
  return batchIds;
@@ -979,9 +1005,8 @@ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterial
979
1005
  };
980
1006
  }
981
1007
 
982
- const uniqueId = uuidv4();
983
- sourceMaterial.uniqueId = uniqueId;
984
- let mergedMaterials: MergedMaterial[] = [{originalMaterialId: uniqueId}];
1008
+ sourceMaterial.id = Number.isFinite(sourceMaterial.id) ? sourceMaterial.id : uuidv4();
1009
+ let mergedMaterials: MergedMaterial[] = [{originalMaterialId: sourceMaterial.id}];
985
1010
  if (!texture) {
986
1011
  // Should use default baseColorFactor if it is not present in source material
987
1012
  // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-pbrmetallicroughness
@@ -1167,7 +1192,7 @@ function extractSharedResourcesTextureInfo(
1167
1192
  // https://github.com/Esri/i3s-spec/blob/master/docs/1.7/image.cmn.md
1168
1193
  id: generateImageId(texture, nodeId),
1169
1194
  size: texture.source?.image.width,
1170
- length: [texture.source?.image.data.length]
1195
+ length: texture.source?.image.data.length ? [texture.source?.image.data.length] : undefined
1171
1196
  }
1172
1197
  ]
1173
1198
  };
@@ -1181,7 +1206,10 @@ function extractSharedResourcesTextureInfo(
1181
1206
  * @returns calculate image ID according to the spec
1182
1207
  */
1183
1208
  function generateImageId(texture: GLTFTexturePostprocessed, nodeId: number) {
1184
- const {width, height} = texture.source?.image;
1209
+ const {width, height} = texture.source?.image || {};
1210
+ if (!width || !height) {
1211
+ return '';
1212
+ }
1185
1213
  const levelCountOfTexture = 1;
1186
1214
  const indexOfLevel = 0;
1187
1215
  const indexOfTextureInStore = nodeId + 1;
@@ -1220,13 +1248,17 @@ function makeFeatureIdsUnique(
1220
1248
 
1221
1249
  /**
1222
1250
  * Generate replace map to make featureIds unique.
1223
- * @param {Array} featureIds
1224
- * @param {Object} batchTable
1225
- * @param {Array} featuresHashArray
1226
- * @returns {Object}
1251
+ * @param featureIds
1252
+ * @param batchTable
1253
+ * @param featuresHashArray
1254
+ * @returns
1227
1255
  */
1228
- function getFeaturesReplaceMap(featureIds, batchTable, featuresHashArray) {
1229
- const featureMap = {};
1256
+ function getFeaturesReplaceMap(
1257
+ featureIds: any[],
1258
+ batchTable: object,
1259
+ featuresHashArray: any[]
1260
+ ): Record<string, any> {
1261
+ const featureMap: Record<string, any> = {};
1230
1262
 
1231
1263
  for (let index = 0; index < featureIds.length; index++) {
1232
1264
  const oldFeatureId = featureIds[index];
@@ -1239,11 +1271,11 @@ function getFeaturesReplaceMap(featureIds, batchTable, featuresHashArray) {
1239
1271
 
1240
1272
  /**
1241
1273
  * Generates string for unique batch id creation.
1242
- * @param {Object} batchTable
1243
- * @param {Number} index
1244
- * @returns {String}
1274
+ * @param batchTable
1275
+ * @param index
1276
+ * @returns
1245
1277
  */
1246
- function generateStringFromBatchTableByIndex(batchTable, index) {
1278
+ function generateStringFromBatchTableByIndex(batchTable: object, index: number): string {
1247
1279
  let str = '';
1248
1280
  for (const key in batchTable) {
1249
1281
  str += batchTable[key][index];
@@ -1253,12 +1285,16 @@ function generateStringFromBatchTableByIndex(batchTable, index) {
1253
1285
 
1254
1286
  /**
1255
1287
  * Return already exited featureId or creates and returns new to support unique feature ids throw nodes.
1256
- * @param {Number} index
1257
- * @param {Object} batchTable
1258
- * @param {Array} featuresHashArray
1259
- * @returns {Number}
1288
+ * @param index
1289
+ * @param batchTable
1290
+ * @param featuresHashArray
1291
+ * @returns
1260
1292
  */
1261
- function getOrCreateUniqueFeatureId(index, batchTable, featuresHashArray) {
1293
+ function getOrCreateUniqueFeatureId(
1294
+ index: number,
1295
+ batchTable: object,
1296
+ featuresHashArray: any[]
1297
+ ): number {
1262
1298
  const batchTableStr = generateStringFromBatchTableByIndex(batchTable, index);
1263
1299
  const hash = md5(batchTableStr);
1264
1300
 
@@ -1270,11 +1306,11 @@ function getOrCreateUniqueFeatureId(index, batchTable, featuresHashArray) {
1270
1306
 
1271
1307
  /**
1272
1308
  * Do replacement of indices for making them unique through all nodes.
1273
- * @param {Array} indicesArray
1274
- * @param {Object} featureMap
1275
- * @returns {void}
1309
+ * @param indicesArray
1310
+ * @param featureMap
1311
+ * @returns
1276
1312
  */
1277
- function replaceIndicesByUnique(indicesArray, featureMap) {
1313
+ function replaceIndicesByUnique(indicesArray: any[], featureMap: Record<string, []>) {
1278
1314
  for (let index = 0; index < indicesArray.length; index++) {
1279
1315
  indicesArray[index] = featureMap[indicesArray[index]];
1280
1316
  }
@@ -1282,16 +1318,16 @@ function replaceIndicesByUnique(indicesArray, featureMap) {
1282
1318
 
1283
1319
  /**
1284
1320
  * Convert property table data to attribute buffers.
1285
- * @param {Array} featureIds
1286
- * @param {Object} propertyTable - table with metadata for particular feature.
1287
- * @param {Array} attributeStorageInfo
1288
- * @returns {Array} - Array of file buffers.
1321
+ * @param featureIds
1322
+ * @param propertyTable - table with metadata for particular feature.
1323
+ * @param attributeStorageInfo
1324
+ * @returns - Array of file buffers.
1289
1325
  */
1290
1326
  function convertPropertyTableToAttributeBuffers(
1291
1327
  featureIds: number[],
1292
1328
  propertyTable: FeatureTableJson,
1293
1329
  attributeStorageInfo: AttributeStorageInfo[]
1294
- ) {
1330
+ ): any[] {
1295
1331
  const attributeBuffers: ArrayBuffer[] = [];
1296
1332
 
1297
1333
  const needFlattenPropertyTable = checkPropertiesLength(featureIds, propertyTable);
@@ -1343,21 +1379,21 @@ function generateAttributeBuffer(type: string, value: any): ArrayBuffer {
1343
1379
 
1344
1380
  /**
1345
1381
  * Return attribute type.
1346
- * @param {String} key
1347
- * @param {Array} attributeStorageInfo
1348
- * @returns {String} attribute type.
1382
+ * @param key
1383
+ * @param attributeStorageInfo
1384
+ * @returns attribute type.
1349
1385
  */
1350
- function getAttributeType(key, attributeStorageInfo) {
1386
+ function getAttributeType(key: string, attributeStorageInfo: any[]): string {
1351
1387
  const attribute = attributeStorageInfo.find((attr) => attr.name === key);
1352
1388
  return attribute.attributeValues.valueType;
1353
1389
  }
1354
1390
 
1355
1391
  /**
1356
1392
  * Convert short integer to attribute arrayBuffer.
1357
- * @param {Array} featureIds
1358
- * @returns {ArrayBuffer} - Buffer with objectId data.
1393
+ * @param featureIds
1394
+ * @returns - Buffer with objectId data.
1359
1395
  */
1360
- function generateShortIntegerAttributeBuffer(featureIds): ArrayBuffer {
1396
+ function generateShortIntegerAttributeBuffer(featureIds: any[]): ArrayBuffer {
1361
1397
  const count = new Uint32Array([featureIds.length]);
1362
1398
  const valuesArray = new Uint32Array(featureIds);
1363
1399
  return concatenateArrayBuffers(count.buffer, valuesArray.buffer);
@@ -1365,10 +1401,10 @@ function generateShortIntegerAttributeBuffer(featureIds): ArrayBuffer {
1365
1401
 
1366
1402
  /**
1367
1403
  * Convert double to attribute arrayBuffer.
1368
- * @param {Array} featureIds
1369
- * @returns {ArrayBuffer} - Buffer with objectId data.
1404
+ * @param featureIds
1405
+ * @returns - Buffer with objectId data.
1370
1406
  */
1371
- function generateDoubleAttributeBuffer(featureIds): ArrayBuffer {
1407
+ function generateDoubleAttributeBuffer(featureIds: any[]): ArrayBuffer {
1372
1408
  const count = new Uint32Array([featureIds.length]);
1373
1409
  const padding = new Uint8Array(4);
1374
1410
  const valuesArray = new Float64Array(featureIds);
@@ -1378,10 +1414,10 @@ function generateDoubleAttributeBuffer(featureIds): ArrayBuffer {
1378
1414
 
1379
1415
  /**
1380
1416
  * Convert batch table attributes to array buffer with batch table data.
1381
- * @param {Array} batchAttributes
1382
- * @returns {ArrayBuffer} - Buffer with batch table data.
1417
+ * @param batchAttributes
1418
+ * @returns - Buffer with batch table data.
1383
1419
  */
1384
- function generateStringAttributeBuffer(batchAttributes): ArrayBuffer {
1420
+ function generateStringAttributeBuffer(batchAttributes: any[]): ArrayBuffer {
1385
1421
  const stringCountArray = new Uint32Array([batchAttributes.length]);
1386
1422
  let totalNumberOfBytes = 0;
1387
1423
  const stringSizesArray = new Uint32Array(batchAttributes.length);
@@ -1408,10 +1444,10 @@ function generateStringAttributeBuffer(batchAttributes): ArrayBuffer {
1408
1444
 
1409
1445
  /**
1410
1446
  * Convert featureIds to BigUint64Array.
1411
- * @param {Array} featureIds
1412
- * @returns {BigUint64Array} - Array of feature ids in BigUint64 format.
1447
+ * @param featureIds
1448
+ * @returns - Array of feature ids in BigUint64 format.
1413
1449
  */
1414
- function generateBigUint64Array(featureIds) {
1450
+ function generateBigUint64Array(featureIds: any[]): BigUint64Array {
1415
1451
  const typedFeatureIds = new BigUint64Array(featureIds.length);
1416
1452
  for (let index = 0; index < featureIds.length; index++) {
1417
1453
  typedFeatureIds[index] = BigInt(featureIds[index]);
@@ -1428,11 +1464,11 @@ function generateBigUint64Array(featureIds) {
1428
1464
  * @returns {Promise<object>} - COmpressed geometry.
1429
1465
  */
1430
1466
  async function generateCompressedGeometry(
1431
- vertexCount,
1432
- convertedAttributes,
1433
- attributes,
1434
- dracoWorkerSoure
1435
- ) {
1467
+ vertexCount: number,
1468
+ convertedAttributes: Record<string, any>,
1469
+ attributes: Record<string, any>,
1470
+ dracoWorkerSoure: string
1471
+ ): Promise<ArrayBuffer> {
1436
1472
  const {positions, normals, texCoords, colors, uvRegions, featureIds, faceRange} = attributes;
1437
1473
  const indices = new Uint32Array(vertexCount);
1438
1474
 
@@ -1492,11 +1528,14 @@ async function generateCompressedGeometry(
1492
1528
 
1493
1529
  /**
1494
1530
  * Generates ordered feature indices based on face range
1495
- * @param {Uint32Array} featureIndex
1496
- * @param {Uint32Array} faceRange
1497
- * @returns {Uint32Array}
1531
+ * @param featureIndex
1532
+ * @param faceRange
1533
+ * @returns
1498
1534
  */
1499
- function generateFeatureIndexAttribute(featureIndex, faceRange) {
1535
+ function generateFeatureIndexAttribute(
1536
+ featureIndex: Uint32Array,
1537
+ faceRange: Uint32Array
1538
+ ): Uint32Array {
1500
1539
  const orderedFeatureIndices = new Uint32Array(featureIndex.length);
1501
1540
  let fillIndex = 0;
1502
1541
  let startIndex = 0;
@@ -1516,10 +1555,14 @@ function generateFeatureIndexAttribute(featureIndex, faceRange) {
1516
1555
  /**
1517
1556
  * Find property table in tile
1518
1557
  * For example it can be batchTable for b3dm files or property table in gLTF extension.
1519
- * @param sourceTile
1558
+ * @param tileContent - 3DTiles tile content
1520
1559
  * @return batch table from b3dm / feature properties from EXT_FEATURE_METADATA
1521
1560
  */
1522
- export function getPropertyTable(tileContent: B3DMContent): FeatureTableJson | null {
1561
+ export function getPropertyTable(tileContent: Tiles3DTileContent | null): FeatureTableJson | null {
1562
+ if (!tileContent) {
1563
+ return null;
1564
+ }
1565
+
1523
1566
  const batchTableJson = tileContent?.batchTableJson;
1524
1567
 
1525
1568
  if (batchTableJson) {
@@ -1534,7 +1577,7 @@ export function getPropertyTable(tileContent: B3DMContent): FeatureTableJson | n
1534
1577
  return null;
1535
1578
  }
1536
1579
  case EXT_FEATURE_METADATA: {
1537
- return getPropertyTableFromExtFeatureMetadata(extension);
1580
+ return getPropertyTableFromExtFeatureMetadata(extension as GLTF_EXT_feature_metadata);
1538
1581
  }
1539
1582
  default:
1540
1583
  return null;
@@ -1543,9 +1586,11 @@ export function getPropertyTable(tileContent: B3DMContent): FeatureTableJson | n
1543
1586
 
1544
1587
  /**
1545
1588
  * Check extensions which can be with property table inside.
1546
- * @param sourceTile
1589
+ * @param tileContent - 3DTiles tile content
1547
1590
  */
1548
- function getPropertyTableExtension(tileContent: B3DMContent) {
1591
+ function getPropertyTableExtension(
1592
+ tileContent: Tiles3DTileContent
1593
+ ): GLTF_EXT_feature_metadata | GLTF_EXT_mesh_features {
1549
1594
  const extensionsWithPropertyTables = [EXT_FEATURE_METADATA, EXT_MESH_FEATURES];
1550
1595
  const extensionsUsed = tileContent?.gltf?.extensionsUsed;
1551
1596
 
@@ -1570,18 +1615,10 @@ function getPropertyTableExtension(tileContent: B3DMContent) {
1570
1615
  /**
1571
1616
  * Handle EXT_feature_metadata to get property table
1572
1617
  * @param extension
1573
- * TODO add EXT_feature_metadata feature textures support.
1574
1618
  */
1575
1619
  function getPropertyTableFromExtFeatureMetadata(
1576
1620
  extension: GLTF_EXT_feature_metadata
1577
1621
  ): FeatureTableJson | null {
1578
- if (extension?.featureTextures) {
1579
- console.warn(
1580
- 'The I3S converter does not yet support the EXT_feature_metadata feature textures'
1581
- );
1582
- return null;
1583
- }
1584
-
1585
1622
  if (extension?.featureTables) {
1586
1623
  /**
1587
1624
  * Take only first feature table to generate attributes storage info object.
@@ -1603,6 +1640,28 @@ function getPropertyTableFromExtFeatureMetadata(
1603
1640
  }
1604
1641
  }
1605
1642
 
1606
- console.warn("The I3S converter couldn't handle EXT_feature_metadata extension");
1643
+ if (extension?.featureTextures) {
1644
+ /**
1645
+ * Take only first feature texture to generate attributes storage info object.
1646
+ * TODO: Think about getting data from all feature textures?
1647
+ * It can be tricky just because 3dTiles is able to have multiple featureTextures.
1648
+ * In I3S we should decide which featureTextures will be passed to geometry data.
1649
+ */
1650
+ const firstTextureName = Object.keys(extension.featureTextures)?.[0];
1651
+ if (firstTextureName) {
1652
+ const featureTable = extension?.featureTextures[firstTextureName];
1653
+ const propertyTable = {};
1654
+
1655
+ for (const propertyName in featureTable.properties) {
1656
+ propertyTable[propertyName] = featureTable.properties[propertyName].data;
1657
+ }
1658
+
1659
+ return propertyTable;
1660
+ }
1661
+ }
1662
+
1663
+ console.warn(
1664
+ "The I3S converter couldn't handle EXT_feature_metadata extension: There is neither featureTables, no featureTextures in the extension."
1665
+ );
1607
1666
  return null;
1608
1667
  }