@loaders.gl/tile-converter 3.1.8 → 3.2.0-alpha.3

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 (238) hide show
  1. package/dist/3d-tiles-attributes-worker.d.ts +28 -0
  2. package/dist/3d-tiles-attributes-worker.d.ts.map +1 -0
  3. package/dist/3d-tiles-attributes-worker.js +4 -0
  4. package/dist/3d-tiles-attributes-worker.js.map +7 -0
  5. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +82 -0
  6. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -0
  7. package/dist/3d-tiles-converter/3d-tiles-converter.js +268 -0
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +84 -0
  9. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -0
  10. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +278 -0
  11. package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.d.ts +13 -0
  12. package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.d.ts.map +1 -0
  13. package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +23 -0
  14. package/dist/3d-tiles-converter/helpers/texture-atlas.d.ts +9 -0
  15. package/dist/3d-tiles-converter/helpers/texture-atlas.d.ts.map +1 -0
  16. package/dist/3d-tiles-converter/helpers/texture-atlas.js +52 -0
  17. package/dist/3d-tiles-converter/json-templates/tileset.d.ts +15 -0
  18. package/dist/3d-tiles-converter/json-templates/tileset.d.ts.map +1 -0
  19. package/dist/3d-tiles-converter/json-templates/tileset.js +43 -0
  20. package/dist/bundle.d.ts +2 -0
  21. package/dist/bundle.d.ts.map +1 -0
  22. package/dist/bundle.js +5 -0
  23. package/dist/converter-cli.d.ts +2 -0
  24. package/dist/converter-cli.d.ts.map +1 -0
  25. package/dist/converter-cli.js +232 -0
  26. package/dist/converter.min.js +68 -68
  27. package/dist/deps-installer/deps-installer.d.ts +14 -0
  28. package/dist/deps-installer/deps-installer.d.ts.map +1 -0
  29. package/dist/deps-installer/deps-installer.js +31 -0
  30. package/dist/dist.min.js +1151 -1264
  31. package/dist/es5/3d-tiles-attributes-worker.js +29 -0
  32. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -0
  33. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +104 -44
  34. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  35. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +34 -43
  36. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  37. package/dist/es5/converter-cli.js +306 -0
  38. package/dist/es5/converter-cli.js.map +1 -0
  39. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  40. package/dist/es5/i3s-attributes-worker.js +29 -0
  41. package/dist/es5/i3s-attributes-worker.js.map +1 -0
  42. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +19 -11
  43. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  44. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +2 -2
  45. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  46. package/dist/es5/i3s-converter/helpers/geometry-converter.js +271 -182
  47. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  48. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +71 -0
  49. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  50. package/dist/es5/i3s-converter/helpers/node-pages.js +47 -99
  51. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  52. package/dist/es5/i3s-converter/i3s-converter.js +311 -245
  53. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  54. package/dist/es5/index.js +0 -16
  55. package/dist/es5/index.js.map +1 -1
  56. package/dist/es5/lib/utils/compress-util.js +14 -17
  57. package/dist/es5/lib/utils/compress-util.js.map +1 -1
  58. package/dist/es5/lib/utils/file-utils.js +39 -14
  59. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  60. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  61. package/dist/es5/lib/utils/queue.js +61 -0
  62. package/dist/es5/lib/utils/queue.js.map +1 -0
  63. package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
  64. package/dist/es5/lib/utils/write-queue.js +225 -0
  65. package/dist/es5/lib/utils/write-queue.js.map +1 -0
  66. package/dist/es5/pgm-loader.js +1 -1
  67. package/dist/es5/pgm-loader.js.map +1 -1
  68. package/dist/es5/workers/3d-tiles-attributes-worker.js +37 -0
  69. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -0
  70. package/dist/es5/workers/i3s-attributes-worker.js +40 -0
  71. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -0
  72. package/dist/esm/3d-tiles-attributes-worker.js +16 -0
  73. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -0
  74. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +32 -5
  75. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  76. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +23 -23
  77. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  78. package/dist/esm/converter-cli.js +230 -0
  79. package/dist/esm/converter-cli.js.map +1 -0
  80. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  81. package/dist/esm/i3s-attributes-worker.js +16 -0
  82. package/dist/esm/i3s-attributes-worker.js.map +1 -0
  83. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +19 -11
  84. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  85. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +2 -2
  86. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  87. package/dist/esm/i3s-converter/helpers/geometry-converter.js +121 -62
  88. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  89. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +54 -0
  90. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  91. package/dist/esm/i3s-converter/helpers/node-pages.js +12 -4
  92. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  93. package/dist/esm/i3s-converter/i3s-converter.js +155 -50
  94. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  95. package/dist/esm/index.js +0 -2
  96. package/dist/esm/index.js.map +1 -1
  97. package/dist/esm/lib/utils/compress-util.js +6 -8
  98. package/dist/esm/lib/utils/compress-util.js.map +1 -1
  99. package/dist/esm/lib/utils/file-utils.js +11 -1
  100. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  101. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  102. package/dist/esm/lib/utils/queue.js +19 -0
  103. package/dist/esm/lib/utils/queue.js.map +1 -0
  104. package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
  105. package/dist/esm/lib/utils/write-queue.js +88 -0
  106. package/dist/esm/lib/utils/write-queue.js.map +1 -0
  107. package/dist/esm/pgm-loader.js +1 -1
  108. package/dist/esm/pgm-loader.js.map +1 -1
  109. package/dist/esm/workers/3d-tiles-attributes-worker.js +5 -0
  110. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -0
  111. package/dist/esm/workers/i3s-attributes-worker.js +4 -0
  112. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -0
  113. package/dist/i3s-attributes-worker.d.ts +33 -0
  114. package/dist/i3s-attributes-worker.d.ts.map +1 -0
  115. package/dist/i3s-attributes-worker.js +10 -0
  116. package/dist/i3s-attributes-worker.js.map +7 -0
  117. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +41 -0
  118. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -0
  119. package/dist/i3s-converter/helpers/coordinate-converter.js +122 -0
  120. package/dist/i3s-converter/helpers/create-scene-server-path.d.ts +9 -0
  121. package/dist/i3s-converter/helpers/create-scene-server-path.d.ts.map +1 -0
  122. package/dist/i3s-converter/helpers/create-scene-server-path.js +28 -0
  123. package/dist/i3s-converter/helpers/geometry-attributes.d.ts +8 -0
  124. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -0
  125. package/dist/i3s-converter/helpers/geometry-attributes.js +177 -0
  126. package/dist/i3s-converter/helpers/geometry-converter.d.ts +29 -0
  127. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -0
  128. package/dist/i3s-converter/helpers/geometry-converter.js +901 -0
  129. package/dist/i3s-converter/helpers/gltf-attributes.d.ts +9 -0
  130. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -0
  131. package/dist/i3s-converter/helpers/gltf-attributes.js +56 -0
  132. package/dist/i3s-converter/helpers/node-debug.d.ts +8 -0
  133. package/dist/i3s-converter/helpers/node-debug.d.ts.map +1 -0
  134. package/dist/i3s-converter/helpers/node-debug.js +114 -0
  135. package/dist/i3s-converter/helpers/node-pages.d.ts +117 -0
  136. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -0
  137. package/dist/i3s-converter/helpers/node-pages.js +208 -0
  138. package/dist/i3s-converter/i3s-converter.d.ts +323 -0
  139. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -0
  140. package/dist/i3s-converter/i3s-converter.js +1074 -0
  141. package/dist/i3s-converter/json-templates/layers.d.ts +95 -0
  142. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -0
  143. package/dist/i3s-converter/json-templates/layers.js +199 -0
  144. package/dist/i3s-converter/json-templates/metadata.d.ts +22 -0
  145. package/dist/i3s-converter/json-templates/metadata.d.ts.map +1 -0
  146. package/dist/i3s-converter/json-templates/metadata.js +25 -0
  147. package/dist/i3s-converter/json-templates/node.d.ts +61 -0
  148. package/dist/i3s-converter/json-templates/node.d.ts.map +1 -0
  149. package/dist/i3s-converter/json-templates/node.js +89 -0
  150. package/dist/i3s-converter/json-templates/scene-server.d.ts +28 -0
  151. package/dist/i3s-converter/json-templates/scene-server.d.ts.map +1 -0
  152. package/dist/i3s-converter/json-templates/scene-server.js +31 -0
  153. package/dist/i3s-converter/json-templates/shared-resources.d.ts +14 -0
  154. package/dist/i3s-converter/json-templates/shared-resources.d.ts.map +1 -0
  155. package/dist/i3s-converter/json-templates/shared-resources.js +129 -0
  156. package/dist/i3s-converter/json-templates/store.d.ts +95 -0
  157. package/dist/i3s-converter/json-templates/store.d.ts.map +1 -0
  158. package/dist/i3s-converter/json-templates/store.js +103 -0
  159. package/dist/i3s-converter/types.d.ts +114 -0
  160. package/dist/i3s-converter/types.d.ts.map +1 -0
  161. package/dist/i3s-converter/types.js +2 -0
  162. package/dist/i3s-server/app.d.ts +3 -0
  163. package/dist/i3s-server/app.d.ts.map +1 -0
  164. package/dist/i3s-server/app.js +14 -0
  165. package/dist/i3s-server/controllers/index-controller.d.ts +2 -0
  166. package/dist/i3s-server/controllers/index-controller.d.ts.map +1 -0
  167. package/dist/i3s-server/controllers/index-controller.js +23 -0
  168. package/dist/i3s-server/routes/index.d.ts +3 -0
  169. package/dist/i3s-server/routes/index.d.ts.map +1 -0
  170. package/dist/i3s-server/routes/index.js +16 -0
  171. package/dist/index.d.ts +3 -0
  172. package/dist/index.d.ts.map +1 -0
  173. package/dist/index.js +10 -0
  174. package/dist/lib/utils/compress-util.d.ts +45 -0
  175. package/dist/lib/utils/compress-util.d.ts.map +1 -0
  176. package/dist/lib/utils/compress-util.js +257 -0
  177. package/dist/{esm/lib → lib}/utils/file-utils.d.ts +6 -14
  178. package/dist/lib/utils/file-utils.d.ts.map +1 -0
  179. package/dist/lib/utils/file-utils.js +81 -0
  180. package/dist/lib/utils/lod-conversion-utils.d.ts +41 -0
  181. package/dist/lib/utils/lod-conversion-utils.d.ts.map +1 -0
  182. package/dist/lib/utils/lod-conversion-utils.js +76 -0
  183. package/dist/lib/utils/queue.d.ts +7 -0
  184. package/dist/lib/utils/queue.d.ts.map +1 -0
  185. package/dist/lib/utils/queue.js +18 -0
  186. package/dist/lib/utils/statistic-utills.d.ts +3 -0
  187. package/dist/lib/utils/statistic-utills.d.ts.map +1 -0
  188. package/dist/lib/utils/statistic-utills.js +64 -0
  189. package/dist/lib/utils/write-queue.d.ts +22 -0
  190. package/dist/lib/utils/write-queue.d.ts.map +1 -0
  191. package/dist/lib/utils/write-queue.js +62 -0
  192. package/dist/pgm-loader.d.ts +6 -0
  193. package/dist/pgm-loader.d.ts.map +1 -0
  194. package/dist/pgm-loader.js +23 -0
  195. package/dist/workers/3d-tiles-attributes-worker.d.ts +2 -0
  196. package/dist/workers/3d-tiles-attributes-worker.d.ts.map +1 -0
  197. package/dist/workers/3d-tiles-attributes-worker.js +9 -0
  198. package/dist/workers/i3s-attributes-worker.d.ts +2 -0
  199. package/dist/workers/i3s-attributes-worker.d.ts.map +1 -0
  200. package/dist/workers/i3s-attributes-worker.js +5 -0
  201. package/package.json +19 -18
  202. package/src/3d-tiles-attributes-worker.ts +43 -0
  203. package/src/3d-tiles-converter/3d-tiles-converter.ts +49 -6
  204. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +21 -18
  205. package/src/converter-cli.ts +310 -0
  206. package/src/deps-installer/{deps-installer.js → deps-installer.ts} +11 -1
  207. package/src/i3s-attributes-worker.ts +46 -0
  208. package/src/i3s-converter/helpers/coordinate-converter.ts +29 -24
  209. package/src/i3s-converter/helpers/geometry-attributes.ts +4 -3
  210. package/src/i3s-converter/helpers/{geometry-converter.js → geometry-converter.ts} +425 -179
  211. package/src/i3s-converter/helpers/gltf-attributes.ts +68 -0
  212. package/src/i3s-converter/helpers/node-pages.ts +25 -17
  213. package/src/i3s-converter/i3s-converter.ts +154 -87
  214. package/src/i3s-converter/types.ts +90 -8
  215. package/src/index.ts +0 -4
  216. package/src/lib/utils/{compress-util.js → compress-util.ts} +105 -18
  217. package/src/lib/utils/file-utils.ts +84 -0
  218. package/src/lib/utils/{lod-conversion-utils.js → lod-conversion-utils.ts} +27 -5
  219. package/src/lib/utils/queue.ts +17 -0
  220. package/src/lib/utils/{statistic-utills.js → statistic-utills.ts} +0 -0
  221. package/src/lib/utils/write-queue.ts +75 -0
  222. package/src/workers/3d-tiles-attributes-worker.ts +6 -0
  223. package/src/workers/i3s-attributes-worker.ts +6 -0
  224. package/dist/es5/deps-installer/deps-installer.d.ts +0 -10
  225. package/dist/es5/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  226. package/dist/es5/lib/utils/compress-util.d.ts +0 -53
  227. package/dist/es5/lib/utils/file-utils.d.ts +0 -43
  228. package/dist/es5/lib/utils/lod-conversion-utils.d.ts +0 -32
  229. package/dist/esm/deps-installer/deps-installer.d.ts +0 -10
  230. package/dist/esm/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  231. package/dist/esm/lib/utils/compress-util.d.ts +0 -53
  232. package/dist/esm/lib/utils/lod-conversion-utils.d.ts +0 -32
  233. package/src/deps-installer/deps-installer.d.ts +0 -10
  234. package/src/i3s-converter/helpers/geometry-converter.d.ts +0 -44
  235. package/src/lib/utils/compress-util.d.ts +0 -53
  236. package/src/lib/utils/file-utils.d.ts +0 -43
  237. package/src/lib/utils/file-utils.js +0 -38
  238. package/src/lib/utils/lod-conversion-utils.d.ts +0 -32
