@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,27 +1,18 @@
1
- import type {Tileset3DProps} from '@loaders.gl/tiles';
2
- import type {GLTFMaterial} from '@loaders.gl/gltf';
3
- import type {BatchTableJson, B3DMContent} from '@loaders.gl/3d-tiles';
1
+ // loaders.gl, MIT license
4
2
 
3
+ import type {Tileset3DProps} from '@loaders.gl/tiles';
4
+ import type {FeatureTableJson} from '@loaders.gl/3d-tiles';
5
+ import type {WriteQueueItem} from '../lib/utils/write-queue';
5
6
  import type {
6
- AttributeStorageInfo,
7
7
  SceneLayer3D,
8
8
  BoundingVolumes,
9
- Node3DIndexDocument,
10
- NodeReference,
11
- I3SGeometry,
12
9
  MaxScreenThresholdSQ,
13
- NodeInPage,
14
- LodSelection,
15
- SharedResources,
16
- TextureImage,
17
- Attribute,
18
- ESRIField,
19
- Field,
20
- PopupInfo
10
+ NodeInPage
21
11
  } from '@loaders.gl/i3s';
22
- import {load, encode} from '@loaders.gl/core';
12
+ import {load, encode, fetchFile, getLoaderOptions, isBrowser} from '@loaders.gl/core';
23
13
  import {Tileset3D} from '@loaders.gl/tiles';
24
- import {CesiumIonLoader} from '@loaders.gl/3d-tiles';
14
+ import {CesiumIonLoader, Tiles3DLoader} from '@loaders.gl/3d-tiles';
15
+ import {Geoid} from '@math.gl/geoid';
25
16
  import {join} from 'path';
26
17
  import {v4 as uuidv4} from 'uuid';
27
18
  import process from 'process';
@@ -29,41 +20,58 @@ import transform from 'json-map-transform';
29
20
  import md5 from 'md5';
30
21
 
31
22
  import NodePages from './helpers/node-pages';
32
- import {writeFile, removeDir, writeFileForSlpk} from '../lib/utils/file-utils';
23
+ import {writeFile, removeDir, writeFileForSlpk, removeFile} from '../lib/utils/file-utils';
33
24
  import {
25
+ compressFileWithGzip,
34
26
  compressWithChildProcess
35
27
  // generateHash128FromZip,
36
28
  // addFileToZip
37
29
  } from '../lib/utils/compress-util';
38
30
  import {calculateFilesSize, timeConverter} from '../lib/utils/statistic-utills';
39
- import convertB3dmToI3sGeometry from './helpers/geometry-converter';
31
+ import convertB3dmToI3sGeometry, {getPropertyTable} from './helpers/geometry-converter';
40
32
  import {
41
33
  createBoundingVolumes,
42
- convertCommonToI3SExtentCoordinate
34
+ convertBoundingVolumeToI3SFullExtent
43
35
  } from './helpers/coordinate-converter';
44
36
  import {createSceneServerPath} from './helpers/create-scene-server-path';
45
37
  import {convertGeometricErrorToScreenThreshold} from '../lib/utils/lod-conversion-utils';
46
38
  import {PGMLoader} from '../pgm-loader';
47
39
 
48
40
  import {LAYERS as layersTemplate} from './json-templates/layers';
49
- import {NODE as nodeTemplate} from './json-templates/node';
50
- import {SHARED_RESOURCES_TEMPLATE} from './json-templates/shared-resources';
41
+ import {GEOMETRY_DEFINITION as geometryDefinitionTemlate} from './json-templates/geometry-definitions';
42
+ import {SHARED_RESOURCES as sharedResourcesTemplate} from './json-templates/shared-resources';
51
43
  import {validateNodeBoundingVolumes} from './helpers/node-debug';
52
- import {GeoidHeightModel} from '../lib/geoid-height-model';
53
- import TileHeader from '@loaders.gl/tiles/src/tileset/tile-3d';
54
- import {KTX2BasisUniversalTextureWriter} from '@loaders.gl/textures';
44
+ // loaders.gl, MIT license
45
+
46
+ import {Tile3D} from '@loaders.gl/tiles';
47
+ import {KTX2BasisWriterWorker} from '@loaders.gl/textures';
48
+ import {LoaderWithParser} from '@loaders.gl/loader-utils';
49
+ import {I3SMaterialDefinition, TextureSetDefinitionFormats} from '@loaders.gl/i3s/src/types';
50
+ import {ImageWriter} from '@loaders.gl/images';
51
+ import {GLTFImagePostprocessed} from '@loaders.gl/gltf';
52
+ import {I3SConvertedResources, SharedResourcesArrays} from './types';
53
+ import {getWorkerURL, WorkerFarm} from '@loaders.gl/worker-utils';
54
+ import {DracoWriterWorker} from '@loaders.gl/draco';
55
+ import WriteQueue from '../lib/utils/write-queue';
56
+ import {I3SAttributesWorker} from '../i3s-attributes-worker';
57
+ import {BROWSER_ERROR_MESSAGE} from '../constants';
58
+ import {
59
+ createdStorageAttribute,
60
+ createFieldAttribute,
61
+ createPopupInfo,
62
+ getAttributeType,
63
+ getFieldAttributeType
64
+ } from './helpers/feature-attributes';
65
+ import {NodeIndexDocument} from './helpers/node-index-document';
55
66
 
56
67
  const ION_DEFAULT_TOKEN =
57
- process.env.IonToken || // eslint-disable-line
68
+ process.env?.IonToken || // eslint-disable-line
58
69
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlYWMxMzcyYy0zZjJkLTQwODctODNlNi01MDRkZmMzMjIxOWIiLCJpZCI6OTYyMCwic2NvcGVzIjpbImFzbCIsImFzciIsImdjIl0sImlhdCI6MTU2Mjg2NjI3M30.1FNiClUyk00YH_nWfSGpiQAjR5V2OvREDq1PJ5QMjWQ'; // eslint-disable-line
59
70
  const HARDCODED_NODES_PER_PAGE = 64;
60
71
  const _3D_TILES = '3DTILES';
61
72
  const _3D_OBJECT_LAYER_TYPE = '3DObject';
62
- const STRING_TYPE = 'string';
63
- const SHORT_INT_TYPE = 'Int32';
64
- const DOUBLE_TYPE = 'double';
65
- const OBJECT_ID_TYPE = 'OBJECTID';
66
73
  const REFRESH_TOKEN_TIMEOUT = 1800; // 30 minutes in seconds
74
+ const CESIUM_DATASET_PREFIX = 'https://';
67
75
  // const FS_FILE_TOO_LARGE = 'ERR_FS_FILE_TOO_LARGE';
68
76
 
69
77
  /**
@@ -71,32 +79,41 @@ const REFRESH_TOKEN_TIMEOUT = 1800; // 30 minutes in seconds
71
79
  */
72
80
  export default class I3SConverter {
73
81
  nodePages: NodePages;
74
- fileMap: {[key: string]: string};
75
82
  options: any;
76
83
  layers0Path: string;
77
- materialMap: Map<any, any>;
78
- materialDefinitions: GLTFMaterial[];
84
+ materialMap: Map<string, number>;
85
+ materialDefinitions: I3SMaterialDefinition[];
86
+ geometryMap: Map<string, number>;
87
+ geometryConfigs: {hasTexture: boolean; hasUvRegions: boolean}[];
79
88
  vertexCounter: number;
80
- layers0: SceneLayer3D;
89
+ layers0: SceneLayer3D | null;
81
90
  featuresHashArray: string[];
82
91
  refinementCounter: {
83
92
  tilesCount: number;
84
93
  tilesWithAddRefineCount: number;
85
94
  };
86
95
  validate: boolean;
87
- boundingVolumeWarnings?: string[];
88
- conversionStartTime: [number, number];
89
- refreshTokenTime: [number, number];
90
- sourceTileset: Tileset3D | null;
91
- geoidHeightModel: GeoidHeightModel | null;
96
+ boundingVolumeWarnings?: string[] = [];
97
+ conversionStartTime: [number, number] = [0, 0];
98
+ refreshTokenTime: [number, number] = [0, 0];
99
+ sourceTileset: Tileset3D | null = null;
100
+ geoidHeightModel: Geoid | null = null;
101
+ Loader: LoaderWithParser = Tiles3DLoader;
102
+ generateTextures: boolean;
103
+ generateBoundingVolumes: boolean;
104
+ layersHasTexture: boolean;
105
+ workerSource: {[key: string]: string} = {};
106
+ writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue();
107
+ compressList: string[] | null = null;
92
108
 
93
109
  constructor() {
94
- this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE);
95
- this.fileMap = {};
110
+ this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE, this);
96
111
  this.options = {};
97
112
  this.layers0Path = '';
98
113
  this.materialMap = new Map();
99
114
  this.materialDefinitions = [];
115
+ this.geometryMap = new Map();
116
+ this.geometryConfigs = [];
100
117
  this.vertexCounter = 0;
101
118
  this.layers0 = null;
102
119
  this.featuresHashArray = [];
@@ -105,7 +122,10 @@ export default class I3SConverter {
105
122
  tilesWithAddRefineCount: 0
106
123
  };
