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

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 (407) 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 +3 -0
  4. package/dist/3d-tiles-attributes-worker.js.map +7 -0
  5. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +90 -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 +273 -231
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +79 -18
  9. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -0
  10. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +269 -236
  11. package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.d.ts +4 -7
  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 +22 -9
  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 +47 -28
  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 +42 -36
  20. package/dist/bundle.d.ts +2 -0
  21. package/dist/bundle.d.ts.map +1 -0
  22. package/dist/bundle.js +2 -2
  23. package/dist/constants.d.ts +2 -0
  24. package/dist/constants.d.ts.map +1 -0
  25. package/dist/constants.js +4 -0
  26. package/dist/converter-cli.d.ts +2 -0
  27. package/dist/converter-cli.d.ts.map +1 -0
  28. package/dist/converter-cli.js +280 -0
  29. package/dist/converter.min.js +186 -190
  30. package/dist/deps-installer/deps-installer.d.ts +11 -3
  31. package/dist/deps-installer/deps-installer.d.ts.map +1 -0
  32. package/dist/deps-installer/deps-installer.js +60 -23
  33. package/dist/dist.min.js +63496 -0
  34. package/dist/es5/3d-tiles-attributes-worker.js +25 -0
  35. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -0
  36. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +470 -0
  37. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -0
  38. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +301 -0
  39. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -0
  40. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +18 -0
  41. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -0
  42. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js +33 -0
  43. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js.map +1 -0
  44. package/dist/es5/3d-tiles-converter/json-templates/tileset.js +61 -0
  45. package/dist/es5/3d-tiles-converter/json-templates/tileset.js.map +1 -0
  46. package/dist/es5/bundle.js +6 -0
  47. package/dist/es5/bundle.js.map +1 -0
  48. package/dist/es5/constants.js +9 -0
  49. package/dist/es5/constants.js.map +1 -0
  50. package/dist/es5/converter-cli.js +289 -0
  51. package/dist/es5/converter-cli.js.map +1 -0
  52. package/dist/es5/deps-installer/deps-installer.js +123 -0
  53. package/dist/es5/deps-installer/deps-installer.js.map +1 -0
  54. package/dist/es5/i3s-attributes-worker.js +25 -0
  55. package/dist/es5/i3s-attributes-worker.js.map +1 -0
  56. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +116 -0
  57. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
  58. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +90 -0
  59. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -0
  60. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js +41 -0
  61. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js.map +1 -0
  62. package/dist/es5/i3s-converter/helpers/feature-attributes.js +174 -0
  63. package/dist/es5/i3s-converter/helpers/feature-attributes.js.map +1 -0
  64. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +213 -0
  65. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -0
  66. package/dist/es5/i3s-converter/helpers/geometry-converter.js +1173 -0
  67. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -0
  68. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +83 -0
  69. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  70. package/dist/es5/i3s-converter/helpers/node-debug.js +76 -0
  71. package/dist/es5/i3s-converter/helpers/node-debug.js.map +1 -0
  72. package/dist/es5/i3s-converter/helpers/node-index-document.js +492 -0
  73. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -0
  74. package/dist/es5/i3s-converter/helpers/node-pages.js +519 -0
  75. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -0
  76. package/dist/es5/i3s-converter/i3s-converter.js +1519 -0
  77. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -0
  78. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js +107 -0
  79. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  80. package/dist/es5/i3s-converter/json-templates/layers.js +163 -0
  81. package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -0
  82. package/dist/es5/i3s-converter/json-templates/metadata.js +31 -0
  83. package/dist/es5/i3s-converter/json-templates/metadata.js.map +1 -0
  84. package/dist/es5/i3s-converter/json-templates/node.js +99 -0
  85. package/dist/es5/i3s-converter/json-templates/node.js.map +1 -0
  86. package/dist/es5/i3s-converter/json-templates/scene-server.js +39 -0
  87. package/dist/es5/i3s-converter/json-templates/scene-server.js.map +1 -0
  88. package/dist/es5/i3s-converter/json-templates/shared-resources.js +173 -0
  89. package/dist/es5/i3s-converter/json-templates/shared-resources.js.map +1 -0
  90. package/dist/es5/i3s-converter/json-templates/store.js +107 -0
  91. package/dist/es5/i3s-converter/json-templates/store.js.map +1 -0
  92. package/dist/es5/i3s-converter/types.js +2 -0
  93. package/dist/es5/i3s-converter/types.js.map +1 -0
  94. package/dist/es5/i3s-server/app.js +18 -0
  95. package/dist/es5/i3s-server/app.js.map +1 -0
  96. package/dist/es5/i3s-server/controllers/index-controller.js +55 -0
  97. package/dist/es5/i3s-server/controllers/index-controller.js.map +1 -0
  98. package/dist/es5/i3s-server/routes/index.js +37 -0
  99. package/dist/es5/i3s-server/routes/index.js.map +1 -0
  100. package/dist/es5/index.js +21 -0
  101. package/dist/es5/index.js.map +1 -0
  102. package/dist/es5/lib/utils/compress-util.js +346 -0
  103. package/dist/es5/lib/utils/compress-util.js.map +1 -0
  104. package/dist/es5/lib/utils/file-utils.js +208 -0
  105. package/dist/es5/lib/utils/file-utils.js.map +1 -0
  106. package/dist/es5/lib/utils/lod-conversion-utils.js +44 -0
  107. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -0
  108. package/dist/es5/lib/utils/queue.js +47 -0
  109. package/dist/es5/lib/utils/queue.js.map +1 -0
  110. package/dist/es5/lib/utils/statistic-utills.d.ts +25 -0
  111. package/dist/es5/lib/utils/statistic-utills.js +147 -0
  112. package/dist/es5/lib/utils/statistic-utills.js.map +1 -0
  113. package/dist/es5/lib/utils/write-queue.js +214 -0
  114. package/dist/es5/lib/utils/write-queue.js.map +1 -0
  115. package/dist/es5/pgm-loader.js +41 -0
  116. package/dist/es5/pgm-loader.js.map +1 -0
  117. package/dist/es5/workers/3d-tiles-attributes-worker.js +28 -0
  118. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -0
  119. package/dist/es5/workers/i3s-attributes-worker.js +30 -0
  120. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -0
  121. package/dist/esm/3d-tiles-attributes-worker.js +16 -0
  122. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -0
  123. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +248 -0
  124. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -0
  125. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +224 -0
  126. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -0
  127. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +10 -0
  128. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -0
  129. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js +27 -0
  130. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js.map +1 -0
  131. package/dist/esm/3d-tiles-converter/json-templates/tileset.js +37 -0
  132. package/dist/esm/3d-tiles-converter/json-templates/tileset.js.map +1 -0
  133. package/dist/esm/bundle.js +4 -0
  134. package/dist/esm/bundle.js.map +1 -0
  135. package/dist/esm/constants.js +2 -0
  136. package/dist/esm/constants.js.map +1 -0
  137. package/dist/esm/converter-cli.js +232 -0
  138. package/dist/esm/converter-cli.js.map +1 -0
  139. package/dist/esm/deps-installer/deps-installer.js +44 -0
  140. package/dist/esm/deps-installer/deps-installer.js.map +1 -0
  141. package/dist/esm/i3s-attributes-worker.js +16 -0
  142. package/dist/esm/i3s-attributes-worker.js.map +1 -0
  143. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +105 -0
  144. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
  145. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +80 -0
  146. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -0
  147. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js +16 -0
  148. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js.map +1 -0
  149. package/dist/esm/i3s-converter/helpers/feature-attributes.js +147 -0
  150. package/dist/esm/i3s-converter/helpers/feature-attributes.js.map +1 -0
  151. package/{src → dist/esm}/i3s-converter/helpers/geometry-attributes.js +80 -106
  152. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -0
  153. package/dist/esm/i3s-converter/helpers/geometry-converter.js +887 -0
  154. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -0
  155. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +76 -0
  156. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -0
  157. package/{src → dist/esm}/i3s-converter/helpers/node-debug.js +20 -41
  158. package/dist/esm/i3s-converter/helpers/node-debug.js.map +1 -0
  159. package/dist/esm/i3s-converter/helpers/node-index-document.js +188 -0
  160. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -0
  161. package/dist/esm/i3s-converter/helpers/node-pages.js +206 -0
  162. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -0
  163. package/dist/esm/i3s-converter/i3s-converter.js +771 -0
  164. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -0
  165. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js +89 -0
  166. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  167. package/dist/esm/i3s-converter/json-templates/layers.js +133 -0
  168. package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -0
  169. package/dist/esm/i3s-converter/json-templates/metadata.js +22 -0
  170. package/dist/esm/i3s-converter/json-templates/metadata.js.map +1 -0
  171. package/dist/esm/i3s-converter/json-templates/node.js +80 -0
  172. package/dist/esm/i3s-converter/json-templates/node.js.map +1 -0
  173. package/dist/esm/i3s-converter/json-templates/scene-server.js +28 -0
  174. package/dist/esm/i3s-converter/json-templates/scene-server.js.map +1 -0
  175. package/dist/esm/i3s-converter/json-templates/shared-resources.js +123 -0
  176. package/dist/esm/i3s-converter/json-templates/shared-resources.js.map +1 -0
  177. package/dist/esm/i3s-converter/json-templates/store.js +98 -0
  178. package/dist/esm/i3s-converter/json-templates/store.js.map +1 -0
  179. package/dist/esm/i3s-converter/types.js +2 -0
  180. package/dist/esm/i3s-converter/types.js.map +1 -0
  181. package/dist/esm/i3s-server/app.js +16 -0
  182. package/dist/esm/i3s-server/app.js.map +1 -0
  183. package/dist/esm/i3s-server/bin/www +102 -0
  184. package/dist/esm/i3s-server/certs/cert.pem +19 -0
  185. package/dist/esm/i3s-server/certs/key.pem +27 -0
  186. package/dist/esm/i3s-server/controllers/index-controller.js +24 -0
  187. package/dist/esm/i3s-server/controllers/index-controller.js.map +1 -0
  188. package/dist/esm/i3s-server/routes/index.js +16 -0
  189. package/dist/esm/i3s-server/routes/index.js.map +1 -0
  190. package/dist/esm/index.js +3 -0
  191. package/dist/esm/index.js.map +1 -0
  192. package/dist/esm/lib/utils/compress-util.js +168 -0
  193. package/dist/esm/lib/utils/compress-util.js.map +1 -0
  194. package/dist/esm/lib/utils/file-utils.js +87 -0
  195. package/dist/esm/lib/utils/file-utils.js.map +1 -0
  196. package/dist/esm/lib/utils/lod-conversion-utils.js +37 -0
  197. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -0
  198. package/dist/esm/lib/utils/queue.js +15 -0
  199. package/dist/esm/lib/utils/queue.js.map +1 -0
  200. package/dist/esm/lib/utils/statistic-utills.d.ts +25 -0
  201. package/dist/esm/lib/utils/statistic-utills.js +62 -0
  202. package/dist/esm/lib/utils/statistic-utills.js.map +1 -0
  203. package/dist/esm/lib/utils/write-queue.js +85 -0
  204. package/dist/esm/lib/utils/write-queue.js.map +1 -0
  205. package/dist/esm/pgm-loader.js +15 -0
  206. package/dist/esm/pgm-loader.js.map +1 -0
  207. package/dist/esm/workers/3d-tiles-attributes-worker.js +8 -0
  208. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -0
  209. package/dist/esm/workers/i3s-attributes-worker.js +7 -0
  210. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -0
  211. package/dist/i3s-attributes-worker.d.ts +37 -0
  212. package/dist/i3s-attributes-worker.d.ts.map +1 -0
  213. package/dist/i3s-attributes-worker.js +9 -0
  214. package/dist/i3s-attributes-worker.js.map +7 -0
  215. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +11 -0
  216. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -0
  217. package/dist/i3s-converter/helpers/batch-ids-extensions.js +141 -0
  218. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +41 -0
  219. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -0
  220. package/dist/i3s-converter/helpers/coordinate-converter.js +120 -42
  221. package/dist/i3s-converter/helpers/create-scene-server-path.d.ts +9 -0
  222. package/dist/i3s-converter/helpers/create-scene-server-path.d.ts.map +1 -0
  223. package/dist/i3s-converter/helpers/create-scene-server-path.js +27 -15
  224. package/dist/i3s-converter/helpers/feature-attributes.d.ts +56 -0
  225. package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -0
  226. package/dist/i3s-converter/helpers/feature-attributes.js +216 -0
  227. package/dist/i3s-converter/helpers/geometry-attributes.d.ts +8 -0
  228. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -0
  229. package/dist/i3s-converter/helpers/geometry-attributes.js +188 -185
  230. package/dist/i3s-converter/helpers/geometry-converter.d.ts +36 -35
  231. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -0
  232. package/dist/i3s-converter/helpers/geometry-converter.js +1149 -650
  233. package/dist/i3s-converter/helpers/gltf-attributes.d.ts +9 -0
  234. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -0
  235. package/dist/i3s-converter/helpers/gltf-attributes.js +88 -0
  236. package/dist/i3s-converter/helpers/node-debug.d.ts +8 -0
  237. package/dist/i3s-converter/helpers/node-debug.d.ts.map +1 -0
  238. package/dist/i3s-converter/helpers/node-debug.js +106 -74
  239. package/dist/i3s-converter/helpers/node-index-document.d.ts +95 -0
  240. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -0
  241. package/dist/i3s-converter/helpers/node-index-document.js +250 -0
  242. package/dist/i3s-converter/helpers/node-pages.d.ts +125 -113
  243. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -0
  244. package/dist/i3s-converter/helpers/node-pages.js +313 -133
  245. package/dist/i3s-converter/i3s-converter.d.ts +267 -0
  246. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -0
  247. package/dist/i3s-converter/i3s-converter.js +860 -861
  248. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts +7 -0
  249. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts.map +1 -0
  250. package/dist/i3s-converter/json-templates/geometry-definitions.js +87 -0
  251. package/dist/i3s-converter/json-templates/layers.d.ts +70 -0
  252. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -0
  253. package/dist/i3s-converter/json-templates/layers.js +138 -190
  254. package/dist/i3s-converter/json-templates/metadata.d.ts +22 -0
  255. package/dist/i3s-converter/json-templates/metadata.d.ts.map +1 -0
  256. package/dist/i3s-converter/json-templates/metadata.js +25 -22
  257. package/dist/i3s-converter/json-templates/node.d.ts +61 -0
  258. package/dist/i3s-converter/json-templates/node.d.ts.map +1 -0
  259. package/dist/i3s-converter/json-templates/node.js +88 -79
  260. package/dist/i3s-converter/json-templates/scene-server.d.ts +28 -0
  261. package/dist/i3s-converter/json-templates/scene-server.d.ts.map +1 -0
  262. package/dist/i3s-converter/json-templates/scene-server.js +31 -28
  263. package/dist/i3s-converter/json-templates/shared-resources.d.ts +14 -0
  264. package/dist/i3s-converter/json-templates/shared-resources.d.ts.map +1 -0
  265. package/dist/i3s-converter/json-templates/shared-resources.js +124 -125
  266. package/dist/i3s-converter/json-templates/store.d.ts +95 -0
  267. package/dist/i3s-converter/json-templates/store.d.ts.map +1 -0
  268. package/dist/i3s-converter/json-templates/store.js +100 -95
  269. package/dist/i3s-converter/types.d.ts +145 -0
  270. package/dist/i3s-converter/types.d.ts.map +1 -0
  271. package/dist/i3s-converter/types.js +2 -0
  272. package/dist/i3s-server/app.d.ts +3 -0
  273. package/dist/i3s-server/app.d.ts.map +1 -0
  274. package/dist/i3s-server/app.js +2 -9
  275. package/dist/i3s-server/controllers/index-controller.d.ts +2 -0
  276. package/dist/i3s-server/controllers/index-controller.d.ts.map +1 -0
  277. package/dist/i3s-server/controllers/index-controller.js +16 -24
  278. package/dist/i3s-server/routes/index.d.ts +3 -0
  279. package/dist/i3s-server/routes/index.d.ts.map +1 -0
  280. package/dist/i3s-server/routes/index.js +11 -15
  281. package/dist/index.d.ts +3 -0
  282. package/dist/index.d.ts.map +1 -0
  283. package/dist/index.js +10 -5
  284. package/dist/lib/utils/compress-util.d.ts +45 -0
  285. package/dist/lib/utils/compress-util.d.ts.map +1 -0
  286. package/dist/lib/utils/compress-util.js +238 -160
  287. package/dist/lib/utils/file-utils.d.ts +22 -14
  288. package/dist/lib/utils/file-utils.d.ts.map +1 -0
  289. package/dist/lib/utils/file-utils.js +133 -36
  290. package/dist/lib/utils/lod-conversion-utils.d.ts +21 -12
  291. package/dist/lib/utils/lod-conversion-utils.d.ts.map +1 -0
  292. package/dist/lib/utils/lod-conversion-utils.js +72 -39
  293. package/dist/lib/utils/queue.d.ts +7 -0
  294. package/dist/lib/utils/queue.d.ts.map +1 -0
  295. package/dist/lib/utils/queue.js +18 -0
  296. package/dist/lib/utils/statistic-utills.d.ts +3 -25
  297. package/dist/lib/utils/statistic-utills.d.ts.map +1 -0
  298. package/dist/lib/utils/statistic-utills.js +58 -67
  299. package/dist/lib/utils/write-queue.d.ts +39 -0
  300. package/dist/lib/utils/write-queue.d.ts.map +1 -0
  301. package/dist/lib/utils/write-queue.js +80 -0
  302. package/dist/pgm-loader.d.ts +6 -0
  303. package/dist/pgm-loader.d.ts.map +1 -0
  304. package/dist/pgm-loader.js +23 -14
  305. package/dist/workers/3d-tiles-attributes-worker.d.ts +2 -0
  306. package/dist/workers/3d-tiles-attributes-worker.d.ts.map +1 -0
  307. package/dist/workers/3d-tiles-attributes-worker.js +9 -0
  308. package/dist/workers/i3s-attributes-worker.d.ts +2 -0
  309. package/dist/workers/i3s-attributes-worker.d.ts.map +1 -0
  310. package/dist/workers/i3s-attributes-worker.js +5 -0
  311. package/package.json +35 -24
  312. package/src/3d-tiles-attributes-worker.ts +43 -0
  313. package/src/3d-tiles-converter/3d-tiles-converter.ts +124 -59
  314. package/src/3d-tiles-converter/helpers/{b3dm-converter.js → b3dm-converter.ts} +71 -38
  315. package/src/3d-tiles-converter/helpers/{i3s-obb-to-3d-tiles-obb.js → i3s-obb-to-3d-tiles-obb.ts} +16 -1
  316. package/src/3d-tiles-converter/helpers/texture-atlas.ts +4 -4
  317. package/src/3d-tiles-converter/json-templates/{tileset.js → tileset.ts} +9 -9
  318. package/src/constants.ts +2 -0
  319. package/src/converter-cli.ts +370 -0
  320. package/src/deps-installer/deps-installer.ts +71 -0
  321. package/src/i3s-attributes-worker.ts +50 -0
  322. package/src/i3s-converter/helpers/batch-ids-extensions.ts +206 -0
  323. package/src/i3s-converter/helpers/coordinate-converter.ts +87 -27
  324. package/src/i3s-converter/helpers/create-scene-server-path.ts +29 -0
  325. package/src/i3s-converter/helpers/feature-attributes.ts +247 -0
  326. package/src/i3s-converter/helpers/geometry-attributes.ts +267 -0
  327. package/src/i3s-converter/helpers/geometry-converter.ts +1608 -0
  328. package/src/i3s-converter/helpers/gltf-attributes.ts +103 -0
  329. package/src/i3s-converter/helpers/node-debug.ts +146 -0
  330. package/src/i3s-converter/helpers/node-index-document.ts +315 -0
  331. package/src/i3s-converter/helpers/node-pages.ts +344 -0
  332. package/src/i3s-converter/i3s-converter.ts +557 -627
  333. package/src/i3s-converter/json-templates/geometry-definitions.ts +83 -0
  334. package/src/i3s-converter/json-templates/layers.ts +137 -0
  335. package/src/i3s-converter/json-templates/{metadata.js → metadata.ts} +2 -2
  336. package/src/i3s-converter/json-templates/{node.js → node.ts} +12 -12
  337. package/src/i3s-converter/json-templates/{scene-server.js → scene-server.ts} +2 -2
  338. package/src/i3s-converter/json-templates/{shared-resources.js → shared-resources.ts} +17 -17
  339. package/src/i3s-converter/types.ts +165 -0
  340. package/src/index.ts +0 -4
  341. package/src/lib/utils/{compress-util.js → compress-util.ts} +105 -18
  342. package/src/lib/utils/file-utils.ts +139 -0
  343. package/src/lib/utils/{lod-conversion-utils.js → lod-conversion-utils.ts} +27 -5
  344. package/src/lib/utils/queue.ts +17 -0
  345. package/src/lib/utils/write-queue.ts +110 -0
  346. package/src/pgm-loader.ts +3 -3
  347. package/src/workers/3d-tiles-attributes-worker.ts +6 -0
  348. package/src/workers/i3s-attributes-worker.ts +7 -0
  349. package/dist/3d-tiles-converter/3d-tiles-converter.js.map +0 -1
  350. package/dist/3d-tiles-converter/helpers/b3dm-converter.js.map +0 -1
  351. package/dist/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +0 -1
  352. package/dist/3d-tiles-converter/helpers/texture-atlas.js.map +0 -1
  353. package/dist/3d-tiles-converter/json-templates/tileset.js.map +0 -1
  354. package/dist/bundle.js.map +0 -1
  355. package/dist/deps-installer/deps-installer.js.map +0 -1
  356. package/dist/i3s-converter/helpers/coordinate-converter.js.map +0 -1
  357. package/dist/i3s-converter/helpers/create-scene-server-path.js.map +0 -1
  358. package/dist/i3s-converter/helpers/geometry-attributes.js.map +0 -1
  359. package/dist/i3s-converter/helpers/geometry-converter.js.map +0 -1
  360. package/dist/i3s-converter/helpers/node-debug.js.map +0 -1
  361. package/dist/i3s-converter/helpers/node-pages.js.map +0 -1
  362. package/dist/i3s-converter/i3s-converter.js.map +0 -1
  363. package/dist/i3s-converter/json-templates/layers.js.map +0 -1
  364. package/dist/i3s-converter/json-templates/metadata.js.map +0 -1
  365. package/dist/i3s-converter/json-templates/node.js.map +0 -1
  366. package/dist/i3s-converter/json-templates/scene-server.js.map +0 -1
  367. package/dist/i3s-converter/json-templates/shared-resources.js.map +0 -1
  368. package/dist/i3s-converter/json-templates/store.js.map +0 -1
  369. package/dist/i3s-server/app.js.map +0 -1
  370. package/dist/i3s-server/controllers/index-controller.js.map +0 -1
  371. package/dist/i3s-server/routes/index.js.map +0 -1
  372. package/dist/index.js.map +0 -1
  373. package/dist/lib/geoid-height-model.d.ts +0 -41
  374. package/dist/lib/geoid-height-model.js +0 -140
  375. package/dist/lib/geoid-height-model.js.map +0 -1
  376. package/dist/lib/pgm-parser.d.ts +0 -14
  377. package/dist/lib/pgm-parser.js +0 -183
  378. package/dist/lib/pgm-parser.js.map +0 -1
  379. package/dist/lib/utils/compress-util.js.map +0 -1
  380. package/dist/lib/utils/compress-utils.d.ts +0 -53
  381. package/dist/lib/utils/file-utils.js.map +0 -1
  382. package/dist/lib/utils/lod-conversion-utils.js.map +0 -1
  383. package/dist/lib/utils/statistic-utills.js.map +0 -1
  384. package/dist/pgm-loader.js.map +0 -1
  385. package/src/3d-tiles-converter/helpers/b3dm-converter.d.ts +0 -23
  386. package/src/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.d.ts +0 -16
  387. package/src/deps-installer/deps-installer.d.ts +0 -10
  388. package/src/deps-installer/deps-installer.js +0 -22
  389. package/src/i3s-converter/helpers/create-scene-server-path.js +0 -25
  390. package/src/i3s-converter/helpers/geometry-converter.d.ts +0 -40
  391. package/src/i3s-converter/helpers/geometry-converter.js +0 -915
  392. package/src/i3s-converter/helpers/node-pages.d.ts +0 -144
  393. package/src/i3s-converter/helpers/node-pages.js +0 -208
  394. package/src/i3s-converter/json-templates/layers.js +0 -199
  395. package/src/lib/geoid-height-model.d.ts +0 -41
  396. package/src/lib/geoid-height-model.js +0 -239
  397. package/src/lib/pgm-parser.d.ts +0 -14
  398. package/src/lib/pgm-parser.js +0 -179
  399. package/src/lib/utils/compress-utils.d.ts +0 -53
  400. package/src/lib/utils/file-utils.d.ts +0 -43
  401. package/src/lib/utils/file-utils.js +0 -38
  402. package/src/lib/utils/lod-conversion-utils.d.ts +0 -32
  403. /package/dist/{i3s-server → es5/i3s-server}/bin/www +0 -0
  404. /package/dist/{i3s-server → es5/i3s-server}/certs/cert.pem +0 -0
  405. /package/dist/{i3s-server → es5/i3s-server}/certs/key.pem +0 -0
  406. /package/src/i3s-converter/json-templates/{store.js → store.ts} +0 -0
  407. /package/src/lib/utils/{statistic-utills.js → statistic-utills.ts} +0 -0