@@ -1,12 +1,35 @@
1
1
  import {Vector3, Matrix4, Vector4} from '@math.gl/core';
2
2
  import {Ellipsoid} from '@math.gl/geospatial';
3
3
 
4
- import {DracoWriter} from '@loaders.gl/draco';
5
- import {encode, assert} from '@loaders.gl/core';
4
+ import {DracoWriterWorker} from '@loaders.gl/draco';
5
+ import {assert, encode} from '@loaders.gl/core';
6
6
  import {concatenateArrayBuffers, concatenateTypedArrays} from '@loaders.gl/loader-utils';
7
7
  import md5 from 'md5';
8
8
  import {generateAttributes} from './geometry-attributes';
9
9
  import {createBoundingVolumesFromGeometry} from './coordinate-converter';
10
+ import {
11
+ ConvertedAttributes,
12
+ I3SConvertedResources,
13
+ I3SMaterialWithTexture,
14
+ SharedResourcesArrays
15
+ } from '../types';
16
+ import {B3DMContent} from '@loaders.gl/3d-tiles';
17
+ import {GLTFMaterialPostprocessed, GLTFNodePostprocessed} from '@loaders.gl/gltf';
18
+ import {
19
+ AttributeStorageInfo,
20
+ I3SMaterialDefinition,
21
+ MaterialDefinitionInfo,
22
+ TextureDefinitionInfo
23
+ } from '@loaders.gl/i3s';
24
+ import {TypedArray} from '@loaders.gl/schema';
25
+ import {Geoid} from '@math.gl/geoid';
26
+ import {
27
+ GLTFAccessorPostprocessed,
28
+ GLTFMeshPostprocessed,
29
+ GLTFTexturePostprocessed
30
+ } from 'modules/gltf/src/lib/types/gltf-types';
31
+ import {B3DMAttributesData /*transformI3SAttributesOnWorker */} from '../../i3s-attributes-worker';
32
+ import {prepareDataForAttributesConversion} from './gltf-attributes';
10
33
 