107
124
  this.validate = false;
108
- this.boundingVolumeWarnings = null;
125
+ this.generateTextures = false;
126
+ this.generateBoundingVolumes = false;
127
+ this.layersHasTexture = false;
128
+ this.compressList = null;
109
129
  }
110
130
 
111
131
  /**
@@ -121,19 +141,30 @@ export default class I3SConverter {
121
141
  * @param options.token Token for Cesium ION tilesets authentication
122
142
  * @param options.draco Generate I3S 1.7 draco compressed geometries
123
143
  * @param options.validate -enable validation
144
+ * @param options.generateTextures - generate alternative type of textures (to have non-compressed jpeg/png and compressed ktx2)
145
+ * @param options.generateBoundingVolumes - generate bounding volumes from vertices coordinates instead of source tiles bounding volumes
146
+ * @param options.instantNodeWriting - Keep created 3DNodeIndexDocument files on disk instead of memory. This option reduce memory usage but decelerates conversion speed
124
147
  */
125
148
  async convert(options: {
126
149
  inputUrl: string;
127
150
  outputPath: string;
128
151
  tilesetName: string;
129
152
  sevenZipExe: string;
130
- egmFilePath?: string;
153
+ egmFilePath: string;
131
154
  maxDepth?: number;
132
155
  slpk?: boolean;
133
156
  token?: string;
134
157
  draco?: boolean;
158
+ mergeMaterials?: boolean;
135
159
  validate?: boolean;
160
+ generateTextures?: boolean;
161
+ generateBoundingVolumes?: boolean;
162
+ instantNodeWriting?: boolean;
136
163
  }): Promise<any> {
164
+ if (isBrowser) {
165
+ console.log(BROWSER_ERROR_MESSAGE);
166
+ return BROWSER_ERROR_MESSAGE;
167
+ }
137
168
  this.conversionStartTime = process.hrtime();
138
169
  const {
139
170
  tilesetName,
@@ -142,13 +173,34 @@ export default class I3SConverter {
142
173
  inputUrl,
143
174
  validate,
144
175
  outputPath,
145
- draco,
176
+ draco = true,
146
177
  sevenZipExe,
147
178
  maxDepth,
148
- token
179
+ token,
180
+ generateTextures,
181
+ generateBoundingVolumes,
182
+ instantNodeWriting = false,
183
+ mergeMaterials = true
149
184
  } = options;
150
- this.options = {maxDepth, slpk, sevenZipExe, egmFilePath, draco, token, inputUrl};
151
- this.validate = validate;
185
+ this.options = {
186
+ maxDepth,
187
+ slpk,
188
+ sevenZipExe,
189
+ egmFilePath,
190
+ draco,
191
+ token,
192
+ inputUrl,
193
+ instantNodeWriting,
194
+ mergeMaterials
195
+ };
196
+ this.compressList = (this.options.instantNodeWriting && []) || null;
197
+ this.validate = Boolean(validate);
198
+ this.Loader = inputUrl.indexOf(CESIUM_DATASET_PREFIX) !== -1 ? CesiumIonLoader : Tiles3DLoader;
199
+ this.generateTextures = Boolean(generateTextures);
200
+ this.generateBoundingVolumes = Boolean(generateBoundingVolumes);
201
+
202
+ this.writeQueue = new WriteQueue();
203
+ this.writeQueue.startListening();
152
204
 
153
205
  console.log('Loading egm file...'); // eslint-disable-line
154
206
  this.geoidHeightModel = await load(egmFilePath, PGMLoader);
@@ -158,19 +210,44 @@ export default class I3SConverter {
158
210
  this.nodePages.useWriteFunction(writeFileForSlpk);
159
211
  }
160
212
 
161
- const preloadOptions = await this._fetchPreloadOptions();
162
- const tilesetOptions: Tileset3DProps = {loadOptions: {}};
163
- if (preloadOptions.headers) {
164
- tilesetOptions.loadOptions.fetch = {headers: preloadOptions.headers};
213
+ await this.loadWorkers();
214
+
215
+ try {
216
+ const preloadOptions = await this._fetchPreloadOptions();
217
+ const tilesetOptions: Tileset3DProps = {
218
+ loadOptions: {
219
+ _nodeWorkers: true,
220
+ reuseWorkers: true,
221
+ basis: {format: 'rgba32'},
222
+ 'basis-nodejs': {
223
+ format: 'rgba32',
224
+ workerUrl: './modules/textures/dist/basis-nodejs-worker.js'
225
+ },
226
+ 'draco-nodejs': {workerUrl: './modules/draco/dist/draco-nodejs-worker.js'}
227
+ }
228
+ };
229
+ if (preloadOptions.headers) {
230
+ tilesetOptions.loadOptions!.fetch = {headers: preloadOptions.headers};
231
+ }
232
+ Object.assign(tilesetOptions, preloadOptions);
233
+ const sourceTilesetJson = await load(inputUrl, this.Loader, tilesetOptions.loadOptions);
234
+ // console.log(tilesetJson); // eslint-disable-line
235
+ this.sourceTileset = new Tileset3D(sourceTilesetJson, tilesetOptions);
236
+
237
+ await this._createAndSaveTileset(
238
+ outputPath,
239
+ tilesetName,
240
+ sourceTilesetJson?.root?.boundingVolume?.region
241
+ );
242
+ await this._finishConversion({slpk: Boolean(slpk), outputPath, tilesetName});
243
+ return sourceTilesetJson;
244
+ } catch (error) {
245
+ throw error;
246
+ } finally {
247
+ // Clean up worker pools
248
+ const workerFarm = WorkerFarm.getWorkerFarm({});
249
+ workerFarm.destroy();
165
250
  }
166
- Object.assign(tilesetOptions, preloadOptions);
167
- const sourceTilesetJson = await load(inputUrl, CesiumIonLoader, tilesetOptions.loadOptions);
168
- // console.log(tilesetJson); // eslint-disable-line
169
- this.sourceTileset = new Tileset3D(sourceTilesetJson, tilesetOptions);
170
-
171
- await this._createAndSaveTileset(outputPath, tilesetName);
172
- await this._finishConversion({slpk, outputPath, tilesetName});
173
- return sourceTilesetJson;
174
251
  }
175
252
 
176
253
  /**
@@ -178,7 +255,11 @@ export default class I3SConverter {
178
255
  * @param outputPath - path to save output data
179
256
  * @param tilesetName - new tileset path
180
257
  */
181
- private async _createAndSaveTileset(outputPath: string, tilesetName: string): Promise<void> {
258
+ private async _createAndSaveTileset(
259
+ outputPath: string,
260
+ tilesetName: string,
261
+ boundingVolumeRegion?: number[]
262
+ ): Promise<void> {
182
263
  const tilesetPath = join(`${outputPath}`, `${tilesetName}`);
183
264
  // Removing the tilesetPath needed to exclude erroneous files after conversion
184
265
  try {
@@ -189,29 +270,47 @@ export default class I3SConverter {
189
270
 
190
271
  this.layers0Path = join(tilesetPath, 'SceneServer', 'layers', '0');
191
272
 
192
- this._formLayers0(tilesetName);
273
+ this._formLayers0(tilesetName, boundingVolumeRegion);
193
274
 
194
275
  this.materialDefinitions = [];
195
276
  this.materialMap = new Map();
196
277
 
197
- const sourceRootTile = this.sourceTileset.root;
198
- const boundingVolumes = createBoundingVolumes(sourceRootTile, this.geoidHeightModel);
199
- const parentId = this.nodePages.push({
278
+ const sourceRootTile: Tile3D = this.sourceTileset!.root!;
279
+ const boundingVolumes = createBoundingVolumes(sourceRootTile, this.geoidHeightModel!);
280
+ await this.nodePages.push({
281
+ index: 0,
200
282
  lodThreshold: 0,
201
283
  obb: boundingVolumes.obb,
202
284
  children: []
203
285
  });
204
286
 
205
- const isCreateSlpk = this.options.slpk;
206
- const root0 = this._formRootNodeIndexDocument(boundingVolumes);
287
+ const rootNode = await NodeIndexDocument.createRootNode(boundingVolumes, this);
288
+ await this._convertNodesTree(rootNode, sourceRootTile);
207
289
 
208
- await this._convertNodesTree(root0, sourceRootTile, parentId, boundingVolumes);
290
+ this.layers0!.materialDefinitions = this.materialDefinitions;
291
+ // @ts-ignore
292
+ this.layers0.geometryDefinitions = transform(
293
+ this.geometryConfigs.map((config) => ({
294
+ geometryConfig: {...config, draco: this.options.draco}
295
+ })),
296
+ geometryDefinitionTemlate()
297
+ );
298
+
299
+ if (this.layersHasTexture === false) {
300
+ this.layers0!.store.defaultGeometrySchema.ordering =
301
+ this.layers0!.store.defaultGeometrySchema.ordering.filter(
302
+ (attribute) => attribute !== 'uv0'
303
+ );
304
+ }
209
305
 
210
- this.layers0.materialDefinitions = this.materialDefinitions;
211
306
  await this._writeLayers0();
212
- createSceneServerPath(tilesetName, this.layers0, tilesetPath);
213
- await this._writeNodeIndexDocument(root0, 'root', join(this.layers0Path, 'nodes', 'root'));
214
- await this.nodePages.save(this.layers0Path, this.fileMap, isCreateSlpk);
307
+ createSceneServerPath(tilesetName, this.layers0!, tilesetPath);
308
+ for (const filePath of this.compressList || []) {
309
+ await compressFileWithGzip(filePath);
310
+ await removeFile(filePath);
311
+ }
312
+ await this.nodePages.save();
313
+ await this.writeQueue.finalize();
215
314
  await this._createSlpk(tilesetPath);
216
315
  }
217
316
 
@@ -219,8 +318,15 @@ export default class I3SConverter {
219
318
  * Form object of 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
220
319
  * @param tilesetName - Name of layer
221
320
  */
222
- private _formLayers0(tilesetName: string): void {
223
- const extent = convertCommonToI3SExtentCoordinate(this.sourceTileset);
321
+ private _formLayers0(tilesetName: string, boundingVolumeRegion?: number[]): void {
322
+ const fullExtent = convertBoundingVolumeToI3SFullExtent(
323
+ this.sourceTileset?.boundingVolume || this.sourceTileset?.root?.boundingVolume
324
+ );
325
+ if (boundingVolumeRegion) {
326
+ fullExtent.zmin = boundingVolumeRegion[4];
327
+ fullExtent.zmax = boundingVolumeRegion[5];
328
+ }
329
+ const extent = [fullExtent.xmin, fullExtent.ymin, fullExtent.xmax, fullExtent.ymax];
224
330
  const layers0data = {
225
331
  version: `{${uuidv4().toUpperCase()}}`,
226
332
  id: 0,
@@ -233,79 +339,37 @@ export default class I3SConverter {
233
339
  nodePages: {
234
340
  nodesPerPage: HARDCODED_NODES_PER_PAGE
235
341
  },
236
- compressGeometry: this.options.draco
342
+ compressGeometry: this.options.draco,
343
+ fullExtent
237
344
  };
238
-
239
- this.layers0 = transform(layers0data, layersTemplate);
240
- }
241
-
242
- /**
243
- * Convert and save the layer and embedded tiles
244
- * @param boundingVolumes - mbs and obb data about node's bounding volume
245
- * @return 3DNodeIndexDocument data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
246
- */
247
- private _formRootNodeIndexDocument(boundingVolumes: BoundingVolumes): Node3DIndexDocument {
248
- const root0data = {
249
- version: `{${uuidv4().toUpperCase()}}`,
250
- id: 'root',
251
- level: 0,
252
- lodSelection: [
253
- {
254
- metricType: 'maxScreenThresholdSQ',
255
- maxError: 0
256
- },
257
- {
258
- metricType: 'maxScreenThreshold',
259
- maxError: 0
260
- }
261
- ],
262
- ...boundingVolumes,
263
- children: []
264
- };
265
- return transform(root0data, nodeTemplate);
345
+ this.layers0 = transform(layers0data, layersTemplate());
266
346
  }
267
347
 
268
348
  /**
269
349
  * Form object of 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
270
- * @param root0 - 3DNodeIndexDocument of root node https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
350
+ * @param rootNode - 3DNodeIndexDocument of root node https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
271
351
  * @param sourceRootTile - Source (3DTile) tile data
272
- * @param parentId - node id in node pages
273
- * @param boundingVolumes - mbs and obb data about node's bounding volume
274
352
  */
275
353
  private async _convertNodesTree(
276
- root0: Node3DIndexDocument,
277
- sourceRootTile: TileHeader,
278
- parentId: number,
279
- boundingVolumes: BoundingVolumes
354
+ rootNode: NodeIndexDocument,
355
+ sourceRootTile: Tile3D
280
356
  ): Promise<void> {
281
- await this.sourceTileset._loadTile(sourceRootTile);
282
- if (sourceRootTile.content && sourceRootTile.content.type === 'b3dm') {
283
- root0.children.push({
284
- id: '1',
285
- href: './1',
286
- ...boundingVolumes
287
- });
288
- const [child] = await this._createNode(root0, sourceRootTile, parentId, 0);
289
- const childPath = join(this.layers0Path, 'nodes', child.path);
290
-
291
- if (this.options.slpk) {
292
- this.fileMap['nodes/1/3dNodeIndexDocument.json.gz'] = await writeFileForSlpk(
293
- childPath,
294
- JSON.stringify(child),
295
- '3dNodeIndexDocument.json'
296
- );
297
- } else {
298
- await writeFile(childPath, JSON.stringify(child));
357
+ await this.sourceTileset!._loadTile(sourceRootTile);
358
+ if (this.isContentSupported(sourceRootTile)) {
359
+ const childNodes = await this._createNode(rootNode, sourceRootTile, 0);
360
+ for (const childNode of childNodes) {
361
+ await childNode.save();
299
362
  }
363
+ await rootNode.addChildren(childNodes);
300
364
  } else {
301
365
  await this._addChildrenWithNeighborsAndWriteFile({
302
- parentNode: root0,
366
+ parentNode: rootNode,
303
367
  sourceTiles: sourceRootTile.children,
304
- parentId,
305
368
  level: 1
306
369
  });
307
370
  }
308
371
  await sourceRootTile.unloadContent();
372
+ await rootNode.save();
309
373
  }
310
374
 
311
375
  /**
@@ -313,32 +377,15 @@ export default class I3SConverter {
313
377
  */
314
378
  private async _writeLayers0(): Promise<void> {
315
379
  if (this.options.slpk) {
316
- this.fileMap['3dSceneLayer.json.gz'] = await writeFileForSlpk(
317
- this.layers0Path,
318
- JSON.stringify(this.layers0),
319
- '3dSceneLayer.json'
320
- );
321
- } else {
322
- await writeFile(this.layers0Path, JSON.stringify(this.layers0));
323
- }
324
- }
325
-
326
- /**
327
- * Write 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md in file
328
- */
329
- private async _writeNodeIndexDocument(
330
- root0: Node3DIndexDocument,
331
- nodePath: string,
332
- rootPath: string
333
- ): Promise<void> {
334
- if (this.options.slpk) {
335
- this.fileMap[`nodes/${nodePath}/3dNodeIndexDocument.json.gz`] = await writeFileForSlpk(
336
- rootPath,
337
- JSON.stringify(root0),
338
- '3dNodeIndexDocument.json'
339
- );
380
+ await this.writeQueue.enqueue({
381
+ archiveKey: '3dSceneLayer.json.gz',
382
+ writePromise: () =>
383
+ writeFileForSlpk(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
384
+ });
340
385
  } else {
341
- await writeFile(rootPath, JSON.stringify(root0));
386
+ await this.writeQueue.enqueue({
387
+ writePromise: () => writeFile(this.layers0Path, JSON.stringify(this.layers0))
388
+ });
342
389
  }
343
390
  }
344
391
 
@@ -387,64 +434,85 @@ export default class I3SConverter {
387
434
  /**
388
435
  * Add child nodes recursively and write them to files
389
436
  * @param data - arguments
437
+ * @param data.parentNode - 3DNodeIndexDocument of parent node
390
438
  * @param data.sourceTiles - array of source child nodes
391
- * @param data.parentNode - 3DNodeIndexDocument of parent node for processing child nodes
392
- * @param data.parentId - id of parent node in node pages
393
439
  * @param data.level - level of node (distanse to root node in the tree)
394
440
  */
395
441
  private async _addChildrenWithNeighborsAndWriteFile(data: {
396
- parentNode: Node3DIndexDocument;
397
- sourceTiles: TileHeader[];
398
- parentId: number;
442
+ parentNode: NodeIndexDocument;
443
+ sourceTiles: Tile3D[];
399
444
  level: number;
400
445
  }): Promise<void> {
401
- const childNodes = [];
402
- await this._addChildren({...data, childNodes});
403
- await this._addNeighborsAndWriteFile(data.parentNode, childNodes);
446
+ await this._addChildren(data);
447
+ await data.parentNode.addNeighbors();
448
+ }
449
+
450
+ /**
451
+ * Convert nested subtree of 3DTiles dataset
452
+ * @param param0
453
+ * @param data.parentNode - 3DNodeIndexDocument of parent node
454
+ * @param param0.sourceTile - source 3DTile data
455
+ * @param param0.level - tree level
456
+ */
457
+ private async convertNestedTileset({
458
+ parentNode,
459
+ sourceTile,
460
+ level
461
+ }: {
462
+ parentNode: NodeIndexDocument;
463
+ sourceTile: Tile3D;
464
+ level: number;
465
+ }) {
466
+ await this.sourceTileset!._loadTile(sourceTile);
467
+ await this._addChildren({
468
+ parentNode,
469
+ sourceTiles: sourceTile.children,
470
+ level: level + 1
471
+ });
472
+ await sourceTile.unloadContent();
473
+ }
474
+
475
+ /**
476
+ * Convert 3DTiles tile to I3S node
477
+ * @param param0
478
+ * @param param0.parentNode - 3DNodeIndexDocument of parent node
479
+ * @param param0.sourceTile - source 3DTile data
480
+ * @param param0.level - tree level
481
+ */
482
+ private async convertNode({
483
+ parentNode,
484
+ sourceTile,
485
+ level
486
+ }: {
487
+ parentNode: NodeIndexDocument;
488
+ sourceTile: Tile3D;
489
+ level: number;
490
+ }) {
491
+ const childNodes = await this._createNode(parentNode, sourceTile, level);
492
+ await parentNode.addChildren(childNodes);
404
493
  }
405
494
 
406
495
  /**
407
496
  * Add child nodes recursively and write them to files
408
- * @param data - arguments
409
- * @param data.childNodes - array of target child nodes
410
- * @param data.sourceTiles - array of source child nodes
411
- * @param data.parentNode - 3DNodeIndexDocument of parent node for processing child nodes
412
- * @param data.parentId - id of parent node in node pages
413
- * @param data.level - level of node (distanse to root node in the tree)
497
+ * @param param0 - arguments
498
+ * @param param0.parentNode - 3DNodeIndexDocument of parent node
499
+ * @param param0.sourceTile - source 3DTile data
500
+ * @param param0.level - tree level
414
501
  */
415
502
  private async _addChildren(data: {
416
- childNodes: NodeReference[];
417
- sourceTiles: TileHeader[];
418
- parentNode: Node3DIndexDocument;
419
- parentId: number;
503
+ parentNode: NodeIndexDocument;
504
+ sourceTiles: Tile3D[];
420
505
  level: number;
421
506
  }): Promise<void> {
422
- const {childNodes, sourceTiles, parentNode, parentId, level} = data;
507
+ const {sourceTiles, parentNode, level} = data;
423
508
  if (this.options.maxDepth && level > this.options.maxDepth) {
424
509
  return;
425
510
  }
426
511
  for (const sourceTile of sourceTiles) {
427
512
  if (sourceTile.type === 'json') {
428
- await this.sourceTileset._loadTile(sourceTile);
429
- await this._addChildren({
430
- parentNode,
431
- sourceTiles: sourceTile.children,
432
- childNodes,
433
- parentId,
434
- level: level + 1
435
- });
436
- await sourceTile.unloadContent();
513
+ await this.convertNestedTileset({parentNode, sourceTile, level});
437
514
  } else {
438
- const boundingVolumes = createBoundingVolumes(sourceTile, this.geoidHeightModel);
439
- const children = await this._createNode(parentNode, sourceTile, parentId, level);
440
- for (const child of children) {
441
- parentNode.children.push({
442
- id: child.id,
443
- href: `../${child.path}`,
444
- ...boundingVolumes
445
- });
446
- childNodes.push(child);
447
- }
515
+ await this.convertNode({parentNode, sourceTile, level});
448
516
  }
449
517
  if (sourceTile.id) {
450
518
  console.log(sourceTile.id); // eslint-disable-line
@@ -452,172 +520,145 @@ export default class I3SConverter {
452
520
  }
453
521
  }
454
522
 
455
- /**
456
- * Add neightbors to 3DNodeIndexDocument and write it in a file
457
- * @param parentNode - arguments
458
- * @param childNodes - array of target child nodes
459
- */
460
- private async _addNeighborsAndWriteFile(
461
- parentNode: Node3DIndexDocument,
462
- childNodes: Node3DIndexDocument[]
463
- ): Promise<void> {
464
- for (const node of childNodes) {
465
- const childPath = join(this.layers0Path, 'nodes', node.path);
466
- const nodePath = node.path;
467
- delete node.path;
468
-
469
- // Don't do large amount of "neightbors" to avoid big memory consumption
470
- if (parentNode.children.length < 1000) {
471
- for (const neighbor of parentNode.children) {
472
- // eslint-disable-next-line max-depth
473
- if (node.id === neighbor.id) {
474
- continue; // eslint-disable-line
475
- }
476
-
477
- node.neighbors.push({...neighbor});
478
- }
479
- } else {
480
- // eslint-disable-next-line no-console, no-undef
481
- console.warn(
482
- `Node ${node.id}: neighbors attribute is omited because of large number of neigbors`
483
- );
484
- delete node.neighbors;
485
- }
486
- await this._writeNodeIndexDocument(node, nodePath, childPath);
487
- node.neighbors = [];
488
- }
489
- }
490
-
491
523
  /**
492
524
  * Convert tile to one or more I3S nodes
493
- * @param parentTile - parent 3DNodeIndexDocument
494
- * @param sourceTile - source tile (3DTile)
495
- * @param parentId - id of parent node in node pages
496
- * @param level - level of node (distanse to root node in the tree)
525
+ * @param parentNode - 3DNodeIndexDocument of parent node
526
+ * @param sourceTile - source 3DTile data
527
+ * @param level - tree level
497
528
  */
498
529
  private async _createNode(
499
- parentTile: Node3DIndexDocument,
500
- sourceTile: TileHeader,
501
- parentId: number,
530
+ parentNode: NodeIndexDocument,
531
+ sourceTile: Tile3D,
502
532
  level: number
503
- ): Promise<Node3DIndexDocument[]> {
504
- if (this.validate) {
505
- this._checkAddRefinementTypeForTile(sourceTile);
506
- }
533
+ ): Promise<NodeIndexDocument[]> {
534
+ this._checkAddRefinementTypeForTile(sourceTile);
507
535
 
508
536
  await this._updateTilesetOptions();
509
- await this.sourceTileset._loadTile(sourceTile);
510
- const boundingVolumes = createBoundingVolumes(sourceTile, this.geoidHeightModel);
537
+ await this.sourceTileset!._loadTile(sourceTile);
511
538
 
512
- const lodSelection = convertGeometricErrorToScreenThreshold(sourceTile, boundingVolumes);
513
- const maxScreenThresholdSQ = lodSelection.find(
514
- (val) => val.metricType === 'maxScreenThresholdSQ'
515
- ) || {maxError: 0};
539
+ let boundingVolumes = createBoundingVolumes(sourceTile, this.geoidHeightModel!);
516
540
 
517
- const batchTable = sourceTile?.content?.batchTableJson;
541
+ const propertyTable = getPropertyTable(sourceTile.content);
518
542
 
519
- if (batchTable) {
520
- this._convertAttributeStorageInfo(sourceTile.content);
543
+ if (propertyTable && !this.layers0?.attributeStorageInfo?.length) {
544
+ this._convertPropertyTableToNodeAttributes(propertyTable);
521
545
  }
522
546
 
523
- const resourcesData = await this._convertResources(sourceTile);
547
+ const resourcesData = await this._convertResources(
548
+ sourceTile,
549
+ parentNode.inPageId,
550
+ propertyTable
551
+ );
524
552
 
525
- const nodes = [];
553
+ const nodes: NodeIndexDocument[] = [];
554
+ const nodeIds: number[] = [];
555
+ const nodesInPage: NodeInPage[] = [];
526
556
  const emptyResources = {
527
557
  geometry: null,
528
558
  compressedGeometry: null,
529
559
  texture: null,
560
+ hasUvRegions: false,
530
561
  sharedResources: null,
531
562
  meshMaterial: null,
532
563
  vertexCount: null,
533
564
  attributes: null,
534
- featureCount: null
565
+ featureCount: null,
566
+ boundingVolumes: null
535
567
  };
568
+
536
569
  for (const resources of resourcesData || [emptyResources]) {
537
- const nodeInPage = this._createNodeInNodePages(
570
+ this.layersHasTexture = this.layersHasTexture || Boolean(resources.texture);
571
+
572
+ if (this.generateBoundingVolumes && resources.boundingVolumes) {
573
+ boundingVolumes = resources.boundingVolumes;
574
+ }
575
+
576
+ const lodSelection = convertGeometricErrorToScreenThreshold(sourceTile, boundingVolumes);
577
+ const maxScreenThresholdSQ = lodSelection.find(
578
+ (val) => val.metricType === 'maxScreenThresholdSQ'
579
+ ) || {maxError: 0};
580
+
581
+ const nodeInPage = await this._updateNodeInNodePages(
538
582
  maxScreenThresholdSQ,
539
583
  boundingVolumes,
540
584
  sourceTile,
541
- parentId,
585
+ parentNode.inPageId,
542
586
  resources
543
587
  );
544
- const node = this._createNodeIndexDocument(
545
- parentTile,
588
+
589
+ const nodeData = await NodeIndexDocument.createNodeIndexDocument(
590
+ parentNode,
546
591
  boundingVolumes,
547
592
  lodSelection,
548
593
  nodeInPage,
549
594
  resources
550
595
  );
596
+ const node = await new NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
597
+ nodes.push(node);
551
598
 
552
599
  if (nodeInPage.mesh) {
553
- await this._writeResources(resources, node.path);
600
+ await this._writeResources(resources, node.id);
554
601
  }
555
602
 
556
603
  if (this.validate) {
557
- this.boundingVolumeWarnings = validateNodeBoundingVolumes(node);
604
+ this.boundingVolumeWarnings = validateNodeBoundingVolumes(nodeData);
558
605
 
559
606
  if (this.boundingVolumeWarnings && this.boundingVolumeWarnings.length) {
560
607
  console.warn('Bounding Volume Warnings: ', ...this.boundingVolumeWarnings); //eslint-disable-line
561
608
  }
562
609
  }
563
610
 
564
- nodes.push(node);
611
+ nodeIds.push(nodeInPage.index);
612
+ nodesInPage.push(nodeInPage);
565
613
  }
566
614
 
567
615
  sourceTile.unloadContent();
568
616
 
569
- const firstNode = nodes[0];
570
617
  await this._addChildrenWithNeighborsAndWriteFile({
571
- parentNode: firstNode,
618
+ parentNode: nodes[0],
572
619
  sourceTiles: sourceTile.children,
573
- parentId: firstNode.id,
574
620
  level: level + 1
575
621
  });
576
622
  return nodes;
577
623
  }
578
624
 
579
- /**
580
- * Convert attributesStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
581
- * from B3DM batch table
582
- * @param sourceTileContent - tile content of 3DTile
583
- * @return {void}
584
- */
585
- private _convertAttributeStorageInfo(sourceTileContent: B3DMContent): void {
586
- // In legacy b3dm files sometimes sourceTileContent is null.
587
- const batchTable = sourceTileContent && sourceTileContent.batchTableJson;
588
- if (batchTable && !this.layers0.attributeStorageInfo.length) {
589
- this._convertBatchTableInfoToNodeAttributes(batchTable);
590
- }
591
- }
592
-
593
625
  /**
594
626
  * Convert tile to one or more I3S nodes
595
627
  * @param sourceTile - source tile (3DTile)
596
- * result.geometry - ArrayBuffer with geometry attributes
597
- * result.compressedGeometry - ArrayBuffer with compressed (draco) geometry
598
- * result.texture - texture image
599
- * result.sharedResources - shared resource data object
600
- * result.meshMaterial - PBR-like material object
601
- * result.vertexCount - number of vertices in geometry
602
- * result.attributes - feature attributes
603
- * result.featureCount - number of features
628
+ * @param parentId - id of parent node in node pages
629
+ * @param propertyTable - batch table from b3dm / feature properties from EXT_FEATURE_METADATA
630
+ * @returns - converted node resources
604
631
  */
605
- private async _convertResources(sourceTile: TileHeader): Promise<I3SGeometry[]> {
606
- if (!sourceTile.content || sourceTile.content.type !== 'b3dm') {
632
+ private async _convertResources(
633
+ sourceTile: Tile3D,
634
+ parentId: number,
635
+ propertyTable: FeatureTableJson | null
636
+ ): Promise<I3SConvertedResources[] | null> {
637
+ if (!this.isContentSupported(sourceTile)) {
607
638
  return null;
608
639
  }
640
+ const draftObb = {
641
+ center: [],
642
+ halfSize: [],
643
+ quaternion: []
644
+ };
609
645
  const resourcesData = await convertB3dmToI3sGeometry(
610
646
  sourceTile.content,
611
- Number(this.nodePages.nodesCounter),
647
+ async () => (await this.nodePages.push({index: 0, obb: draftObb}, parentId)).index,
648
+ propertyTable,
612
649
  this.featuresHashArray,
613
- this.layers0.attributeStorageInfo,
614
- this.options.draco
650
+ this.layers0?.attributeStorageInfo,
651
+ this.options.draco,
652
+ this.generateBoundingVolumes,
653
+ this.options.mergeMaterials,
654
+ this.geoidHeightModel!,
655
+ this.workerSource
615
656
  );
616
657
  return resourcesData;
617
658
  }
618
659
 
619
660
  /**
620
- * Create a new node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
661
+ * Update node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
621
662
  * in node pages (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/nodePage.cmn.md)
622
663
  * @param maxScreenThresholdSQ - Level of Details (LOD) metric
623
664
  * @param boundingVolumes - Bounding volumes
@@ -628,112 +669,64 @@ export default class I3SConverter {
628
669
  * @param resources.texture - texture image
629
670
  * @param resources.vertexCount - number of vertices in geometry
630
671
  * @param resources.featureCount - number of features
672
+ * @param resources.geometry - Uint8Array with geometry attributes
631
673
  * @return the node object in node pages
632
674
  */
633
- private _createNodeInNodePages(
675
+ private async _updateNodeInNodePages(
634
676
  maxScreenThresholdSQ: MaxScreenThresholdSQ,
635
677
  boundingVolumes: BoundingVolumes,
636
- sourceTile: TileHeader,
678
+ sourceTile: Tile3D,
637
679
  parentId: number,
638
- resources: I3SGeometry
639
- ): NodeInPage {
640
- const {meshMaterial, texture, vertexCount, featureCount, geometry} = resources;
641
- const nodeInPage = {
680
+ resources: I3SConvertedResources
681
+ ): Promise<NodeInPage> {
682
+ const {meshMaterial, texture, vertexCount, featureCount, geometry, hasUvRegions} = resources;
683
+ const nodeInPage: NodeInPage = {
684
+ index: 0,
642
685
  lodThreshold: maxScreenThresholdSQ.maxError,
643
686
  obb: boundingVolumes.obb,
644
- children: [],
645
- mesh: null
687
+ children: []
646
688
  };
647
- if (geometry && sourceTile.content && sourceTile.content.type === 'b3dm') {
689
+ if (geometry && this.isContentSupported(sourceTile)) {
648
690
  nodeInPage.mesh = {
649
691
  geometry: {
650
- definition: texture ? 0 : 1
692
+ definition: this.findOrCreateGeometryDefinition(Boolean(texture), hasUvRegions),
693
+ resource: 0
651
694
  },
652
- attribute: {}
695
+ attribute: {
696
+ resource: 0
697
+ },
698
+ material: {
699
+ definition: 0
700
+ }
653
701
  };
654
702
  }
655
- const nodeId = this.nodePages.push(nodeInPage, parentId);
656
703
 
657
- if (meshMaterial) {
658
- this.nodePages.updateMaterialByNodeId(nodeId, this._findOrCreateMaterial(meshMaterial));
704
+ let nodeId = resources.nodeId;
705
+ let node;
706
+ if (!nodeId) {
707
+ node = await this.nodePages.push(nodeInPage, parentId);
708
+ } else {
709
+ node = await this.nodePages.getNodeById(nodeId);
659
710
  }
660
711
 
712
+ NodePages.updateAll(node, nodeInPage);
713
+ if (meshMaterial) {
714
+ NodePages.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
715
+ }
661
716
  if (texture) {
662
717
  const texelCountHint = texture.image.height * texture.image.width;
663
- this.nodePages.updateTexelCountHintByNodeId(nodeId, texelCountHint);
718
+ NodePages.updateTexelCountHintByNodeId(node, texelCountHint);
664
719
  }
665
-
666
720
  if (vertexCount) {
667
721
  this.vertexCounter += vertexCount;
668
- this.nodePages.updateVertexCountByNodeId(nodeId, vertexCount);
722
+ NodePages.updateVertexCountByNodeId(node, vertexCount);
669
723
  }
670
- this.nodePages.updateNodeAttributeByNodeId(nodeId);
724
+ NodePages.updateNodeAttributeByNodeId(node);
671
725
  if (featureCount) {
672
- this.nodePages.updateFeatureCountByNodeId(nodeId, featureCount);
726
+ NodePages.updateFeatureCountByNodeId(node, featureCount);
673
727
  }
674
728
 
675
- return nodeInPage;
676
- }
677
-
678
- /**
679
- * Create a new node page object in node pages
680
- * @param parentNode - 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md object of the parent node
681
- * @param boundingVolumes - Bounding volumes
682
- * @param lodSelection - Level of Details (LOD) metrics
683
- * @param nodeInPage - corresponding node object in a node page
684
- * @param resources - the node resources data
685
- * @param resources.texture - texture image
686
- * @param resources.attributes - feature attributes
687
- * @return 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md object
688
- */
689
- private _createNodeIndexDocument(
690
- parentNode: Node3DIndexDocument,
691
- boundingVolumes: BoundingVolumes,
692
- lodSelection: LodSelection[],
693
- nodeInPage: NodeInPage,
694
- resources: I3SGeometry
695
- ): Node3DIndexDocument {
696
- const {texture, attributes} = resources;
697
- const nodeId = nodeInPage.index;
698
- const nodeData = {
699
- version: parentNode.version,
700
- id: nodeId.toString(),
701
- path: nodeId.toString(),
702
- level: parentNode.level + 1,
703
- ...boundingVolumes,
704
- lodSelection,
705
- parentNode: {
706
- id: parentNode.id,
707
- href: `../${parentNode.id}`,
708
- mbs: parentNode.mbs,
709
- obb: parentNode.obb
710
- },
711
- children: [],
712
- neighbors: []
713
- };
714
- const node = transform(nodeData, nodeTemplate);
715
-
716
- if (nodeInPage.mesh) {
717
- node.geometryData = [{href: './geometries/0'}];
718
- node.sharedResource = {href: './shared'};
719
-
720
- if (texture) {
721
- node.textureData = [{href: './textures/0'}, {href: './textures/1'}];
722
- }
723
-
724
- if (
725
- attributes &&
726
- attributes.length &&
727
- this.layers0.attributeStorageInfo &&
728
- this.layers0.attributeStorageInfo.length
729
- ) {
730
- node.attributeData = [];
731
- for (let index = 0; index < attributes.length; index++) {
732
- const folderName = this.layers0.attributeStorageInfo[index].key;
733
- node.attributeData.push({href: `./attributes/${folderName}/0`});
734
- }
735
- }
736
- }
729
+ this.nodePages.saveNode(node);
737
730
 
738
731
  return node;
739
732
  }
@@ -748,7 +741,7 @@ export default class I3SConverter {
748
741
  * @param resources.attributes - feature attributes
749
742
  * @return {Promise<void>}
750
743
  */
751
- private async _writeResources(resources: I3SGeometry, nodePath: string): Promise<void> {
744
+ private async _writeResources(resources: I3SConvertedResources, nodePath: string): Promise<void> {
752
745
  const {
753
746
  geometry: geometryBuffer,
754
747
  compressedGeometry,
@@ -759,7 +752,7 @@ export default class I3SConverter {
759
752
  const childPath = join(this.layers0Path, 'nodes', nodePath);
760
753
  const slpkChildPath = join('nodes', nodePath);
761
754
 
762
- await this._writeGeometries(geometryBuffer, compressedGeometry, childPath, slpkChildPath);
755
+ await this._writeGeometries(geometryBuffer!, compressedGeometry!, childPath, slpkChildPath);
763
756
  await this._writeShared(sharedResources, childPath, slpkChildPath, nodePath);
764
757
  await this._writeTexture(texture, childPath, slpkChildPath);
765
758
  await this._writeAttributes(attributes, childPath, slpkChildPath);
@@ -774,33 +767,36 @@ export default class I3SConverter {
774
767
  */
775
768
  private async _writeGeometries(
776
769
  geometryBuffer: ArrayBuffer,
777
- compressedGeometry: ArrayBuffer,
770
+ compressedGeometry: Promise<ArrayBuffer>,
778
771
  childPath: string,
779
772
  slpkChildPath: string
780
773
  ): Promise<void> {
781
774
  if (this.options.slpk) {
782
775
  const slpkGeometryPath = join(childPath, 'geometries');
783
- this.fileMap[`${slpkChildPath}/geometries/0.bin.gz`] = await writeFileForSlpk(
784
- slpkGeometryPath,
785
- geometryBuffer,
786
- '0.bin'
787
- );
776
+ await this.writeQueue.enqueue({
777
+ archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
778
+ writePromise: () => writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
779
+ });
788
780
  } else {
789
781
  const geometryPath = join(childPath, 'geometries/0/');
790
- await writeFile(geometryPath, geometryBuffer, 'index.bin');
782
+ await this.writeQueue.enqueue({
783
+ writePromise: () => writeFile(geometryPath, geometryBuffer, 'index.bin')
784
+ });
791
785
  }
792
786
 
793
787
  if (this.options.draco) {
794
788
  if (this.options.slpk) {
795
789
  const slpkCompressedGeometryPath = join(childPath, 'geometries');
796
- this.fileMap[`${slpkChildPath}/geometries/1.bin.gz`] = await writeFileForSlpk(
797
- slpkCompressedGeometryPath,
798
- compressedGeometry,
799
- '1.bin'
800
- );
790
+ await this.writeQueue.enqueue({
791
+ archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
792
+ writePromise: () =>
793
+ writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
794
+ });
801
795
  } else {
802
796
  const compressedGeometryPath = join(childPath, 'geometries/1/');
803
- await writeFile(compressedGeometryPath, compressedGeometry, 'index.bin');
797
+ await this.writeQueue.enqueue({
798
+ writePromise: () => writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
799
+ });
804
800
  }
805
801
  }
806
802
  }
@@ -813,85 +809,130 @@ export default class I3SConverter {
813
809
  * @param nodePath - a node path
814
810
  */
815
811
  private async _writeShared(
816
- sharedResources: SharedResources,
812
+ sharedResources: SharedResourcesArrays | null,
817
813
  childPath: string,
818
814
  slpkChildPath: string,
819
815
  nodePath: string
820
816
  ): Promise<void> {
817
+ if (!sharedResources) {
818
+ return;
819
+ }
821
820
  sharedResources.nodePath = nodePath;
822
- const sharedData = transform(sharedResources, SHARED_RESOURCES_TEMPLATE);
821
+ const sharedData = transform(sharedResources, sharedResourcesTemplate());
823
822
  const sharedDataStr = JSON.stringify(sharedData);
824
823
  if (this.options.slpk) {
825
824
  const slpkSharedPath = join(childPath, 'shared');
826
- this.fileMap[`${slpkChildPath}/shared/sharedResource.json.gz`] = await writeFileForSlpk(
827
- slpkSharedPath,
828
- sharedDataStr,
829
- 'sharedResource.json'
830
- );
825
+ await this.writeQueue.enqueue({
826
+ archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
827
+ writePromise: () => writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
828
+ });
831
829
  } else {
832
830
  const sharedPath = join(childPath, 'shared/');
833
- await writeFile(sharedPath, sharedDataStr);
831
+ await this.writeQueue.enqueue({writePromise: () => writeFile(sharedPath, sharedDataStr)});
834
832
  }
835
833
  }
836
834
 
837
835
  /**
838
- * Write the texture image in a file
836
+ * Generates textures based on texture mime type and fill in textureSetDefinitions data.
839
837
  * @param texture - the texture image
840
838
  * @param childPath - a child path to write resources
841
839
  * @param slpkChildPath - the resource path inside *slpk file
842
840
  */
843
841
  private async _writeTexture(
844
- texture: TextureImage,
842
+ texture: GLTFImagePostprocessed,
845
843
  childPath: string,
846
844
  slpkChildPath: string
847
845
  ): Promise<void> {
848
846
  if (texture) {
849
- const format = this._getFormatByMimeType(texture.mimeType);
850
- if (!this.layers0.textureSetDefinitions.length) {
851
- this.layers0.textureSetDefinitions.push({
852
- formats: [
853
- {
854
- name: '0',
855
- format
856
- },
857
- {
858
- name: '1',
859
- format: 'ktx2'
860
- }
861
- ]
862
- });
863
- }
864
-
865
- const textureData = texture.bufferView.data;
866
- const ktx2TextureData = await encode(texture.image, KTX2BasisUniversalTextureWriter);
847
+ const format = this._getFormatByMimeType(texture?.mimeType);
848
+ const formats: TextureSetDefinitionFormats = [];
849
+ const textureData = texture.bufferView!.data;
850
+
851
+ switch (format) {
852
+ case 'jpg':
853
+ case 'png': {
854
+ formats.push({name: '0', format});
855
+ await this.writeTextureFile(textureData, '0', format, childPath, slpkChildPath);
856
+
857
+ if (this.generateTextures) {
858
+ formats.push({name: '1', format: 'ktx2'});
859
+ // For Node.js texture.image.data is type of Buffer
860
+ const copyArrayBuffer = texture.image.data.subarray();
861
+ const arrayToEncode = new Uint8Array(copyArrayBuffer);
862
+ const ktx2TextureData = encode(
863
+ {...texture.image, data: arrayToEncode},
864
+ KTX2BasisWriterWorker,
865
+ {
866
+ ...KTX2BasisWriterWorker.options,
867
+ source: this.workerSource.ktx2,
868
+ reuseWorkers: true,
869
+ _nodeWorkers: true
870
+ }
871
+ );
872
+
873
+ await this.writeTextureFile(ktx2TextureData, '1', 'ktx2', childPath, slpkChildPath);
874
+ }
867
875
 
868
- if (this.options.slpk) {
869
- const slpkTexturePath = join(childPath, 'textures');
870
- const compress = false;
871
-
872
- this.fileMap[`${slpkChildPath}/textures/0.${format}`] = await writeFileForSlpk(
873
- slpkTexturePath,
874
- textureData,
875
- `0.${format}`,
876
- compress
877
- );
876
+ break;
877
+ }
878
878
 
879
- this.fileMap[`${slpkChildPath}/textures/1.ktx2`] = await writeFileForSlpk(
880
- slpkTexturePath,
881
- ktx2TextureData,
882
- `1.ktx2`,
883
- compress
884
- );
885
- } else {
886
- const texturePath = join(childPath, 'textures/0/');
887
- await writeFile(texturePath, textureData, `index.${format}`);
879
+ case 'ktx2': {
880
+ formats.push({name: '1', format});
881
+ await this.writeTextureFile(textureData, '1', format, childPath, slpkChildPath);
882
+
883
+ if (this.generateTextures) {
884
+ formats.push({name: '0', format: 'jpg'});
885
+ const decodedFromKTX2TextureData = encode(texture.image!.data[0], ImageWriter);
886
+ await this.writeTextureFile(
887
+ decodedFromKTX2TextureData,
888
+ '0',
889
+ 'jpg',
890
+ childPath,
891
+ slpkChildPath
892
+ );
893
+ }
894
+ }
895
+ }
888
896
 
889
- const ktx2TexturePath = join(childPath, 'textures/1/');
890
- await writeFile(ktx2TexturePath, ktx2TextureData, `index.ktx2`);
897
+ if (!this.layers0!.textureSetDefinitions!.length) {
898
+ this.layers0!.textureSetDefinitions!.push({formats});
899
+ this.layers0!.textureSetDefinitions!.push({formats, atlas: true});
891
900
  }
892
901
  }
893
902
  }
894
903
 
904
+ /**
905
+ * Write the texture image in a file
906
+ * @param textureData
907
+ * @param name
908
+ * @param format
909
+ * @param childPath
910
+ * @param slpkChildPath
911
+ */
912
+ private async writeTextureFile(
913
+ textureData: Promise<ArrayBuffer>,
914
+ name: string,
915
+ format: 'jpg' | 'png' | 'ktx2',
916
+ childPath: string,
917
+ slpkChildPath: string
918
+ ): Promise<void> {
919
+ if (this.options.slpk) {
920
+ const slpkTexturePath = join(childPath, 'textures');
921
+ const compress = false;
922
+
923
+ await this.writeQueue.enqueue({
924
+ archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
925
+ writePromise: () =>
926
+ writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
927
+ });
928
+ } else {
929
+ const texturePath = join(childPath, `textures/${name}/`);
930
+ await this.writeQueue.enqueue({
931
+ writePromise: () => writeFile(texturePath, textureData, `index.${format}`)
932
+ });
933
+ }
934
+ }
935
+
895
936
  /**
896
937
  * Write feature attributes in files
897
938
  * @param attributes - feature attributes
@@ -899,29 +940,26 @@ export default class I3SConverter {
899
940
  * @param slpkChildPath - the resource path inside *slpk file
900
941
  */
901
942
  private async _writeAttributes(
902
- attributes: ArrayBuffer[],
943
+ attributes: ArrayBuffer[] | null = [],
903
944
  childPath: string,
904
945
  slpkChildPath: string
905
946
  ): Promise<void> {
906
- if (
907
- attributes.length &&
908
- this.layers0.attributeStorageInfo &&
909
- this.layers0.attributeStorageInfo.length
910
- ) {
947
+ if (attributes?.length && this.layers0?.attributeStorageInfo?.length) {
911
948
  for (let index = 0; index < attributes.length; index++) {
912
949
  const folderName = this.layers0.attributeStorageInfo[index].key;
913
950
  const fileBuffer = new Uint8Array(attributes[index]);
914
951
 
915
952
  if (this.options.slpk) {
916
953
  const slpkAttributesPath = join(childPath, 'attributes', folderName);
917
- this.fileMap[`${slpkChildPath}/attributes/${folderName}.bin.gz`] = await writeFileForSlpk(
918
- slpkAttributesPath,
919
- fileBuffer,
920
- '0.bin'
921
- );
954
+ await this.writeQueue.enqueue({
955
+ archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
956
+ writePromise: () => writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
957
+ });
922
958
  } else {
923
959
  const attributesPath = join(childPath, `attributes/${folderName}/0`);
924
- await writeFile(attributesPath, fileBuffer, 'index.bin');
960
+ await this.writeQueue.enqueue({
961
+ writePromise: () => writeFile(attributesPath, fileBuffer, 'index.bin')
962
+ });
925
963
  }
926
964
  }
927
965
  }
@@ -931,12 +969,14 @@ export default class I3SConverter {
931
969
  * Return file format by its MIME type
932
970
  * @param mimeType - feature attributes
933
971
  */
934
- private _getFormatByMimeType(mimeType: string): string {
972
+ private _getFormatByMimeType(mimeType: string | undefined): 'jpg' | 'png' | 'ktx2' {
935
973
  switch (mimeType) {
936
974
  case 'image/jpeg':
937
975
  return 'jpg';
938
976
  case 'image/png':
939
977
  return 'png';
978
+ case 'image/ktx2':
979
+ return 'ktx2';
940
980
  default:
941
981
  return 'jpg';
942
982
  }
@@ -947,10 +987,10 @@ export default class I3SConverter {
947
987
  * @param material - end-to-end index of the node
948
988
  * @return material id
949
989
  */
950
- private _findOrCreateMaterial(material: GLTFMaterial): number {
990
+ private _findOrCreateMaterial(material: I3SMaterialDefinition): number {
951
991
  const hash = md5(JSON.stringify(material));
952
992
  if (this.materialMap.has(hash)) {
953
- return this.materialMap.get(hash);
993
+ return this.materialMap.get(hash) || 0;
954
994
  }
955
995
  const newMaterialId = this.materialDefinitions.push(material) - 1;
956
996
  this.materialMap.set(hash, newMaterialId);
@@ -958,196 +998,52 @@ export default class I3SConverter {
958
998
  }
959
999
 
960
1000
  /**
961
- * Generate storage attribute for map segmentation.
962
- * @param attributeIndex - order index of attribute (f_0, f_1 ...).
963
- * @param key - attribute key from batch table.\
964
- * @param attributeType - attribute type.
965
- * @return Updated storageAttribute.
1001
+ * Get unique geometry configuration index
1002
+ * In the end of conversion configurations will be transformed to geometryDefinitions array
1003
+ * @param hasTexture
1004
+ * @param hasUvRegions
1005
+ * @returns
966
1006
  */
967
- private _createdStorageAttribute(
968
- attributeIndex: number,
969
- key: string,
970
- attributeType: Attribute
971
- ): AttributeStorageInfo {
972
- const storageAttribute = {
973
- key: `f_${attributeIndex}`,
974
- name: key,
975
- ordering: ['attributeValues'],
976
- header: [{property: 'count', valueType: 'UInt32'}],
977
- attributeValues: {valueType: 'Int32', valuesPerElement: 1}
978
- };
979
-
980
- switch (attributeType) {
981
- case OBJECT_ID_TYPE:
982
- this._setupIdAttribute(storageAttribute);
983
- break;
984
- case STRING_TYPE:
985
- this._setupStringAttribute(storageAttribute);
986
- break;
987
- case DOUBLE_TYPE:
988
- this._setupDoubleAttribute(storageAttribute);
989
- break;
990
- case SHORT_INT_TYPE:
991
- break;
992
- default:
993
- this._setupStringAttribute(storageAttribute);
1007
+ private findOrCreateGeometryDefinition(hasTexture: boolean, hasUvRegions: boolean): number {
1008
+ const geometryConfig = {hasTexture, hasUvRegions};
1009
+ const hash = md5(JSON.stringify(geometryConfig));
1010
+ if (this.geometryMap.has(hash)) {
1011
+ return this.geometryMap.get(hash) || 0;
994
1012
  }
995
-
996
- return storageAttribute;
997
- }
998
-
999
- /**
1000
- * Get the attribute type for attributeStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
1001
- * @param key - attribute's key
1002
- * @param attribute - attribute's type in batchTable
1003
- */
1004
- private getAttributeType(key: string, attribute: string): string {
1005
- if (key === OBJECT_ID_TYPE) {
1006
- return OBJECT_ID_TYPE;
1007
- }
1008
- if (typeof attribute === STRING_TYPE) {
1009
- return STRING_TYPE;
1010
- } else if (typeof attribute === 'number') {
1011
- return Number.isInteger(attribute) ? SHORT_INT_TYPE : DOUBLE_TYPE;
1012
- }
1013
- return STRING_TYPE;
1014
- }
1015
-
1016
- /**
1017
- * Setup storage attribute as string.
1018
- * @param storageAttribute - attribute for map segmentation.
1019
- */
1020
- private _setupStringAttribute(storageAttribute: AttributeStorageInfo): void {
1021
- storageAttribute.ordering.unshift('attributeByteCounts');
1022
- storageAttribute.header.push({property: 'attributeValuesByteCount', valueType: 'UInt32'});
1023
- storageAttribute.attributeValues = {
1024
- valueType: 'String',
1025
- encoding: 'UTF-8',
1026
- valuesPerElement: 1
1027
- };
1028
- storageAttribute.attributeByteCounts = {
1029
- valueType: 'UInt32',
1030
- valuesPerElement: 1
1031
- };
1032
- }
1033
-
1034
- /**
1035
- * Setup Id attribute for map segmentation.
1036
- * @param storageAttribute - attribute for map segmentation .
1037
- */
1038
- private _setupIdAttribute(storageAttribute: AttributeStorageInfo): void {
1039
- storageAttribute.attributeValues = {
1040
- valueType: 'Oid32',
1041
- valuesPerElement: 1
1042
- };
1043
- }
1044
-
1045
- /**
1046
- * Setup double attribute for map segmentation.
1047
- * @param storageAttribute - attribute for map segmentation .
1048
- */
1049
- private _setupDoubleAttribute(storageAttribute: AttributeStorageInfo): void {
1050
- storageAttribute.attributeValues = {
1051
- valueType: 'Float64',
1052
- valuesPerElement: 1
1053
- };
1054
- }
1055
-
1056
- /**
1057
- * Setup field attribute for map segmentation.
1058
- * @param key - attribute for map segmentation.
1059
- * @param fieldAttributeType - esri attribute type ('esriFieldTypeString' or 'esriFieldTypeOID').
1060
- */
1061
- private _createFieldAttribute(key: string, fieldAttributeType: ESRIField): Field {
1062
- return {
1063
- name: key,
1064
- type: fieldAttributeType,
1065
- alias: key
1066
- };
1013
+ const newGeometryId = this.geometryConfigs.push(geometryConfig) - 1;
1014
+ this.geometryMap.set(hash, newGeometryId);
1015
+ return newGeometryId;
1067
1016
  }
1068
1017
 
1069
1018
  /**
1070
- * Do conversion of 3DTiles batch table to I3s node attributes.
1071
- * @param batchTable - Table with layer meta data.
1019
+ * Do conversion of 3DTiles property table to I3s node attributes.
1020
+ * @param propertyTable - Table with layer meta data.
1072
1021
  */
1073
- private _convertBatchTableInfoToNodeAttributes(batchTable: BatchTableJson): void {
1022
+ private _convertPropertyTableToNodeAttributes(propertyTable: FeatureTableJson): void {
1074
1023
  let attributeIndex = 0;
1075
- const batchTableWithObjectId = {
1024
+ const propertyTableWithObjectId = {
1076
1025
  OBJECTID: [0],
1077
- ...batchTable
1026
+ ...propertyTable
1078
1027
  };
1079
1028
 
1080
- for (const key in batchTableWithObjectId) {
1081
- const firstAttribute = batchTableWithObjectId[key][0];
1082
- const attributeType = this.getAttributeType(key, firstAttribute);
1029
+ for (const key in propertyTableWithObjectId) {
1030
+ const firstAttribute = propertyTableWithObjectId[key][0];
1031
+ const attributeType = getAttributeType(key, firstAttribute);
1083
1032
 
1084
- const storageAttribute = this._createdStorageAttribute(attributeIndex, key, attributeType);
1085
- const fieldAttributeType = this._getFieldAttributeType(attributeType);
1086
- const fieldAttribute = this._createFieldAttribute(key, fieldAttributeType);
1087
- const popupInfo = this._createPopupInfo(batchTableWithObjectId);
1033
+ const storageAttribute = createdStorageAttribute(attributeIndex, key, attributeType);
1034
+ const fieldAttributeType = getFieldAttributeType(attributeType);
1035
+ const fieldAttribute = createFieldAttribute(key, fieldAttributeType);
1036
+ const popupInfo = createPopupInfo(propertyTableWithObjectId);
1088
1037
 
1089
- this.layers0.attributeStorageInfo.push(storageAttribute);
1090
- this.layers0.fields.push(fieldAttribute);
1091
- this.layers0.popupInfo = popupInfo;
1092
- this.layers0.layerType = _3D_OBJECT_LAYER_TYPE;
1038
+ this.layers0!.attributeStorageInfo!.push(storageAttribute);
1039
+ this.layers0!.fields!.push(fieldAttribute);
1040
+ this.layers0!.popupInfo = popupInfo;
1041
+ this.layers0!.layerType = _3D_OBJECT_LAYER_TYPE;
1093
1042
 
1094
1043
  attributeIndex += 1;
1095
1044
  }
1096
1045
  }
1097
1046
 
1098
- /**
1099
- * Find and return attribute type based on key form Batch table.
1100
- * @param attributeType
1101
- */
1102
- private _getFieldAttributeType(attributeType: Attribute): ESRIField {
1103
- switch (attributeType) {
1104
- case OBJECT_ID_TYPE:
1105
- return 'esriFieldTypeOID';
1106
- case STRING_TYPE:
1107
- return 'esriFieldTypeString';
1108
- case SHORT_INT_TYPE:
1109
- return 'esriFieldTypeInteger';
1110
- case DOUBLE_TYPE:
1111
- return 'esriFieldTypeDouble';
1112
- default:
1113
- return 'esriFieldTypeString';
1114
- }
1115
- }
1116
-
1117
- /**
1118
- * Generate popup info to show metadata on the map.
1119
- * @param batchTable - Batch table data with OBJECTID.
1120
- * @return data for correct rendering of popup.
1121
- */
1122
- private _createPopupInfo(batchTable: BatchTableJson): PopupInfo {
1123
- const title = '{OBJECTID}';
1124
- const mediaInfos = [];
1125
- const fieldInfos = [];
1126
- const popupElements = [];
1127
- const expressionInfos = [];
1128
-
1129
- for (const key in batchTable) {
1130
- fieldInfos.push({
1131
- fieldName: key,
1132
- visible: true,
1133
- isEditable: false,
1134
- label: key
1135
- });
1136
- }
1137
- popupElements.push({
1138
- fieldInfos,
1139
- type: 'fields'
1140
- });
1141
-
1142
- return {
1143
- title,
1144
- mediaInfos,
1145
- popupElements,
1146
- fieldInfos,
1147
- expressionInfos
1148
- };
1149
- }
1150
-
1151
1047
  /**
1152
1048
  * Print statistics in the end of conversion
1153
1049
  * @param params - output files data
@@ -1177,10 +1073,13 @@ export default class I3SConverter {
1177
1073
  * Fetch preload options for ION tileset
1178
1074
  */
1179
1075
  private async _fetchPreloadOptions(): Promise<any> {
1076
+ if (!this.Loader.preload) {
1077
+ return {};
1078
+ }
1180
1079
  const options = {
1181
1080
  'cesium-ion': {accessToken: this.options.token || ION_DEFAULT_TOKEN}
1182
1081
  };
1183
- const preloadOptions = await CesiumIonLoader.preload(this.options.inputUrl, options);
1082
+ const preloadOptions = await this.Loader.preload(this.options.inputUrl, options);
1184
1083
  this.refreshTokenTime = process.hrtime();
1185
1084
  return {...options, ...preloadOptions};
1186
1085
  }
@@ -1196,10 +1095,10 @@ export default class I3SConverter {
1196
1095
  this.refreshTokenTime = process.hrtime();
1197
1096
 
1198
1097
  const preloadOptions = await this._fetchPreloadOptions();
1199
- this.sourceTileset.options = {...this.sourceTileset.options, ...preloadOptions};
1098
+ this.sourceTileset!.options = {...this.sourceTileset!.options, ...preloadOptions};
1200
1099
  if (preloadOptions.headers) {
1201
- this.sourceTileset.loadOptions.fetch = {
1202
- ...this.sourceTileset.loadOptions.fetch,
1100
+ this.sourceTileset!.loadOptions.fetch = {
1101
+ ...this.sourceTileset!.loadOptions.fetch,
1203
1102
  headers: preloadOptions.headers
1204
1103
  };
1205
1104
  console.log('Authorization Bearer token has been updated'); // eslint-disable-line no-undef, no-console
@@ -1209,7 +1108,7 @@ export default class I3SConverter {
1209
1108
  /** Do calculations of all tiles and tiles with "ADD" type of refinement.
1210
1109
  * @param tile
1211
1110
  */
1212
- private _checkAddRefinementTypeForTile(tile: TileHeader): void {
1111
+ private _checkAddRefinementTypeForTile(tile: Tile3D): void {
1213
1112
  const ADD_TILE_REFINEMENT = 1;
1214
1113
 
1215
1114
  if (tile.refine === ADD_TILE_REFINEMENT) {
@@ -1219,4 +1118,35 @@ export default class I3SConverter {
1219
1118
 
1220
1119
  this.refinementCounter.tilesCount += 1;
1221
1120
  }
1121
+ /**
1122
+ * Check if the tile's content format is supported by the converter
1123
+ * @param sourceRootTile
1124
+ * @returns
1125
+ */
1126
+ private isContentSupported(sourceRootTile: Tile3D): boolean {
1127
+ return ['b3dm', 'glTF'].includes(sourceRootTile?.content?.type);
1128
+ }
1129
+
1130
+ private async loadWorkers(): Promise<void> {
1131
+ console.log(`Loading workers source...`); // eslint-disable-line no-undef, no-console
1132
+ if (this.options.draco) {
1133
+ const url = getWorkerURL(DracoWriterWorker, {...getLoaderOptions()});
1134
+ const sourceResponse = await fetchFile(url);
1135
+ const source = await sourceResponse.text();
1136
+ this.workerSource.draco = source;
1137
+ }
1138
+
1139
+ if (this.generateTextures) {
1140
+ const url = getWorkerURL(KTX2BasisWriterWorker, {...getLoaderOptions()});
1141
+ const sourceResponse = await fetchFile(url);
1142
+ const source = await sourceResponse.text();
1143
+ this.workerSource.ktx2 = source;
1144
+ }
1145
+
1146
+ const i3sAttributesWorkerUrl = getWorkerURL(I3SAttributesWorker, {...getLoaderOptions()});
1147
+ const sourceResponse = await fetchFile(i3sAttributesWorkerUrl);
1148
+ const source = await sourceResponse.text();
1149
+ this.workerSource.I3SAttributes = source;
1150
+ console.log(`Loading workers source completed!`); // eslint-disable-line no-undef, no-console
1151
+ }
1222
1152
  }