@loaders.gl/tile-converter 5.0.0-alpha.12 → 5.0.0-alpha.14

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 (132) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +4 -4
  3. package/dist/converter.min.cjs +149 -158
  4. package/dist/i3s-server/bin/i3s-server.min.cjs +113 -158
  5. package/dist/index.cjs +17486 -17479
  6. package/dist/index.js +25572 -25560
  7. package/dist/v5/adapters.cjs +540 -190
  8. package/dist/v5/adapters.d.ts +4 -0
  9. package/dist/v5/adapters.js +501 -151
  10. package/dist/v5/archive-source.d.ts +1 -1
  11. package/dist/v5/browser.d.ts +1 -1
  12. package/dist/v5/conversion-api.d.ts +25 -0
  13. package/dist/v5/converter-cli.js +23 -7
  14. package/dist/v5/core.cjs +76 -17
  15. package/dist/v5/core.d.ts +1 -1
  16. package/dist/v5/core.js +69 -10
  17. package/dist/v5/feature-arrow.d.ts +1 -1
  18. package/dist/v5/i3s-mesh-conversion.d.ts +1 -1
  19. package/dist/v5/i3s-mesh-source-features.d.ts +2 -2
  20. package/dist/v5/i3s-mesh-source-material.d.ts +1 -1
  21. package/dist/v5/i3s-mesh-source.d.ts +2 -2
  22. package/dist/v5/i3s-selection-source.d.ts +3 -3
  23. package/dist/v5/index.cjs +11 -6
  24. package/dist/v5/index.d.ts +5 -1
  25. package/dist/v5/index.js +8 -0
  26. package/dist/v5/mesh-conversion.d.ts +3 -3
  27. package/dist/v5/mesh-draco.d.ts +2 -2
  28. package/dist/v5/mesh-features.d.ts +2 -2
  29. package/dist/v5/mesh-source-features.d.ts +4 -4
  30. package/dist/v5/mesh-source-schema.d.ts +2 -2
  31. package/dist/v5/mesh-source-texture.d.ts +3 -3
  32. package/dist/v5/mesh-source.d.ts +5 -5
  33. package/dist/v5/mesh-tileset-sink.d.ts +1 -1
  34. package/dist/v5/mesh.d.ts +1 -1
  35. package/dist/v5/node-conversion.d.ts +2 -0
  36. package/dist/v5/node-i3s-source.d.ts +3 -3
  37. package/dist/v5/node-source.d.ts +1 -1
  38. package/dist/v5/node.cjs +19 -6
  39. package/dist/v5/node.js +19 -6
  40. package/dist/v5/point-cloud-attributes.d.ts +19 -0
  41. package/dist/v5/point-cloud-conversion.d.ts +1 -1
  42. package/dist/v5/point-cloud-copc.d.ts +44 -0
  43. package/dist/v5/point-cloud-file.d.ts +4 -4
  44. package/dist/v5/point-cloud-potree.d.ts +3 -3
  45. package/dist/v5/point-cloud-source-encoder.d.ts +1 -1
  46. package/dist/v5/point-cloud-source.d.ts +1 -1
  47. package/dist/v5/point-cloud-tileset.d.ts +3 -3
  48. package/dist/v5/point-cloud.d.ts +1 -1
  49. package/dist/v5/spatial-conversion.d.ts +1 -1
  50. package/dist/v5/tileset-source.d.ts +1 -1
  51. package/package.json +17 -32
  52. package/src/v4/3d-tiles-converter/3d-tiles-converter.ts +11 -12
  53. package/src/v4/3d-tiles-converter/helpers/3d-tiles-content-converter.ts +7 -3
  54. package/src/v4/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.ts +2 -2
  55. package/src/v4/3d-tiles-converter/helpers/load-i3s.ts +3 -3
  56. package/src/v4/3d-tiles-converter/helpers/texture-atlas.ts +1 -1
  57. package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +2 -2
  58. package/src/v4/3d-tiles-converter/json-templates/tileset.ts +58 -39
  59. package/src/v4/converter-cli.ts +3 -3
  60. package/src/v4/deps-installer/deps-installer.ts +3 -3
  61. package/src/v4/i3s-converter/helpers/attribute-metadata-info.ts +1 -1
  62. package/src/v4/i3s-converter/helpers/batch-ids-extensions.ts +9 -10
  63. package/src/v4/i3s-converter/helpers/conversion-gltf.ts +108 -0
  64. package/src/v4/i3s-converter/helpers/coordinate-converter.ts +6 -5
  65. package/src/v4/i3s-converter/helpers/create-scene-server-path.ts +5 -6
  66. package/src/v4/i3s-converter/helpers/feature-attributes.ts +4 -4
  67. package/src/v4/i3s-converter/helpers/geometry-attributes.ts +1 -1
  68. package/src/v4/i3s-converter/helpers/geometry-converter.ts +69 -77
  69. package/src/v4/i3s-converter/helpers/gltf-attributes.ts +58 -74
  70. package/src/v4/i3s-converter/helpers/load-3d-tiles.ts +5 -5
  71. package/src/v4/i3s-converter/helpers/node-debug.ts +7 -3
  72. package/src/v4/i3s-converter/helpers/node-index-document.ts +6 -7
  73. package/src/v4/i3s-converter/helpers/node-pages.ts +3 -4
  74. package/src/v4/i3s-converter/helpers/preprocess-3d-tiles.ts +1 -1
  75. package/src/v4/i3s-converter/helpers/tileset-traversal.ts +1 -1
  76. package/src/v4/i3s-converter/i3s-converter.ts +29 -31
  77. package/src/v4/i3s-converter/json-templates/geometry-definitions.ts +71 -66
  78. package/src/v4/i3s-converter/json-templates/layers.ts +97 -132
  79. package/src/v4/i3s-converter/json-templates/metadata.ts +31 -21
  80. package/src/v4/i3s-converter/json-templates/node.ts +60 -74
  81. package/src/v4/i3s-converter/json-templates/scene-server.ts +36 -27
  82. package/src/v4/i3s-converter/json-templates/shared-resources.ts +62 -123
  83. package/src/v4/i3s-converter/json-templates/store.ts +39 -58
  84. package/src/v4/i3s-converter/types.ts +4 -4
  85. package/src/v4/i3s-server/controllers/slpk-controller.ts +3 -3
  86. package/src/v4/i3s-server/utils/create-scene-server.ts +3 -3
  87. package/src/v4/lib/utils/builder-input.ts +8 -0
  88. package/src/v4/lib/utils/conversion-dump.ts +5 -1
  89. package/src/v4/lib/utils/file-utils.ts +1 -1
  90. package/src/v4/lib/utils/hash-string.ts +21 -0
  91. package/src/v4/lib/utils/lod-conversion-utils.ts +3 -3
  92. package/src/v4/pgm-loader.ts +2 -2
  93. package/src/v5/adapters.ts +5 -0
  94. package/src/v5/archive-source.ts +4 -4
  95. package/src/v5/browser.ts +1 -0
  96. package/src/v5/conversion-api.ts +115 -8
  97. package/src/v5/conversion-archive.ts +2 -2
  98. package/src/v5/core.ts +1 -0
  99. package/src/v5/feature-arrow.ts +2 -2
  100. package/src/v5/i3s-mesh-conversion.ts +2 -2
  101. package/src/v5/i3s-mesh-source-features.ts +3 -3
  102. package/src/v5/i3s-mesh-source-material.ts +18 -11
  103. package/src/v5/i3s-mesh-source.ts +2 -2
  104. package/src/v5/i3s-selection-source.ts +4 -4
  105. package/src/v5/index.ts +15 -0
  106. package/src/v5/mesh-conversion.ts +4 -4
  107. package/src/v5/mesh-draco.ts +2 -2
  108. package/src/v5/mesh-features.ts +3 -3
  109. package/src/v5/mesh-hierarchy.ts +1 -1
  110. package/src/v5/mesh-source-features.ts +137 -55
  111. package/src/v5/mesh-source-schema.ts +10 -4
  112. package/src/v5/mesh-source-texture.ts +49 -19
  113. package/src/v5/mesh-source.ts +65 -46
  114. package/src/v5/mesh-tileset-archive.ts +1 -1
  115. package/src/v5/mesh-tileset-sink.ts +1 -1
  116. package/src/v5/mesh.ts +1 -1
  117. package/src/v5/node-cli.ts +4 -0
  118. package/src/v5/node-conversion.ts +19 -2
  119. package/src/v5/node-source.ts +2 -2
  120. package/src/v5/point-cloud-attributes.ts +113 -0
  121. package/src/v5/point-cloud-conversion.ts +1 -1
  122. package/src/v5/point-cloud-copc.ts +289 -0
  123. package/src/v5/point-cloud-file.ts +8 -8
  124. package/src/v5/point-cloud-potree.ts +8 -4
  125. package/src/v5/point-cloud-source-encoder.ts +1 -1
  126. package/src/v5/point-cloud-source.ts +1 -1
  127. package/src/v5/point-cloud-spatial.ts +2 -2
  128. package/src/v5/point-cloud-tileset.ts +4 -4
  129. package/src/v5/point-cloud.ts +3 -3
  130. package/src/v5/selected-mesh-source.ts +4 -4
  131. package/src/v5/spatial-conversion.ts +2 -2
  132. package/src/v5/tileset-source.ts +2 -2
