@loaders.gl/tile-converter 3.2.12 → 3.3.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/dist/3d-tiles-attributes-worker.d.ts +3 -3
  2. package/dist/3d-tiles-attributes-worker.d.ts.map +1 -1
  3. package/dist/3d-tiles-attributes-worker.js +2 -3
  4. package/dist/3d-tiles-attributes-worker.js.map +3 -3
  5. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +8 -0
  6. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  7. package/dist/3d-tiles-converter/3d-tiles-converter.js +57 -43
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +5 -5
  9. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
  10. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +21 -17
  11. package/dist/converter-cli.js +43 -8
  12. package/dist/converter.min.js +24 -21
  13. package/dist/deps-installer/deps-installer.d.ts +5 -1
  14. package/dist/deps-installer/deps-installer.d.ts.map +1 -1
  15. package/dist/deps-installer/deps-installer.js +29 -1
  16. package/dist/dist.min.js +58405 -61237
  17. package/dist/es5/3d-tiles-attributes-worker.js +4 -7
  18. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -1
  19. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +125 -210
  20. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  21. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +53 -85
  22. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  23. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +0 -8
  24. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
  25. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js +0 -5
  26. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
  27. package/dist/es5/3d-tiles-converter/json-templates/tileset.js +0 -6
  28. package/dist/es5/3d-tiles-converter/json-templates/tileset.js.map +1 -1
  29. package/dist/es5/bundle.js +0 -1
  30. package/dist/es5/bundle.js.map +1 -1
  31. package/dist/es5/constants.js.map +1 -1
  32. package/dist/es5/converter-cli.js +50 -60
  33. package/dist/es5/converter-cli.js.map +1 -1
  34. package/dist/es5/deps-installer/deps-installer.js +73 -28
  35. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  36. package/dist/es5/i3s-attributes-worker.js +3 -6
  37. package/dist/es5/i3s-attributes-worker.js.map +1 -1
  38. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +124 -0
  39. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
  40. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +2 -19
  41. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  42. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js +0 -11
  43. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
  44. package/dist/es5/i3s-converter/helpers/feature-attributes.js +184 -0
  45. package/dist/es5/i3s-converter/helpers/feature-attributes.js.map +1 -0
  46. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +60 -51
  47. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  48. package/dist/es5/i3s-converter/helpers/geometry-converter.js +516 -356
  49. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  50. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +57 -43
  51. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  52. package/dist/es5/i3s-converter/helpers/node-debug.js +4 -23
  53. package/dist/es5/i3s-converter/helpers/node-debug.js.map +1 -1
  54. package/dist/es5/i3s-converter/helpers/node-index-document.js +507 -0
  55. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -0
  56. package/dist/es5/i3s-converter/helpers/node-pages.js +462 -208
  57. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  58. package/dist/es5/i3s-converter/i3s-converter.js +722 -1153
  59. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  60. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js +107 -0
  61. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  62. package/dist/es5/i3s-converter/json-templates/layers.js +2 -107
  63. package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -1
  64. package/dist/es5/i3s-converter/json-templates/metadata.js +0 -2
  65. package/dist/es5/i3s-converter/json-templates/metadata.js.map +1 -1
  66. package/dist/es5/i3s-converter/json-templates/node.js +2 -12
  67. package/dist/es5/i3s-converter/json-templates/node.js.map +1 -1
  68. package/dist/es5/i3s-converter/json-templates/scene-server.js +0 -2
  69. package/dist/es5/i3s-converter/json-templates/scene-server.js.map +1 -1
  70. package/dist/es5/i3s-converter/json-templates/shared-resources.js +9 -32
  71. package/dist/es5/i3s-converter/json-templates/shared-resources.js.map +1 -1
  72. package/dist/es5/i3s-converter/json-templates/store.js.map +1 -1
  73. package/dist/es5/i3s-converter/types.js.map +1 -1
  74. package/dist/es5/i3s-server/app.js +0 -5
  75. package/dist/es5/i3s-server/app.js.map +1 -1
  76. package/dist/es5/i3s-server/controllers/index-controller.js +0 -16
  77. package/dist/es5/i3s-server/controllers/index-controller.js.map +1 -1
  78. package/dist/es5/i3s-server/routes/index.js +1 -10
  79. package/dist/es5/i3s-server/routes/index.js.map +1 -1
  80. package/dist/es5/index.js +0 -3
  81. package/dist/es5/index.js.map +1 -1
  82. package/dist/es5/lib/utils/compress-util.js +19 -74
  83. package/dist/es5/lib/utils/compress-util.js.map +1 -1
  84. package/dist/es5/lib/utils/file-utils.js +103 -47
  85. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  86. package/dist/es5/lib/utils/lod-conversion-utils.js +0 -7
  87. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  88. package/dist/es5/lib/utils/queue.js +0 -14
  89. package/dist/es5/lib/utils/queue.js.map +1 -1
  90. package/dist/es5/lib/utils/statistic-utills.js +1 -46
  91. package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
  92. package/dist/es5/lib/utils/write-queue.js +41 -82
  93. package/dist/es5/lib/utils/write-queue.js.map +1 -1
  94. package/dist/es5/pgm-loader.js +1 -8
  95. package/dist/es5/pgm-loader.js.map +1 -1
  96. package/dist/es5/workers/3d-tiles-attributes-worker.js +2 -9
  97. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -1
  98. package/dist/es5/workers/i3s-attributes-worker.js +2 -10
  99. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -1
  100. package/dist/esm/3d-tiles-attributes-worker.js +4 -2
  101. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -1
  102. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +60 -77
  103. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  104. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +29 -50
  105. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  106. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +1 -0
  107. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
  108. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js +1 -4
  109. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
  110. package/dist/esm/3d-tiles-converter/json-templates/tileset.js +0 -3
  111. package/dist/esm/3d-tiles-converter/json-templates/tileset.js.map +1 -1
  112. package/dist/esm/bundle.js +1 -1
  113. package/dist/esm/bundle.js.map +1 -1
  114. package/dist/esm/constants.js.map +1 -1
  115. package/dist/esm/converter-cli.js +46 -40
  116. package/dist/esm/converter-cli.js.map +1 -1
  117. package/dist/esm/deps-installer/deps-installer.js +30 -4
  118. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  119. package/dist/esm/i3s-attributes-worker.js +3 -1
  120. package/dist/esm/i3s-attributes-worker.js.map +1 -1
  121. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +113 -0
  122. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
  123. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +5 -6
  124. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  125. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js +1 -0
  126. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
  127. package/dist/esm/i3s-converter/helpers/feature-attributes.js +158 -0
  128. package/dist/esm/i3s-converter/helpers/feature-attributes.js.map +1 -0
  129. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +39 -33
  130. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  131. package/dist/esm/i3s-converter/helpers/geometry-converter.js +295 -196
  132. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  133. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +59 -34
  134. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  135. package/dist/esm/i3s-converter/helpers/node-debug.js +3 -13
  136. package/dist/esm/i3s-converter/helpers/node-debug.js.map +1 -1
  137. package/dist/esm/i3s-converter/helpers/node-index-document.js +197 -0
  138. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -0
  139. package/dist/esm/i3s-converter/helpers/node-pages.js +161 -87
  140. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  141. package/dist/esm/i3s-converter/i3s-converter.js +216 -491
  142. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  143. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js +89 -0
  144. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  145. package/dist/esm/i3s-converter/json-templates/layers.js +2 -95
  146. package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -1
  147. package/dist/esm/i3s-converter/json-templates/metadata.js.map +1 -1
  148. package/dist/esm/i3s-converter/json-templates/node.js +0 -4
  149. package/dist/esm/i3s-converter/json-templates/node.js.map +1 -1
  150. package/dist/esm/i3s-converter/json-templates/scene-server.js.map +1 -1
  151. package/dist/esm/i3s-converter/json-templates/shared-resources.js +3 -15
  152. package/dist/esm/i3s-converter/json-templates/shared-resources.js.map +1 -1
  153. package/dist/esm/i3s-converter/json-templates/store.js.map +1 -1
  154. package/dist/esm/i3s-converter/types.js.map +1 -1
  155. package/dist/esm/i3s-server/app.js +0 -5
  156. package/dist/esm/i3s-server/app.js.map +1 -1
  157. package/dist/esm/i3s-server/controllers/index-controller.js +0 -5
  158. package/dist/esm/i3s-server/controllers/index-controller.js.map +1 -1
  159. package/dist/esm/i3s-server/routes/index.js +0 -3
  160. package/dist/esm/i3s-server/routes/index.js.map +1 -1
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/lib/utils/compress-util.js +19 -12
  163. package/dist/esm/lib/utils/compress-util.js.map +1 -1
  164. package/dist/esm/lib/utils/file-utils.js +54 -11
  165. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  166. package/dist/esm/lib/utils/lod-conversion-utils.js +2 -6
  167. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  168. package/dist/esm/lib/utils/queue.js +0 -4
  169. package/dist/esm/lib/utils/queue.js.map +1 -1
  170. package/dist/esm/lib/utils/statistic-utills.js +0 -11
  171. package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
  172. package/dist/esm/lib/utils/write-queue.js +27 -38
  173. package/dist/esm/lib/utils/write-queue.js.map +1 -1
  174. package/dist/esm/pgm-loader.js +3 -1
  175. package/dist/esm/pgm-loader.js.map +1 -1
  176. package/dist/esm/workers/3d-tiles-attributes-worker.js +4 -1
  177. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -1
  178. package/dist/esm/workers/i3s-attributes-worker.js +4 -1
  179. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -1
  180. package/dist/i3s-attributes-worker.d.ts +7 -3
  181. package/dist/i3s-attributes-worker.d.ts.map +1 -1
  182. package/dist/i3s-attributes-worker.js +2 -3
  183. package/dist/i3s-attributes-worker.js.map +3 -3
  184. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +11 -0
  185. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -0
  186. package/dist/i3s-converter/helpers/batch-ids-extensions.js +141 -0
  187. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +2 -2
  188. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
  189. package/dist/i3s-converter/helpers/feature-attributes.d.ts +56 -0
  190. package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -0
  191. package/dist/i3s-converter/helpers/feature-attributes.js +216 -0
  192. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  193. package/dist/i3s-converter/helpers/geometry-attributes.js +42 -17
  194. package/dist/i3s-converter/helpers/geometry-converter.d.ts +18 -6
  195. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  196. package/dist/i3s-converter/helpers/geometry-converter.js +349 -99
  197. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
  198. package/dist/i3s-converter/helpers/gltf-attributes.js +53 -21
  199. package/dist/i3s-converter/helpers/node-index-document.d.ts +91 -0
  200. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -0
  201. package/dist/i3s-converter/helpers/node-index-document.js +242 -0
  202. package/dist/i3s-converter/helpers/node-pages.d.ts +81 -42
  203. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  204. package/dist/i3s-converter/helpers/node-pages.js +200 -92
  205. package/dist/i3s-converter/i3s-converter.d.ts +52 -108
  206. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  207. package/dist/i3s-converter/i3s-converter.js +218 -403
  208. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts +7 -0
  209. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts.map +1 -0
  210. package/dist/i3s-converter/json-templates/geometry-definitions.js +87 -0
  211. package/dist/i3s-converter/json-templates/layers.d.ts +1 -30
  212. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -1
  213. package/dist/i3s-converter/json-templates/layers.js +2 -86
  214. package/dist/i3s-converter/json-templates/shared-resources.js +3 -3
  215. package/dist/i3s-converter/types.d.ts +38 -8
  216. package/dist/i3s-converter/types.d.ts.map +1 -1
  217. package/dist/lib/utils/file-utils.d.ts +17 -1
  218. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  219. package/dist/lib/utils/file-utils.js +64 -7
  220. package/dist/lib/utils/write-queue.d.ts +19 -3
  221. package/dist/lib/utils/write-queue.d.ts.map +1 -1
  222. package/dist/lib/utils/write-queue.js +21 -16
  223. package/dist/pgm-loader.d.ts.map +1 -1
  224. package/dist/pgm-loader.js +2 -1
  225. package/dist/workers/3d-tiles-attributes-worker.js +1 -1
  226. package/dist/workers/i3s-attributes-worker.js +1 -1
  227. package/package.json +18 -16
  228. package/src/3d-tiles-attributes-worker.ts +1 -1
  229. package/src/3d-tiles-converter/3d-tiles-converter.ts +71 -55
  230. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +25 -18
  231. package/src/converter-cli.ts +54 -8
  232. package/src/deps-installer/deps-installer.ts +38 -2
  233. package/src/i3s-attributes-worker.ts +5 -1
  234. package/src/i3s-converter/helpers/batch-ids-extensions.ts +206 -0
  235. package/src/i3s-converter/helpers/coordinate-converter.ts +2 -2
  236. package/src/i3s-converter/helpers/feature-attributes.ts +247 -0
  237. package/src/i3s-converter/helpers/geometry-attributes.ts +46 -18
  238. package/src/i3s-converter/helpers/geometry-converter.ts +423 -111
  239. package/src/i3s-converter/helpers/gltf-attributes.ts +59 -24
  240. package/src/i3s-converter/helpers/node-index-document.ts +306 -0
  241. package/src/i3s-converter/helpers/node-pages.ts +222 -109
  242. package/src/i3s-converter/i3s-converter.ts +264 -487
  243. package/src/i3s-converter/json-templates/geometry-definitions.ts +83 -0
  244. package/src/i3s-converter/json-templates/layers.ts +2 -91
  245. package/src/i3s-converter/json-templates/shared-resources.ts +3 -3
  246. package/src/i3s-converter/types.ts +33 -2
  247. package/src/lib/utils/file-utils.ts +62 -7
  248. package/src/lib/utils/write-queue.ts +42 -19
  249. package/src/pgm-loader.ts +2 -2
  250. package/src/workers/3d-tiles-attributes-worker.ts +1 -1
  251. package/src/workers/i3s-attributes-worker.ts +2 -1