@@ -1,10 +1,48 @@
1
- import { Vector3, Matrix4, Vector4 } from '@math.gl/core';
2
- import { Ellipsoid } from '@math.gl/geospatial';
3
- import { DracoWriter } from '@loaders.gl/draco';
4
- import { encode, assert } from '@loaders.gl/core';
5
- import { concatenateArrayBuffers, concatenateTypedArrays } from '@loaders.gl/loader-utils';
6
- import md5 from 'md5';
7
- import { generateAttributes } from './geometry-attributes';
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.getPropertyTable = exports.convertAttributes = void 0;
30
+ const core_1 = require("@math.gl/core");
31
+ const geospatial_1 = require("@math.gl/geospatial");
32
+ const draco_1 = require("@loaders.gl/draco");
33
+ const core_2 = require("@loaders.gl/core");
34
+ const loader_utils_1 = require("@loaders.gl/loader-utils");
35
+ const md5_1 = __importDefault(require("md5"));
36
+ const uuid_1 = require("uuid");
37
+ const geometry_attributes_1 = require("./geometry-attributes");
38
+ const coordinate_converter_1 = require("./coordinate-converter");
39
+ const gltf_attributes_1 = require("./gltf-attributes");
40
+ const batch_ids_extensions_1 = require("./batch-ids-extensions");
41
+ const feature_attributes_1 = require("./feature-attributes");
42
+ const math_1 = require("@loaders.gl/math");
43
+ // Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.7/pbrMetallicRoughness.cmn.md
44
+ const DEFAULT_ROUGHNESS_FACTOR = 1;
45
+ const DEFAULT_METALLIC_FACTOR = 1;
8
46
  const VALUES_PER_VERTEX = 3;