@@ -1,12 +1,15 @@
1
+ import {getConversionMaterials} from './conversion-gltf';
2
+ import type {
3
+ ConversionAccessor,
4
+ ConversionMaterial,
5
+ ConversionNode,
6
+ ConversionPrimitive,
7
+ ConversionMesh,
8
+ ConversionTexture
9
+ } from './conversion-gltf';
1
10
  /* eslint-disable camelcase */
2
- import type {FeatureTableJson, Tiles3DTileContent} from '@loaders.gl/3d-tiles';
11
+ import type {FeatureTableJson, Tiles3DTileContent} from '@loaders.gl/tiles-3d/3d-tiles';
3
12
  import type {
4
- GLTFAccessorPostprocessed,
5
- GLTFMaterialPostprocessed,
6
- GLTFNodePostprocessed,
7
- GLTFMeshPrimitivePostprocessed,
8
- GLTFMeshPostprocessed,
9
- GLTFTexturePostprocessed,
10
13
  GLTF_EXT_feature_metadata_GLTF,
11
14
  GLTF_EXT_feature_metadata_FeatureTable,
12
15
  GLTF_EXT_feature_metadata_FeatureTexture,
@@ -23,15 +26,15 @@ import {createRequire} from 'node:module';
23
26
  /* @ts-expect-error TS2732: Cannot find module 'node:module' or its corresponding type declarations. */
24
27
 
25
28
  import {DracoWriterWorker} from '@loaders.gl/draco';
26
- import {assert, encode} from '@loaders.gl/core';
29
+ import {encode, assert} from '@loaders.gl/core';
27
30
  import {
28
31
  concatenateArrayBuffers,
29
32
  concatenateTypedArrays,
30
33
  NumberArray,
31
34
  TypedArray
32
- } from '@loaders.gl/loader-utils';
33
- import md5 from 'md5';
34
- import {v4 as uuidv4} from 'uuid';
35
+ } from '@loaders.gl/core/loader-utils';
36
+ import {hashString} from '../../lib/utils/hash-string';
37
+ import {randomUUID} from 'node:crypto';
35
38
  import {generateAttributes} from './geometry-attributes';