@@ -0,0 +1,206 @@
1
+ import {
2
+ GLTFAccessorPostprocessed,
3
+ GLTFImagePostprocessed,
4
+ GLTFMeshPrimitivePostprocessed
5
+ } from '@loaders.gl/gltf';
6
+ import type {
7
+ GLTF_EXT_feature_metadata_attribute,
8
+ GLTF_EXT_feature_metadata_primitive
9
+ } from 'modules/gltf/src/lib/types/gltf-json-schema';
10
+
11
+ const EXT_MESH_FEATURES = 'EXT_mesh_features';
12
+ const EXT_FEATURE_METADATA = 'EXT_feature_metadata';
13
+
14
+ /**
15
+ * Getting batchIds from 3DTilesNext extensions.
16
+ * @param attributes - gltf accessors
17
+ * @param primitive - gltf primitive data
18
+ * @param images - gltf texture images
19
+ */
20
+ export function handleBatchIdsExtensions(
21
+ attributes: {
22
+ [key: string]: GLTFAccessorPostprocessed;
23
+ },
24
+ primitive: GLTFMeshPrimitivePostprocessed,
25
+ images: GLTFImagePostprocessed[]
26
+ ): number[] {
27
+ const extensions = primitive?.extensions;
28
+
29
+ if (!extensions) {
30
+ return [];
31
+ }
32
+
33
+ for (const [extensionName, extensionData] of Object.entries(extensions || {})) {
34
+ switch (extensionName) {
35
+ case EXT_FEATURE_METADATA:
36
+ return handleExtFeatureMetadataExtension(
37
+ attributes,
38
+ extensionData as GLTF_EXT_feature_metadata_primitive,
39
+ images
40
+ );
41
+ case EXT_MESH_FEATURES:
42
+ console.warn('EXT_mesh_features extension is not supported yet');
43
+ return [];
44
+ default:
45
+ return [];
46
+ }
47
+ }
48
+
49
+ return [];
50
+ }
51
+
52
+ /**
53
+ * Get batchIds from EXT_feature_metadata extension.
54
+ * Docs - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata
55
+ * @param attributes
56
+ * @param extFeatureMetadata
57
+ * @param textures
58
+ */
59
+ function handleExtFeatureMetadataExtension(
60
+ attributes: {
61
+ [key: string]: GLTFAccessorPostprocessed;
62
+ },
63
+ extFeatureMetadata: GLTF_EXT_feature_metadata_primitive,
64
+ images: GLTFImagePostprocessed[]
65
+ ): number[] {
66
+ // Take only first extension object to get batchIds attribute name.
67
+ const featureIdAttribute = extFeatureMetadata?.featureIdAttributes?.[0];
68
+
69
+ if (featureIdAttribute?.featureIds?.attribute) {
70
+ const batchIdsAttribute = attributes[featureIdAttribute.featureIds.attribute];
71
+ return batchIdsAttribute.value;
72
+ }
73
+
74
+ if (
75
+ featureIdAttribute?.featureIds?.hasOwnProperty('constant') &&
76
+ featureIdAttribute?.featureIds?.hasOwnProperty('divisor')
77
+ ) {
78
+ const featuresCount = attributes?.POSITIONS?.value.length / 3 || 0;
79
+ return generateImplicitFeatureIds(
80
+ featuresCount,
81
+ featureIdAttribute.featureIds.constant,
82
+ featureIdAttribute.featureIds.divisor
83
+ );
84
+ }
85
+
86
+ // Take only first extension object to get batchIds attribute name.
87
+ const featureIdTexture =
88
+ extFeatureMetadata?.featureIdTextures && extFeatureMetadata?.featureIdTextures[0];
89
+
90
+ if (featureIdTexture) {
91
+ const textureAttributeIndex = featureIdTexture?.featureIds?.texture?.texCoord || 0;
92
+ const textCoordAttribute = `TEXCOORD_${textureAttributeIndex}`;
93
+ const textureCoordinates = attributes[textCoordAttribute].value;
94
+ return generateBatchIdsFromTexture(featureIdTexture, textureCoordinates, images);
95
+ }
96
+
97
+ // Take only first extension texture to get batchIds from the root EXT_feature_metadata object.
98
+ const featureTexture =
99
+ extFeatureMetadata?.featureTextures && extFeatureMetadata?.featureTextures[0];
100
+
101
+ /**
102
+ * TODO need to get batchIds from root extension
103
+ */
104
+ if (featureTexture) {
105
+ console.warn("EXT_feature_metadata doesn't yet support featureTextures in primitive");
106
+ return [];
107
+ }
108
+
109
+ return [];
110
+ }
111
+
112
+ /**
113
+ * Generates implicit feature ids
114
+ * Spec - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata#implicit-feature-ids
115
+ * @param featuresCount
116
+ * @param constant
117
+ * @param devisor
118
+ */
119
+ function generateImplicitFeatureIds(
120
+ featuresCount: number,
121
+ constant: number = 0,
122
+ divisor: number = 0
123
+ ): number[] {
124
+ let featureIds: number[] = [];
125
+
126
+ if (divisor > 0) {
127
+ let currentValue = constant;
128
+ let devisorCounter = divisor;
129
+
130
+ for (let index = 0; index < featuresCount; index++) {
131
+ featureIds.push(currentValue);
132
+
133
+ devisorCounter -= 1;
134
+
135
+ if (devisorCounter === 0) {
136
+ currentValue++;
137
+ devisorCounter = divisor;
138
+ }
139
+ }
140
+ } else {
141
+ featureIds = Array<number>(featuresCount).fill(constant, 0, featuresCount);
142
+ }
143
+
144
+ return featureIds;
145
+ }
146
+
147
+ /**
148
+ * Get batchIds from texture.
149
+ * @param primitive
150
+ * @param featureIdTextures
151
+ */
152
+ function generateBatchIdsFromTexture(
153
+ featureIdTexture: GLTF_EXT_feature_metadata_attribute,
154
+ textureCoordinates: Float32Array,
155
+ images: GLTFImagePostprocessed[]
156
+ ) {
157
+ if (!images?.length) {
158
+ return [];
159
+ }
160
+
161
+ const CHANNELS_MAP = {
162
+ r: 0,
163
+ g: 1,
164
+ b: 2,
165
+ a: 3
166
+ };
167
+
168
+ const textureIndex = featureIdTexture?.featureIds?.texture?.index;
169
+ const featureChannel = featureIdTexture?.featureIds?.channels;
170
+
171
+ if (!featureChannel || textureIndex === undefined) {
172
+ return [];
173
+ }
174
+
175
+ const image = images[textureIndex];
176
+ const batchIds: number[] = [];
177
+ const channels = CHANNELS_MAP[featureChannel];
178
+
179
+ if (!image.compressed) {
180
+ for (let index = 0; index < textureCoordinates.length; index += 2) {
181
+ const u = textureCoordinates[index];
182
+ const v = textureCoordinates[index + 1];
183
+
184
+ const tx = Math.min((emod(u) * image.width) | 0, image.width - 1);
185
+ const ty = Math.min((emod(v) * image.height) | 0, image.height - 1);
186
+
187
+ const offset = (ty * image.width + tx) * image.components + channels;
188
+ const batchId = new Uint8Array(image.data)[offset];
189
+
190
+ batchIds.push(batchId);
191
+ }
192
+ } else {
193
+ console.warn(`Can't get batch Ids from ${image.mimeType} compressed texture`);
194
+ }
195
+
196
+ return batchIds;
197
+ }
198
+
199
+ /**
200
+ * Handle UVs if they are out of range [0,1].
201
+ * @param n
202
+ * @param m
203
+ */
204
+ function emod(n: number): number {
205
+ return ((n % 1) + 1) % 1;
206
+ }
@@ -8,7 +8,7 @@ import {
8
8
  makeBoundingSphereFromPoints,
9
9
  BoundingSphere
10
10
  } from '@math.gl/culling';