11
34
  // Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
12
35
  const DEFAULT_ROUGHNESS_FACTOR = 1;
@@ -29,18 +52,47 @@ const BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES = ['CUSTOM_ATTRIBUTE_2', '_BATCHID', '
29
52
 
30
53
  let scratchVector = new Vector3();
31
54
 
55
+ /**
56
+ * Convert binary data from b3dm file to i3s resources
57
+ *
58
+ * @param tileContent - 3d tile content
59
+ * @param nodeId - target nodeId. If a few nodes will be created - ids will be nodeId+n where n - index in the resulting array
60
+ * @param featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
61
+ * @param attributeStorageInfo - attributes metadata from 3DSceneLayer json
62
+ * @param draco - is converter should create draco compressed geometry
63
+ * @param generateBoundingVolumes - is converter should create accurate bounding voulmes from geometry attributes
64
+ * @param geoidHeightModel - model to convert elevation from elipsoidal to geoid
65
+ * @returns Array of node resources to create one or more i3s nodes
66
+ */
32
67
  export default async function convertB3dmToI3sGeometry(
33
- tileContent,
34
- nodeId,
35
- featuresHashArray,
36
- attributeStorageInfo,
37
- draco,
38
- generateBoundingVolumes,
39
- geoidHeightModel
68
+ tileContent: B3DMContent,
69
+ nodeId: number,
70
+ featuresHashArray: string[],
71
+ attributeStorageInfo: AttributeStorageInfo[] | undefined,
72
+ draco: boolean,
73
+ generateBoundingVolumes: boolean,
74
+ geoidHeightModel: Geoid,
75
+ workerSource: {[key: string]: string}
40
76
  ) {
41
77
  const useCartesianPositions = generateBoundingVolumes;
42
- const materialAndTextureList = convertMaterials(tileContent);
43
- const convertedAttributesMap = convertAttributes(tileContent, useCartesianPositions);
78
+ const materialAndTextureList: I3SMaterialWithTexture[] = convertMaterials(
79
+ tileContent.gltf?.materials
80
+ );
81
+
82
+ const dataForAttributesConversion = prepareDataForAttributesConversion(tileContent);
83
+
84
+ const convertedAttributesMap: Map<string, ConvertedAttributes> = await convertAttributes(
85
+ dataForAttributesConversion,
86
+ useCartesianPositions
87
+ );
88
+ // TODO uncomment it when worker will be published on CDN.
89
+ /*
90
+ const convertedAttributesMap: Map<string, ConvertedAttributes> =
91
+ await transformI3SAttributesOnWorker(dataForAttributesConversion, {
92
+ useCartesianPositions,
93
+ source: workerSource.I3SAttributes
94
+ });
95
+ */
44
96
 
45
97
  if (generateBoundingVolumes) {
46
98
  _generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeightModel);
@@ -52,9 +104,9 @@ export default async function convertB3dmToI3sGeometry(
52
104
  });
53
105
  }
54
106
 
55
- const result = [];
107
+ const result: I3SConvertedResources[] = [];
56
108
  let nodesCounter = nodeId;
57
- let {materials = []} = tileContent.gltf;
109
+ let {materials = []} = tileContent.gltf || {materials: []};
58
110
  if (!materials?.length) {
59
111
  materials.push({id: 'default'});
60
112
  }
@@ -64,6 +116,9 @@ export default async function convertB3dmToI3sGeometry(
64
116
  continue; // eslint-disable-line no-continue
65
117
  }
66
118
  const convertedAttributes = convertedAttributesMap.get(sourceMaterial.id);
119
+ if (!convertedAttributes) {
120
+ continue;
121
+ }
67
122
  const {material, texture} = materialAndTextureList[i];