36
39
  import {encodeStringAttribute} from './encode-string-attribute';
37
40
  import {createBoundingVolumesFromGeometry} from './coordinate-converter';
@@ -47,21 +50,21 @@ import {
47
50
  I3SMaterialDefinition,
48
51
  MaterialDefinitionInfo,
49
52
  TextureDefinitionInfo
50
- } from '@loaders.gl/i3s';
51
- import {Geoid} from '@math.gl/geoid';
53
+ } from '@loaders.gl/tiles-3d/i3s';
54
+ import {Geoid} from '@math.gl/earth/geoid';
52
55
  import {prepareDataForAttributesConversion} from './gltf-attributes';
53
56
  import {getTextureByMetadataClass, handleBatchIdsExtensions} from './batch-ids-extensions';
54
57
  import {checkPropertiesLength, flattenPropertyTableByFeatureIds} from './feature-attributes';
55
- import {GL} from '@math.gl/geometry-utils';
58
+ import {GL} from '@math.gl/geometry/utils';
56
59
 
57
60
  /*
58
- At the moment of writing the type TypedArrayConstructor is not exported in '@math.gl/types'.
61
+ At the moment of writing the type TypedArrayConstructor is not exported in '@math.gl/core/types'.
59
62
  So the following import is replaced with the local import
60
- import type {TypedArrayConstructor} from '@math.gl/types';
63
+ import type {TypedArrayConstructor} from '@math.gl/core/types';
61
64
  */
62
- import type {GLTFAttributesData, TextureImageProperties, TypedArrayConstructor} from '../types';
65
+ import type {GLTFAttributesData, TextureImageProperties} from '../types';
63
66
  import {generateSyntheticIndices} from '../../lib/utils/geometry-utils';
64
- import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
67
+ import {BoundingSphere, OrientedBoundingBox} from '@math.gl/geometry/culling';
65
68
 
66
69
  import {EXT_FEATURE_METADATA, EXT_STRUCTURAL_METADATA} from '@loaders.gl/gltf';
67
70
 