11
- import TileHeader from '@loaders.gl/tiles/src/tileset/tile-3d';
11
+ import {Tile3D} from '@loaders.gl/tiles';
12
12
  import {Geoid} from '@math.gl/geoid';
13
13
 
14
14
  /**
@@ -17,7 +17,7 @@ import {Geoid} from '@math.gl/geoid';
17
17
  * @param geoidHeightModel
18
18
  * @returns - Bounding volumes object
19
19
  */
20
- export function createBoundingVolumes(tile: TileHeader, geoidHeightModel: Geoid): BoundingVolumes {
20
+ export function createBoundingVolumes(tile: Tile3D, geoidHeightModel: Geoid): BoundingVolumes {
21
21
  let radius;
22
22
  let halfSize;
23
23
  let quaternion;
@@ -0,0 +1,247 @@
1
+ import type {FeatureTableJson} from '@loaders.gl/3d-tiles';
2
+ import {
3
+ Attribute,
4
+ AttributeStorageInfo,
5
+ ESRIField,
6
+ Field,
7
+ FieldInfo,
8
+ PopupInfo
9
+ } from '@loaders.gl/i3s';
10
+
11
+ /**
12
+ * Takes attributes from property table based on featureIds.
13
+ * If there is no property value for particular featureId (index) the property will be null.
14
+ * Example:
15
+ * Initial data:
16
+ * OBJECTID: [0, 1, 5]
17
+ * component: ['Windows', 'Frames', 'Wall', 'Roof', 'Skylight']
18
+ * Result:
19
+ * OBJECTID: [0, 1, 5]
20
+ * component: ['Windows', 'Frames', 'null']
21
+ * @param featureIds
22
+ * @param propertyTable
23
+ */
24
+ export function flattenPropertyTableByFeatureIds(
25
+ featureIds: number[],
26
+ propertyTable: FeatureTableJson
27
+ ): FeatureTableJson {
28
+ const resultPropertyTable: FeatureTableJson = {};
29
+ for (const propertyName in propertyTable) {
30
+ const properties = propertyTable[propertyName];
31
+ resultPropertyTable[propertyName] = getPropertiesByFeatureIds(properties, featureIds);
32
+ }
33
+
34
+ return resultPropertyTable;
35
+ }
36
+
37
+ /**
38
+ * Getting properties by featureId index
39
+ * @param properties
40
+ * @param featureIds
41
+ */
42
+ function getPropertiesByFeatureIds(properties: any[], featureIds: number[]): any[] {
43
+ const resultProperties: any = [];
44
+
45
+ for (const featureId of featureIds) {
46
+ const property = properties[featureId] || null;
47
+ resultProperties.push(property);
48
+ }
49
+
50
+ return resultProperties;
51
+ }
52
+
53
+ /**
54
+ * Check that all attributes in propertyTable have the same length as FeatureIds.
55
+ * If there are differencies between lengths we should flatten property table based on exiesting featureIds.
56
+ * @param featureIds
57
+ * @param propertyTable
58
+ * @returns
59
+ */
60
+ export function checkPropertiesLength(
61
+ featureIds: number[],
62
+ propertyTable: FeatureTableJson
63
+ ): boolean {
64
+ let needFlatten = false;
65
+
66
+ for (const attribute of Object.values(propertyTable)) {
67
+ if (featureIds.length !== attribute.length) {
68
+ needFlatten = true;
69
+ }
70
+ }
71
+
72
+ return needFlatten;
73
+ }
74
+
75
+ /** String data type name for feature attributes */
76
+ const STRING_TYPE = 'string';
77
+ /** Integer data type name for feature attributes */
78
+ const SHORT_INT_TYPE = 'Int32';
79
+ /** Double data type name for feature attributes */
80
+ const DOUBLE_TYPE = 'double';
81
+ /** Type of attribute that is linked with feature ids */
82
+ const OBJECT_ID_TYPE = 'OBJECTID';
83
+ /**
84
+ * Get the attribute type for attributeStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
85
+ * @param key - attribute's key
86
+ * @param attribute - attribute's type in propertyTable
87
+ */
88
+ export function getAttributeType(key: string, attribute: string): string {
89
+ if (key === OBJECT_ID_TYPE) {
90
+ return OBJECT_ID_TYPE;
91
+ }
92
+ if (typeof attribute === STRING_TYPE) {
93
+ return STRING_TYPE;
94
+ } else if (typeof attribute === 'number') {
95
+ return Number.isInteger(attribute) ? SHORT_INT_TYPE : DOUBLE_TYPE;
96
+ }
97
+ return STRING_TYPE;
98
+ }
99
+
100
+ /**
101
+ * Generate storage attribute for map segmentation.
102
+ * @param attributeIndex - order index of attribute (f_0, f_1 ...).
103
+ * @param key - attribute key from propertyTable.
104
+ * @param attributeType - attribute type.
105
+ * @return Updated storageAttribute.
106
+ */
107
+ export function createdStorageAttribute(
108
+ attributeIndex: number,
109
+ key: string,
110
+ attributeType: Attribute
111
+ ): AttributeStorageInfo {
112
+ const storageAttribute = {
113
+ key: `f_${attributeIndex}`,
114
+ name: key,
115
+ ordering: ['attributeValues'],
116
+ header: [{property: 'count', valueType: 'UInt32'}],
117
+ attributeValues: {valueType: 'Int32', valuesPerElement: 1}
118
+ };
119
+
120
+ switch (attributeType) {
121
+ case OBJECT_ID_TYPE:
122
+ setupIdAttribute(storageAttribute);
123
+ break;
124
+ case STRING_TYPE:
125
+ setupStringAttribute(storageAttribute);
126
+ break;
127
+ case DOUBLE_TYPE:
128
+ setupDoubleAttribute(storageAttribute);
129
+ break;
130
+ case SHORT_INT_TYPE:
131
+ break;
132
+ default:
133
+ setupStringAttribute(storageAttribute);
134
+ }
135
+
136
+ return storageAttribute;
137
+ }
138
+
139
+ /**
140
+ * Find and return attribute type based on key form propertyTable.
141
+ * @param attributeType
142
+ */
143
+ export function getFieldAttributeType(attributeType: Attribute): ESRIField {
144
+ switch (attributeType) {
145
+ case OBJECT_ID_TYPE:
146
+ return 'esriFieldTypeOID';
147
+ case STRING_TYPE:
148
+ return 'esriFieldTypeString';
149
+ case SHORT_INT_TYPE:
150
+ return 'esriFieldTypeInteger';
151
+ case DOUBLE_TYPE:
152
+ return 'esriFieldTypeDouble';
153
+ default:
154
+ return 'esriFieldTypeString';
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Setup field attribute for map segmentation.
160
+ * @param key - attribute for map segmentation.
161
+ * @param fieldAttributeType - esri attribute type ('esriFieldTypeString' or 'esriFieldTypeOID').
162
+ */
163
+ export function createFieldAttribute(key: string, fieldAttributeType: ESRIField): Field {
164
+ return {
165
+ name: key,
166
+ type: fieldAttributeType,
167
+ alias: key
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Generate popup info to show metadata on the map.
173
+ * @param propertyTable - table data with OBJECTID.
174
+ * @return data for correct rendering of popup.
175
+ */
176
+ export function createPopupInfo(propertyTable: FeatureTableJson): PopupInfo {
177
+ const title = '{OBJECTID}';
178
+ const mediaInfos = [];
179
+ const fieldInfos: FieldInfo[] = [];
180
+ const popupElements: {
181
+ fieldInfos: FieldInfo[];
182
+ type: string;
183
+ }[] = [];
184
+ const expressionInfos = [];
185
+
186
+ for (const key in propertyTable) {
187
+ fieldInfos.push({
188
+ fieldName: key,
189
+ visible: true,
190
+ isEditable: false,
191
+ label: key
192
+ });
193
+ }
194
+ popupElements.push({
195
+ fieldInfos,
196
+ type: 'fields'
197
+ });
198
+
199
+ return {
200
+ title,
201
+ mediaInfos,
202
+ popupElements,
203
+ fieldInfos,
204
+ expressionInfos
205
+ };
206
+ }
207
+
208
+ /**
209
+ * Setup storage attribute as string.
210
+ * @param storageAttribute - attribute for map segmentation.
211
+ */
212
+ function setupStringAttribute(storageAttribute: AttributeStorageInfo): void {
213
+ // @ts-expect-error
214
+ storageAttribute.ordering.unshift('attributeByteCounts');
215
+ storageAttribute.header.push({property: 'attributeValuesByteCount', valueType: 'UInt32'});
216
+ storageAttribute.attributeValues = {
217
+ valueType: 'String',
218
+ encoding: 'UTF-8',
219
+ valuesPerElement: 1
220
+ };
221
+ storageAttribute.attributeByteCounts = {
222
+ valueType: 'UInt32',
223
+ valuesPerElement: 1
224
+ };
225
+ }
226
+
227
+ /**
228
+ * Setup Id attribute for map segmentation.
229
+ * @param storageAttribute - attribute for map segmentation .
230
+ */
231
+ function setupIdAttribute(storageAttribute: AttributeStorageInfo): void {
232
+ storageAttribute.attributeValues = {
233
+ valueType: 'Oid32',
234
+ valuesPerElement: 1
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Setup double attribute for map segmentation.
240
+ * @param storageAttribute - attribute for map segmentation .
241
+ */
242
+ function setupDoubleAttribute(storageAttribute: AttributeStorageInfo): void {
243
+ storageAttribute.attributeValues = {
244
+ valueType: 'Float64',
245
+ valuesPerElement: 1
246
+ };
247
+ }
@@ -10,7 +10,7 @@ const POSITIONS_AND_NORMALS_PER_TRIANGLE = 9;
10
10
  * @returns attirbutes with featureCount, featureIds and changed faceRange.
11
11
  */
12
12
  export function generateAttributes(attributes: ConvertedAttributes): GeometryAttributes {
13
- const {positions, normals, texCoords, colors, featureIndices} = attributes;
13
+ const {positions, normals, texCoords, colors, uvRegions, featureIndices} = attributes;
14
14
  const triangleCount = positions.length / POSITIONS_AND_NORMALS_PER_TRIANGLE;
15
15
 
16
16
  if (!featureIndices.length) {
@@ -21,7 +21,8 @@ export function generateAttributes(attributes: ConvertedAttributes): GeometryAtt
21
21
  positions,
22
22
  normals,
23
23
  texCoords,
24
- colors
24
+ colors,
25
+ uvRegions
25
26
  };
26
27
  }
27
28
 
@@ -47,7 +48,7 @@ function calculateFaceRangesAndFeaturesCount(featureIndices: number[]): {
47
48
  } {
48
49
  let rangeIndex = 1;
49
50
  let featureIndex = 1;
50
- let currentFeatureId = featureIndices[0];
51
+ let currentFeatureId = getFrequentValue(featureIndices.slice(0, VALUES_PER_VERTEX));
51
52
  const faceRangeList: any[] = [];
52
53
  const featureIds: any[] = [];
53
54
  const uniqueFeatureIds = [currentFeatureId];
@@ -55,20 +56,21 @@ function calculateFaceRangesAndFeaturesCount(featureIndices: number[]): {
55
56
  faceRangeList[0] = 0;
56
57
  featureIds[0] = currentFeatureId;
57
58
 
58
- for (let index = 1; index < featureIndices.length; index++) {
59
- if (currentFeatureId !== featureIndices[index]) {
59
+ for (let index = VALUES_PER_VERTEX; index < featureIndices.length; index += VALUES_PER_VERTEX) {
60
+ const newFeatureId = getFrequentValue(featureIndices.slice(index, index + VALUES_PER_VERTEX));
61
+ if (currentFeatureId !== newFeatureId) {
60
62
  faceRangeList[rangeIndex] = index / VALUES_PER_VERTEX - 1;
61
63
  faceRangeList[rangeIndex + 1] = index / VALUES_PER_VERTEX;
62
- featureIds[featureIndex] = featureIndices[index];
64
+ featureIds[featureIndex] = newFeatureId;
63
65
 
64
- if (!uniqueFeatureIds.includes(featureIndices[index])) {
65
- uniqueFeatureIds.push(featureIndices[index]);
66
+ if (!uniqueFeatureIds.includes(newFeatureId)) {
67
+ uniqueFeatureIds.push(newFeatureId);
66
68
  }
67
69
 
68
70
  rangeIndex += 2;
69
71
  featureIndex += 1;
70
72
  }
71
- currentFeatureId = featureIndices[index];
73
+ currentFeatureId = newFeatureId;
72
74
  }
73
75
 
74
76
  faceRangeList[rangeIndex] = featureIndices.length / VALUES_PER_VERTEX - 1;
@@ -79,6 +81,28 @@ function calculateFaceRangesAndFeaturesCount(featureIndices: number[]): {
79
81
  return {faceRange, featureCount, featureIds};
80
82
  }
81
83
 
84
+ /**
85
+ * Find most frequent value to avoid situation where one vertex can be part of multiple features (objects).
86
+ * @param values
87
+ */
88
+ function getFrequentValue(values: number[]): number {
89
+ const map: {[key: number]: number} = {};
90
+
91
+ let mostFrequentValue = values[0];
92
+ let maxCount = 1;
93
+
94
+ for (const value of values) {
95
+ // Save item and it's frequency count to the map.
96
+ map[value] = (map[value] || 0) + 1;
97
+ // Find max count of frequency.
98
+ maxCount = maxCount > map[value] ? maxCount : map[value];
99
+ // Find the most frequent value.
100
+ mostFrequentValue = maxCount > map[value] ? mostFrequentValue : value;
101
+ }
102
+
103
+ return mostFrequentValue;
104
+ }
105
+
82
106
  /**
83
107
  * Generate list of attribute object grouped by feature ids.
84
108
  * @param attributes
@@ -90,6 +114,7 @@ function makeAttributeObjects(attributes: GeometryAttributes): GroupedByFeatureI
90
114
  positions,
91
115
  normals,
92
116
  colors,
117
+ uvRegions,
93
118
  texCoords,
94
119
  faceRange = new Uint32Array(0)
95
120
  } = attributes;
@@ -99,16 +124,16 @@ function makeAttributeObjects(attributes: GeometryAttributes): GroupedByFeatureI
99
124
  let normalsList = new Float32Array(normals);
100
125
  let colorsList = new Uint8Array(colors);
101
126
  let texCoordsList = new Float32Array(texCoords);
102
-
103
- let faceRangeIndex = 0;
127
+ let uvRegionsList = new Uint16Array(uvRegions);
104
128
 
105
129
  for (let index = 0; index < featureIds.length; index++) {
106
- const startIndex = faceRange[index + faceRangeIndex];
107
- const endIndex = faceRange[index + faceRangeIndex + 1];
130
+ const startIndex = faceRange[index * 2];
131
+ const endIndex = faceRange[index * 2 + 1];
108
132
 
109
133
  const positionsCount = getSliceAttributeCount('positions', startIndex, endIndex);
110
134
  const normalsCount = getSliceAttributeCount('normals', startIndex, endIndex);
111
135
  const colorsCount = getSliceAttributeCount('colors', startIndex, endIndex);
136
+ const uvRegionsCount = getSliceAttributeCount('uvRegions', startIndex, endIndex);
112
137
  const texCoordsCount = getSliceAttributeCount('texCoords', startIndex, endIndex);
113
138
 
114
139
  groupedData.push({
@@ -116,15 +141,15 @@ function makeAttributeObjects(attributes: GeometryAttributes): GroupedByFeatureI
116
141
  positions: positionsList.slice(0, positionsCount),
117
142
  normals: normalsList.slice(0, normalsCount),
118
143
  colors: colorsList.slice(0, colorsCount),
144
+ uvRegions: uvRegionsList.slice(0, uvRegionsCount),
119
145
  texCoords: texCoordsList.slice(0, texCoordsCount)
120
146
  });
121
147
 
122
148
  positionsList = positionsList.slice(positionsCount);
123
149
  normalsList = normalsList.slice(normalsCount);
124
150
  colorsList = colorsList.slice(colorsCount);
151
+ uvRegionsList = uvRegionsList.slice(uvRegionsCount);
125
152
  texCoordsList = texCoordsList.slice(texCoordsCount);
126
-
127
- faceRangeIndex += 1;
128
153
  }
129
154
 
130
155
  return groupedData.sort((first, second) => first.featureId - second.featureId);
@@ -142,7 +167,7 @@ function getSliceAttributeCount(
142
167
  startIndex: number,
143
168
  endIndex: number
144
169
  ): number {
145
- const colorsPerVertex = 4;
170
+ const itemsPerVertex4 = 4;
146
171
  const texCoordsPerVertex = 2;
147
172
 
148
173
  const trianglesCount = endIndex - startIndex + 1;
@@ -153,7 +178,8 @@ function getSliceAttributeCount(
153
178
  case 'normals':
154
179
  return trianglesCount * POSITIONS_AND_NORMALS_PER_TRIANGLE;
155
180
  case 'colors':
156
- return vertexCount * colorsPerVertex;
181
+ case 'uvRegions':
182
+ return vertexCount * itemsPerVertex4;
157
183
  case 'texCoords':
158
184
  return vertexCount * texCoordsPerVertex;
159
185
  default:
@@ -209,6 +235,7 @@ function groupAttributesAndRangesByFeatureId(
209
235
  let positions = new Float32Array(firstAttributeObject.positions);
210
236
  let normals = new Float32Array(firstAttributeObject.normals);
211
237
  let colors = new Uint8Array(firstAttributeObject.colors);
238
+ let uvRegions = new Uint16Array(firstAttributeObject.uvRegions);
212
239
  let texCoords = new Float32Array(firstAttributeObject.texCoords);
213
240
  const range = [0];
214
241
 
@@ -222,6 +249,7 @@ function groupAttributesAndRangesByFeatureId(
222
249
  positions = concatenateTypedArrays(positions, currentAttributesObject.positions);
223
250
  normals = concatenateTypedArrays(normals, currentAttributesObject.normals);
224
251
  colors = concatenateTypedArrays(colors, currentAttributesObject.colors);
252
+ uvRegions = concatenateTypedArrays(uvRegions, currentAttributesObject.uvRegions);
225
253
  texCoords = concatenateTypedArrays(texCoords, currentAttributesObject.texCoords);
226
254
 
227
255
  const groupedObject = unifiedObjects[objIndex];
@@ -235,5 +263,5 @@ function groupAttributesAndRangesByFeatureId(
235
263
  range.push(positions.length / POSITIONS_AND_NORMALS_PER_TRIANGLE - 1);
236
264
 
237
265
  const faceRange = new Uint32Array(range);
238
- return {faceRange, featureIds, positions, normals, colors, texCoords, featureCount};
266
+ return {faceRange, featureIds, positions, normals, colors, uvRegions, texCoords, featureCount};
239
267
  }