9
47
  const VALUES_PER_TEX_COORD = 2;
10
48
  const VALUES_PER_COLOR_ELEMENT = 4;
@@ -12,685 +50,1146 @@ const STRING_TYPE = 'string';
12
50
  const SHORT_INT_TYPE = 'Int32';
13
51
  const DOUBLE_TYPE = 'Float64';
14
52
  const OBJECT_ID_TYPE = 'Oid32';
53
+ /*
54
+ * 'CUSTOM_ATTRIBUTE_2' - Attribute name which includes batch info and used by New York map.
55
+ * _BATCHID - Default attribute name which includes batch info.
56
+ * BATCHID - Legacy attribute name which includes batch info.
57
+ */
15
58
  const BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES = ['CUSTOM_ATTRIBUTE_2', '_BATCHID', 'BATCHID'];
16
- export default async function convertB3dmToI3sGeometry(tileContent, nodeId, featuresHashArray, attributeStorageInfo, draco) {
17
- const materialAndTextureList = convertMaterials(tileContent);
18
- const convertedAttributesMap = convertAttributes(tileContent);
19
-
20
- if (convertedAttributesMap.has('default')) {
21
- materialAndTextureList.push({
22
- material: getDefaultMaterial()
23
- });
24
- }
25
-
26
- const result = [];
27
- let nodesCounter = nodeId;
28
- let {
29
- materials = []
30
- } = tileContent.gltf;
31
-
32
- if (!materials.length === 0) {
33
- materials.push({
34
- id: 'default'
35
- });
36
- }
37
-
38
- for (let i = 0; i < materials.length; i++) {
39
- const sourceMaterial = materials[i];
40
-
41
- if (!convertedAttributesMap.has(sourceMaterial.id)) {
42
- continue;
43
- }
44
-
45
- const convertedAttributes = convertedAttributesMap.get(sourceMaterial.id);
46
- const {
47
- material,
48
- texture
49
- } = materialAndTextureList[i];
50
- result.push(await _makeNodeResources({
51
- convertedAttributes,
52
- material,
53
- texture,
54
- tileContent,
55
- nodeId: nodesCounter,
56
- featuresHashArray,
57
- attributeStorageInfo,
58
- draco
59
- }));
60
- nodesCounter++;
61
- }
62
-
63
- if (!result.length) {
64
- return null;
65
- }
66
-
67
- return result;
68
- }
69
-
70
- async function _makeNodeResources({
71
- convertedAttributes,
72
- material,
73
- texture,
74
- tileContent,
75
- nodeId,
76
- featuresHashArray,
77
- attributeStorageInfo,
78
- draco
79
- }) {
80
- const vertexCount = convertedAttributes.positions.length / VALUES_PER_VERTEX;
81
- const triangleCount = vertexCount / 3;
82
- const {
83
- faceRange,
84
- featureIds,
85
- positions,
86
- normals,
87
- colors,
88
- texCoords,
89
- featureCount
90
- } = generateAttributes({
91
- triangleCount,
92
- ...convertedAttributes
93
- });
94
-
95
- if (tileContent.batchTableJson) {
96
- makeFeatureIdsUnique(featureIds, convertedAttributes.featureIndices, featuresHashArray, tileContent.batchTableJson);
97
- }
98
-
99
- const header = new Uint32Array(2);
100
- const typedFeatureIds = generateBigUint64Array(featureIds);
101
- header.set([vertexCount, featureCount], 0);
102
- const fileBuffer = new Uint8Array(concatenateArrayBuffers(header.buffer, positions.buffer, normals.buffer, texture ? texCoords.buffer : new ArrayBuffer(0), colors.buffer, typedFeatureIds.buffer, faceRange.buffer));
103
- const compressedGeometry = draco ? await generateCompressedGeometry(vertexCount, convertedAttributes, {
104
- positions,
105
- normals,
106
- texCoords: texture ? texCoords : new Float32Array(0),
107
- colors,
108
- featureIds,
109
- faceRange
110
- }) : null;
111
- const attributes = convertBatchTableToAttributeBuffers(tileContent.batchTableJson, featureIds, attributeStorageInfo);
112
- return {
113
- geometry: fileBuffer,
114
- compressedGeometry,
115
- texture,
116
- sharedResources: getSharedResources(tileContent, nodeId),
117
- meshMaterial: material,
118
- vertexCount,
119
- attributes,
120
- featureCount
121
- };
122
- }
123
-
124
- function convertAttributes(tileContent) {
125
- var _tileContent$gltf$sce;
126
-
127
- const attributesMap = new Map();
128
-
129
- for (const material of tileContent.gltf.materials || [{
130
- id: 'default'
131
- }]) {
132
- attributesMap.set(material.id, {
133
- positions: new Float32Array(0),
134
- normals: new Float32Array(0),
135
- texCoords: new Float32Array(0),
136
- colors: new Uint8Array(0),
137
- featureIndices: []
138
- });
139
- }
140
-
141
- const nodes = (tileContent.gltf.scene || ((_tileContent$gltf$sce = tileContent.gltf.scenes) === null || _tileContent$gltf$sce === void 0 ? void 0 : _tileContent$gltf$sce[0]) || tileContent.gltf).nodes;
142
- convertNodes(nodes, tileContent, attributesMap);
143
-
144
- for (const attrKey of attributesMap.keys()) {
145
- const attributes = attributesMap.get(attrKey);
146
-
147
- if (attributes.positions.length === 0) {
148
- attributesMap.delete(attrKey);
149
- continue;
150
- }
151
-
152
- const vertexCount = attributes.positions.length / VALUES_PER_VERTEX;
153
-
154
- if (!attributes.colors.length) {
155
- attributes.colors = new Uint8Array(vertexCount * VALUES_PER_COLOR_ELEMENT);
156
-
157
- for (let index = 0; index < attributes.colors.length; index += 4) {
158
- attributes.colors.set([255, 255, 255, 255], index);
159
- }
160
- }
161
-
162
- if (!attributes.texCoords.length) {
163
- attributes.texCoords = new Float32Array(vertexCount * VALUES_PER_TEX_COORD);
164
-
165
- for (let index = 0; index < attributes.texCoords.length; index += 2) {
166
- attributes.texCoords.set([1, 1], index);
167
- }
168
- }
169
-
170
- attributes.featureIndices = attributes.featureIndices.reduce((acc, value) => acc.concat(value));
171
- }
172
-
173
- return attributesMap;
174
- }
175
-
176
- function convertNodes(nodes, tileContent, attributesMap, matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])) {
177
- if (nodes) {
178
- for (const node of nodes) {
179
- convertNode(node, tileContent, attributesMap, matrix);
180
- }
181
- }
182
- }
183
-
184
- function convertNode(node, tileContent, attributesMap, matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])) {
185
- const nodeMatrix = node.matrix;
186
- const compositeMatrix = nodeMatrix ? matrix.multiplyRight(nodeMatrix) : matrix;
187
- const mesh = node.mesh;
188
-
189
- if (mesh) {
190
- convertMesh(mesh, tileContent, attributesMap, compositeMatrix);
191
- }
192
-
193
- convertNodes(node.children, tileContent, attributesMap, compositeMatrix);
194
- }
195
-
196
- function convertMesh(mesh, content, attributesMap, matrix = new Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])) {
197
- for (const primitive of mesh.primitives) {
198
- let outputAttributes = null;
199
-
200
- if (primitive.material) {
201
- outputAttributes = attributesMap.get(primitive.material.id);
202
- } else if (attributesMap.has('default')) {
203
- outputAttributes = attributesMap.get('default');
204
- }
205
-
206
- assert(outputAttributes !== null, 'Primitive - material mapping failed');
207
- const attributes = primitive.attributes;
208
- outputAttributes.positions = concatenateTypedArrays(outputAttributes.positions, transformVertexArray({
209
- vertices: attributes.POSITION.value,
210
- cartographicOrigin: content.cartographicOrigin,
211
- cartesianModelMatrix: content.cartesianModelMatrix,
212
- nodeMatrix: matrix,
213
- indices: primitive.indices.value,
214
- attributeSpecificTransformation: transformVertexPositions
215
- }));
216
- outputAttributes.normals = concatenateTypedArrays(outputAttributes.normals, transformVertexArray({
217
- vertices: attributes.NORMAL && attributes.NORMAL.value,
218
- cartographicOrigin: content.cartographicOrigin,
219
- cartesianModelMatrix: content.cartesianModelMatrix,
220
- nodeMatrix: matrix,
221
- indices: primitive.indices.value,
222
- attributeSpecificTransformation: transformVertexNormals
223
- }));
224
- outputAttributes.texCoords = concatenateTypedArrays(outputAttributes.texCoords, flattenTexCoords(attributes.TEXCOORD_0 && attributes.TEXCOORD_0.value, primitive.indices.value));
225
- outputAttributes.colors = concatenateTypedArrays(outputAttributes.colors, flattenColors(attributes.COLOR_0, primitive.indices.value));
226
- outputAttributes.featureIndices.push(flattenBatchIds(getBatchIdsByAttributeName(attributes), primitive.indices.value));
227
- }
228
- }
229
-
59
+ const EXT_FEATURE_METADATA = 'EXT_feature_metadata';
60
+ const EXT_MESH_FEATURES = 'EXT_mesh_features';
61
+ let scratchVector = new core_1.Vector3();
62
+ /**
63
+ * Convert binary data from b3dm file to i3s resources
64
+ *
65
+ * @param tileContent - 3d tile content
66
+ * @param addNodeToNodePage - function to add new node to node pages
67
+ * @param propertyTable - batch table (corresponding to feature attributes data)
68
+ * @param featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
69
+ * @param attributeStorageInfo - attributes metadata from 3DSceneLayer json
70
+ * @param draco - is converter should create draco compressed geometry
71
+ * @param generateBoundingVolumes - is converter should create accurate bounding voulmes from geometry attributes
72
+ * @param shouldMergeMaterials - Try to merge similar materials to be able to merge meshes into one node
73
+ * @param geoidHeightModel - model to convert elevation from elipsoidal to geoid
74
+ * @param workerSource - source code of used workers
75
+ * @returns Array of node resources to create one or more i3s nodes
76
+ */
77
+ async function convertB3dmToI3sGeometry(tileContent, addNodeToNodePage, propertyTable, featuresHashArray, attributeStorageInfo, draco, generateBoundingVolumes, shouldMergeMaterials, geoidHeightModel, workerSource) {
78
+ const useCartesianPositions = generateBoundingVolumes;
79
+ const materialAndTextureList = await convertMaterials(tileContent.gltf?.materials, shouldMergeMaterials);
80
+ const dataForAttributesConversion = (0, gltf_attributes_1.prepareDataForAttributesConversion)(tileContent);
81
+ const convertedAttributesMap = await convertAttributes(dataForAttributesConversion, materialAndTextureList, useCartesianPositions);
82
+ /** Usage of worker here brings more overhead than advantage */
83
+ // const convertedAttributesMap: Map<string, ConvertedAttributes> =
84
+ // await transformI3SAttributesOnWorker(dataForAttributesConversion, {
85
+ // reuseWorkers: true,
86
+ // _nodeWorkers: true,
87
+ // useCartesianPositions,
88
+ // source: workerSource.I3SAttributes
89
+ // });
90
+ if (generateBoundingVolumes) {
91
+ _generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeightModel);
92
+ }
93
+ const result = [];
94
+ for (const materialAndTexture of materialAndTextureList) {
95
+ const originarMaterialId = materialAndTexture.mergedMaterials[0].originalMaterialId;
96
+ if (!convertedAttributesMap.has(originarMaterialId)) {
97
+ continue; // eslint-disable-line no-continue
98
+ }
99
+ const convertedAttributes = convertedAttributesMap.get(originarMaterialId);
100
+ if (!convertedAttributes) {
101
+ continue;
102
+ }
103
+ const { material, texture } = materialAndTexture;
104
+ const nodeId = await addNodeToNodePage();
105
+ result.push(await _makeNodeResources({
106
+ convertedAttributes,
107
+ material,
108
+ texture,
109
+ tileContent,
110
+ nodeId,
111
+ featuresHashArray,
112
+ propertyTable,
113
+ attributeStorageInfo,
114
+ draco,
115
+ workerSource
116
+ }));
117
+ }
118
+ if (!result.length) {
119
+ return null;
120
+ }
121
+ return result;
122
+ }
123
+ exports.default = convertB3dmToI3sGeometry;
124
+ /**
125
+ * Create bounding volumes based on positions
126
+ * @param convertedAttributesMap - geometry attributes map
127
+ * @param geoidHeightModel - geoid height model to convert elevation from elipsoidal to geoid
128
+ */
129
+ function _generateBoundingVolumesFromGeometry(convertedAttributesMap, geoidHeightModel) {
130
+ for (const attributes of convertedAttributesMap.values()) {
131
+ const boundingVolumes = (0, coordinate_converter_1.createBoundingVolumesFromGeometry)(attributes.positions, geoidHeightModel);
132
+ attributes.boundingVolumes = boundingVolumes;
133
+ const cartographicOrigin = boundingVolumes.obb.center;
134
+ for (let index = 0; index < attributes.positions.length; index += VALUES_PER_VERTEX) {
135
+ const vertex = attributes.positions.subarray(index, index + VALUES_PER_VERTEX);
136
+ geospatial_1.Ellipsoid.WGS84.cartesianToCartographic(Array.from(vertex), scratchVector);
137
+ scratchVector[2] =
138
+ scratchVector[2] - geoidHeightModel.getHeight(scratchVector[1], scratchVector[0]);
139
+ scratchVector = scratchVector.subtract(cartographicOrigin);
140
+ attributes.positions.set(scratchVector, index);
141
+ }
142
+ }
143
+ }
144
+ /**
145
+ *
146
+ * @param params
147
+ * @param params.convertedAttributes - Converted geometry attributes
148
+ * @param params.material - I3S PBR-like material definition
149
+ * @param params.texture - texture content
150
+ * @param params.tileContent - B3DM decoded content
151
+ * @param params.nodeId - new node ID
152
+ * @param params.featuresHashArray - hash array of features that is needed to not to mix up same features in parent and child nodes
153
+ * @param params.propertyTable - batch table (corresponding to feature attributes data)
154
+ * @param params.attributeStorageInfo - attributes metadata from 3DSceneLayer json
155
+ * @param params.draco - is converter should create draco compressed geometry
156
+ * @param params.workerSource - source code of used workers
157
+ * @returns Array of I3S node resources
158
+ */
159
+ async function _makeNodeResources({ convertedAttributes, material, texture, tileContent, nodeId, featuresHashArray, propertyTable, attributeStorageInfo, draco, workerSource }) {
160
+ const boundingVolumes = convertedAttributes.boundingVolumes;
161
+ const vertexCount = convertedAttributes.positions.length / VALUES_PER_VERTEX;
162
+ const { faceRange, featureIds, positions, normals, colors, uvRegions, texCoords, featureCount } = (0, geometry_attributes_1.generateAttributes)(convertedAttributes);
163
+ if (tileContent.batchTableJson) {
164
+ makeFeatureIdsUnique(featureIds, convertedAttributes.featureIndices, featuresHashArray, tileContent.batchTableJson);
165
+ }
166
+ const header = new Uint32Array(2);
167
+ const typedFeatureIds = generateBigUint64Array(featureIds);
168
+ header.set([vertexCount, featureCount], 0);
169
+ const fileBuffer = new Uint8Array((0, loader_utils_1.concatenateArrayBuffers)(header.buffer, positions.buffer, normals.buffer, texture ? texCoords.buffer : new ArrayBuffer(0), colors.buffer, uvRegions, typedFeatureIds.buffer, faceRange.buffer));
170
+ const compressedGeometry = draco
171
+ ? generateCompressedGeometry(vertexCount, convertedAttributes, {
172
+ positions,
173
+ normals,
174
+ texCoords: texture ? texCoords : new Float32Array(0),
175
+ colors,
176
+ uvRegions,
177
+ featureIds,
178
+ faceRange
179
+ }, workerSource.draco)
180
+ : null;
181
+ let attributes = [];
182
+ if (attributeStorageInfo && propertyTable) {
183
+ attributes = convertPropertyTableToAttributeBuffers(featureIds, propertyTable, attributeStorageInfo);
184
+ }
185
+ return {
186
+ nodeId,
187
+ geometry: fileBuffer,
188
+ compressedGeometry,
189
+ texture,
190
+ hasUvRegions: Boolean(uvRegions.length),
191
+ sharedResources: getSharedResources(tileContent.gltf?.materials || [], nodeId),
192
+ meshMaterial: material,
193
+ vertexCount,
194
+ attributes,
195
+ featureCount,
196
+ boundingVolumes
197
+ };
198
+ }
199
+ /**
200
+ * Convert attributes from the gltf nodes tree to i3s plain geometry
201
+ * @param attributesData - geometry attributes from gltf
202
+ * @param materialAndTextureList - array of data about materials and textures of the content
203
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
204
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
205
+ * @returns map of converted geometry attributes
206
+ */
207
+ async function convertAttributes(attributesData, materialAndTextureList, useCartesianPositions) {
208
+ const { nodes, images, cartographicOrigin, cartesianModelMatrix } = attributesData;
209
+ const attributesMap = new Map();
210
+ for (const materialAndTexture of materialAndTextureList) {
211
+ const attributes = {
212
+ positions: new Float32Array(0),
213
+ normals: new Float32Array(0),
214
+ texCoords: new Float32Array(0),
215
+ colors: new Uint8Array(0),
216
+ uvRegions: new Uint16Array(0),
217
+ featureIndicesGroups: [],
218
+ featureIndices: [],
219
+ boundingVolumes: null,
220
+ mergedMaterials: materialAndTexture.mergedMaterials
221
+ };
222
+ for (const mergedMaterial of materialAndTexture.mergedMaterials) {
223
+ attributesMap.set(mergedMaterial.originalMaterialId, attributes);
224
+ }
225
+ }
226
+ convertNodes(nodes, images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions);
227
+ for (const attrKey of attributesMap.keys()) {
228
+ const attributes = attributesMap.get(attrKey);
229
+ if (!attributes) {
230
+ continue;
231
+ }
232
+ if (attributes.positions.length === 0) {
233
+ attributesMap.delete(attrKey);
234
+ continue; // eslint-disable-line no-continue
235
+ }
236
+ if (attributes.featureIndicesGroups) {
237
+ attributes.featureIndices = attributes.featureIndicesGroups.reduce((acc, value) => acc.concat(value));
238
+ delete attributes.featureIndicesGroups;
239
+ }
240
+ }
241
+ return attributesMap;
242
+ }
243
+ exports.convertAttributes = convertAttributes;
244
+ /**
245
+ * Gltf has hierarchical structure of nodes. This function converts nodes starting from those which are in gltf scene object.
246
+ * The goal is applying tranformation matrix for all children. Functions "convertNodes" and "convertNode" work together recursively.
247
+ * @param nodes - gltf nodes array
248
+ * @param images - gltf images array
249
+ * @param cartographicOrigin - cartographic origin of bounding volume
250
+ * @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
251
+ * @param attributesMap - for recursive concatenation of attributes
252
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
253
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
254
+ * @param matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
255
+ * @returns {void}
256
+ */
257
+ function convertNodes(nodes, images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions, matrix = new core_1.Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])) {
258
+ if (nodes) {
259
+ for (const node of nodes) {
260
+ convertNode(node, images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions, matrix);
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * Generate transformation matrix for node
266
+ * Aapply all gltf transformations to initial transformation matrix.
267
+ * @param node
268
+ * @param matrix
269
+ */
270
+ function getCompositeTransformationMatrix(node, matrix) {
271
+ let transformationMatrix = matrix;
272
+ const { matrix: nodeMatrix, rotation, scale, translation } = node;
273
+ if (nodeMatrix) {
274
+ transformationMatrix = matrix.multiplyRight(nodeMatrix);
275
+ }
276
+ if (translation) {
277
+ transformationMatrix = transformationMatrix.translate(translation);
278
+ }
279
+ if (rotation) {
280
+ transformationMatrix = transformationMatrix.rotateXYZ(rotation);
281
+ }
282
+ if (scale) {
283
+ transformationMatrix = transformationMatrix.scale(scale);
284
+ }
285
+ return transformationMatrix;
286
+ }
287
+ /**
288
+ * Convert all primitives of node and all children nodes
289
+ * @param node - gltf node
290
+ * @param images - gltf images array
291
+ * @param cartographicOrigin - cartographic origin of bounding volume
292
+ * @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
293
+ * @param {Map} attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
294
+ * attributes
295
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
296
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
297
+ * @param {Matrix4} matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
298
+ */
299
+ function convertNode(node, images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions, matrix = new core_1.Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])) {
300
+ const transformationMatrix = getCompositeTransformationMatrix(node, matrix);
301
+ const mesh = node.mesh;
302
+ if (mesh) {
303
+ convertMesh(mesh, images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions, transformationMatrix);
304
+ }
305
+ convertNodes(node.children || [], images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions, transformationMatrix);
306
+ }
307
+ /**
308
+ * Convert all primitives of the mesh
309
+ * @param mesh - gltf mesh data
310
+ * @param images - gltf images array
311
+ * @param cartographicOrigin - cartographic origin of bounding volume
312
+ * @param cartesianModelMatrix - cartesian model matrix to convert coordinates to cartographic
313
+ * @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
314
+ * attributes
315
+ * @param useCartesianPositions - convert positions to absolute cartesian coordinates instead of cartographic offsets.
316
+ * Cartesian coordinates will be required for creating bounding voulmest from geometry positions
317
+ * @param attributesMap Map<{positions: Float32Array, normals: Float32Array, texCoords: Float32Array, colors: Uint8Array, featureIndices: Array}> - for recursive concatenation of
318
+ * attributes
319
+
320
+ * @param {Matrix4} matrix - transformation matrix - cumulative transformation matrix formed from all parent node matrices
321
+ */
322
+ function convertMesh(mesh, images, cartographicOrigin, cartesianModelMatrix, attributesMap, useCartesianPositions = false, matrix = new core_1.Matrix4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])) {
323
+ for (const primitive of mesh.primitives) {
324
+ let outputAttributes = null;
325
+ let materialUvRegion;
326
+ if (primitive.material) {
327
+ outputAttributes = attributesMap.get(primitive.material.uniqueId);
328
+ materialUvRegion = outputAttributes?.mergedMaterials.find(({ originalMaterialId }) => originalMaterialId === primitive.material?.uniqueId)?.uvRegion;
329
+ }
330
+ else if (attributesMap.has('default')) {
331
+ outputAttributes = attributesMap.get('default');
332
+ }
333
+ (0, core_2.assert)(outputAttributes !== null, 'Primitive - material mapping failed');
334
+ const attributes = primitive.attributes;
335
+ if (!outputAttributes) {
336
+ continue;
337
+ }
338
+ const indices = getIndices(primitive);
339
+ outputAttributes.positions = (0, loader_utils_1.concatenateTypedArrays)(outputAttributes.positions, transformVertexArray({
340
+ vertices: attributes.POSITION.value,
341
+ cartographicOrigin,
342
+ cartesianModelMatrix,
343
+ nodeMatrix: matrix,
344
+ indices,
345
+ attributeSpecificTransformation: transformVertexPositions,
346
+ useCartesianPositions
347
+ }));
348
+ outputAttributes.normals = (0, loader_utils_1.concatenateTypedArrays)(outputAttributes.normals, transformVertexArray({
349
+ vertices: attributes.NORMAL && attributes.NORMAL.value,
350
+ cartographicOrigin,
351
+ cartesianModelMatrix,
352
+ nodeMatrix: matrix,
353
+ indices,
354
+ attributeSpecificTransformation: transformVertexNormals,
355
+ useCartesianPositions: false
356
+ }));
357
+ outputAttributes.texCoords = (0, loader_utils_1.concatenateTypedArrays)(outputAttributes.texCoords, flattenTexCoords(attributes.TEXCOORD_0 && attributes.TEXCOORD_0.value, indices));
358
+ outputAttributes.colors = (0, loader_utils_1.concatenateTypedArrays)(outputAttributes.colors, flattenColors(attributes.COLOR_0, indices));
359
+ if (materialUvRegion) {
360
+ outputAttributes.uvRegions = (0, loader_utils_1.concatenateTypedArrays)(outputAttributes.uvRegions, createUvRegion(materialUvRegion, indices));
361
+ }
362
+ outputAttributes.featureIndicesGroups = outputAttributes.featureIndicesGroups || [];
363
+ outputAttributes.featureIndicesGroups.push(flattenBatchIds(getBatchIds(attributes, primitive, images), indices));
364
+ }
365
+ }
366
+ /**
367
+ * Converts TRIANGLE-STRIPS to independent TRIANGLES
368
+ * @param {MeshPrimitive} primitive - the primitive to get the indices from
369
+ * @returns indices of vertices of the independent triangles
370
+ */
371
+ function getIndices(primitive) {
372
+ let indices = primitive.indices?.value;
373
+ if (indices && primitive.mode === math_1.GL.TRIANGLE_STRIP) {
374
+ /*
375
+ TRIANGLE_STRIP geometry contains n+2 vertices for n triangles;
376
+ TRIANGLE geometry contains n*3 vertices for n triangles.
377
+ The conversion from TRIANGLE_STRIP to TRIANGLE implies duplicating adjacent vertices.
378
+ */
379
+ const TypedArrayConstructor = indices.constructor;
380
+ const newIndices = new TypedArrayConstructor((indices.length - 2) * 3);
381
+ // Copy the first triangle indices with no modification like [i0, i1, i2, ...] -> [i0, i1, i2, ...]
382
+ let triangleIndex = 0;
383
+ let currentTriangle = indices.slice(0, 3);
384
+ newIndices.set(currentTriangle, 0);
385
+ // The rest triangle indices are being taken from strips using the following logic:
386
+ // [i1, i2, i3, i4, i5, i6, ...] -> [i3, i2, i1, i2, i3, i4, i5, i4, i3, i4, i5, i6, ...]
387
+ for (let i = 1; i + 2 < indices.length; i++) {
388
+ triangleIndex += 3;
389
+ currentTriangle = indices.slice(i, i + 3);
390
+ if (i % 2 === 0) {
391
+ newIndices.set(currentTriangle, triangleIndex);
392
+ }
393
+ else {
394
+ // The following "reverce" is necessary to calculate normals correctly
395
+ newIndices.set(currentTriangle.reverse(), triangleIndex);
396
+ }
397
+ }
398
+ indices = newIndices;
399
+ }
400
+ return indices;
401
+ }
402
+ /**
403
+ * Convert vertices attributes (POSITIONS or NORMALS) to i3s compatible format
404
+ * @param args
405
+ * @param args.vertices - gltf primitive POSITION or NORMAL attribute
406
+ * @param args.cartographicOrigin - cartographic origin coordinates
407
+ * @param args.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
408
+ * @param args.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
409
+ * @param args.indices - gltf primitive indices
410
+ * @param args.attributeSpecificTransformation - function to do attribute - specific transformations
411
+ * @param args.useCartesianPositions - use coordinates as it is.
412
+ * @returns {Float32Array}
413
+ */
230
414
  function transformVertexArray(args) {
231
- const {
232
- vertices,
233
- indices,
234
- attributeSpecificTransformation
235
- } = args;
236
- const newVertices = new Float32Array(indices.length * VALUES_PER_VERTEX);
237
-
238
- if (!vertices) {
415
+ const { vertices, indices, attributeSpecificTransformation } = args;
416
+ const newVertices = new Float32Array(indices.length * VALUES_PER_VERTEX);
417
+ if (!vertices) {
418
+ return newVertices;
419
+ }
420
+ for (let i = 0; i < indices.length; i++) {
421
+ const coordIndex = indices[i] * VALUES_PER_VERTEX;
422
+ const vertex = vertices.subarray(coordIndex, coordIndex + VALUES_PER_VERTEX);
423
+ let vertexVector = new core_1.Vector3(Array.from(vertex));
424
+ vertexVector = attributeSpecificTransformation(vertexVector, args);
425
+ newVertices[i * VALUES_PER_VERTEX] = vertexVector.x;
426
+ newVertices[i * VALUES_PER_VERTEX + 1] = vertexVector.y;
427
+ newVertices[i * VALUES_PER_VERTEX + 2] = vertexVector.z;
428
+ }
239
429
  return newVertices;
240
- }
241
-
242
- for (let i = 0; i < indices.length; i++) {
243
- const coordIndex = indices[i] * VALUES_PER_VERTEX;
244
- const vertex = vertices.subarray(coordIndex, coordIndex + VALUES_PER_VERTEX);
245
- let vertexVector = new Vector3(Array.from(vertex));
246
- vertexVector = attributeSpecificTransformation(vertexVector, args);
247
- newVertices[i * VALUES_PER_VERTEX] = vertexVector.x;
248
- newVertices[i * VALUES_PER_VERTEX + 1] = vertexVector.y;
249
- newVertices[i * VALUES_PER_VERTEX + 2] = vertexVector.z;
250
- }
251
-
252
- return newVertices;
253
- }
254
-
430
+ }
431
+ /**
432
+ * Trasform positions vector with the attribute specific transformations
433
+ * @param vertexVector - source positions vector to transform
434
+ * @param calleeArgs
435
+ * @param calleeArgs.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
436
+ * @param calleeArgs.cartographicOrigin - cartographic origin coordinates
437
+ * @param calleeArgs.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
438
+ * @param calleeArgs.useCartesianPositions - use coordinates as it is.
439
+ * @returns transformed positions vector
440
+ */
255
441
  function transformVertexPositions(vertexVector, calleeArgs) {
256
- const {
257
- cartesianModelMatrix,
258
- cartographicOrigin,
259
- nodeMatrix
260
- } = calleeArgs;
261
-
262
- if (nodeMatrix) {
263
- vertexVector = vertexVector.transform(nodeMatrix);
264
- }
265
-
266
- vertexVector = vertexVector.transform(cartesianModelMatrix);
267
- Ellipsoid.WGS84.cartesianToCartographic([vertexVector[0], vertexVector[1], vertexVector[2]], vertexVector);
268
- vertexVector = vertexVector.subtract(cartographicOrigin);
269
- return vertexVector;
270
- }
271
-
442
+ const { cartesianModelMatrix, cartographicOrigin, nodeMatrix, useCartesianPositions } = calleeArgs;
443
+ if (nodeMatrix) {
444
+ vertexVector = vertexVector.transform(nodeMatrix);
445
+ }
446
+ vertexVector = vertexVector.transform(cartesianModelMatrix);
447
+ if (useCartesianPositions) {
448
+ return vertexVector;
449
+ }
450
+ geospatial_1.Ellipsoid.WGS84.cartesianToCartographic([vertexVector[0], vertexVector[1], vertexVector[2]], vertexVector);
451
+ vertexVector = vertexVector.subtract(cartographicOrigin);
452
+ return vertexVector;
453
+ }
454
+ /**
455
+ * Trasform normals vector with the attribute specific transformations
456
+ * @param vertexVector - source normals vector to transform
457
+ * @param calleeArgs
458
+ * @param calleeArgs.cartesianModelMatrix - a cartesian model matrix to transform coordnates from cartesian to cartographic format
459
+ * @param calleeArgs.nodeMatrix - a gltf node transformation matrix - cumulative transformation matrix formed from all parent node matrices
460
+ * @returns transformed normals vector
461
+ */
272
462
  function transformVertexNormals(vertexVector, calleeArgs) {
273
- const {
274
- cartesianModelMatrix,
275
- nodeMatrix
276
- } = calleeArgs;
277
-
278
- if (nodeMatrix) {
279
- vertexVector = vertexVector.transformAsVector(nodeMatrix);
280
- }
281
-
282
- vertexVector = vertexVector.transformAsVector(cartesianModelMatrix);
283
- return vertexVector;
284
- }
285
-
463
+ const { cartesianModelMatrix, nodeMatrix } = calleeArgs;
464
+ if (nodeMatrix) {
465
+ vertexVector = vertexVector.transformAsVector(nodeMatrix);
466
+ }
467
+ vertexVector = vertexVector.transformAsVector(cartesianModelMatrix);
468
+ return vertexVector;
469
+ }
470
+ /**
471
+ * Convert uv0 (texture coordinates) from coords based on indices to plain arrays, compatible with i3s
472
+ * @param texCoords - gltf primitive TEXCOORD_0 attribute
473
+ * @param indices - gltf primitive indices
474
+ * @returns flattened texture coordinates
475
+ */
286
476
  function flattenTexCoords(texCoords, indices) {
287
- if (!texCoords) {
288
- return new Float32Array(0);
289
- }
290
-
291
- const newTexCoords = new Float32Array(indices.length * VALUES_PER_TEX_COORD);
292
-
293
- for (let i = 0; i < indices.length; i++) {
294
- const coordIndex = indices[i] * VALUES_PER_TEX_COORD;
295
- const texCoord = texCoords.subarray(coordIndex, coordIndex + VALUES_PER_TEX_COORD);
296
- newTexCoords[i * VALUES_PER_TEX_COORD] = texCoord[0];
297
- newTexCoords[i * VALUES_PER_TEX_COORD + 1] = texCoord[1];
298
- }
299
-
300
- return newTexCoords;
301
- }
302
-
477
+ const newTexCoords = new Float32Array(indices.length * VALUES_PER_TEX_COORD);
478
+ if (!texCoords) {
479
+ // We need dummy UV0s because it is required in 1.6
480
+ // https://github.com/Esri/i3s-spec/blob/master/docs/1.6/vertexAttribute.cmn.md
481
+ newTexCoords.fill(1);
482
+ return newTexCoords;
483
+ }
484
+ for (let i = 0; i < indices.length; i++) {
485
+ const coordIndex = indices[i] * VALUES_PER_TEX_COORD;
486
+ const texCoord = texCoords.subarray(coordIndex, coordIndex + VALUES_PER_TEX_COORD);
487
+ newTexCoords[i * VALUES_PER_TEX_COORD] = texCoord[0];
488
+ newTexCoords[i * VALUES_PER_TEX_COORD + 1] = texCoord[1];
489
+ }
490
+ return newTexCoords;
491
+ }
492
+ /**
493
+ * Convert color from COLOR_0 based on indices to plain arrays, compatible with i3s
494
+ * @param colorsAttribute - gltf primitive COLOR_0 attribute
495
+ * @param indices - gltf primitive indices
496
+ * @returns flattened colors attribute
497
+ */
303
498
  function flattenColors(colorsAttribute, indices) {
304
- if (!colorsAttribute) {
305
- return new Uint8Array(0);
306
- }
307
-
308
- const components = colorsAttribute.components;
309
- const colors = colorsAttribute.value;
310
- const newColors = new Uint8Array(indices.length * components);
311
-
312
- for (let i = 0; i < indices.length; i++) {
313
- const colorIndex = indices[i] * components;
314
- const color = colors.subarray(colorIndex, colorIndex + components);
315
- const colorUint8 = new Uint8Array(components);
316
-
317
- for (let j = 0; j < color.length; j++) {
318
- colorUint8[j] = color[j] * 255;
319
- }
320
-
321
- newColors.set(colorUint8, i * components);
322
- }
323
-
324
- return newColors;
325
- }
326
-
499
+ const components = colorsAttribute?.components || VALUES_PER_COLOR_ELEMENT;
500
+ const newColors = new Uint8Array(indices.length * components);
501
+ if (!colorsAttribute) {
502
+ // Vertex color multiplies by material color so it must be normalized 1 by default
503
+ newColors.fill(255);
504
+ return newColors;
505
+ }
506
+ const colors = colorsAttribute.value;
507
+ for (let i = 0; i < indices.length; i++) {
508
+ const colorIndex = indices[i] * components;
509
+ const color = colors.subarray(colorIndex, colorIndex + components);
510
+ const colorUint8 = new Uint8Array(components);
511
+ for (let j = 0; j < color.length; j++) {
512
+ colorUint8[j] = color[j] * 255;
513
+ }
514
+ newColors.set(colorUint8, i * components);
515
+ }
516
+ return newColors;
517
+ }
518
+ /**
519
+ * Create per-vertex uv-region array
520
+ * @param materialUvRegion - uv-region fragment for a single vertex
521
+ * @param indices - geometry indices data
522
+ * @returns - uv-region array
523
+ */
524
+ function createUvRegion(materialUvRegion, indices) {
525
+ const result = new Uint16Array(indices.length * 4);
526
+ for (let i = 0; i < result.length; i += 4) {
527
+ result.set(materialUvRegion, i);
528
+ }
529
+ return result;
530
+ }
531
+ /**
532
+ * Flatten batchedIds list based on indices to right ordered array, compatible with i3s
533
+ * @param batchedIds - gltf primitive
534
+ * @param indices - gltf primitive indices
535
+ * @returns flattened batch ids
536
+ */
327
537
  function flattenBatchIds(batchedIds, indices) {
328
- if (!batchedIds.length || !indices.length) {
538
+ if (!batchedIds.length || !indices.length) {
539
+ return [];
540
+ }
541
+ const newBatchIds = [];
542
+ for (let i = 0; i < indices.length; i++) {
543
+ const coordIndex = indices[i];
544
+ newBatchIds.push(batchedIds[coordIndex]);
545
+ }
546
+ return newBatchIds;
547
+ }
548
+ /**
549
+ * Get batchIds for featureIds creation
550
+ * @param attributes - gltf accessors
551
+ * @param primitive - gltf primitive data
552
+ * @param images - gltf texture images
553
+ */
554
+ function getBatchIds(attributes, primitive, images) {
555
+ const batchIds = (0, batch_ids_extensions_1.handleBatchIdsExtensions)(attributes, primitive, images);
556
+ if (batchIds.length) {
557
+ return batchIds;
558
+ }
559
+ for (let index = 0; index < BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES.length; index++) {
560
+ const possibleBatchIdAttributeName = BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES[index];
561
+ if (attributes[possibleBatchIdAttributeName] &&
562
+ attributes[possibleBatchIdAttributeName].value) {
563
+ return attributes[possibleBatchIdAttributeName].value;
564
+ }
565
+ }
329
566
  return [];
330
- }
331
-
332
- const newBatchIds = [];
333
-
334
- for (let i = 0; i < indices.length; i++) {
335
- const coordIndex = indices[i];
336
- newBatchIds.push(batchedIds[coordIndex]);
337
- }
338
-
339
- return newBatchIds;
340
- }
341
-
342
- function getBatchIdsByAttributeName(attributes) {
343
- let batchIds = [];
344
-
345
- for (let index = 0; index < BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES.length; index++) {
346
- const possibleBatchIdAttributeName = BATCHED_ID_POSSIBLE_ATTRIBUTE_NAMES[index];
347
-
348
- if (attributes[possibleBatchIdAttributeName] && attributes[possibleBatchIdAttributeName].value) {
349
- batchIds = attributes[possibleBatchIdAttributeName].value;
350
- break;
351
- }
352
- }
353
-
354
- return batchIds;
355
- }
356
-
357
- function convertMaterials(tileContent) {
358
- const result = [];
359
- const sourceMaterials = tileContent.gltf.materials || [];
360
-
361
- for (const sourceMaterial of sourceMaterials) {
362
- result.push(convertMaterial(sourceMaterial));
363
- }
364
-
365
- return result;
366
- }
367
-
567
+ }
568
+ /**
569
+ * Convert GLTF material to I3S material definitions and textures
570
+ * @param sourceMaterials Source GLTF materials
571
+ * @param shouldMergeMaterials - if true - the converter will try to merge similar materials
572
+ * to be able to merge primitives having those materials
573
+ * @returns Array of Couples I3SMaterialDefinition + texture content
574
+ */
575
+ async function convertMaterials(sourceMaterials = [], shouldMergeMaterials) {
576
+ let materials = [];
577
+ for (const sourceMaterial of sourceMaterials) {
578
+ materials.push(convertMaterial(sourceMaterial));
579
+ }
580
+ if (shouldMergeMaterials) {
581
+ materials = await mergeAllMaterials(materials);
582
+ }
583
+ return materials;
584
+ }
585
+ /**
586
+ * Merge materials when possible
587
+ * @param materials materials array
588
+ * @returns merged materials array
589
+ */
590
+ async function mergeAllMaterials(materials) {
591
+ const result = [];
592
+ while (materials.length > 0) {
593
+ let newMaterial = materials.splice(0, 1)[0];
594
+ const mergedIndices = [];
595
+ for (let i = 0; i < materials.length; i++) {
596
+ const material = materials[i];
597
+ if ((newMaterial.texture && material.texture) ||
598
+ (!newMaterial.texture && !material.texture)) {
599
+ newMaterial = await mergeMaterials(newMaterial, material);
600
+ mergedIndices.push(i);
601
+ }
602
+ }
603
+ if (newMaterial.texture && mergedIndices.length) {
604
+ const newWidth = newMaterial.mergedMaterials?.reduce((accum, { textureSize }) => accum + (textureSize?.width || 0), 0);
605
+ const newHeight = newMaterial.mergedMaterials?.reduce((accum, { textureSize }) => Math.max(accum, textureSize?.height || 0), 0);
606
+ let currentX = -1;
607
+ for (const aTextureMetadata of newMaterial.mergedMaterials) {
608
+ if (aTextureMetadata.textureSize) {
609
+ const newX = currentX +
610
+ 1 +
611
+ (aTextureMetadata.textureSize.width / newWidth) *
612
+ 2 ** (Uint16Array.BYTES_PER_ELEMENT * 8) -
613
+ 1;
614
+ aTextureMetadata.uvRegion = new Uint16Array([
615
+ currentX + 1,
616
+ 0,
617
+ newX,
618
+ (aTextureMetadata.textureSize.height / newHeight) *
619
+ 2 ** (Uint16Array.BYTES_PER_ELEMENT * 8) -
620
+ 1
621
+ ]);
622
+ currentX = newX;
623
+ }
624
+ }
625
+ newMaterial.texture.image.width = newWidth;
626
+ newMaterial.texture.image.height = newHeight;
627
+ }
628
+ for (const index of mergedIndices.reverse()) {
629
+ materials.splice(index, 1);
630
+ }
631
+ result.push(newMaterial);
632
+ }
633
+ if (!result.length) {
634
+ result.push({
635
+ material: getDefaultMaterial(),
636
+ mergedMaterials: [{ originalMaterialId: 'default' }]
637
+ });
638
+ }
639
+ return result;
640
+ }
641
+ /**
642
+ * Merge 2 materials including texture
643
+ * @param material1
644
+ * @param material2
645
+ * @returns
646
+ */
647
+ async function mergeMaterials(material1, material2) {
648
+ if (material1.texture?.bufferView &&
649
+ material2.texture?.bufferView &&
650
+ material1.mergedMaterials &&
651
+ material2.mergedMaterials) {
652
+ const buffer1 = Buffer.from(material1.texture.bufferView.data);
653
+ const buffer2 = Buffer.from(material2.texture.bufferView.data);
654
+ try {
655
+ // @ts-ignore
656
+ const { joinImages } = await Promise.resolve().then(() => __importStar(require('join-images')));
657
+ const sharpData = await joinImages([buffer1, buffer2], { direction: 'horizontal' });
658
+ material1.texture.bufferView.data = await sharpData
659
+ .toFormat(material1.texture.mimeType === 'image/png' ? 'png' : 'jpeg')
660
+ .toBuffer();
661
+ }
662
+ catch (error) {
663
+ console.log('Join images into a texture atlas has failed. Consider usage `--split-nodes` option. (See documentation https://loaders.gl/modules/tile-converter/docs/cli-reference/tile-converter)');
664
+ throw error;
665
+ }
666
+ // @ts-ignore
667
+ material1.material.pbrMetallicRoughness.baseColorTexture.textureSetDefinitionId = 1;
668
+ }
669
+ material1.mergedMaterials = material1.mergedMaterials.concat(material2.mergedMaterials);
670
+ return material1;
671
+ }
672
+ /**
673
+ * Convert texture and material from gltf 2.0 material object
674
+ * @param sourceMaterial - material object
675
+ * @returns I3S material definition and texture
676
+ */
368
677
  function convertMaterial(sourceMaterial) {
369
- const material = {
370
- doubleSided: sourceMaterial.doubleSided,
371
- emissiveFactor: sourceMaterial.emissiveFactor.map(c => Math.round(c * 255)),
372
- alphaMode: (sourceMaterial.alphaMode || 'OPAQUE').toLowerCase(),
373
- pbrMetallicRoughness: {
374
- roughnessFactor: sourceMaterial.pbrMetallicRoughness.roughnessFactor,
375
- metallicFactor: sourceMaterial.pbrMetallicRoughness.metallicFactor
376
- }
377
- };
378
- let texture;
379
-
380
- if (sourceMaterial.pbrMetallicRoughness.baseColorTexture) {
381
- texture = sourceMaterial.pbrMetallicRoughness.baseColorTexture.texture.source;
382
- material.pbrMetallicRoughness.baseColorTexture = {
383
- textureSetDefinitionId: 0
678
+ const material = {
679
+ doubleSided: sourceMaterial.doubleSided,
680
+ emissiveFactor: sourceMaterial.emissiveFactor?.map((c) => Math.round(c * 255)),
681
+ // It is in upper case in GLTF: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#alpha-coverage
682
+ // But it is in lower case in I3S: https://github.com/Esri/i3s-spec/blob/master/docs/1.7/materialDefinitions.cmn.md
683
+ alphaMode: convertAlphaMode(sourceMaterial.alphaMode),
684
+ pbrMetallicRoughness: {
685
+ roughnessFactor: sourceMaterial?.pbrMetallicRoughness?.roughnessFactor || DEFAULT_ROUGHNESS_FACTOR,
686
+ metallicFactor: sourceMaterial?.pbrMetallicRoughness?.metallicFactor || DEFAULT_METALLIC_FACTOR
687
+ }
384
688
  };
385
- } else if (sourceMaterial.emissiveTexture) {
386
- texture = sourceMaterial.emissiveTexture.texture.source;
387
- material.pbrMetallicRoughness.baseColorTexture = {
388
- textureSetDefinitionId: 0
389
- };
390
- }
391
-
392
- if (!texture) {
393
- const baseColorFactor = sourceMaterial.pbrMetallicRoughness.baseColorFactor;
394
- material.pbrMetallicRoughness.baseColorFactor = baseColorFactor && baseColorFactor.map(c => Math.round(c * 255)) || undefined;
395
- }
396
-
397
- return {
398
- material,
399
- texture
400
- };
401
- }
402
-
689
+ let texture;
690
+ if (sourceMaterial?.pbrMetallicRoughness?.baseColorTexture) {
691
+ texture = sourceMaterial.pbrMetallicRoughness.baseColorTexture.texture.source;
692
+ material.pbrMetallicRoughness.baseColorTexture = {
693
+ textureSetDefinitionId: 0
694
+ };
695
+ }
696
+ else if (sourceMaterial.emissiveTexture) {
697
+ texture = sourceMaterial.emissiveTexture.texture.source;
698
+ // ArcGIS webscene doesn't show emissiveTexture but shows baseColorTexture
699
+ material.pbrMetallicRoughness.baseColorTexture = {
700
+ textureSetDefinitionId: 0
701
+ };
702
+ }
703
+ const uniqueId = (0, uuid_1.v4)();
704
+ sourceMaterial.uniqueId = uniqueId;
705
+ let mergedMaterials = [{ originalMaterialId: uniqueId }];
706
+ if (!texture) {
707
+ // Should use default baseColorFactor if it is not present in source material
708
+ // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-pbrmetallicroughness
709
+ const baseColorFactor = sourceMaterial?.pbrMetallicRoughness?.baseColorFactor;
710
+ material.pbrMetallicRoughness.baseColorFactor =
711
+ (baseColorFactor && baseColorFactor.map((c) => Math.round(c * 255))) || undefined;
712
+ }
713
+ else {
714
+ mergedMaterials[0].textureSize = { width: texture.image.width, height: texture.image.height };
715
+ }
716
+ return { material, texture, mergedMaterials };
717
+ }
718
+ /**
719
+ * Converts from `alphaMode` material property from GLTF to I3S format
720
+ * @param gltfAlphaMode Gltf material `alphaMode` property
721
+ * @returns I3SMaterialDefinition.alphaMode property
722
+ */
723
+ function convertAlphaMode(gltfAlphaMode) {
724
+ switch (gltfAlphaMode) {
725
+ case 'OPAQUE':
726
+ return 'opaque';
727
+ case 'MASK':
728
+ return 'mask';
729
+ case 'BLEND':
730
+ return 'blend';
731
+ default:
732
+ return 'opaque';
733
+ }
734
+ }
735
+ /**
736
+ * Form default I3SMaterialDefinition
737
+ * @returns I3S material definition
738
+ */
403
739
  function getDefaultMaterial() {
404
- return {
405
- alphaMode: 'opaque',
406
- pbrMetallicRoughness: {}
407
- };
408
- }
409
-
410
- function getSharedResources(tileContent, nodeId) {
411
- const gltfMaterials = tileContent.gltf.materials;
412
- const i3sResources = {};
413
-
414
- if (!gltfMaterials || !gltfMaterials.length) {
740
+ return {
741
+ alphaMode: 'opaque',
742
+ pbrMetallicRoughness: {
743
+ metallicFactor: 1,
744
+ roughnessFactor: 1
745
+ }
746
+ };
747
+ }
748
+ /**
749
+ * Form "sharedResources" from gltf materials array
750
+ * @param gltfMaterials - GLTF materials array
751
+ * @param nodeId - I3S node ID
752
+ * @returns {materialDefinitionInfos: Object[], textureDefinitionInfos: Object[]} -
753
+ * 2 arrays in format of i3s sharedResources data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/sharedResource.cmn.md
754
+ */
755
+ function getSharedResources(gltfMaterials, nodeId) {
756
+ const i3sResources = {};
757
+ if (!gltfMaterials || !gltfMaterials.length) {
758
+ return i3sResources;
759
+ }
760
+ i3sResources.materialDefinitionInfos = [];
761
+ for (const gltfMaterial of gltfMaterials) {
762
+ const { materialDefinitionInfo, textureDefinitionInfo } = convertGLTFMaterialToI3sSharedResources(gltfMaterial, nodeId);
763
+ i3sResources.materialDefinitionInfos.push(materialDefinitionInfo);
764
+ if (textureDefinitionInfo) {
765
+ i3sResources.textureDefinitionInfos = i3sResources.textureDefinitionInfos || [];
766
+ i3sResources.textureDefinitionInfos.push(textureDefinitionInfo);
767
+ }
768
+ }
415
769
  return i3sResources;
416
- }
417
-
418
- i3sResources.materialDefinitionInfos = [];
419
-
420
- for (const gltfMaterial of gltfMaterials) {
421
- const {
422
- materialDefinitionInfo,
423
- textureDefinitionInfo
424
- } = convertGLTFMaterialToI3sSharedResources(gltfMaterial, nodeId);
425
- i3sResources.materialDefinitionInfos.push(materialDefinitionInfo);
426
-
427
- if (textureDefinitionInfo) {
428
- i3sResources.textureDefinitionInfos = i3sResources.textureDefinitionInfos || [];
429
- i3sResources.textureDefinitionInfos.push(textureDefinitionInfo);
430
- }
431
- }
432
-
433
- return i3sResources;
434
- }
435
-
770
+ }
771
+ /**
772
+ * Convert gltf material into I3S sharedResources data
773
+ * @param gltfMaterial - gltf material data
774
+ * @param nodeId - I3S node ID
775
+ * @returns - Couple {materialDefinitionInfo, textureDefinitionInfo} extracted from gltf material data
776
+ */
436
777
  function convertGLTFMaterialToI3sSharedResources(gltfMaterial, nodeId) {
437
- const texture = gltfMaterial.pbrMetallicRoughness.baseColorTexture || gltfMaterial.emissiveTexture;
438
- let textureDefinitionInfo = null;
439
-
440
- if (texture) {
441
- textureDefinitionInfo = extractSharedResourcesTextureInfo(texture.texture, nodeId);
442
- }
443
-
444
- const {
445
- baseColorFactor,
446
- metallicFactor
447
- } = gltfMaterial.pbrMetallicRoughness;
448
- let colorFactor = baseColorFactor;
449
-
450
- if ((!baseColorFactor || baseColorFactor[3] === 0) && gltfMaterial.emissiveFactor) {
451
- colorFactor = gltfMaterial.emissiveFactor;
452
- colorFactor[3] = colorFactor[3] || 1;
453
- }
454
-
455
- return {
456
- materialDefinitionInfo: extractSharedResourcesMaterialInfo(colorFactor, metallicFactor),
457
- textureDefinitionInfo
458
- };
459
- }
460
-
461
- function extractSharedResourcesMaterialInfo(baseColorFactor, metallicFactor = 0) {
462
- const matDielectricColorComponent = 0.04 / 255;
463
- const black = new Vector4(0, 0, 0, 1);
464
- const unitVector = new Vector4(1, 1, 1, 1);
465
- const dielectricSpecular = new Vector4(matDielectricColorComponent, matDielectricColorComponent, matDielectricColorComponent, 0);
466
- const baseColorVector = new Vector4(baseColorFactor);
467
- const firstOperand = unitVector.subtract(dielectricSpecular).multiply(baseColorVector);
468
- const diffuse = firstOperand.lerp(firstOperand, black, metallicFactor);
469
- dielectricSpecular[3] = 1;
470
- const specular = dielectricSpecular.lerp(dielectricSpecular, baseColorVector, metallicFactor);
471
- return {
472
- diffuse: diffuse.toArray(),
473
- specular: specular.toArray()
474
- };
475
- }
476
-
778
+ const texture = gltfMaterial?.pbrMetallicRoughness?.baseColorTexture || gltfMaterial.emissiveTexture;
779
+ let textureDefinitionInfo = null;
780
+ if (texture) {
781
+ textureDefinitionInfo = extractSharedResourcesTextureInfo(texture.texture, nodeId);
782
+ }
783
+ const { baseColorFactor, metallicFactor } = gltfMaterial?.pbrMetallicRoughness || {};
784
+ let colorFactor = baseColorFactor;
785
+ // If alpha channel is 0 try to get emissive factor from gltf material.
786
+ if ((!baseColorFactor || baseColorFactor[3] === 0) && gltfMaterial.emissiveFactor) {
787
+ colorFactor = gltfMaterial.emissiveFactor;
788
+ colorFactor[3] = colorFactor[3] || 1;
789
+ }
790
+ return {
791
+ materialDefinitionInfo: extractSharedResourcesMaterialInfo(colorFactor || [1, 1, 1, 1], metallicFactor),
792
+ textureDefinitionInfo
793
+ };
794
+ }
795
+ /**
796
+ * Form "materialDefinition" which is part of "sharedResouces"
797
+ * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materials
798
+ * See formulas in appendix "Appendix B: BRDF Implementation":
799
+ * const dielectricSpecular = rgb(0.04, 0.04, 0.04)
800
+ * const black = rgb(0, 0, 0)
801
+ * cdiff = lerp(baseColor.rgb * (1 - dielectricSpecular.r), black, metallic)
802
+ * F0 = lerp(dieletricSpecular, baseColor.rgb, metallic)
803
+ *
804
+ * Assumption: F0 - specular in i3s ("specular reflection" <-> "reflectance value at normal incidence")
805
+ * cdiff - diffuse in i3s ("Diffuse color" <-> "'c' diffuse" (c means color?))
806
+ * @param baseColorFactor - RGBA color in 0..1 format
807
+ * @param metallicFactor - "metallicFactor" attribute of gltf material object
808
+ * @returns material definition info for I3S shared resource
809
+ */
810
+ function extractSharedResourcesMaterialInfo(baseColorFactor, metallicFactor = 1) {
811
+ const matDielectricColorComponent = 0.04 / 255; // Color from rgb (255) to 0..1 resolution
812
+ // All color resolutions are 0..1
813
+ const black = new core_1.Vector4(0, 0, 0, 1);
814
+ const unitVector = new core_1.Vector4(1, 1, 1, 1);
815
+ const dielectricSpecular = new core_1.Vector4(matDielectricColorComponent, matDielectricColorComponent, matDielectricColorComponent, 0);
816
+ const baseColorVector = new core_1.Vector4(baseColorFactor);
817
+ // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
818
+ // Formulas for Cdiff & F0
819
+ const firstOperand = unitVector.subtract(dielectricSpecular).multiply(baseColorVector);
820
+ const diffuse = firstOperand.lerp(firstOperand, black, metallicFactor);
821
+ dielectricSpecular[3] = 1;
822
+ const specular = dielectricSpecular.lerp(dielectricSpecular, baseColorVector, metallicFactor);
823
+ return {
824
+ params: {
825
+ // @ts-expect-error NumericArray
826
+ diffuse: diffuse.toArray(),
827
+ // @ts-expect-error NumericArray
828
+ specular: specular.toArray(),
829
+ renderMode: 'solid'
830
+ }
831
+ };
832
+ }
833
+ /**
834
+ * Form "textureDefinition" which is part of "sharedResouces"
835
+ * @param texture - texture image info
836
+ * @param nodeId - I3S node ID
837
+ * @returns texture definition infor for shared resource
838
+ */
477
839
  function extractSharedResourcesTextureInfo(texture, nodeId) {
478
- return {
479
- encoding: [texture.source.mimeType],
480
- images: [{
481
- id: generateImageId(texture, nodeId),
482
- size: texture.source.image.width,
483
- length: [texture.source.image.data.length]
484
- }]
485
- };
486
- }
487
-
840
+ return {
841
+ encoding: texture?.source?.mimeType ? [texture.source.mimeType] : undefined,
842
+ images: [
843
+ {
844
+ // 'i3s' has just size which is width of the image. Images are supposed to be square.
845
+ // https://github.com/Esri/i3s-spec/blob/master/docs/1.7/image.cmn.md
846
+ id: generateImageId(texture, nodeId),
847
+ size: texture.source?.image.width,
848
+ length: [texture.source?.image.data.length]
849
+ }
850
+ ]
851
+ };
852
+ }
853
+ /**
854
+ * Formula for calculating imageId:
855
+ * https://github.com/Esri/i3s-spec/blob/0a6366a9249b831db8436c322f8d27521e86cf07/format/Indexed%203d%20Scene%20Layer%20Format%20Specification.md#generating-image-ids
856
+ * @param texture - texture image info
857
+ * @param nodeId - I3S node ID
858
+ * @returns calculate image ID according to the spec
859
+ */
488
860
  function generateImageId(texture, nodeId) {
489
- const {
490
- width,
491
- height
492
- } = texture.source.image;
493
- const levelCountOfTexture = 1;
494
- const indexOfLevel = 0;
495
- const indexOfTextureInStore = nodeId + 1;
496
- const zerosCount = 32 - indexOfTextureInStore.toString(2).length;
497
- const rightHalf = '0'.repeat(zerosCount).concat(indexOfTextureInStore.toString(2));
498
- const shiftedLevelCountOfTexture = levelCountOfTexture << 28;
499
- const shiftedIndexOfLevel = indexOfLevel << 24;
500
- const shiftedWidth = width - 1 << 12;
501
- const shiftedHeight = height - 1 << 0;
502
- const leftHalf = shiftedLevelCountOfTexture + shiftedIndexOfLevel + shiftedWidth + shiftedHeight;
503
- const imageId = BigInt("0b".concat(leftHalf.toString(2)).concat(rightHalf));
504
- return imageId.toString();
505
- }
506
-
861
+ const { width, height } = texture.source?.image;
862
+ const levelCountOfTexture = 1;
863
+ const indexOfLevel = 0;
864
+ const indexOfTextureInStore = nodeId + 1;
865
+ const zerosCount = 32 - indexOfTextureInStore.toString(2).length;
866
+ const rightHalf = '0'.repeat(zerosCount).concat(indexOfTextureInStore.toString(2));
867
+ const shiftedLevelCountOfTexture = levelCountOfTexture << 28;
868
+ const shiftedIndexOfLevel = indexOfLevel << 24;
869
+ const shiftedWidth = (width - 1) << 12;
870
+ const shiftedHeight = (height - 1) << 0;
871
+ const leftHalf = shiftedLevelCountOfTexture + shiftedIndexOfLevel + shiftedWidth + shiftedHeight;
872
+ const imageId = BigInt(`0b${leftHalf.toString(2)}${rightHalf}`);
873
+ return imageId.toString();
874
+ }
875
+ /**
876
+ * Make all feature ids unique through all nodes in layout.
877
+ * @param featureIds
878
+ * @param featureIndices
879
+ * @param featuresHashArray
880
+ * @param batchTable
881
+ * @returns {void}
882
+ */
507
883
  function makeFeatureIdsUnique(featureIds, featureIndices, featuresHashArray, batchTable) {
508
- const replaceMap = getFeaturesReplaceMap(featureIds, batchTable, featuresHashArray);
509
- replaceIndicesByUnique(featureIndices, replaceMap);
510
- replaceIndicesByUnique(featureIds, replaceMap);
884
+ const replaceMap = getFeaturesReplaceMap(featureIds, batchTable, featuresHashArray);
885
+ replaceIndicesByUnique(featureIndices, replaceMap);
886
+ replaceIndicesByUnique(featureIds, replaceMap);
511
887
  }