68
123
  result.push(
69
124
  await _makeNodeResources({
@@ -74,7 +129,8 @@ export default async function convertB3dmToI3sGeometry(
74
129
  nodeId: nodesCounter,
75
130
  featuresHashArray,
76
131
  attributeStorageInfo,
77
- draco
132
+ draco,
133
+ workerSource
78
134
  })
79
135
  );
80
136
  nodesCounter++;
@@ -88,10 +144,13 @@ export default async function convertB3dmToI3sGeometry(
88
144
 
89
145
  /**
90
146
  * Create bounding volumes based on positions
91
- * @param convertedAttributesMap
92
- * @param geoidHeightModel
147
+ * @param convertedAttributesMap - geometry attributes map
148
+ * @param geoidHeightModel - geoid height model to convert elevation from elipsoidal to geoid
93
149
  */
94
- function _generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeightModel) {
150
+ function _generateBoundingVolumesFromGeometry(
151
+ convertedAttributesMap: Map<string, ConvertedAttributes>,
152
+ geoidHeightModel: Geoid
153
+ ) {
95
154
  for (const attributes of convertedAttributesMap.values()) {
96
155
  const boundingVolumes = createBoundingVolumesFromGeometry(
97
156
  attributes.positions,
@@ -112,6 +171,19 @@ function _generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeigh
112
171
  }
113
172
  }
114
173
 
174
+ /**
175
+ *
176
+ * @param params
177
+ * @param params.convertedAttributes - Converted geometry attributes
178
+ * @param params.material - I3S PBR-like material definition
179
+ * @param params.texture - texture content
180
+ * @param params.tileContent - B3DM decoded content
181
+ * @param params.nodeId - new node ID
182
+ * @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.attributesStorageInfo - attributes metadata from 3DSceneLayer json
184
+ * @param params.draco - is converter should create draco compressed geometry
185
+ * @returns Array of I3S node resources
186
+ */
115
187
  async function _makeNodeResources({
116
188
  convertedAttributes,
117
189
  material,
@@ -120,13 +192,23 @@ async function _makeNodeResources({
120
192
  nodeId,
121
193
  featuresHashArray,
122
194
  attributeStorageInfo,
123
- draco
124
- }) {
195
+ draco,
196
+ workerSource
197
+ }: {
198
+ convertedAttributes: ConvertedAttributes;
199
+ material: I3SMaterialDefinition;
200
+ texture?: {};
201
+ tileContent: B3DMContent;
202
+ nodeId: number;
203
+ featuresHashArray: string[];
204
+ attributeStorageInfo?: AttributeStorageInfo[];
205
+ draco: boolean;
206
+ workerSource: {[key: string]: string};
207
+ }): Promise<I3SConvertedResources> {
125
208
  const boundingVolumes = convertedAttributes.boundingVolumes;
126
209
  const vertexCount = convertedAttributes.positions.length / VALUES_PER_VERTEX;
127
- const triangleCount = vertexCount / 3;
128
210
  const {faceRange, featureIds, positions, normals, colors, texCoords, featureCount} =
129
- generateAttributes({triangleCount, ...convertedAttributes});
211
+ generateAttributes(convertedAttributes);
130
212
 
131
213
  if (tileContent.batchTableJson) {
132
214
  makeFeatureIdsUnique(
@@ -153,14 +235,19 @@ async function _makeNodeResources({
153
235
  )
154
236
  );
155
237
  const compressedGeometry = draco
156
- ? await generateCompressedGeometry(vertexCount, convertedAttributes, {
157
- positions,
158
- normals,
159
- texCoords: texture ? texCoords : new Float32Array(0),
160
- colors,
161
- featureIds,
162
- faceRange
163
- })
238
+ ? generateCompressedGeometry(
239
+ vertexCount,
240
+ convertedAttributes,
241
+ {
242
+ positions,
243
+ normals,
244
+ texCoords: texture ? texCoords : new Float32Array(0),
245
+ colors,
246
+ featureIds,
247
+ faceRange
248
+ },
249
+ workerSource.draco
250
+ )
164
251
  : null;
165
252
 
166
253
  const attributes = convertBatchTableToAttributeBuffers(
@@ -173,7 +260,7 @@ async function _makeNodeResources({
173
260
  geometry: fileBuffer,
174
261
  compressedGeometry,
175
262
  texture,
176
- sharedResources: getSharedResources(tileContent, nodeId),
263
+ sharedResources: getSharedResources(tileContent.gltf?.materials || [], nodeId),
177
264
  meshMaterial: material,
178
265
  vertexCount,
179
266
  attributes,
@@ -184,40 +271,53 @@ async function _makeNodeResources({
184
271
 
185
272
  /**
186
273
  * Convert attributes from the gltf nodes tree to i3s plain geometry
187
- * @param {Object} tileContent - 3d tile content
188
- * @returns {Map}
189
- * Map<{
190
- * positions: Float32Array,
191
- * normals: Float32Array,
192
- * colors: Uint8Array,
193
- * texCoords: Float32Array
194
- * }>
195
- * @todo implement colors support (if applicable for gltf format)
196
- */
197
- function convertAttributes(tileContent, useCartesianPositions) {
198
- const attributesMap = new Map();
199
-
200
- for (const material of tileContent.gltf.materials || [{id: 'default'}]) {
274
+ * @param tileContent - 3d tile content
275
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
276
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
277
+ * @returns map of converted geometry attributes
278
+ */
279
+ export async function convertAttributes(
280
+ attributesData: B3DMAttributesData,
281
+ useCartesianPositions: boolean
282
+ ): Promise<Map<string, ConvertedAttributes>> {
283
+ const {gltfMaterials, nodes, cartographicOrigin, cartesianModelMatrix} = attributesData;
284
+ const attributesMap = new Map<string, ConvertedAttributes>();
285
+
286
+ for (const material of gltfMaterials || [{id: 'default'}]) {
201
287
  attributesMap.set(material.id, {
202
288
  positions: new Float32Array(0),
203
289
  normals: new Float32Array(0),
204
290
  texCoords: new Float32Array(0),
205
291
  colors: new Uint8Array(0),
292
+ featureIndicesGroups: [],
206
293
  featureIndices: [],
207
294
  boundingVolumes: null
208
295
  });
209
296
  }
210
297
 
211
- const nodes = (tileContent.gltf.scene || tileContent.gltf.scenes?.[0] || tileContent.gltf).nodes;
212
- convertNodes(nodes, tileContent, attributesMap, useCartesianPositions);
298
+ convertNodes(
299
+ nodes,
300
+ cartographicOrigin,
301
+ cartesianModelMatrix,
302
+ attributesMap,
303
+ useCartesianPositions
304
+ );
213
305
 
214
306
  for (const attrKey of attributesMap.keys()) {
215
307
  const attributes = attributesMap.get(attrKey);
308
+ if (!attributes) {
309
+ continue;
310
+ }
216
311
  if (attributes.positions.length === 0) {
217
312
  attributesMap.delete(attrKey);
218
313
  continue; // eslint-disable-line no-continue
219
314
  }
220
- attributes.featureIndices = attributes.featureIndices.reduce((acc, value) => acc.concat(value));
315
+ if (attributes.featureIndicesGroups) {
316
+ attributes.featureIndices = attributes.featureIndicesGroups.reduce((acc, value) =>
317
+ acc.concat(value)
318
+ );
319
+ delete attributes.featureIndicesGroups;
320
+ }
221
321
  }
222
322
 
223
323
  return attributesMap;
@@ -226,23 +326,32 @@ function convertAttributes(tileContent, useCartesianPositions) {
226
326
  /**
227
327
  * Gltf has hierarchical structure of nodes. This function converts nodes starting from those which are in gltf scene object.
228
328
  * The goal is applying tranformation matrix for all children. Functions "convertNodes" and "convertNode" work together recursively.
229
- * @param {Object[]} nodes - gltf nodes array
230
- * @param {Object} tileContent - 3d tile content
231
- * @param {Map} attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: UInt8Array, featureIndices: Array}> - for recursive concatenation of
232
- * attributes
233
- * @param {Matrix4} matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
329
+ * @param nodes - gltf nodes array
330
+ * @param tileContent - 3d tile content
331
+ * @param attributesMap - for recursive concatenation of attributes
332
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
333
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
334
+ * @param matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
234
335
  * @returns {void}
235
336
  */
236
337
  function convertNodes(
237
- nodes,
238
- tileContent,
239
- attributesMap,
240
- useCartesianPositions,
241
- matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
338
+ nodes: GLTFNodePostprocessed[],
339
+ cartographicOrigin: Vector3,
340
+ cartesianModelMatrix: Matrix4,
341
+ attributesMap: Map<string, ConvertedAttributes>,
342
+ useCartesianPositions: boolean,
343
+ matrix: Matrix4 = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
242
344
  ) {
243
345
  if (nodes) {
244
346
  for (const node of nodes) {
245
- convertNode(node, tileContent, attributesMap, useCartesianPositions, matrix);
347
+ convertNode(
348
+ node,
349
+ cartographicOrigin,
350
+ cartesianModelMatrix,
351
+ attributesMap,
352
+ useCartesianPositions,
353
+ matrix
354
+ );
246
355
  }
247
356
  }
248
357
  }
@@ -262,6 +371,10 @@ function getCompositeTransformationMatrix(node, matrix) {
262
371
  transformationMatrix = matrix.multiplyRight(nodeMatrix);
263
372
  }
264
373
 
374
+ if (translation) {
375
+ transformationMatrix = transformationMatrix.translate(translation);
376
+ }
377
+
265
378
  if (rotation) {
266
379
  transformationMatrix = transformationMatrix.rotateXYZ(rotation);
267
380
  }
@@ -270,26 +383,24 @@ function getCompositeTransformationMatrix(node, matrix) {
270
383
  transformationMatrix = transformationMatrix.scale(scale);
271
384
  }
272
385
 
273
- if (translation) {
274
- transformationMatrix = transformationMatrix.translate(translation);
275
- }
276
-
277
386
  return transformationMatrix;
278
387
  }
279
388
 
280
389
  /**
281
390
  * Convert all primitives of node and all children nodes
282
- * @param {Object} node - gltf node
391
+ * @param node - gltf node
283
392
  * @param {Object} tileContent - 3d tile content
284
393
  * @param {Map} attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
285
394
  * attributes
395
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
396
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
286
397
  * @param {Matrix4} matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
287
- * @todo: optimize arrays concatenation
288
398
  */
289
399
  function convertNode(
290
- node,
291
- tileContent,
292
- attributesMap,
400
+ node: GLTFNodePostprocessed,
401
+ cartographicOrigin: Vector3,
402
+ cartesianModelMatrix: Matrix4,
403
+ attributesMap: Map<string, ConvertedAttributes>,
293
404
  useCartesianPositions,
294
405
  matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
295
406
  ) {
@@ -297,12 +408,20 @@ function convertNode(
297
408
 
298
409
  const mesh = node.mesh;
299
410
  if (mesh) {
300
- convertMesh(mesh, tileContent, attributesMap, useCartesianPositions, transformationMatrix);
411
+ convertMesh(
412
+ mesh,
413
+ cartographicOrigin,
414
+ cartesianModelMatrix,
415
+ attributesMap,
416
+ useCartesianPositions,
417
+ transformationMatrix
418
+ );
301
419
  }
302
420
 
303
421
  convertNodes(
304
- node.children,
305
- tileContent,
422
+ node.children || [],
423
+ cartographicOrigin,
424
+ cartesianModelMatrix,
306
425
  attributesMap,
307
426
  useCartesianPositions,
308
427
  transformationMatrix
@@ -311,22 +430,25 @@ function convertNode(
311
430
 
312
431
  /**
313
432
  * Convert all primitives of node and all children nodes
314
- * @param {Object} mesh - gltf node
315
- * @param {Object} content - 3d tile content
316
- * @param {Map} attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
433
+ * @param mesh - gltf node
434
+ * @param content - 3d tile content
435
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
436
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
437
+ * @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
317
438
  * attributes
439
+
318
440
  * @param {Matrix4} matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
319
- * @todo: optimize arrays concatenation
320
441
  */
321
442
  function convertMesh(
322
- mesh,
323
- content,
324
- attributesMap,
443
+ mesh: GLTFMeshPostprocessed,
444
+ cartographicOrigin: Vector3,
445
+ cartesianModelMatrix: Matrix4,
446
+ attributesMap: Map<string, ConvertedAttributes>,
325
447
  useCartesianPositions = false,
326
448
  matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
327
449
  ) {
328
450
  for (const primitive of mesh.primitives) {
329
- let outputAttributes = null;
451
+ let outputAttributes: ConvertedAttributes | null | undefined = null;
330
452
  if (primitive.material) {
331
453
  outputAttributes = attributesMap.get(primitive.material.id);
332
454
  } else if (attributesMap.has('default')) {
@@ -334,15 +456,17 @@ function convertMesh(
334
456
  }
335
457
  assert(outputAttributes !== null, 'Primitive - material mapping failed');
336
458
  const attributes = primitive.attributes;
337
-
459
+ if (!outputAttributes) {
460
+ continue;
461
+ }
338
462
  outputAttributes.positions = concatenateTypedArrays(
339
463
  outputAttributes.positions,
340
464
  transformVertexArray({
341
465
  vertices: attributes.POSITION.value,
342
- cartographicOrigin: content.cartographicOrigin,
343
- cartesianModelMatrix: content.cartesianModelMatrix,
466
+ cartographicOrigin,
467
+ cartesianModelMatrix,
344
468
  nodeMatrix: matrix,
345
- indices: primitive.indices.value,
469
+ indices: primitive.indices?.value,
346
470
  attributeSpecificTransformation: transformVertexPositions,
347
471
  useCartesianPositions
348
472
  })
@@ -351,10 +475,10 @@ function convertMesh(
351
475
  outputAttributes.normals,
352
476
  transformVertexArray({
353
477
  vertices: attributes.NORMAL && attributes.NORMAL.value,
354
- cartographicOrigin: content.cartographicOrigin,
355
- cartesianModelMatrix: content.cartesianModelMatrix,
478
+ cartographicOrigin,
479
+ cartesianModelMatrix,
356
480
  nodeMatrix: matrix,
357
- indices: primitive.indices.value,
481
+ indices: primitive.indices?.value,
358
482
  attributeSpecificTransformation: transformVertexNormals,
359
483
  useCartesianPositions: false
360
484
  })
@@ -363,34 +487,43 @@ function convertMesh(
363
487
  outputAttributes.texCoords,
364
488
  flattenTexCoords(
365
489
  attributes.TEXCOORD_0 && attributes.TEXCOORD_0.value,
366
- primitive.indices.value
490
+ primitive.indices?.value
367
491
  )
368
492
  );
369
493
 
370
494
  outputAttributes.colors = concatenateTypedArrays(
371
495
  outputAttributes.colors,
372
- flattenColors(attributes.COLOR_0, primitive.indices.value)
496
+ flattenColors(attributes.COLOR_0, primitive.indices?.value)
373
497
  );
374
498
 
375
- outputAttributes.featureIndices.push(
376
- flattenBatchIds(getBatchIdsByAttributeName(attributes), primitive.indices.value)
499
+ outputAttributes.featureIndicesGroups = outputAttributes.featureIndicesGroups || [];
500
+ outputAttributes.featureIndicesGroups.push(
501
+ flattenBatchIds(getBatchIdsByAttributeName(attributes), primitive.indices?.value)
377
502
  );
378
503
  }
379
504
  }
380
505
 
381
506
  /**
382
507
  * Convert vertices attributes (POSITIONS or NORMALS) to i3s compatible format
383
- * @param {object} args - source tile (3DTile)
384
- * @param {Float32Array} args.vertices - gltf primitive POSITION or NORMAL attribute
385
- * @param {Object} args.cartographicOrigin - cartographic origin coordinates
386
- * @param {Object} args.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
387
- * @param {Matrix4} args.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
388
- * @param {Uint8Array} args.indices - gltf primitive indices
389
- * @param {Function} args.attributeSpecificTransformation - function to do attribute - specific transformations
390
- * @param {Boolean} args.useCartesianPositions - use coordinates as it is.
508
+ * @param args
509
+ * @param args.vertices - gltf primitive POSITION or NORMAL attribute
510
+ * @param args.cartographicOrigin - cartographic origin coordinates
511
+ * @param args.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
512
+ * @param args.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
513
+ * @param args.indices - gltf primitive indices
514
+ * @param args.attributeSpecificTransformation - function to do attribute - specific transformations
515
+ * @param args.useCartesianPositions - use coordinates as it is.
391
516
  * @returns {Float32Array}
392
517
  */
393
- function transformVertexArray(args) {
518
+ function transformVertexArray(args: {
519
+ vertices: Float32Array;
520
+ cartographicOrigin: number[];
521
+ cartesianModelMatrix: number[];
522
+ nodeMatrix: Matrix4;
523
+ indices: Uint8Array;
524
+ attributeSpecificTransformation: Function;
525
+ useCartesianPositions: boolean;
526
+ }) {
394
527
  const {vertices, indices, attributeSpecificTransformation} = args;
395
528
  const newVertices = new Float32Array(indices.length * VALUES_PER_VERTEX);
396
529
  if (!vertices) {
@@ -410,7 +543,17 @@ function transformVertexArray(args) {
410
543
  return newVertices;
411
544
  }
412
545
 
413
- function transformVertexPositions(vertexVector, calleeArgs) {
546
+ /**
547
+ * Trasform positions vector with the attribute specific transformations
548
+ * @param vertexVector - source positions vector to transform
549
+ * @param calleeArgs
550
+ * @param calleeArgs.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
551
+ * @param calleeArgs.cartographicOrigin - cartographic origin coordinates
552
+ * @param calleeArgs.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
553
+ * @param calleeArgs.useCartesianPositions - use coordinates as it is.
554
+ * @returns transformed positions vector
555
+ */
556
+ function transformVertexPositions(vertexVector, calleeArgs): number[] {
414
557
  const {cartesianModelMatrix, cartographicOrigin, nodeMatrix, useCartesianPositions} = calleeArgs;
415
558
 
416
559
  if (nodeMatrix) {
@@ -431,7 +574,15 @@ function transformVertexPositions(vertexVector, calleeArgs) {
431
574
  return vertexVector;
432
575
  }
433
576
 
434
- function transformVertexNormals(vertexVector, calleeArgs) {
577
+ /**
578
+ * Trasform normals vector with the attribute specific transformations
579
+ * @param vertexVector - source normals vector to transform
580
+ * @param calleeArgs
581
+ * @param calleeArgs.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
582
+ * @param calleeArgs.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
583
+ * @returns transformed normals vector
584
+ */
585
+ function transformVertexNormals(vertexVector, calleeArgs): number[] {
435
586
  const {cartesianModelMatrix, nodeMatrix} = calleeArgs;
436
587
 
437
588
  if (nodeMatrix) {
@@ -444,11 +595,11 @@ function transformVertexNormals(vertexVector, calleeArgs) {
444
595
 
445
596
  /**
446
597
  * Convert uv0 (texture coordinates) from coords based on indices to plain arrays, compatible with i3s
447
- * @param {Float32Array} texCoords - gltf primitive TEXCOORD_0 attribute
448
- * @param {Uint8Array} indices - gltf primitive indices
449
- * @returns {Float32Array}
598
+ * @param texCoords - gltf primitive TEXCOORD_0 attribute
599
+ * @param indices - gltf primitive indices
600
+ * @returns flattened texture coordinates
450
601
  */
451
- function flattenTexCoords(texCoords, indices) {
602
+ function flattenTexCoords(texCoords: Float32Array, indices: Uint8Array): Float32Array {
452
603
  const newTexCoords = new Float32Array(indices.length * VALUES_PER_TEX_COORD);
453
604
  if (!texCoords) {
454
605
  // We need dummy UV0s because it is required in 1.6
@@ -467,11 +618,14 @@ function flattenTexCoords(texCoords, indices) {
467
618
 
468
619
  /**
469
620
  * Convert color from COLOR_0 based on indices to plain arrays, compatible with i3s
470
- * @param {object} colorsAttribute - gltf primitive COLOR_0 attribute
471
- * @param {Uint8Array} indices - gltf primitive indices
472
- * @returns {Uint8Array}
621
+ * @param colorsAttribute - gltf primitive COLOR_0 attribute
622
+ * @param indices - gltf primitive indices
623
+ * @returns flattened colors attribute
473
624
  */
474
- function flattenColors(colorsAttribute, indices) {
625
+ function flattenColors(
626
+ colorsAttribute: GLTFAccessorPostprocessed,
627
+ indices: Uint8Array
628
+ ): Uint8Array {
475
629
  const components = colorsAttribute?.components || VALUES_PER_COLOR_ELEMENT;
476
630
  const newColors = new Uint8Array(indices.length * components);
477
631
  if (!colorsAttribute) {
@@ -494,28 +648,31 @@ function flattenColors(colorsAttribute, indices) {
494
648
 
495
649
  /**
496
650
  * Flatten batchedIds list based on indices to right ordered array, compatible with i3s
497
- * @param {Array} batchedIds - gltf primitive
498
- * @param {Uint8Array} indices - gltf primitive indices
499
- * @returns {Array}
651
+ * @param batchedIds - gltf primitive
652
+ * @param indices - gltf primitive indices
653
+ * @returns flattened batch ids
500
654
  */
501
- function flattenBatchIds(batchedIds, indices) {
655
+ function flattenBatchIds(batchedIds: number[], indices: Uint8Array): number[] {
502
656
  if (!batchedIds.length || !indices.length) {
503
657
  return [];
504
658
  }
505
- const newBatchIds = [];
659
+ const newBatchIds: number[] = [];
506
660
  for (let i = 0; i < indices.length; i++) {
507
661
  const coordIndex = indices[i];
508
662
  newBatchIds.push(batchedIds[coordIndex]);
509
663
  }
510
664
  return newBatchIds;
511
665
  }
666
+
512
667
  /**
513
668
  * Return batchIds based on possible attribute names for different kind of maps.
514
- * @param {Object} attributes {attributeName: Float32Array}
515
- * @returns {Array}
669
+ * @param attributes - the gltf primitive attributes
670
+ * @returns batch ids attribute
516
671
  */
517
- function getBatchIdsByAttributeName(attributes) {
518
- let batchIds = [];
672
+ function getBatchIdsByAttributeName(attributes: {
673
+ [key: string]: GLTFAccessorPostprocessed;
674
+ }): number[] {
675
+ let batchIds: number[] = [];
519
676
 
520
677
  for (let index = 0; index < BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES.length; index++) {
521
678
  const possibleBatchIdAttributeName = BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES[index];
@@ -531,9 +688,15 @@ function getBatchIdsByAttributeName(attributes) {
531
688
  return batchIds;
532
689
  }
533
690
 
534
- function convertMaterials(tileContent) {
535
- const result = [];
536
- const sourceMaterials = tileContent.gltf.materials || [];
691
+ /**
692
+ * Convert GLTF material to I3S material definitions and textures
693
+ * @param sourceMaterials Source GLTF materials
694
+ * @returns Array of Couples I3SMaterialDefinition + texture content
695
+ */
696
+ function convertMaterials(
697
+ sourceMaterials: GLTFMaterialPostprocessed[] = []
698
+ ): I3SMaterialWithTexture[] {
699
+ const result: I3SMaterialWithTexture[] = [];
537
700
  for (const sourceMaterial of sourceMaterials) {
538
701
  result.push(convertMaterial(sourceMaterial));
539
702
  }
@@ -542,16 +705,20 @@ function convertMaterials(tileContent) {
542
705
 
543
706
  /**
544
707
  * Convert texture and material from gltf 2.0 material object
545
- * @param {Object} sourceMaterial - material object
546
- * @returns {Object}
708
+ * @param sourceMaterial - material object
709
+ * @returns I3S material definition and texture
547
710
  */
548
- function convertMaterial(sourceMaterial) {
549
- const material = {
711
+ function convertMaterial(sourceMaterial: GLTFMaterialPostprocessed): I3SMaterialWithTexture {
712
+ const material: I3SMaterialDefinition = {
550
713
  doubleSided: sourceMaterial.doubleSided,
551
- emissiveFactor: sourceMaterial.emissiveFactor.map((c) => Math.round(c * 255)),
714
+ emissiveFactor: sourceMaterial.emissiveFactor?.map((c) => Math.round(c * 255)) as [
715
+ number,
716
+ number,
717
+ number
718
+ ],
552
719
  // It is in upper case in GLTF: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#alpha-coverage
553
720
  // But it is in lower case in I3S: https://github.com/Esri/i3s-spec/blob/master/docs/1.7/materialDefinitions.cmn.md
554
- alphaMode: (sourceMaterial.alphaMode || 'OPAQUE').toLowerCase(),
721
+ alphaMode: convertAlphaMode(sourceMaterial.alphaMode),
555
722
  pbrMetallicRoughness: {
556
723
  roughnessFactor:
557
724
  sourceMaterial?.pbrMetallicRoughness?.roughnessFactor || DEFAULT_ROUGHNESS_FACTOR,
@@ -579,28 +746,63 @@ function convertMaterial(sourceMaterial) {
579
746
  // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-pbrmetallicroughness
580
747
  const baseColorFactor = sourceMaterial?.pbrMetallicRoughness?.baseColorFactor;
581
748
  material.pbrMetallicRoughness.baseColorFactor =
582
- (baseColorFactor && baseColorFactor.map((c) => Math.round(c * 255))) || undefined;
749
+ ((baseColorFactor && baseColorFactor.map((c) => Math.round(c * 255))) as [
750
+ number,
751
+ number,
752
+ number,
753
+ number
754
+ ]) || undefined;
583
755
  }
584
756
 
585
757
  return {material, texture};
586
758
  }
587
759
 
588
- function getDefaultMaterial() {
760
+ /**
761
+ * Converts from `alphaMode` material property from GLTF to I3S format
762
+ * @param gltfAlphaMode Gltf material `alphaMode` property
763
+ * @returns I3SMaterialDefinition.alphaMode property
764
+ */
765
+ function convertAlphaMode(
766
+ gltfAlphaMode?: 'OPAQUE' | 'MASK' | 'BLEND' | string
767
+ ): 'opaque' | 'mask' | 'blend' {
768
+ switch (gltfAlphaMode) {
769
+ case 'OPAQUE':
770
+ return 'opaque';
771
+ case 'MASK':
772
+ return 'mask';
773
+ case 'BLEND':
774
+ return 'blend';
775
+ default:
776
+ return 'opaque';
777
+ }
778
+ }
779
+
780
+ /**
781
+ * Form default I3SMaterialDefinition
782
+ * @returns I3S material definition
783
+ */
784
+ function getDefaultMaterial(): I3SMaterialDefinition {
589
785
  return {
590
786
  alphaMode: 'opaque',
591
- pbrMetallicRoughness: {}
787
+ pbrMetallicRoughness: {
788
+ metallicFactor: 1,
789
+ roughnessFactor: 1
790
+ }
592
791
  };
593
792
  }
594
793
 
595
794
  /**
596
795
  * Form "sharedResources" from gltf materials array
597
- * @param {Object} tileContent - 3d tile content
598
- * @returns {Object} {materialDefinitionInfos: Object[], textureDefinitionInfos: Object[]} -
796
+ * @param gltfMaterials - GLTF materials array
797
+ * @param nodeId - I3S node ID
798
+ * @returns {materialDefinitionInfos: Object[], textureDefinitionInfos: Object[]} -
599
799
  * 2 arrays in format of i3s sharedResources data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/sharedResource.cmn.md
600
800
  */
601
- function getSharedResources(tileContent, nodeId) {
602
- const gltfMaterials = tileContent.gltf.materials;
603
- const i3sResources = {};
801
+ function getSharedResources(
802
+ gltfMaterials: GLTFMaterialPostprocessed[],
803
+ nodeId: number
804
+ ): SharedResourcesArrays {
805
+ const i3sResources: SharedResourcesArrays = {};
604
806
 
605
807
  if (!gltfMaterials || !gltfMaterials.length) {
606
808
  return i3sResources;
@@ -623,13 +825,20 @@ function getSharedResources(tileContent, nodeId) {
623
825
 
624
826
  /**
625
827
  * Convert gltf material into I3S sharedResources data
626
- * @param {Object} gltfMaterial - gltf material data
627
- * @returns {Object} - Couple {materialDefinitionInfo, textureDefinitionInfo} extracted from gltf material data
828
+ * @param gltfMaterial - gltf material data
829
+ * @param nodeId - I3S node ID
830
+ * @returns - Couple {materialDefinitionInfo, textureDefinitionInfo} extracted from gltf material data
628
831
  */
629
- function convertGLTFMaterialToI3sSharedResources(gltfMaterial, nodeId) {
832
+ function convertGLTFMaterialToI3sSharedResources(
833
+ gltfMaterial: GLTFMaterialPostprocessed,
834
+ nodeId: number
835
+ ): {
836
+ materialDefinitionInfo: MaterialDefinitionInfo;
837
+ textureDefinitionInfo: TextureDefinitionInfo | null;
838
+ } {
630
839
  const texture =
631
840
  gltfMaterial?.pbrMetallicRoughness?.baseColorTexture || gltfMaterial.emissiveTexture;
632
- let textureDefinitionInfo = null;
841
+ let textureDefinitionInfo: TextureDefinitionInfo | null = null;
633
842
  if (texture) {
634
843
  textureDefinitionInfo = extractSharedResourcesTextureInfo(texture.texture, nodeId);
635
844
  }
@@ -642,7 +851,10 @@ function convertGLTFMaterialToI3sSharedResources(gltfMaterial, nodeId) {
642
851
  }
643
852
 
644
853
  return {
645
- materialDefinitionInfo: extractSharedResourcesMaterialInfo(colorFactor, metallicFactor),
854
+ materialDefinitionInfo: extractSharedResourcesMaterialInfo(
855
+ colorFactor || [1, 1, 1, 1],
856
+ metallicFactor
857
+ ),
646
858
  textureDefinitionInfo
647
859
  };
648
860
  }
@@ -658,11 +870,14 @@ function convertGLTFMaterialToI3sSharedResources(gltfMaterial, nodeId) {
658
870
  *
659
871
  * Assumption: F0 - specular in i3s ("specular reflection" <-> "reflectance value at normal incidence")
660
872
  * cdiff - diffuse in i3s ("Diffuse color" <-> "'c' diffuse" (c means color?))
661
- * @param {number[]} baseColorFactor - RGBA color in 0..1 format
662
- * @param {number} metallicFactor - "metallicFactor" attribute of gltf material object
663
- * @returns {Object}
873
+ * @param baseColorFactor - RGBA color in 0..1 format
874
+ * @param metallicFactor - "metallicFactor" attribute of gltf material object
875
+ * @returns material definition info for I3S shared resource
664
876
  */
665
- function extractSharedResourcesMaterialInfo(baseColorFactor, metallicFactor = 1) {
877
+ function extractSharedResourcesMaterialInfo(
878
+ baseColorFactor: number[],
879
+ metallicFactor: number = 1
880
+ ): MaterialDefinitionInfo {
666
881
  const matDielectricColorComponent = 0.04 / 255; // Color from rgb (255) to 0..1 resolution
667
882
  // All color resolutions are 0..1
668
883
  const black = new Vector4(0, 0, 0, 1);
@@ -681,38 +896,47 @@ function extractSharedResourcesMaterialInfo(baseColorFactor, metallicFactor = 1)
681
896
  dielectricSpecular[3] = 1;
682
897
  const specular = dielectricSpecular.lerp(dielectricSpecular, baseColorVector, metallicFactor);
683
898
  return {
684
- diffuse: diffuse.toArray(),
685
- specular: specular.toArray()
899
+ params: {
900
+ diffuse: diffuse.toArray(),
901
+ specular: specular.toArray(),
902
+ renderMode: 'solid'
903
+ }
686
904
  };
687
905
  }
688
906
 
689
907
  /**
690
908
  * Form "textureDefinition" which is part of "sharedResouces"
691
- * @param {Object} texture - texture image info
692
- * @returns {Object}
909
+ * @param texture - texture image info
910
+ * @param nodeId - I3S node ID
911
+ * @returns texture definition infor for shared resource
693
912
  */
694
- function extractSharedResourcesTextureInfo(texture, nodeId) {
913
+ function extractSharedResourcesTextureInfo(
914
+ texture: GLTFTexturePostprocessed,
915
+ nodeId: number
916
+ ): TextureDefinitionInfo {
695
917
  return {
696
- encoding: [texture.source.mimeType],
918
+ encoding: texture?.source?.mimeType ? [texture.source.mimeType] : undefined,
697
919
  images: [
698
920
  {
699
921
  // 'i3s' has just size which is width of the image. Images are supposed to be square.
700
922
  // https://github.com/Esri/i3s-spec/blob/master/docs/1.7/image.cmn.md
701
923
  id: generateImageId(texture, nodeId),
702
- size: texture.source.image.width,
703
- length: [texture.source.image.data.length]
924
+ size: texture.source?.image.width,
925
+ length: [texture.source?.image.data.length]
704
926
  }
705
927
  ]
706
928
  };
707
929
  }
708
- /*
930
+
931
+ /**
709
932
  * Formula for counting imageId:
710
933
  * https://github.com/Esri/i3s-spec/blob/0a6366a9249b831db8436c322f8d27521e86cf07/format/Indexed%203d%20Scene%20Layer%20Format%20Specification.md#generating-image-ids
711
- * @param {Object} texture - texture image info
712
- * @returns {string}
934
+ * @param texture - texture image info
935
+ * @param nodeId - I3S node ID
936
+ * @returns calculate image ID according to the spec
713
937
  */
714
- function generateImageId(texture, nodeId) {
715
- const {width, height} = texture.source.image;
938
+ function generateImageId(texture: GLTFTexturePostprocessed, nodeId) {
939
+ const {width, height} = texture.source?.image;
716
940
  const levelCountOfTexture = 1;
717
941
  const indexOfLevel = 0;
718
942
  const indexOfTextureInStore = nodeId + 1;
@@ -732,13 +956,18 @@ function generateImageId(texture, nodeId) {
732
956
 
733
957
  /**
734
958
  * Make all feature ids unique through all nodes in layout.
735
- * @param {Array} featureIds
736
- * @param {Array} featureIndices
737
- * @param {Array} featuresHashArray
738
- * @param {Object} batchTable
959
+ * @param featureIds
960
+ * @param featureIndices
961
+ * @param featuresHashArray
962
+ * @param batchTable
739
963
  * @returns {void}
740
964
  */
741
- function makeFeatureIdsUnique(featureIds, featureIndices, featuresHashArray, batchTable) {
965
+ function makeFeatureIdsUnique(
966
+ featureIds: number[],
967
+ featureIndices: number[],
968
+ featuresHashArray: string[],
969
+ batchTable: {[key: string]: any}
970
+ ) {
742
971
  const replaceMap = getFeaturesReplaceMap(featureIds, batchTable, featuresHashArray);
743
972
  replaceIndicesByUnique(featureIndices, replaceMap);
744
973
  replaceIndicesByUnique(featureIds, replaceMap);
@@ -814,7 +1043,7 @@ function replaceIndicesByUnique(indicesArray, featureMap) {
814
1043
  * @returns {Array} - Array of file buffers.
815
1044
  */
816
1045
  function convertBatchTableToAttributeBuffers(batchTable, featureIds, attributeStorageInfo) {
817
- const attributeBuffers = [];
1046
+ const attributeBuffers: ArrayBuffer[] = [];
818
1047
 
819
1048
  if (batchTable) {
820
1049
  const batchTableWithFeatureIds = {
@@ -825,7 +1054,7 @@ function convertBatchTableToAttributeBuffers(batchTable, featureIds, attributeSt
825
1054
  for (const key in batchTableWithFeatureIds) {
826
1055
  const type = getAttributeType(key, attributeStorageInfo);
827
1056
 
828
- let attributeBuffer = null;
1057
+ let attributeBuffer: ArrayBuffer | null = null;
829
1058
 
830
1059
  switch (type) {
831
1060
  case OBJECT_ID_TYPE:
@@ -842,7 +1071,9 @@ function convertBatchTableToAttributeBuffers(batchTable, featureIds, attributeSt
842
1071
  attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
843
1072
  }
844
1073
 
845
- attributeBuffers.push(attributeBuffer);
1074
+ if (attributeBuffer) {
1075
+ attributeBuffers.push(attributeBuffer);
1076
+ }
846
1077
  }
847
1078
  }
848
1079
 
@@ -864,7 +1095,7 @@ function getAttributeType(key, attributeStorageInfo) {
864
1095
  * @param {Array} featureIds
865
1096
  * @returns {ArrayBuffer} - Buffer with objectId data.
866
1097
  */
867
- function generateShortIntegerAttributeBuffer(featureIds) {
1098
+ function generateShortIntegerAttributeBuffer(featureIds): ArrayBuffer {
868
1099
  const count = new Uint32Array([featureIds.length]);
869
1100
  const valuesArray = new Uint32Array(featureIds);
870
1101
  return concatenateArrayBuffers(count.buffer, valuesArray.buffer);
@@ -875,7 +1106,7 @@ function generateShortIntegerAttributeBuffer(featureIds) {
875
1106
  * @param {Array} featureIds
876
1107
  * @returns {ArrayBuffer} - Buffer with objectId data.
877
1108
  */
878
- function generateDoubleAttributeBuffer(featureIds) {
1109
+ function generateDoubleAttributeBuffer(featureIds): ArrayBuffer {
879
1110
  const count = new Uint32Array([featureIds.length]);
880
1111
  const padding = new Uint8Array(4);
881
1112
  const valuesArray = new Float64Array(featureIds);
@@ -888,11 +1119,11 @@ function generateDoubleAttributeBuffer(featureIds) {
888
1119
  * @param {Array} batchAttributes
889
1120
  * @returns {ArrayBuffer} - Buffer with batch table data.
890
1121
  */
891
- function generateStringAttributeBuffer(batchAttributes) {
1122
+ function generateStringAttributeBuffer(batchAttributes): ArrayBuffer {
892
1123
  const stringCountArray = new Uint32Array([batchAttributes.length]);
893
1124
  let totalNumberOfBytes = 0;
894
1125
  const stringSizesArray = new Uint32Array(batchAttributes.length);
895
- const stringBufferArray = [];
1126
+ const stringBufferArray: ArrayBuffer[] = [];
896
1127
 
897
1128
  for (let index = 0; index < batchAttributes.length; index++) {
898
1129
  const currentString = `${String(batchAttributes[index])}\0`;
@@ -929,10 +1160,17 @@ function generateBigUint64Array(featureIds) {
929
1160
  /**
930
1161
  * Generates draco compressed geometry
931
1162
  * @param {Number} vertexCount
932
- * @param {Object} convertedAttributes
1163
+ * @param {Object} convertedAttributes - get rid of this argument here
1164
+ * @param {Object} attributes - geometry attributes to compress
1165
+ * @param {string} dracoWorkerSoure - draco worker source code
933
1166
  * @returns {Promise<object>} - COmpressed geometry.
934
1167
  */
935
- async function generateCompressedGeometry(vertexCount, convertedAttributes, attributes) {
1168
+ async function generateCompressedGeometry(
1169
+ vertexCount,
1170
+ convertedAttributes,
1171
+ attributes,
1172
+ dracoWorkerSoure
1173
+ ) {
936
1174
  const {positions, normals, texCoords, colors, featureIds, faceRange} = attributes;
937
1175
  const indices = new Uint32Array(vertexCount);
938
1176
 
@@ -946,7 +1184,13 @@ async function generateCompressedGeometry(vertexCount, convertedAttributes, attr
946
1184
 
947
1185
  const featureIndex = generateFeatureIndexAttribute(featureIndices, faceRange);
948
1186
 
949
- const compressedAttributes = {
1187
+ const compressedAttributes: {
1188
+ positions: TypedArray;
1189
+ normals: TypedArray;
1190
+ colors: TypedArray;
1191
+ 'feature-index': TypedArray;
1192
+ texCoords?: TypedArray;
1193
+ } = {
950
1194
  positions,
951
1195
  normals,
952
1196
  colors,
@@ -964,14 +1208,16 @@ async function generateCompressedGeometry(vertexCount, convertedAttributes, attr
964
1208
  }
965
1209
  };
966
1210
 
967
- return new Uint8Array(
968
- await encode({attributes: compressedAttributes, indices}, DracoWriter, {
969
- draco: {
970
- method: 'MESH_SEQUENTIAL_ENCODING',
971
- attributesMetadata
972
- }
973
- })
974
- );
1211
+ return encode({attributes: compressedAttributes, indices}, DracoWriterWorker, {
1212
+ ...DracoWriterWorker.options,
1213
+ source: dracoWorkerSoure,
1214
+ reuseWorkers: true,
1215
+ _nodeWorkers: true,
1216
+ draco: {
1217
+ method: 'MESH_SEQUENTIAL_ENCODING',
1218
+ attributesMetadata
1219
+ }
1220
+ });
975
1221
  }
976
1222
 
977
1223
  /**