@loaders.gl/tile-converter 4.0.0-alpha.1 → 4.0.0-alpha.11

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