512
-
888
+ /**
889
+ * Generate replace map to make featureIds unique.
890
+ * @param {Array} featureIds
891
+ * @param {Object} batchTable
892
+ * @param {Array} featuresHashArray
893
+ * @returns {Object}
894
+ */
513
895
  function getFeaturesReplaceMap(featureIds, batchTable, featuresHashArray) {
514
- const featureMap = {};
515
-
516
- for (let index = 0; index < featureIds.length; index++) {
517
- const oldFeatureId = featureIds[index];
518
- const uniqueFeatureId = getOrCreateUniqueFeatureId(index, batchTable, featuresHashArray);
519
- featureMap[oldFeatureId.toString()] = uniqueFeatureId;
520
- }
521
-
522
- return featureMap;
523
- }
524
-
896
+ const featureMap = {};
897
+ for (let index = 0; index < featureIds.length; index++) {
898
+ const oldFeatureId = featureIds[index];
899
+ const uniqueFeatureId = getOrCreateUniqueFeatureId(index, batchTable, featuresHashArray);
900
+ featureMap[oldFeatureId.toString()] = uniqueFeatureId;
901
+ }
902
+ return featureMap;
903
+ }
904
+ /**
905
+ * Generates string for unique batch id creation.
906
+ * @param {Object} batchTable
907
+ * @param {Number} index
908
+ * @returns {String}
909
+ */
525
910
  function generateStringFromBatchTableByIndex(batchTable, index) {
526
- let str = '';
527
-
528
- for (const key in batchTable) {
529
- str += batchTable[key][index];
530
- }
531
-
532
- return str;
533
- }
534
-
911
+ let str = '';
912
+ for (const key in batchTable) {
913
+ str += batchTable[key][index];
914
+ }
915
+ return str;
916
+ }
917
+ /**
918
+ * Return already exited featureId or creates and returns new to support unique feature ids throw nodes.
919
+ * @param {Number} index
920
+ * @param {Object} batchTable
921
+ * @param {Array} featuresHashArray
922
+ * @returns {Number}
923
+ */
535
924
  function getOrCreateUniqueFeatureId(index, batchTable, featuresHashArray) {
536
- const batchTableStr = generateStringFromBatchTableByIndex(batchTable, index);
537
- const hash = md5(batchTableStr);
538
-
539
- if (featuresHashArray.includes(hash)) {
540
- return featuresHashArray.indexOf(hash);
541
- }
542
-
543
- return featuresHashArray.push(hash) - 1;
544
- }
545
-
925
+ const batchTableStr = generateStringFromBatchTableByIndex(batchTable, index);
926
+ const hash = (0, md5_1.default)(batchTableStr);
927
+ if (featuresHashArray.includes(hash)) {
928
+ return featuresHashArray.indexOf(hash);
929
+ }
930
+ return featuresHashArray.push(hash) - 1;
931
+ }
932
+ /**
933
+ * Do replacement of indices for making them unique through all nodes.
934
+ * @param {Array} indicesArray
935
+ * @param {Object} featureMap
936
+ * @returns {void}
937
+ */
546
938
  function replaceIndicesByUnique(indicesArray, featureMap) {
547
- for (let index = 0; index < indicesArray.length; index++) {
548
- indicesArray[index] = featureMap[indicesArray[index]];
549
- }
550
- }
551
-
552
- function convertBatchTableToAttributeBuffers(batchTable, featureIds, attributeStorageInfo) {
553
- const attributeBuffers = [];
554
-
555
- if (batchTable) {
556
- const batchTableWithFeatureIds = {
557
- OBJECTID: featureIds,
558
- ...batchTable
939
+ for (let index = 0; index < indicesArray.length; index++) {
940
+ indicesArray[index] = featureMap[indicesArray[index]];
941
+ }
942
+ }
943
+ /**
944
+ * Convert property table data to attribute buffers.
945
+ * @param {Array} featureIds
946
+ * @param {Object} propertyTable - table with metadata for particular feature.
947
+ * @param {Array} attributeStorageInfo
948
+ * @returns {Array} - Array of file buffers.
949
+ */
950
+ function convertPropertyTableToAttributeBuffers(featureIds, propertyTable, attributeStorageInfo) {
951
+ const attributeBuffers = [];
952
+ const needFlattenPropertyTable = (0, feature_attributes_1.checkPropertiesLength)(featureIds, propertyTable);
953
+ const properties = needFlattenPropertyTable
954
+ ? (0, feature_attributes_1.flattenPropertyTableByFeatureIds)(featureIds, propertyTable)
955
+ : propertyTable;
956
+ const propertyTableWithObjectIds = {
957
+ OBJECTID: featureIds,
958
+ ...properties
559
959
  };
560
-
561
- for (const key in batchTableWithFeatureIds) {
562
- const type = getAttributeType(key, attributeStorageInfo);
563
- let attributeBuffer = null;
564
-
565
- switch (type) {
960
+ for (const propertyName in propertyTableWithObjectIds) {
961
+ const type = getAttributeType(propertyName, attributeStorageInfo);
962
+ const value = propertyTableWithObjectIds[propertyName];
963
+ const attributeBuffer = generateAttributeBuffer(type, value);
964
+ attributeBuffers.push(attributeBuffer);
965
+ }
966
+ return attributeBuffers;
967
+ }
968
+ /**
969
+ * Generates attribute buffer based on attribute type
970
+ * @param type
971
+ * @param value
972
+ */
973
+ function generateAttributeBuffer(type, value) {
974
+ let attributeBuffer;
975
+ switch (type) {
566
976
  case OBJECT_ID_TYPE:
567
977
  case SHORT_INT_TYPE:
568
- attributeBuffer = generateShortIntegerAttributeBuffer(batchTableWithFeatureIds[key]);
569
- break;
570
-
978
+ attributeBuffer = generateShortIntegerAttributeBuffer(value);
979
+ break;
571
980
  case DOUBLE_TYPE:
572
- attributeBuffer = generateDoubleAttributeBuffer(batchTableWithFeatureIds[key]);
573
- break;
574
-
981
+ attributeBuffer = generateDoubleAttributeBuffer(value);
982
+ break;
575
983
  case STRING_TYPE:
576
- attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
577
- break;
578
-
984
+ attributeBuffer = generateStringAttributeBuffer(value);
985
+ break;
579
986
  default:
580
- attributeBuffer = generateStringAttributeBuffer(batchTableWithFeatureIds[key]);
581
- }
582
-
583
- attributeBuffers.push(attributeBuffer);
987
+ attributeBuffer = generateStringAttributeBuffer(value);
584
988
  }
585
- }
586
-
587
- return attributeBuffers;
989
+ return attributeBuffer;
588
990
  }
589
-
991
+ /**
992
+ * Return attribute type.
993
+ * @param {String} key
994
+ * @param {Array} attributeStorageInfo
995
+ * @returns {String} attribute type.
996
+ */
590
997
  function getAttributeType(key, attributeStorageInfo) {
591
- const attribute = attributeStorageInfo.find(attr => attr.name === key);
592
- return attribute.attributeValues.valueType;
998
+ const attribute = attributeStorageInfo.find((attr) => attr.name === key);
999
+ return attribute.attributeValues.valueType;
593
1000
  }
594
-
1001
+ /**
1002
+ * Convert short integer to attribute arrayBuffer.
1003
+ * @param {Array} featureIds
1004
+ * @returns {ArrayBuffer} - Buffer with objectId data.
1005
+ */
595
1006
  function generateShortIntegerAttributeBuffer(featureIds) {
596
- const count = new Uint32Array([featureIds.length]);
597
- const valuesArray = new Uint32Array(featureIds);
598
- return concatenateArrayBuffers(count.buffer, valuesArray.buffer);
1007
+ const count = new Uint32Array([featureIds.length]);
1008
+ const valuesArray = new Uint32Array(featureIds);
1009
+ return (0, loader_utils_1.concatenateArrayBuffers)(count.buffer, valuesArray.buffer);
599
1010
  }
600
-
1011
+ /**
1012
+ * Convert double to attribute arrayBuffer.
1013
+ * @param {Array} featureIds
1014
+ * @returns {ArrayBuffer} - Buffer with objectId data.
1015
+ */
601
1016
  function generateDoubleAttributeBuffer(featureIds) {
602
- const count = new Uint32Array([featureIds.length]);
603
- const padding = new Uint8Array(4);
604
- const valuesArray = new Float64Array(featureIds);
605
- return concatenateArrayBuffers(count.buffer, padding.buffer, valuesArray.buffer);
1017
+ const count = new Uint32Array([featureIds.length]);
1018
+ const padding = new Uint8Array(4);
1019
+ const valuesArray = new Float64Array(featureIds);
1020
+ return (0, loader_utils_1.concatenateArrayBuffers)(count.buffer, padding.buffer, valuesArray.buffer);
606
1021
  }
607
-
1022
+ /**
1023
+ * Convert batch table attributes to array buffer with batch table data.
1024
+ * @param {Array} batchAttributes
1025
+ * @returns {ArrayBuffer} - Buffer with batch table data.
1026
+ */
608
1027
  function generateStringAttributeBuffer(batchAttributes) {
609
- const stringCountArray = new Uint32Array([batchAttributes.length]);
610
- let totalNumberOfBytes = 0;
611
- const stringSizesArray = new Uint32Array(batchAttributes.length);
612
- const stringBufferArray = [];
613
-
614
- for (let index = 0; index < batchAttributes.length; index++) {
615
- const currentString = "".concat(String(batchAttributes[index]), "\0");
616
- const currentStringBuffer = Buffer.from(currentString);
617
- const currentStringSize = currentStringBuffer.length;
618
- totalNumberOfBytes += currentStringSize;
619
- stringSizesArray[index] = currentStringSize;
620
- stringBufferArray.push(currentStringBuffer);
621
- }
622
-
623
- const totalBytes = new Uint32Array([totalNumberOfBytes]);
624
- return concatenateArrayBuffers(stringCountArray.buffer, totalBytes.buffer, stringSizesArray.buffer, ...stringBufferArray);
625
- }
626
-
1028
+ const stringCountArray = new Uint32Array([batchAttributes.length]);
1029
+ let totalNumberOfBytes = 0;
1030
+ const stringSizesArray = new Uint32Array(batchAttributes.length);
1031
+ const stringBufferArray = [];
1032
+ for (let index = 0; index < batchAttributes.length; index++) {
1033
+ const currentString = `${String(batchAttributes[index])}\0`;
1034
+ const currentStringBuffer = Buffer.from(currentString);
1035
+ const currentStringSize = currentStringBuffer.length;
1036
+ totalNumberOfBytes += currentStringSize;
1037
+ stringSizesArray[index] = currentStringSize;
1038
+ stringBufferArray.push(currentStringBuffer);
1039
+ }
1040
+ const totalBytes = new Uint32Array([totalNumberOfBytes]);
1041
+ return (0, loader_utils_1.concatenateArrayBuffers)(stringCountArray.buffer, totalBytes.buffer, stringSizesArray.buffer, ...stringBufferArray);
1042
+ }
1043
+ /**
1044
+ * Convert featureIds to BigUint64Array.
1045
+ * @param {Array} featureIds
1046
+ * @returns {BigUint64Array} - Array of feature ids in BigUint64 format.
1047
+ */
627
1048
  function generateBigUint64Array(featureIds) {
628
- const typedFeatureIds = new BigUint64Array(featureIds.length);
629
-
630
- for (let index = 0; index < featureIds.length; index++) {
631
- typedFeatureIds[index] = BigInt(featureIds[index]);
632
- }
633
-
634
- return typedFeatureIds;
635
- }
636
-
637
- async function generateCompressedGeometry(vertexCount, convertedAttributes, attributes) {
638
- const {
639
- positions,
640
- normals,
641
- texCoords,
642
- colors,
643
- featureIds,
644
- faceRange
645
- } = attributes;
646
- const indices = new Uint32Array(vertexCount);
647
-
648
- for (let index = 0; index < indices.length; index++) {
649
- indices.set([index], index);
650
- }
651
-
652
- const featureIndices = new Uint32Array(convertedAttributes.featureIndices.length ? convertedAttributes.featureIndices : vertexCount);
653
- const featureIndex = generateFeatureIndexAttribute(featureIndices, faceRange);
654
- const compressedAttributes = {
655
- positions,
656
- normals,
657
- colors,
658
- 'feature-index': featureIndex
659
- };
660
-
661
- if (texCoords.length) {
662
- compressedAttributes.texCoords = texCoords;
663
- }
664
-
665
- const attributesMetadata = {
666
- 'feature-index': {
667
- 'i3s-attribute-type': 'feature-index',
668
- 'i3s-feature-ids': new Int32Array(featureIds)
669
- }
670
- };
671
- return new Uint8Array(await encode({
672
- attributes: compressedAttributes,
673
- indices
674
- }, DracoWriter, {
675
- draco: {
676
- method: 'MESH_SEQUENTIAL_ENCODING',
677
- attributesMetadata
678
- }
679
- }));
680
- }
681
-
1049
+ const typedFeatureIds = new BigUint64Array(featureIds.length);
1050
+ for (let index = 0; index < featureIds.length; index++) {
1051
+ typedFeatureIds[index] = BigInt(featureIds[index]);
1052
+ }
1053
+ return typedFeatureIds;
1054
+ }
1055
+ /**
1056
+ * Generates draco compressed geometry
1057
+ * @param {Number} vertexCount
1058
+ * @param {Object} convertedAttributes - get rid of this argument here
1059
+ * @param {Object} attributes - geometry attributes to compress
1060
+ * @param {string} dracoWorkerSoure - draco worker source code
1061
+ * @returns {Promise<object>} - COmpressed geometry.
1062
+ */
1063
+ async function generateCompressedGeometry(vertexCount, convertedAttributes, attributes, dracoWorkerSoure) {
1064
+ const { positions, normals, texCoords, colors, uvRegions, featureIds, faceRange } = attributes;
1065
+ const indices = new Uint32Array(vertexCount);
1066
+ for (let index = 0; index < indices.length; index++) {
1067
+ indices.set([index], index);
1068
+ }
1069
+ const featureIndices = new Uint32Array(convertedAttributes.featureIndices.length ? convertedAttributes.featureIndices : vertexCount);
1070
+ const featureIndex = generateFeatureIndexAttribute(featureIndices, faceRange);
1071
+ const compressedAttributes = {
1072
+ positions,
1073
+ normals,
1074
+ colors,
1075
+ 'feature-index': featureIndex
1076
+ };
1077
+ if (texCoords.length) {
1078
+ compressedAttributes.texCoords = texCoords;
1079
+ }
1080
+ const attributesMetadata = {
1081
+ 'feature-index': {
1082
+ 'i3s-attribute-type': 'feature-index',
1083
+ 'i3s-feature-ids': new Int32Array(featureIds)
1084
+ }
1085
+ };
1086
+ if (uvRegions.length) {
1087
+ compressedAttributes['uv-region'] = uvRegions;
1088
+ attributesMetadata['uv-region'] = {
1089
+ 'i3s-attribute-type': 'uv-region'
1090
+ };
1091
+ }
1092
+ return (0, core_2.encode)({ attributes: compressedAttributes, indices }, draco_1.DracoWriterWorker, {
1093
+ ...draco_1.DracoWriterWorker.options,
1094
+ source: dracoWorkerSoure,
1095
+ reuseWorkers: true,
1096
+ _nodeWorkers: true,
1097
+ draco: {
1098
+ method: 'MESH_SEQUENTIAL_ENCODING',
1099
+ attributesMetadata
1100
+ }
1101
+ });
1102
+ }
1103
+ /**
1104
+ * Generates ordered feature indices based on face range
1105
+ * @param {Uint32Array} featureIndex
1106
+ * @param {Uint32Array} faceRange
1107
+ * @returns {Uint32Array}
1108
+ */
682
1109
  function generateFeatureIndexAttribute(featureIndex, faceRange) {
683
- const orderedFeatureIndices = new Uint32Array(featureIndex.length);
684
- let fillIndex = 0;
685
- let startIndex = 0;
686
-
687
- for (let index = 1; index < faceRange.length; index += 2) {
688
- const endIndex = (faceRange[index] + 1) * VALUES_PER_VERTEX;
689
- orderedFeatureIndices.fill(fillIndex, startIndex, endIndex);
690
- fillIndex++;
691
- startIndex = endIndex + 1;
692
- }
693
-
694
- return orderedFeatureIndices;
695
- }
696
- //# sourceMappingURL=geometry-converter.js.map
1110
+ const orderedFeatureIndices = new Uint32Array(featureIndex.length);
1111
+ let fillIndex = 0;
1112
+ let startIndex = 0;
1113
+ for (let index = 1; index < faceRange.length; index += 2) {
1114
+ const endIndex = (faceRange[index] + 1) * VALUES_PER_VERTEX;
1115
+ orderedFeatureIndices.fill(fillIndex, startIndex, endIndex);
1116
+ fillIndex++;
1117
+ startIndex = endIndex + 1;
1118
+ }
1119
+ return orderedFeatureIndices;
1120
+ }
1121
+ /**
1122
+ * Find property table in tile
1123
+ * For example it can be batchTable for b3dm files or property table in gLTF extension.
1124
+ * @param sourceTile
1125
+ * @return batch table from b3dm / feature properties from EXT_FEATURE_METADATA
1126
+ */
1127
+ function getPropertyTable(tileContent) {
1128
+ const batchTableJson = tileContent?.batchTableJson;
1129
+ if (batchTableJson) {
1130
+ return batchTableJson;
1131
+ }
1132
+ const { extensionName, extension } = getPropertyTableExtension(tileContent);
1133
+ switch (extensionName) {
1134
+ case EXT_MESH_FEATURES: {
1135
+ console.warn('The I3S converter does not yet support the EXT_mesh_features extension');
1136
+ return null;
1137
+ }
1138
+ case EXT_FEATURE_METADATA: {
1139
+ return getPropertyTableFromExtFeatureMetadata(extension);
1140
+ }
1141
+ default:
1142
+ return null;
1143
+ }
1144
+ }
1145
+ exports.getPropertyTable = getPropertyTable;
1146
+ /**
1147
+ * Check extensions which can be with property table inside.
1148
+ * @param sourceTile
1149
+ */
1150
+ function getPropertyTableExtension(tileContent) {
1151
+ const extensionsWithPropertyTables = [EXT_FEATURE_METADATA, EXT_MESH_FEATURES];
1152
+ const extensionsUsed = tileContent?.gltf?.extensionsUsed;
1153
+ if (!extensionsUsed) {
1154
+ return { extensionName: null, extension: null };
1155
+ }
1156
+ let extensionName = '';
1157
+ for (const extensionItem of tileContent?.gltf?.extensionsUsed || []) {
1158
+ if (extensionsWithPropertyTables.includes(extensionItem)) {
1159
+ extensionName = extensionItem;
1160
+ break;
1161
+ }
1162
+ }
1163
+ const extension = tileContent?.gltf?.extensions?.[extensionName];
1164
+ return { extensionName, extension };
1165
+ }
1166
+ /**
1167
+ * Handle EXT_feature_metadata to get property table
1168
+ * @param extension
1169
+ * TODO add EXT_feature_metadata feature textures support.
1170
+ */
1171
+ function getPropertyTableFromExtFeatureMetadata(extension) {
1172
+ if (extension?.featureTextures) {
1173
+ console.warn('The I3S converter does not yet support the EXT_feature_metadata feature textures');
1174
+ return null;
1175
+ }
1176
+ if (extension?.featureTables) {
1177
+ /**
1178
+ * Take only first feature table to generate attributes storage info object.
1179
+ * TODO: Think about getting data from all feature tables?
1180
+ * It can be tricky just because 3dTiles is able to have multiple featureId attributes and multiple feature tables.
1181
+ * In I3S we should decide which featureIds attribute will be passed to geometry data.
1182
+ */
1183
+ const firstFeatureTableName = Object.keys(extension.featureTables)?.[0];
1184
+ if (firstFeatureTableName) {
1185
+ const featureTable = extension?.featureTables[firstFeatureTableName];
1186
+ const propertyTable = {};
1187
+ for (const propertyName in featureTable.properties) {
1188
+ propertyTable[propertyName] = featureTable.properties[propertyName].data;
1189
+ }
1190
+ return propertyTable;
1191
+ }
1192
+ }
1193
+ console.warn("The I3S converter couldn't handle EXT_feature_metadata extension");
1194
+ return null;
1195
+ }