@@ -136,7 +139,7 @@ export default async function convertB3dmToI3sGeometry({
136
139
  }): Promise<I3SConvertedResources[] | null> {
137
140
  const useCartesianPositions = generateBoundingVolumes;
138
141
  const materialAndTextureList: I3SMaterialWithTexture[] = await convertMaterials(
139
- tileContent.gltf?.materials,
142
+ tileContent.gltf ? getConversionMaterials(tileContent.gltf) : [],
140
143
  shouldMergeMaterials
141
144
  );
142
145
 
@@ -339,7 +342,10 @@ async function _makeNodeResources({
339
342
  compressedGeometry,
340
343
  texture,
341
344
  hasUvRegions: Boolean(uvRegions.length),
342
- sharedResources: getSharedResources(tileContent.gltf?.materials || [], nodeId),
345
+ sharedResources: getSharedResources(
346
+ tileContent.gltf ? getConversionMaterials(tileContent.gltf) : [],
347
+ nodeId
348
+ ),
343
349
  meshMaterial: material,
344
350
  vertexCount,
345
351
  attributes,
@@ -437,7 +443,7 @@ function convertNodes({
437
443
  matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
438
444
  featureTexture
439
445
  }: {
440
- nodes: GLTFNodePostprocessed[];
446
+ nodes: ConversionNode[];
441
447
  images: (TextureImageProperties | null)[];
442
448
  cartographicOrigin: Vector3;
443
449
  cartesianModelMatrix: Matrix4;
@@ -468,7 +474,7 @@ function convertNodes({
468
474
  * @param node
469
475
  * @param matrix
470
476
  */
471
- function getCompositeTransformationMatrix(node: GLTFNodePostprocessed, matrix: Matrix4) {
477
+ function getCompositeTransformationMatrix(node: ConversionNode, matrix: Matrix4) {
472
478
  let transformationMatrix = matrix;
473
479
 
474
480
  const {matrix: nodeMatrix, rotation, scale, translation} = node;
@@ -515,7 +521,7 @@ function convertNode({
515
521
  matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
516
522
  featureTexture
517
523
  }: {
518
- node: GLTFNodePostprocessed;
524
+ node: ConversionNode;
519
525
  images: (TextureImageProperties | null)[];
520
526
  cartographicOrigin: Vector3;
521
527
  cartesianModelMatrix: Matrix4;
@@ -578,7 +584,7 @@ function convertMeshToTable({
578
584
  matrix,
579
585
  featureTexture
580
586
  }: {
581
- mesh: GLTFMeshPostprocessed;
587
+ mesh: ConversionMesh;
582
588
  images: (TextureImageProperties | null)[];
583
589
  cartographicOrigin: Vector3;
584
590
  cartesianModelMatrix: Matrix4;
@@ -604,7 +610,8 @@ function convertMeshToTable({
604
610
  assert(
605
611
  primitive.mode === undefined ||
606
612
  primitive.mode === GL.TRIANGLES ||
607
- primitive.mode === GL.TRIANGLE_STRIP,
613
+ primitive.mode === GL.TRIANGLE_STRIP ||
614
+ primitive.mode === GL.TRIANGLE_FAN,
608
615
  `Primitive - unsupported mode ${primitive.mode}`
609
616
  );
610
617
  const attributes = primitive.attributes;
@@ -661,44 +668,32 @@ function convertMeshToTable({
661
668
  }
662
669
  }
663
670
  /**
664
- * Converts TRIANGLE-STRIPS to independent TRIANGLES
671
+ * Converts triangle strips and fans to independent triangles
665
672
  * @param primitive - the primitive to get the indices from
666
673
  * @returns indices of vertices of the independent triangles
667
674
  */
668
- function normalizeIndices(primitive: GLTFMeshPrimitivePostprocessed): TypedArray {
669
- let indices: TypedArray | undefined = primitive.indices?.value;
670
- if (!indices) {
671
- const positions = primitive.attributes.POSITION.value;
672
- return generateSyntheticIndices(positions.length / VALUES_PER_VERTEX);
673
- }
674
-
675
- if (indices && primitive.mode === GL.TRIANGLE_STRIP) {
676
- /*
677
- TRIANGLE_STRIP geometry contains n+2 vertices for n triangles;
678
- TRIANGLE geometry contains n*3 vertices for n triangles.
679
- The conversion from TRIANGLE_STRIP to TRIANGLE implies duplicating adjacent vertices.
680
- */
681
- const TypedArrayConstructor = indices.constructor as TypedArrayConstructor;
682
- const newIndices = new TypedArrayConstructor((indices.length - 2) * 3);
683
-
684
- // Copy the first triangle indices with no modification like [i0, i1, i2, ...] -> [i0, i1, i2, ...]
685
- let triangleIndex = 0;
686
- let currentTriangle = indices.slice(0, 3);
687
- newIndices.set(currentTriangle, 0);
688
-
689
- // The rest triangle indices are being taken from strips using the following logic:
690
- // [i1, i2, i3, i4, i5, i6, ...] -> [i3, i2, i1, i2, i3, i4, i5, i4, i3, i4, i5, i6, ...]
691
- for (let i = 1; i + 2 < indices.length; i++) {
692
- triangleIndex += 3;
693
- currentTriangle = indices.slice(i, i + 3);
694
- if (i % 2 === 0) {
695
- newIndices.set(currentTriangle, triangleIndex);
696
- } else {
697
- // The following "reverce" is necessary to calculate normals correctly
698
- newIndices.set(currentTriangle.reverse(), triangleIndex);
699
- }
700
- }
701
- indices = newIndices;
675
+ function normalizeIndices(primitive: ConversionPrimitive): TypedArray {
676
+ const source = primitive.indices?.value;
677
+ const vertexCount = primitive.attributes.POSITION.value.length / VALUES_PER_VERTEX;
678
+ const count = source?.length ?? vertexCount;
679
+ if (primitive.mode !== GL.TRIANGLE_STRIP && primitive.mode !== GL.TRIANGLE_FAN) {
680
+ return source || generateSyntheticIndices(vertexCount);
681
+ }
682
+ const indices = new Uint32Array(Math.max(0, count - 2) * 3);
683
+ for (let triangleIndex = 0; triangleIndex + 2 < count; triangleIndex++) {
684
+ const first = primitive.mode === GL.TRIANGLE_FAN ? 0 : triangleIndex;
685
+ const second =
686
+ primitive.mode === GL.TRIANGLE_FAN
687
+ ? triangleIndex + 1
688
+ : triangleIndex + 1 + (triangleIndex % 2);
689
+ const third =
690
+ primitive.mode === GL.TRIANGLE_FAN
691
+ ? triangleIndex + 2
692
+ : triangleIndex + 2 - (triangleIndex % 2);
693
+ indices.set(
694
+ [source?.[first] ?? first, source?.[second] ?? second, source?.[third] ?? third],
695
+ triangleIndex * 3
696
+ );
702
697
  }
703
698
  return indices;
704
699
  }
@@ -822,10 +817,7 @@ function flattenTexCoords(texCoords: TypedArray, indices: TypedArray): Float32Ar
822
817
  * @param indices - gltf primitive indices
823
818
  * @returns flattened colors attribute
824
819
  */
825
- function flattenColors(
826
- colorsAttribute: GLTFAccessorPostprocessed,
827
- indices: TypedArray
828
- ): Uint8Array {
820
+ function flattenColors(colorsAttribute: ConversionAccessor, indices: TypedArray): Uint8Array {
829
821
  const components = colorsAttribute?.components || VALUES_PER_COLOR_ELEMENT;
830
822
  const newColors = new Uint8Array(indices.length * components);
831
823
  if (!colorsAttribute) {
@@ -888,9 +880,9 @@ function flattenBatchIds(batchedIds: NumberArray, indices: TypedArray): number[]
888
880
  */
889
881
  function getBatchIds(
890
882
  attributes: {
891
- [key: string]: GLTFAccessorPostprocessed;
883
+ [key: string]: ConversionAccessor;
892
884
  },
893
- primitive: GLTFMeshPrimitivePostprocessed,
885
+ primitive: ConversionPrimitive,
894
886
  images: (TextureImageProperties | null)[],
895
887
  featureTexture: string | null
896
888
  ): NumberArray {
@@ -926,7 +918,7 @@ function getBatchIds(
926
918
  * @returns Array of Couples I3SMaterialDefinition + texture content
927
919
  */
928
920
  async function convertMaterials(
929
- sourceMaterials: GLTFMaterialPostprocessed[] = [],
921
+ sourceMaterials: ConversionMaterial[] = [],
930
922
  shouldMergeMaterials: boolean
931
923
  ): Promise<I3SMaterialWithTexture[]> {
932
924
  let materials: I3SMaterialWithTexture[] = [];
@@ -1059,7 +1051,7 @@ async function mergeMaterials(
1059
1051
  * @param sourceMaterial - material object
1060
1052
  * @returns I3S material definition and texture
1061
1053
  */
1062
- export function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterialWithTexture {
1054
+ export function convertMaterial(sourceMaterial: ConversionMaterial): I3SMaterialWithTexture {
1063
1055
  const material: I3SMaterialDefinition = {
1064
1056
  doubleSided: sourceMaterial.doubleSided,
1065
1057
  emissiveFactor: sourceMaterial.emissiveFactor?.map(c => Math.round(c * 255)) as [
@@ -1092,7 +1084,7 @@ export function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SM
1092
1084
  };
1093
1085
  }
1094
1086
 
1095
- sourceMaterial.id = Number.isFinite(sourceMaterial.id) ? sourceMaterial.id : uuidv4();
1087
+ sourceMaterial.id ||= randomUUID();
1096
1088
  const mergedMaterials: MergedMaterial[] = [{originalMaterialId: sourceMaterial.id}];
1097
1089
  if (!texture) {
1098
1090
  // Should use default baseColorFactor if it is not present in source material
@@ -1156,7 +1148,7 @@ function getDefaultMaterial(): I3SMaterialDefinition {
1156
1148
  * 2 arrays in format of i3s sharedResources data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/sharedResource.cmn.md
1157
1149
  */
1158
1150
  function getSharedResources(
1159
- gltfMaterials: GLTFMaterialPostprocessed[],
1151
+ gltfMaterials: ConversionMaterial[],
1160
1152
  nodeId: number
1161
1153
  ): SharedResourcesArrays {
1162
1154
  const i3sResources: SharedResourcesArrays = {};
@@ -1187,7 +1179,7 @@ function getSharedResources(
1187
1179
  * @returns - Couple {materialDefinitionInfo, textureDefinitionInfo} extracted from gltf material data
1188
1180
  */
1189
1181
  function convertGLTFMaterialToI3sSharedResources(
1190
- gltfMaterial: GLTFMaterialPostprocessed,
1182
+ gltfMaterial: ConversionMaterial,
1191
1183
  nodeId: number
1192
1184
  ): {
1193
1185
  materialDefinitionInfo: MaterialDefinitionInfo;
@@ -1270,7 +1262,7 @@ function extractSharedResourcesMaterialInfo(
1270
1262
  * @returns texture definition infor for shared resource
1271
1263
  */
1272
1264
  function extractSharedResourcesTextureInfo(
1273
- texture: GLTFTexturePostprocessed,
1265
+ texture: ConversionTexture,
1274
1266
  nodeId: number
1275
1267
  ): TextureDefinitionInfo {
1276
1268
  return {
@@ -1294,7 +1286,7 @@ function extractSharedResourcesTextureInfo(
1294
1286
  * @param nodeId - I3S node ID
1295
1287
  * @returns calculate image ID according to the spec
1296
1288
  */
1297
- function generateImageId(texture: GLTFTexturePostprocessed, nodeId: number) {
1289
+ function generateImageId(texture: ConversionTexture, nodeId: number) {
1298
1290
  const {width, height} = texture.source?.image || {};
1299
1291
  if (!width || !height) {
1300
1292
  return '';
@@ -1386,7 +1378,7 @@ function getOrCreateUniqueFeatureId(
1386
1378
  featuresHashArray: any[]
1387
1379
  ): number {
1388
1380
  const batchTableStr = generateStringFromBatchTableByIndex(batchTable, index);
1389
- const hash = md5(batchTableStr);
1381
+ const hash = hashString(batchTableStr);
1390
1382
 
1391
1383
  if (featuresHashArray.includes(hash)) {
1392
1384
  return featuresHashArray.indexOf(hash);
@@ -1797,14 +1789,14 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
1797
1789
  extension: string | GLTF_EXT_feature_metadata_GLTF | GLTF_EXT_structural_metadata_GLTF | null;
1798
1790
  } {
1799
1791
  const extensionsWithPropertyTables = [EXT_FEATURE_METADATA, EXT_STRUCTURAL_METADATA];
1800
- const extensionsUsed = tileContent?.gltf?.extensionsUsed;
1792
+ const extensionsUsed = tileContent?.gltf?.json.extensionsUsed;
1801
1793
 
1802
1794
  if (!extensionsUsed) {
1803
1795
  return {extensionName: null, extension: null};
1804
1796
  }
1805
1797
 
1806
1798
  let extensionName: string = '';
1807
- for (const extensionItem of tileContent?.gltf?.extensionsUsed || []) {
1799
+ for (const extensionItem of tileContent?.gltf?.json.extensionsUsed || []) {
1808
1800
  if (extensionsWithPropertyTables.includes(extensionItem)) {
1809
1801
  extensionName = extensionItem;
1810
1802
  /*
@@ -1821,7 +1813,7 @@ function getPropertyTableExtension(tileContent: Tiles3DTileContent): {
1821
1813
  return {extensionName: null, extension: null};
1822
1814
  }
1823
1815
 
1824
- const extension = tileContent?.gltf?.extensions?.[extensionName] as
1816
+ const extension = tileContent?.gltf?.json.extensions?.[extensionName] as
1825
1817
  | string // EXT_mesh_features doesn't have global metadata
1826
1818
  | GLTF_EXT_feature_metadata_GLTF
1827
1819
  | GLTF_EXT_structural_metadata_GLTF;
@@ -1,7 +1,9 @@
1
- import type {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
2
- import type {GLTFAccessorPostprocessed, GLTFNodePostprocessed} from '@loaders.gl/gltf';
3
- import {Matrix4, TypedArray, Vector3} from '@math.gl/core';
4
- import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
1
+ import {getConversionAccessor} from './conversion-gltf';
2
+ import type {GLTFWithBuffers} from '@loaders.gl/gltf';
3
+ import type {ConversionNode} from './conversion-gltf';
4
+ import type {Tiles3DTileContent} from '@loaders.gl/tiles-3d/3d-tiles';
5
+ import {Matrix4, Vector3} from '@math.gl/core';
6
+ import {BoundingSphere, OrientedBoundingBox} from '@math.gl/geometry/culling';
5
7
  import {getImageData} from '@loaders.gl/images';
6
8
  import {Ellipsoid} from '@math.gl/geospatial';
7
9
  import {GLTFAttributesData} from '../types';
@@ -19,32 +21,26 @@ export function prepareDataForAttributesConversion(
19
21
  tileTransform: Matrix4,
20
22
  boundingVolume: OrientedBoundingBox | BoundingSphere
21
23
  ): GLTFAttributesData {
22
- const nodes =
23
- tileContent.gltf?.scene?.nodes ||
24
- tileContent.gltf?.scenes?.[0]?.nodes ||
25
- tileContent.gltf?.nodes ||
24
+ const gltf = tileContent.gltf;
25
+ const json = gltf?.json;
26
+ const roots =
27
+ (json?.scene === undefined ? undefined : json.scenes?.[json.scene]?.nodes) ||
28
+ json?.scenes?.[0]?.nodes ||
29
+ json?.nodes?.map((_, index) => index) ||
26
30
  [];
27
-
28
- const images =
29
- tileContent.gltf?.images?.map(imageObject => {
30
- // Need data only for uncompressed images because we can't get batchIds from compressed textures.
31
- if (imageObject?.image?.compressed) {
32
- return null;
33
- }
34
- const {data, width, height} = getImageData(imageObject.image);
35
- const dataCopy = new Uint8Array(data.length);
36
- dataCopy.set(data);
37
- return {
38
- data: dataCopy,
39
- compressed: false,
40
- height,
41
- width,
42
- components: data.length / (width * height),
43
- mimeType: imageObject.mimeType
44
- };
45
- }) || [];
46
-
47
- prepareNodes(nodes);
31
+ const nodes = gltf ? prepareNodes(gltf, roots) : [];
32
+ const images = (gltf?.images || []).map((image, index) => {
33
+ if (!image || (image as any).compressed) return null;
34
+ const {data, width, height} = getImageData(image);
35
+ return {
36
+ data: Uint8Array.from(data),
37
+ compressed: false,
38
+ height,
39
+ width,
40
+ components: data.length / (width * height),
41
+ mimeType: json?.images?.[index]?.mimeType
42
+ };
43
+ });
48
44
 
49
45
  const {cartographicOrigin, modelMatrix: cartesianModelMatrix} = calculateTransformProps(
50
46
  tileContent,
@@ -60,25 +56,6 @@ export function prepareDataForAttributesConversion(
60
56
  };
61
57
  }
62
58
 
63
- /**
64
- * Keep only values for glTF attributes to pass data to worker thread.
65
- * @param attributes - geometry attributes
66
- * @returns attributes with only `value` item
67
- */
68
- function getB3DMAttributesWithoutBufferView(
69
- attributes: Record<string, GLTFAccessorPostprocessed>
70
- ): Record<string, {value: TypedArray}> {
71
- const attributesWithoutBufferView: Record<string, {value: TypedArray}> = {};
72
-
73
- for (const attributeName in attributes) {
74
- attributesWithoutBufferView[attributeName] = {
75
- value: attributes[attributeName].value
76
- };
77
- }
78
-
79
- return attributesWithoutBufferView;
80
- }
81
-
82
59
  /**
83
60
  * Calculate transformation properties to transform vertex attributes (POSITION, NORMAL, etc.)
84
61
  * from METER_OFFSET coorditantes to LNGLAT_OFFSET coordinates
@@ -133,30 +110,37 @@ export function calculateTransformProps(
133
110
  * Traverse all nodes to replace all sensible data with copy to avoid data corruption in worker.
134
111
  * @param nodes
135
112
  */
136
- function prepareNodes(nodes: GLTFNodePostprocessed[]): void {
137
- for (let index = 0; index < nodes.length; index++) {
138
- const node = nodes[index] as any;
139
-
140
- if (node.mesh) {
141
- nodes[index] = {
142
- ...node,
143
- mesh: {
144
- ...node.mesh,
145
- primitives: node.mesh?.primitives.map(primitive => ({
146
- ...primitive,
147
- indices: {value: primitive?.indices?.value},
148
- attributes: getB3DMAttributesWithoutBufferView(primitive.attributes),
149
- material: {
150
- id: primitive?.material?.id,
151
- uniqueId: primitive?.material?.uniqueId
152
- }
153
- }))
154
- }
155
- };
156
- }
157
-
158
- if (node.children) {
159
- prepareNodes(node.children);
160
- }
161
- }
113
+ function prepareNodes(
114
+ gltf: GLTFWithBuffers,
115
+ indices: number[],
116
+ ancestors = new Set<number>()
117
+ ): ConversionNode[] {
118
+ return indices.map(index => {
119
+ if (ancestors.has(index)) throw new Error('Cyclic glTF node hierarchy');
120
+ const node = gltf.json.nodes![index];
121
+ const mesh = node.mesh === undefined ? undefined : gltf.json.meshes?.[node.mesh];
122
+ return {
123
+ ...node,
124
+ mesh: mesh
125
+ ? {
126
+ primitives: mesh.primitives.map(primitive => ({
127
+ ...primitive,
128
+ indices:
129
+ primitive.indices === undefined
130
+ ? undefined
131
+ : getConversionAccessor(gltf, primitive.indices),
132
+ attributes: Object.fromEntries(
133
+ Object.entries(primitive.attributes).map(([name, reference]) => [
134
+ name,
135
+ getConversionAccessor(gltf, reference)
136
+ ])
137
+ ),
138
+ material:
139
+ primitive.material === undefined ? undefined : {id: String(primitive.material)}
140
+ }))
141
+ }
142
+ : undefined,
143
+ children: prepareNodes(gltf, node.children || [], new Set([...ancestors, index]))
144
+ };
145
+ });
162
146
  }
@@ -3,12 +3,12 @@ import type {
3
3
  Tiles3DTileContent,
4
4
  Tiles3DTileJSONPostprocessed,
5
5
  Tiles3DTilesetJSONPostprocessed
6
- } from '@loaders.gl/3d-tiles';
7
- import {parse3DTilesArchive} from '@loaders.gl/3d-tiles';
6
+ } from '@loaders.gl/tiles-3d/3d-tiles';
7
+ import {parse3DTilesArchive} from '@loaders.gl/tiles-3d/3d-tiles';
8
8
  import {LoaderWithParser, load} from '@loaders.gl/core';
9
- import type {ReadableFile} from '@loaders.gl/loader-utils';
10
- import {HttpFile, NodeFile, isBrowser} from '@loaders.gl/loader-utils';
11
- import {ZipFileSystem} from '@loaders.gl/zip';
9
+ import type {ReadableFile} from '@loaders.gl/core/loader-utils';
10
+ import {HttpFile, NodeFile, isBrowser} from '@loaders.gl/core/loader-utils';
11
+ import {ZipFileSystem} from '@loaders.gl/archives/zip';
12
12
 
13
13
  /**
14
14
  * Load nested 3DTiles tileset. If the sourceTile is not nested tileset - do nothing
@@ -1,5 +1,9 @@
1
- import type {Mbs, Node3DIndexDocument, Obb} from '@loaders.gl/i3s';
2
- import {OrientedBoundingBox, BoundingSphere} from '@math.gl/culling';
1
+ import type {Mbs, Node3DIndexDocument, Obb} from '@loaders.gl/tiles-3d/i3s';
2
+ import {
3
+ OrientedBoundingBox,
4
+ BoundingSphere,
5
+ makeOrientedBoundingBoxFromQuaternion
6
+ } from '@math.gl/geometry/culling';
3
7
  import {Vector3} from '@math.gl/core';
4
8
  import {Ellipsoid} from '@math.gl/geospatial';
5
9
 
@@ -85,7 +89,7 @@ function createBoundingSphereFromTileMbs(mbs: Mbs): BoundingSphere {
85
89
  */
86
90
  function createBoundingBoxFromTileObb(obb: Obb): OrientedBoundingBox {
87
91
  const {center, halfSize, quaternion} = obb;
88
- return new OrientedBoundingBox().fromCenterHalfSizeQuaternion(center, halfSize, quaternion);
92
+ return makeOrientedBoundingBoxFromQuaternion(center, halfSize, quaternion);
89
93
  }
90
94
 
91
95
  /**
@@ -5,12 +5,11 @@ import {
5
5
  Node3DIndexDocument,
6
6
  NodeInPage,
7
7
  NodeReference
8
- } from '@loaders.gl/i3s';
9
- import transform from 'json-map-transform';
10
- import {v4 as uuidv4} from 'uuid';
8
+ } from '@loaders.gl/tiles-3d/i3s';
9
+ import {randomUUID} from 'node:crypto';
11
10
  import {openJson, writeFileForSlpk} from '../../lib/utils/file-utils';
12
11
  import I3SConverter from '../i3s-converter';
13
- import {NODE as nodeTemplate} from '../json-templates/node';
12
+ import {createNode} from '../json-templates/node';
14
13
  import {I3SConvertedResources} from '../types';
15
14
  import {DumpMetadata} from '../../lib/utils/conversion-dump';
16
15
 
@@ -253,7 +252,7 @@ export class NodeIndexDocument {
253
252
  */
254
253
  static createRootNodeIndexDocument(boundingVolumes: BoundingVolumes): Node3DIndexDocument {
255
254
  const root0data = {
256
- version: `{${uuidv4().toUpperCase()}}`,
255
+ version: `{${randomUUID().toUpperCase()}}`,
257
256
  id: 'root',
258
257
  level: 0,
259
258
  lodSelection: [
@@ -269,7 +268,7 @@ export class NodeIndexDocument {
269
268
  ...boundingVolumes,
270
269
  children: []
271
270
  };
272
- return transform(root0data, nodeTemplate());
271
+ return createNode(root0data);
273
272
  }
274
273
 
275
274
  /**
@@ -308,7 +307,7 @@ export class NodeIndexDocument {
308
307
  children: [],
309
308
  neighbors: []
310
309
  };
311
- const node = transform(nodeData, nodeTemplate());
310
+ const node = createNode(nodeData);
312
311
 
313
312
  if (nodeInPage.mesh) {
314
313
  node.geometryData = [{href: './geometries/0'}];
@@ -1,7 +1,6 @@
1
1
  import {join} from 'path';
2
- import transform from 'json-map-transform';
3
- import {METADATA as metadataTemplate} from '../json-templates/metadata';
4
- import {NodeInPage} from '@loaders.gl/i3s';
2
+ import {createMetadata} from '../json-templates/metadata';
3
+ import {NodeInPage} from '@loaders.gl/tiles-3d/i3s';
5
4
  import {isFileExists, openJson} from '../../lib/utils/file-utils';
6
5
  import I3SConverter from '../i3s-converter';
7
6
 
@@ -197,7 +196,7 @@ export default class NodePages {
197
196
  * Save metadata file (for slpk only)
198
197
  */
199
198
  async saveMetadata(): Promise<void> {
200
- const metadata = transform({nodeCount: this.nodesCounter}, metadataTemplate());
199
+ const metadata = createMetadata({nodeCount: this.nodesCounter});
201
200
  const compress = false;
202
201
  await this.converter.writeQueue.enqueue({
203
202
  archiveKey: 'metadata.json',
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- import {Tiles3DTileContent} from '@loaders.gl/3d-tiles';
2
+ import {Tiles3DTileContent} from '@loaders.gl/tiles-3d/3d-tiles';
3
3
  import {GLTFPrimitiveModeString, PreprocessData} from '../types';
4
4
  import {
5
5
  EXT_STRUCTURAL_METADATA,
@@ -1,4 +1,4 @@
1
- import {Tiles3DTileJSONPostprocessed} from '@loaders.gl/3d-tiles';
1
+ import {Tiles3DTileJSONPostprocessed} from '@loaders.gl/tiles-3d/3d-tiles';
2
2
  import {NodeIndexDocument} from './node-index-document';
3
3
  import {Matrix4} from '@math.gl/core';
4
4