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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/dist/3d-tiles-attributes-worker.d.ts +3 -3
  2. package/dist/3d-tiles-attributes-worker.d.ts.map +1 -1
  3. package/dist/3d-tiles-attributes-worker.js +2 -3
  4. package/dist/3d-tiles-attributes-worker.js.map +3 -3
  5. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +8 -0
  6. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  7. package/dist/3d-tiles-converter/3d-tiles-converter.js +57 -43
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +5 -5
  9. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
  10. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +21 -17
  11. package/dist/converter-cli.js +43 -8
  12. package/dist/converter.min.js +24 -21
  13. package/dist/deps-installer/deps-installer.d.ts +5 -1
  14. package/dist/deps-installer/deps-installer.d.ts.map +1 -1
  15. package/dist/deps-installer/deps-installer.js +29 -1
  16. package/dist/dist.min.js +58405 -61237
  17. package/dist/es5/3d-tiles-attributes-worker.js +4 -7
  18. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -1
  19. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +125 -210
  20. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  21. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +53 -85
  22. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  23. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +0 -8
  24. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
  25. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js +0 -5
  26. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
  27. package/dist/es5/3d-tiles-converter/json-templates/tileset.js +0 -6
  28. package/dist/es5/3d-tiles-converter/json-templates/tileset.js.map +1 -1
  29. package/dist/es5/bundle.js +0 -1
  30. package/dist/es5/bundle.js.map +1 -1
  31. package/dist/es5/constants.js.map +1 -1
  32. package/dist/es5/converter-cli.js +50 -60
  33. package/dist/es5/converter-cli.js.map +1 -1
  34. package/dist/es5/deps-installer/deps-installer.js +73 -28
  35. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  36. package/dist/es5/i3s-attributes-worker.js +3 -6
  37. package/dist/es5/i3s-attributes-worker.js.map +1 -1
  38. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +124 -0
  39. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
  40. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +2 -19
  41. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  42. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js +0 -11
  43. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
  44. package/dist/es5/i3s-converter/helpers/feature-attributes.js +184 -0
  45. package/dist/es5/i3s-converter/helpers/feature-attributes.js.map +1 -0
  46. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +60 -51
  47. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  48. package/dist/es5/i3s-converter/helpers/geometry-converter.js +516 -356
  49. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  50. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +57 -43
  51. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  52. package/dist/es5/i3s-converter/helpers/node-debug.js +4 -23
  53. package/dist/es5/i3s-converter/helpers/node-debug.js.map +1 -1
  54. package/dist/es5/i3s-converter/helpers/node-index-document.js +507 -0
  55. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -0
  56. package/dist/es5/i3s-converter/helpers/node-pages.js +462 -208
  57. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  58. package/dist/es5/i3s-converter/i3s-converter.js +722 -1153
  59. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  60. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js +107 -0
  61. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  62. package/dist/es5/i3s-converter/json-templates/layers.js +2 -107
  63. package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -1
  64. package/dist/es5/i3s-converter/json-templates/metadata.js +0 -2
  65. package/dist/es5/i3s-converter/json-templates/metadata.js.map +1 -1
  66. package/dist/es5/i3s-converter/json-templates/node.js +2 -12
  67. package/dist/es5/i3s-converter/json-templates/node.js.map +1 -1
  68. package/dist/es5/i3s-converter/json-templates/scene-server.js +0 -2
  69. package/dist/es5/i3s-converter/json-templates/scene-server.js.map +1 -1
  70. package/dist/es5/i3s-converter/json-templates/shared-resources.js +9 -32
  71. package/dist/es5/i3s-converter/json-templates/shared-resources.js.map +1 -1
  72. package/dist/es5/i3s-converter/json-templates/store.js.map +1 -1
  73. package/dist/es5/i3s-converter/types.js.map +1 -1
  74. package/dist/es5/i3s-server/app.js +0 -5
  75. package/dist/es5/i3s-server/app.js.map +1 -1
  76. package/dist/es5/i3s-server/controllers/index-controller.js +0 -16
  77. package/dist/es5/i3s-server/controllers/index-controller.js.map +1 -1
  78. package/dist/es5/i3s-server/routes/index.js +1 -10
  79. package/dist/es5/i3s-server/routes/index.js.map +1 -1
  80. package/dist/es5/index.js +0 -3
  81. package/dist/es5/index.js.map +1 -1
  82. package/dist/es5/lib/utils/compress-util.js +19 -74
  83. package/dist/es5/lib/utils/compress-util.js.map +1 -1
  84. package/dist/es5/lib/utils/file-utils.js +103 -47
  85. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  86. package/dist/es5/lib/utils/lod-conversion-utils.js +0 -7
  87. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  88. package/dist/es5/lib/utils/queue.js +0 -14
  89. package/dist/es5/lib/utils/queue.js.map +1 -1
  90. package/dist/es5/lib/utils/statistic-utills.js +1 -46
  91. package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
  92. package/dist/es5/lib/utils/write-queue.js +41 -82
  93. package/dist/es5/lib/utils/write-queue.js.map +1 -1
  94. package/dist/es5/pgm-loader.js +1 -8
  95. package/dist/es5/pgm-loader.js.map +1 -1
  96. package/dist/es5/workers/3d-tiles-attributes-worker.js +2 -9
  97. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -1
  98. package/dist/es5/workers/i3s-attributes-worker.js +2 -10
  99. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -1
  100. package/dist/esm/3d-tiles-attributes-worker.js +4 -2
  101. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -1
  102. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +60 -77
  103. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  104. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +29 -50
  105. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  106. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +1 -0
  107. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
  108. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js +1 -4
  109. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
  110. package/dist/esm/3d-tiles-converter/json-templates/tileset.js +0 -3
  111. package/dist/esm/3d-tiles-converter/json-templates/tileset.js.map +1 -1
  112. package/dist/esm/bundle.js +1 -1
  113. package/dist/esm/bundle.js.map +1 -1
  114. package/dist/esm/constants.js.map +1 -1
  115. package/dist/esm/converter-cli.js +46 -40
  116. package/dist/esm/converter-cli.js.map +1 -1
  117. package/dist/esm/deps-installer/deps-installer.js +30 -4
  118. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  119. package/dist/esm/i3s-attributes-worker.js +3 -1
  120. package/dist/esm/i3s-attributes-worker.js.map +1 -1
  121. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +113 -0
  122. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -0
  123. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +5 -6
  124. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  125. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js +1 -0
  126. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
  127. package/dist/esm/i3s-converter/helpers/feature-attributes.js +158 -0
  128. package/dist/esm/i3s-converter/helpers/feature-attributes.js.map +1 -0
  129. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +39 -33
  130. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  131. package/dist/esm/i3s-converter/helpers/geometry-converter.js +295 -196
  132. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  133. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +59 -34
  134. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  135. package/dist/esm/i3s-converter/helpers/node-debug.js +3 -13
  136. package/dist/esm/i3s-converter/helpers/node-debug.js.map +1 -1
  137. package/dist/esm/i3s-converter/helpers/node-index-document.js +197 -0
  138. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -0
  139. package/dist/esm/i3s-converter/helpers/node-pages.js +161 -87
  140. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  141. package/dist/esm/i3s-converter/i3s-converter.js +216 -491
  142. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  143. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js +89 -0
  144. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  145. package/dist/esm/i3s-converter/json-templates/layers.js +2 -95
  146. package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -1
  147. package/dist/esm/i3s-converter/json-templates/metadata.js.map +1 -1
  148. package/dist/esm/i3s-converter/json-templates/node.js +0 -4
  149. package/dist/esm/i3s-converter/json-templates/node.js.map +1 -1
  150. package/dist/esm/i3s-converter/json-templates/scene-server.js.map +1 -1
  151. package/dist/esm/i3s-converter/json-templates/shared-resources.js +3 -15
  152. package/dist/esm/i3s-converter/json-templates/shared-resources.js.map +1 -1
  153. package/dist/esm/i3s-converter/json-templates/store.js.map +1 -1
  154. package/dist/esm/i3s-converter/types.js.map +1 -1
  155. package/dist/esm/i3s-server/app.js +0 -5
  156. package/dist/esm/i3s-server/app.js.map +1 -1
  157. package/dist/esm/i3s-server/controllers/index-controller.js +0 -5
  158. package/dist/esm/i3s-server/controllers/index-controller.js.map +1 -1
  159. package/dist/esm/i3s-server/routes/index.js +0 -3
  160. package/dist/esm/i3s-server/routes/index.js.map +1 -1
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/lib/utils/compress-util.js +19 -12
  163. package/dist/esm/lib/utils/compress-util.js.map +1 -1
  164. package/dist/esm/lib/utils/file-utils.js +54 -11
  165. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  166. package/dist/esm/lib/utils/lod-conversion-utils.js +2 -6
  167. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  168. package/dist/esm/lib/utils/queue.js +0 -4
  169. package/dist/esm/lib/utils/queue.js.map +1 -1
  170. package/dist/esm/lib/utils/statistic-utills.js +0 -11
  171. package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
  172. package/dist/esm/lib/utils/write-queue.js +27 -38
  173. package/dist/esm/lib/utils/write-queue.js.map +1 -1
  174. package/dist/esm/pgm-loader.js +3 -1
  175. package/dist/esm/pgm-loader.js.map +1 -1
  176. package/dist/esm/workers/3d-tiles-attributes-worker.js +4 -1
  177. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -1
  178. package/dist/esm/workers/i3s-attributes-worker.js +4 -1
  179. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -1
  180. package/dist/i3s-attributes-worker.d.ts +7 -3
  181. package/dist/i3s-attributes-worker.d.ts.map +1 -1
  182. package/dist/i3s-attributes-worker.js +2 -3
  183. package/dist/i3s-attributes-worker.js.map +3 -3
  184. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +11 -0
  185. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -0
  186. package/dist/i3s-converter/helpers/batch-ids-extensions.js +141 -0
  187. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +2 -2
  188. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
  189. package/dist/i3s-converter/helpers/feature-attributes.d.ts +56 -0
  190. package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -0
  191. package/dist/i3s-converter/helpers/feature-attributes.js +216 -0
  192. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  193. package/dist/i3s-converter/helpers/geometry-attributes.js +42 -17
  194. package/dist/i3s-converter/helpers/geometry-converter.d.ts +18 -6
  195. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  196. package/dist/i3s-converter/helpers/geometry-converter.js +349 -99
  197. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
  198. package/dist/i3s-converter/helpers/gltf-attributes.js +53 -21
  199. package/dist/i3s-converter/helpers/node-index-document.d.ts +91 -0
  200. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -0
  201. package/dist/i3s-converter/helpers/node-index-document.js +242 -0
  202. package/dist/i3s-converter/helpers/node-pages.d.ts +81 -42
  203. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  204. package/dist/i3s-converter/helpers/node-pages.js +200 -92
  205. package/dist/i3s-converter/i3s-converter.d.ts +52 -108
  206. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  207. package/dist/i3s-converter/i3s-converter.js +218 -403
  208. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts +7 -0
  209. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts.map +1 -0
  210. package/dist/i3s-converter/json-templates/geometry-definitions.js +87 -0
  211. package/dist/i3s-converter/json-templates/layers.d.ts +1 -30
  212. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -1
  213. package/dist/i3s-converter/json-templates/layers.js +2 -86
  214. package/dist/i3s-converter/json-templates/shared-resources.js +3 -3
  215. package/dist/i3s-converter/types.d.ts +38 -8
  216. package/dist/i3s-converter/types.d.ts.map +1 -1
  217. package/dist/lib/utils/file-utils.d.ts +17 -1
  218. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  219. package/dist/lib/utils/file-utils.js +64 -7
  220. package/dist/lib/utils/write-queue.d.ts +19 -3
  221. package/dist/lib/utils/write-queue.d.ts.map +1 -1
  222. package/dist/lib/utils/write-queue.js +21 -16
  223. package/dist/pgm-loader.d.ts.map +1 -1
  224. package/dist/pgm-loader.js +2 -1
  225. package/dist/workers/3d-tiles-attributes-worker.js +1 -1
  226. package/dist/workers/i3s-attributes-worker.js +1 -1
  227. package/package.json +18 -16
  228. package/src/3d-tiles-attributes-worker.ts +1 -1
  229. package/src/3d-tiles-converter/3d-tiles-converter.ts +71 -55
  230. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +25 -18
  231. package/src/converter-cli.ts +54 -8
  232. package/src/deps-installer/deps-installer.ts +38 -2
  233. package/src/i3s-attributes-worker.ts +5 -1
  234. package/src/i3s-converter/helpers/batch-ids-extensions.ts +206 -0
  235. package/src/i3s-converter/helpers/coordinate-converter.ts +2 -2
  236. package/src/i3s-converter/helpers/feature-attributes.ts +247 -0
  237. package/src/i3s-converter/helpers/geometry-attributes.ts +46 -18
  238. package/src/i3s-converter/helpers/geometry-converter.ts +423 -111
  239. package/src/i3s-converter/helpers/gltf-attributes.ts +59 -24
  240. package/src/i3s-converter/helpers/node-index-document.ts +306 -0
  241. package/src/i3s-converter/helpers/node-pages.ts +222 -109
  242. package/src/i3s-converter/i3s-converter.ts +264 -487
  243. package/src/i3s-converter/json-templates/geometry-definitions.ts +83 -0
  244. package/src/i3s-converter/json-templates/layers.ts +2 -91
  245. package/src/i3s-converter/json-templates/shared-resources.ts +3 -3
  246. package/src/i3s-converter/types.ts +33 -2
  247. package/src/lib/utils/file-utils.ts +62 -7
  248. package/src/lib/utils/write-queue.ts +42 -19
  249. package/src/pgm-loader.ts +2 -2
  250. package/src/workers/3d-tiles-attributes-worker.ts +1 -1
  251. package/src/workers/i3s-attributes-worker.ts +2 -1
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
@@ -15,13 +38,13 @@ const node_pages_1 = __importDefault(require("./helpers/node-pages"));
15
38
  const file_utils_1 = require("../lib/utils/file-utils");
16
39
  const compress_util_1 = require("../lib/utils/compress-util");
17
40
  const statistic_utills_1 = require("../lib/utils/statistic-utills");
18
- const geometry_converter_1 = __importDefault(require("./helpers/geometry-converter"));
41
+ const geometry_converter_1 = __importStar(require("./helpers/geometry-converter"));
19
42
  const coordinate_converter_1 = require("./helpers/coordinate-converter");
20
43
  const create_scene_server_path_1 = require("./helpers/create-scene-server-path");
21
44
  const lod_conversion_utils_1 = require("../lib/utils/lod-conversion-utils");
22
45
  const pgm_loader_1 = require("../pgm-loader");
23
46
  const layers_1 = require("./json-templates/layers");
24
- const node_1 = require("./json-templates/node");
47
+ const geometry_definitions_1 = require("./json-templates/geometry-definitions");
25
48
  const shared_resources_1 = require("./json-templates/shared-resources");
26
49
  const node_debug_1 = require("./helpers/node-debug");
27
50
  const textures_1 = require("@loaders.gl/textures");
@@ -31,15 +54,13 @@ const draco_1 = require("@loaders.gl/draco");
31
54
  const write_queue_1 = __importDefault(require("../lib/utils/write-queue"));
32
55
  const i3s_attributes_worker_1 = require("../i3s-attributes-worker");
33
56
  const constants_1 = require("../constants");
57
+ const feature_attributes_1 = require("./helpers/feature-attributes");
58
+ const node_index_document_1 = require("./helpers/node-index-document");
34
59
  const ION_DEFAULT_TOKEN = process_1.default.env?.IonToken || // eslint-disable-line
35
60
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlYWMxMzcyYy0zZjJkLTQwODctODNlNi01MDRkZmMzMjIxOWIiLCJpZCI6OTYyMCwic2NvcGVzIjpbImFzbCIsImFzciIsImdjIl0sImlhdCI6MTU2Mjg2NjI3M30.1FNiClUyk00YH_nWfSGpiQAjR5V2OvREDq1PJ5QMjWQ'; // eslint-disable-line
36
61
  const HARDCODED_NODES_PER_PAGE = 64;
37
62
  const _3D_TILES = '3DTILES';
38
63
  const _3D_OBJECT_LAYER_TYPE = '3DObject';
39
- const STRING_TYPE = 'string';
40
- const SHORT_INT_TYPE = 'Int32';
41
- const DOUBLE_TYPE = 'double';
42
- const OBJECT_ID_TYPE = 'OBJECTID';
43
64
  const REFRESH_TOKEN_TIMEOUT = 1800; // 30 minutes in seconds
44
65
  const CESIUM_DATASET_PREFIX = 'https://';
45
66
  // const FS_FILE_TOO_LARGE = 'ERR_FS_FILE_TOO_LARGE';
@@ -56,11 +77,14 @@ class I3SConverter {
56
77
  this.Loader = _3d_tiles_1.Tiles3DLoader;
57
78
  this.workerSource = {};
58
79
  this.writeQueue = new write_queue_1.default();
59
- this.nodePages = new node_pages_1.default(file_utils_1.writeFile, HARDCODED_NODES_PER_PAGE);
80
+ this.compressList = null;
81
+ this.nodePages = new node_pages_1.default(file_utils_1.writeFile, HARDCODED_NODES_PER_PAGE, this);
60
82
  this.options = {};
61
83
  this.layers0Path = '';
62
84
  this.materialMap = new Map();
63
85
  this.materialDefinitions = [];
86
+ this.geometryMap = new Map();
87
+ this.geometryConfigs = [];
64
88
  this.vertexCounter = 0;
65
89
  this.layers0 = null;
66
90
  this.featuresHashArray = [];
@@ -72,6 +96,7 @@ class I3SConverter {
72
96
  this.generateTextures = false;
73
97
  this.generateBoundingVolumes = false;
74
98
  this.layersHasTexture = false;
99
+ this.compressList = null;
75
100
  }
76
101
  /**
77
102
  * Convert a 3d tileset
@@ -86,6 +111,9 @@ class I3SConverter {
86
111
  * @param options.token Token for Cesium ION tilesets authentication
87
112
  * @param options.draco Generate I3S 1.7 draco compressed geometries
88
113
  * @param options.validate -enable validation
114
+ * @param options.generateTextures - generate alternative type of textures (to have non-compressed jpeg/png and compressed ktx2)
115
+ * @param options.generateBoundingVolumes - generate bounding volumes from vertices coordinates instead of source tiles bounding volumes
116
+ * @param options.instantNodeWriting - Keep created 3DNodeIndexDocument files on disk instead of memory. This option reduce memory usage but decelerates conversion speed
89
117
  */
90
118
  async convert(options) {
91
119
  if (core_1.isBrowser) {
@@ -93,8 +121,19 @@ class I3SConverter {
93
121
  return constants_1.BROWSER_ERROR_MESSAGE;
94
122
  }
95
123
  this.conversionStartTime = process_1.default.hrtime();
96
- const { tilesetName, slpk, egmFilePath, inputUrl, validate, outputPath, draco, sevenZipExe, maxDepth, token, generateTextures, generateBoundingVolumes } = options;
97
- this.options = { maxDepth, slpk, sevenZipExe, egmFilePath, draco, token, inputUrl };
124
+ const { tilesetName, slpk, egmFilePath, inputUrl, validate, outputPath, draco = true, sevenZipExe, maxDepth, token, generateTextures, generateBoundingVolumes, instantNodeWriting = false, mergeMaterials = true } = options;
125
+ this.options = {
126
+ maxDepth,
127
+ slpk,
128
+ sevenZipExe,
129
+ egmFilePath,
130
+ draco,
131
+ token,
132
+ inputUrl,
133
+ instantNodeWriting,
134
+ mergeMaterials
135
+ };
136
+ this.compressList = (this.options.instantNodeWriting && []) || null;
98
137
  this.validate = Boolean(validate);
99
138
  this.Loader = inputUrl.indexOf(CESIUM_DATASET_PREFIX) !== -1 ? _3d_tiles_1.CesiumIonLoader : _3d_tiles_1.Tiles3DLoader;
100
139
  this.generateTextures = Boolean(generateTextures);
@@ -110,7 +149,18 @@ class I3SConverter {
110
149
  await this.loadWorkers();
111
150
  try {
112
151
  const preloadOptions = await this._fetchPreloadOptions();
113
- const tilesetOptions = { loadOptions: { basis: { format: 'rgba32' } } };
152
+ const tilesetOptions = {
153
+ loadOptions: {
154
+ _nodeWorkers: true,
155
+ reuseWorkers: true,
156
+ basis: { format: 'rgba32' },
157
+ 'basis-nodejs': {
158
+ format: 'rgba32',
159
+ workerUrl: './modules/textures/dist/basis-nodejs-worker.js'
160
+ },
161
+ 'draco-nodejs': { workerUrl: './modules/draco/dist/draco-nodejs-worker.js' }
162
+ }
163
+ };
114
164
  if (preloadOptions.headers) {
115
165
  tilesetOptions.loadOptions.fetch = { headers: preloadOptions.headers };
116
166
  }
@@ -151,24 +201,30 @@ class I3SConverter {
151
201
  this.materialMap = new Map();
152
202
  const sourceRootTile = this.sourceTileset.root;
153
203
  const boundingVolumes = (0, coordinate_converter_1.createBoundingVolumes)(sourceRootTile, this.geoidHeightModel);
154
- const parentId = this.nodePages.push({
204
+ await this.nodePages.push({
155
205
  index: 0,
156
206
  lodThreshold: 0,
157
207
  obb: boundingVolumes.obb,
158
208
  children: []
159
209
  });
160
- const isCreateSlpk = this.options.slpk;
161
- const root0 = this._formRootNodeIndexDocument(boundingVolumes);
162
- await this._convertNodesTree(root0, sourceRootTile, parentId, boundingVolumes);
210
+ const rootNode = await node_index_document_1.NodeIndexDocument.createRootNode(boundingVolumes, this);
211
+ await this._convertNodesTree(rootNode, sourceRootTile);
163
212
  this.layers0.materialDefinitions = this.materialDefinitions;
213
+ // @ts-ignore
214
+ this.layers0.geometryDefinitions = (0, json_map_transform_1.default)(this.geometryConfigs.map((config) => ({
215
+ geometryConfig: { ...config, draco: this.options.draco }
216
+ })), (0, geometry_definitions_1.GEOMETRY_DEFINITION)());
164
217
  if (this.layersHasTexture === false) {
165
218
  this.layers0.store.defaultGeometrySchema.ordering =
166
219
  this.layers0.store.defaultGeometrySchema.ordering.filter((attribute) => attribute !== 'uv0');
167
220
  }
168
221
  await this._writeLayers0();
169
222
  (0, create_scene_server_path_1.createSceneServerPath)(tilesetName, this.layers0, tilesetPath);
170
- await this._writeNodeIndexDocument(root0, 'root', (0, path_1.join)(this.layers0Path, 'nodes', 'root'));
171
- await this.nodePages.save(this.layers0Path, this.writeQueue, isCreateSlpk);
223
+ for (const filePath of this.compressList || []) {
224
+ await (0, compress_util_1.compressFileWithGzip)(filePath);
225
+ await (0, file_utils_1.removeFile)(filePath);
226
+ }
227
+ await this.nodePages.save();
172
228
  await this.writeQueue.finalize();
173
229
  await this._createSlpk(tilesetPath);
174
230
  }
@@ -200,68 +256,29 @@ class I3SConverter {
200
256
  };
201
257
  this.layers0 = (0, json_map_transform_1.default)(layers0data, (0, layers_1.LAYERS)());
202
258
  }
203
- /**
204
- * Convert and save the layer and embedded tiles
205
- * @param boundingVolumes - mbs and obb data about node's bounding volume
206
- * @return 3DNodeIndexDocument data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
207
- */
208
- _formRootNodeIndexDocument(boundingVolumes) {
209
- const root0data = {
210
- version: `{${(0, uuid_1.v4)().toUpperCase()}}`,
211
- id: 'root',
212
- level: 0,
213
- lodSelection: [
214
- {
215
- metricType: 'maxScreenThresholdSQ',
216
- maxError: 0
217
- },
218
- {
219
- metricType: 'maxScreenThreshold',
220
- maxError: 0
221
- }
222
- ],
223
- ...boundingVolumes,
224
- children: []
225
- };
226
- return (0, json_map_transform_1.default)(root0data, (0, node_1.NODE)());
227
- }
228
259
  /**
229
260
  * Form object of 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
230
- * @param root0 - 3DNodeIndexDocument of root node https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
261
+ * @param rootNode - 3DNodeIndexDocument of root node https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
231
262
  * @param sourceRootTile - Source (3DTile) tile data
232
- * @param parentId - node id in node pages
233
- * @param boundingVolumes - mbs and obb data about node's bounding volume
234
263
  */
235
- async _convertNodesTree(root0, sourceRootTile, parentId, boundingVolumes) {
264
+ async _convertNodesTree(rootNode, sourceRootTile) {
236
265
  await this.sourceTileset._loadTile(sourceRootTile);
237
266
  if (this.isContentSupported(sourceRootTile)) {
238
- root0.children = root0.children || [];
239
- root0.children.push({
240
- id: '1',
241
- href: './1',
242
- ...boundingVolumes
243
- });
244
- const [child] = await this._createNode(root0, sourceRootTile, parentId, 0);
245
- const childPath = (0, path_1.join)(this.layers0Path, 'nodes', child.path);
246
- if (this.options.slpk) {
247
- await this.writeQueue.enqueue({
248
- archiveKey: 'nodes/1/3dNodeIndexDocument.json.gz',
249
- writePromise: (0, file_utils_1.writeFileForSlpk)(childPath, JSON.stringify(child), '3dNodeIndexDocument.json')
250
- });
251
- }
252
- else {
253
- await this.writeQueue.enqueue({ writePromise: (0, file_utils_1.writeFile)(childPath, JSON.stringify(child)) });
267
+ const childNodes = await this._createNode(rootNode, sourceRootTile, 0);
268
+ for (const childNode of childNodes) {
269
+ await childNode.save();
254
270
  }
271
+ await rootNode.addChildren(childNodes);
255
272
  }
256
273
  else {
257
274
  await this._addChildrenWithNeighborsAndWriteFile({
258
- parentNode: root0,
275
+ parentNode: rootNode,
259
276
  sourceTiles: sourceRootTile.children,
260
- parentId,
261
277
  level: 1
262
278
  });
263
279
  }
264
280
  await sourceRootTile.unloadContent();
281
+ await rootNode.save();
265
282
  }
266
283
  /**
267
284
  * Write 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md in file
@@ -270,29 +287,15 @@ class I3SConverter {
270
287
  if (this.options.slpk) {
271
288
  await this.writeQueue.enqueue({
272
289
  archiveKey: '3dSceneLayer.json.gz',
273
- writePromise: (0, file_utils_1.writeFileForSlpk)(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
290
+ writePromise: () => (0, file_utils_1.writeFileForSlpk)(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
274
291
  });
275
292
  }
276
293
  else {
277
294
  await this.writeQueue.enqueue({
278
- writePromise: (0, file_utils_1.writeFile)(this.layers0Path, JSON.stringify(this.layers0))
295
+ writePromise: () => (0, file_utils_1.writeFile)(this.layers0Path, JSON.stringify(this.layers0))
279
296
  });
280
297
  }
281
298
  }
282
- /**
283
- * Write 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md in file
284
- */
285
- async _writeNodeIndexDocument(root0, nodePath, rootPath) {
286
- if (this.options.slpk) {
287
- await this.writeQueue.enqueue({
288
- archiveKey: `nodes/${nodePath}/3dNodeIndexDocument.json.gz`,
289
- writePromise: (0, file_utils_1.writeFileForSlpk)(rootPath, JSON.stringify(root0), '3dNodeIndexDocument.json')
290
- });
291
- }
292
- else {
293
- await this.writeQueue.enqueue({ writePromise: (0, file_utils_1.writeFile)(rootPath, JSON.stringify(root0)) });
294
- }
295
- }
296
299
  /**
297
300
  * Pack files into *.slpk archive
298
301
  * @param tilesetPath - Path to save file
@@ -331,114 +334,101 @@ class I3SConverter {
331
334
  /**
332
335
  * Add child nodes recursively and write them to files
333
336
  * @param data - arguments
337
+ * @param data.parentNode - 3DNodeIndexDocument of parent node
334
338
  * @param data.sourceTiles - array of source child nodes
335
- * @param data.parentNode - 3DNodeIndexDocument of parent node for processing child nodes
336
- * @param data.parentId - id of parent node in node pages
337
339
  * @param data.level - level of node (distanse to root node in the tree)
338
340
  */
339
341
  async _addChildrenWithNeighborsAndWriteFile(data) {
340
- const childNodes = [];
341
- await this._addChildren({ ...data, childNodes });
342
- await this._addNeighborsAndWriteFile(data.parentNode, childNodes);
342
+ await this._addChildren(data);
343
+ await data.parentNode.addNeighbors();
344
+ }
345
+ /**
346
+ * Convert nested subtree of 3DTiles dataset
347
+ * @param param0
348
+ * @param data.parentNode - 3DNodeIndexDocument of parent node
349
+ * @param param0.sourceTile - source 3DTile data
350
+ * @param param0.level - tree level
351
+ */
352
+ async convertNestedTileset({ parentNode, sourceTile, level }) {
353
+ await this.sourceTileset._loadTile(sourceTile);
354
+ await this._addChildren({
355
+ parentNode,
356
+ sourceTiles: sourceTile.children,
357
+ level: level + 1
358
+ });
359
+ await sourceTile.unloadContent();
360
+ }
361
+ /**
362
+ * Convert 3DTiles tile to I3S node
363
+ * @param param0
364
+ * @param param0.parentNode - 3DNodeIndexDocument of parent node
365
+ * @param param0.sourceTile - source 3DTile data
366
+ * @param param0.level - tree level
367
+ */
368
+ async convertNode({ parentNode, sourceTile, level }) {
369
+ const childNodes = await this._createNode(parentNode, sourceTile, level);
370
+ await parentNode.addChildren(childNodes);
343
371
  }
344
372
  /**
345
373
  * Add child nodes recursively and write them to files
346
- * @param data - arguments
347
- * @param data.childNodes - array of target child nodes
348
- * @param data.sourceTiles - array of source child nodes
349
- * @param data.parentNode - 3DNodeIndexDocument of parent node for processing child nodes
350
- * @param data.parentId - id of parent node in node pages
351
- * @param data.level - level of node (distanse to root node in the tree)
374
+ * @param param0 - arguments
375
+ * @param param0.parentNode - 3DNodeIndexDocument of parent node
376
+ * @param param0.sourceTile - source 3DTile data
377
+ * @param param0.level - tree level
352
378
  */
353
379
  async _addChildren(data) {
354
- const { childNodes, sourceTiles, parentNode, parentId, level } = data;
380
+ const { sourceTiles, parentNode, level } = data;
355
381
  if (this.options.maxDepth && level > this.options.maxDepth) {
356
382
  return;
357
383
  }
384
+ const promises = [];
358
385
  for (const sourceTile of sourceTiles) {
359
386
  if (sourceTile.type === 'json') {
360
- await this.sourceTileset._loadTile(sourceTile);
361
- await this._addChildren({
362
- parentNode,
363
- sourceTiles: sourceTile.children,
364
- childNodes,
365
- parentId,
366
- level: level + 1
367
- });
368
- await sourceTile.unloadContent();
387
+ if (this.options.instantNodeWriting) {
388
+ await this.convertNestedTileset({ parentNode, sourceTile, level });
389
+ }
390
+ else {
391
+ promises.push(this.convertNestedTileset({ parentNode, sourceTile, level }));
392
+ }
369
393
  }
370
394
  else {
371
- const children = await this._createNode(parentNode, sourceTile, parentId, level);
372
- parentNode.children = parentNode.children || [];
373
- for (const child of children) {
374
- parentNode.children.push({
375
- id: child.id,
376
- href: `../${child.path}`,
377
- obb: child.obb,
378
- mbs: child.mbs
379
- });
380
- childNodes.push(child);
395
+ if (this.options.instantNodeWriting) {
396
+ await this.convertNode({ parentNode, sourceTile, level });
397
+ }
398
+ else {
399
+ promises.push(this.convertNode({ parentNode, sourceTile, level }));
381
400
  }
382
401
  }
383
402
  if (sourceTile.id) {
384
403
  console.log(sourceTile.id); // eslint-disable-line
385
404
  }
386
405
  }
387
- }
388
- /**
389
- * Add neightbors to 3DNodeIndexDocument and write it in a file
390
- * @param parentNode - arguments
391
- * @param childNodes - array of target child nodes
392
- */
393
- async _addNeighborsAndWriteFile(parentNode, childNodes) {
394
- for (const node of childNodes) {
395
- const childPath = (0, path_1.join)(this.layers0Path, 'nodes', node.path);
396
- const nodePath = node.path;
397
- delete node.path;
398
- // Don't do large amount of "neightbors" to avoid big memory consumption
399
- if (Number(parentNode?.children?.length) < 1000) {
400
- for (const neighbor of parentNode.children || []) {
401
- // eslint-disable-next-line max-depth
402
- if (node.id === neighbor.id) {
403
- continue; // eslint-disable-line
404
- }
405
- if (node.neighbors) {
406
- node.neighbors.push({ ...neighbor });
407
- }
408
- }
409
- }
410
- else {
411
- // eslint-disable-next-line no-console, no-undef
412
- console.warn(`Node ${node.id}: neighbors attribute is omited because of large number of neigbors`);
413
- delete node.neighbors;
414
- }
415
- await this._writeNodeIndexDocument(node, nodePath, childPath);
416
- node.neighbors = [];
417
- }
406
+ await Promise.all(promises);
418
407
  }
419
408
  /**
420
409
  * Convert tile to one or more I3S nodes
421
- * @param parentTile - parent 3DNodeIndexDocument
422
- * @param sourceTile - source tile (3DTile)
423
- * @param parentId - id of parent node in node pages
424
- * @param level - level of node (distanse to root node in the tree)
410
+ * @param parentNode - 3DNodeIndexDocument of parent node
411
+ * @param sourceTile - source 3DTile data
412
+ * @param level - tree level
425
413
  */
426
- async _createNode(parentTile, sourceTile, parentId, level) {
414
+ async _createNode(parentNode, sourceTile, level) {
427
415
  this._checkAddRefinementTypeForTile(sourceTile);
428
416
  await this._updateTilesetOptions();
429
417
  await this.sourceTileset._loadTile(sourceTile);
430
418
  let boundingVolumes = (0, coordinate_converter_1.createBoundingVolumes)(sourceTile, this.geoidHeightModel);
431
- const batchTable = sourceTile?.content?.batchTableJson;
432
- if (batchTable) {
433
- this._convertAttributeStorageInfo(sourceTile.content);
419
+ const propertyTable = (0, geometry_converter_1.getPropertyTable)(sourceTile.content);
420
+ if (propertyTable && !this.layers0?.attributeStorageInfo?.length) {
421
+ this._convertPropertyTableToNodeAttributes(propertyTable);
434
422
  }
435
- const resourcesData = await this._convertResources(sourceTile);
423
+ const resourcesData = await this._convertResources(sourceTile, parentNode.inPageId, propertyTable);
436
424
  const nodes = [];
425
+ const nodeIds = [];
437
426
  const nodesInPage = [];
438
427
  const emptyResources = {
439
428
  geometry: null,
440
429
  compressedGeometry: null,
441
430
  texture: null,
431
+ hasUvRegions: false,
442
432
  sharedResources: null,
443
433
  meshMaterial: null,
444
434
  vertexCount: null,
@@ -453,63 +443,51 @@ class I3SConverter {
453
443
  }
454
444
  const lodSelection = (0, lod_conversion_utils_1.convertGeometricErrorToScreenThreshold)(sourceTile, boundingVolumes);
455
445
  const maxScreenThresholdSQ = lodSelection.find((val) => val.metricType === 'maxScreenThresholdSQ') || { maxError: 0 };
456
- const nodeInPage = this._createNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources);
457
- const node = this._createNodeIndexDocument(parentTile, boundingVolumes, lodSelection, nodeInPage, resources);
446
+ const nodeInPage = await this._updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentNode.inPageId, resources);
447
+ const nodeData = await node_index_document_1.NodeIndexDocument.createNodeIndexDocument(parentNode, boundingVolumes, lodSelection, nodeInPage, resources);
448
+ const node = await new node_index_document_1.NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
449
+ nodes.push(node);
458
450
  if (nodeInPage.mesh) {
459
- await this._writeResources(resources, node.path);
451
+ await this._writeResources(resources, node.id);
460
452
  }
461
453
  if (this.validate) {
462
- this.boundingVolumeWarnings = (0, node_debug_1.validateNodeBoundingVolumes)(node);
454
+ this.boundingVolumeWarnings = (0, node_debug_1.validateNodeBoundingVolumes)(nodeData);
463
455
  if (this.boundingVolumeWarnings && this.boundingVolumeWarnings.length) {
464
456
  console.warn('Bounding Volume Warnings: ', ...this.boundingVolumeWarnings); //eslint-disable-line
465
457
  }
466
458
  }
467
- nodes.push(node);
459
+ nodeIds.push(nodeInPage.index);
468
460
  nodesInPage.push(nodeInPage);
469
461
  }
470
462
  sourceTile.unloadContent();
471
463
  await this._addChildrenWithNeighborsAndWriteFile({
472
464
  parentNode: nodes[0],
473
465
  sourceTiles: sourceTile.children,
474
- parentId: nodesInPage[0].index,
475
466
  level: level + 1
476
467
  });
477
468
  return nodes;
478
469
  }
479
- /**
480
- * Convert attributesStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
481
- * from B3DM batch table
482
- * @param sourceTileContent - tile content of 3DTile
483
- * @return {void}
484
- */
485
- _convertAttributeStorageInfo(sourceTileContent) {
486
- // In legacy b3dm files sometimes sourceTileContent is null.
487
- const batchTable = sourceTileContent && sourceTileContent.batchTableJson;
488
- if (batchTable && !this.layers0?.attributeStorageInfo?.length) {
489
- this._convertBatchTableInfoToNodeAttributes(batchTable);
490
- }
491
- }
492
470
  /**
493
471
  * Convert tile to one or more I3S nodes
494
472
  * @param sourceTile - source tile (3DTile)
495
- * result.geometry - ArrayBuffer with geometry attributes
496
- * result.compressedGeometry - ArrayBuffer with compressed (draco) geometry
497
- * result.texture - texture image
498
- * result.sharedResources - shared resource data object
499
- * result.meshMaterial - PBR-like material object
500
- * result.vertexCount - number of vertices in geometry
501
- * result.attributes - feature attributes
502
- * result.featureCount - number of features
473
+ * @param parentId - id of parent node in node pages
474
+ * @param propertyTable - batch table from b3dm / feature properties from EXT_FEATURE_METADATA
475
+ * @returns - converted node resources
503
476
  */
504
- async _convertResources(sourceTile) {
477
+ async _convertResources(sourceTile, parentId, propertyTable) {
505
478
  if (!this.isContentSupported(sourceTile)) {
506
479
  return null;
507
480
  }
508
- const resourcesData = await (0, geometry_converter_1.default)(sourceTile.content, Number(this.nodePages.nodesCounter), this.featuresHashArray, this.layers0?.attributeStorageInfo, this.options.draco, this.generateBoundingVolumes, this.geoidHeightModel, this.workerSource);
481
+ const draftObb = {
482
+ center: [],
483
+ halfSize: [],
484
+ quaternion: []
485
+ };
486
+ const resourcesData = await (0, geometry_converter_1.default)(sourceTile.content, async () => (await this.nodePages.push({ index: 0, obb: draftObb }, parentId)).index, propertyTable, this.featuresHashArray, this.layers0?.attributeStorageInfo, this.options.draco, this.generateBoundingVolumes, this.options.mergeMaterials, this.geoidHeightModel, this.workerSource);
509
487
  return resourcesData;
510
488
  }
511
489
  /**
512
- * Create a new node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
490
+ * Update node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
513
491
  * in node pages (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/nodePage.cmn.md)
514
492
  * @param maxScreenThresholdSQ - Level of Details (LOD) metric
515
493
  * @param boundingVolumes - Bounding volumes
@@ -520,10 +498,11 @@ class I3SConverter {
520
498
  * @param resources.texture - texture image
521
499
  * @param resources.vertexCount - number of vertices in geometry
522
500
  * @param resources.featureCount - number of features
501
+ * @param resources.geometry - Uint8Array with geometry attributes
523
502
  * @return the node object in node pages
524
503
  */
525
- _createNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources) {
526
- const { meshMaterial, texture, vertexCount, featureCount, geometry } = resources;
504
+ async _updateNodeInNodePages(maxScreenThresholdSQ, boundingVolumes, sourceTile, parentId, resources) {
505
+ const { meshMaterial, texture, vertexCount, featureCount, geometry, hasUvRegions } = resources;
527
506
  const nodeInPage = {
528
507
  index: 0,
529
508
  lodThreshold: maxScreenThresholdSQ.maxError,
@@ -533,7 +512,7 @@ class I3SConverter {
533
512
  if (geometry && this.isContentSupported(sourceTile)) {
534
513
  nodeInPage.mesh = {
535
514
  geometry: {
536
- definition: texture ? 0 : 1,
515
+ definition: this.findOrCreateGeometryDefinition(Boolean(texture), hasUvRegions),
537
516
  resource: 0
538
517
  },
539
518
  attribute: {
@@ -544,69 +523,31 @@ class I3SConverter {
544
523
  }
545
524
  };
546
525
  }
547
- const nodeId = this.nodePages.push(nodeInPage, parentId);
526
+ let nodeId = resources.nodeId;
527
+ let node;
528
+ if (!nodeId) {
529
+ node = await this.nodePages.push(nodeInPage, parentId);
530
+ }
531
+ else {
532
+ node = await this.nodePages.getNodeById(nodeId);
533
+ }
534
+ node_pages_1.default.updateAll(node, nodeInPage);
548
535
  if (meshMaterial) {
549
- this.nodePages.updateMaterialByNodeId(nodeId, this._findOrCreateMaterial(meshMaterial));
536
+ node_pages_1.default.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
550
537
  }
551
538
  if (texture) {
552
539
  const texelCountHint = texture.image.height * texture.image.width;
553
- this.nodePages.updateTexelCountHintByNodeId(nodeId, texelCountHint);
540
+ node_pages_1.default.updateTexelCountHintByNodeId(node, texelCountHint);
554
541
  }
555
542
  if (vertexCount) {
556
543
  this.vertexCounter += vertexCount;
557
- this.nodePages.updateVertexCountByNodeId(nodeId, vertexCount);
544
+ node_pages_1.default.updateVertexCountByNodeId(node, vertexCount);
558
545
  }
559
- this.nodePages.updateNodeAttributeByNodeId(nodeId);
546
+ node_pages_1.default.updateNodeAttributeByNodeId(node);
560
547
  if (featureCount) {
561
- this.nodePages.updateFeatureCountByNodeId(nodeId, featureCount);
562
- }
563
- return nodeInPage;
564
- }
565
- /**
566
- * Create a new node page object in node pages
567
- * @param parentNode - 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md object of the parent node
568
- * @param boundingVolumes - Bounding volumes
569
- * @param lodSelection - Level of Details (LOD) metrics
570
- * @param nodeInPage - corresponding node object in a node page
571
- * @param resources - the node resources data
572
- * @param resources.texture - texture image
573
- * @param resources.attributes - feature attributes
574
- * @return 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md object
575
- */
576
- _createNodeIndexDocument(parentNode, boundingVolumes, lodSelection, nodeInPage, resources) {
577
- const { texture, attributes } = resources;
578
- const nodeId = nodeInPage.index;
579
- const nodeData = {
580
- version: parentNode.version,
581
- id: nodeId.toString(),
582
- path: nodeId.toString(),
583
- level: parentNode.level + 1,
584
- ...boundingVolumes,
585
- lodSelection,
586
- parentNode: {
587
- id: parentNode.id,
588
- href: `../${parentNode.id}`,
589
- mbs: parentNode.mbs,
590
- obb: parentNode.obb
591
- },
592
- children: [],
593
- neighbors: []
594
- };
595
- const node = (0, json_map_transform_1.default)(nodeData, (0, node_1.NODE)());
596
- if (nodeInPage.mesh) {
597
- node.geometryData = [{ href: './geometries/0' }];
598
- node.sharedResource = { href: './shared' };
599
- if (texture) {
600
- node.textureData = [{ href: './textures/0' }, { href: './textures/1' }];
601
- }
602
- if (attributes && attributes.length && this.layers0?.attributeStorageInfo?.length) {
603
- node.attributeData = [];
604
- for (let index = 0; index < attributes.length; index++) {
605
- const folderName = this.layers0.attributeStorageInfo[index].key;
606
- node.attributeData.push({ href: `./attributes/${folderName}/0` });
607
- }
608
- }
548
+ node_pages_1.default.updateFeatureCountByNodeId(node, featureCount);
609
549
  }
550
+ this.nodePages.saveNode(node);
610
551
  return node;
611
552
  }
612
553
  /**
@@ -640,13 +581,13 @@ class I3SConverter {
640
581
  const slpkGeometryPath = (0, path_1.join)(childPath, 'geometries');
641
582
  await this.writeQueue.enqueue({
642
583
  archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
643
- writePromise: (0, file_utils_1.writeFileForSlpk)(slpkGeometryPath, geometryBuffer, '0.bin')
584
+ writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkGeometryPath, geometryBuffer, '0.bin')
644
585
  });
645
586
  }
646
587
  else {
647
588
  const geometryPath = (0, path_1.join)(childPath, 'geometries/0/');
648
589
  await this.writeQueue.enqueue({
649
- writePromise: (0, file_utils_1.writeFile)(geometryPath, geometryBuffer, 'index.bin')
590
+ writePromise: () => (0, file_utils_1.writeFile)(geometryPath, geometryBuffer, 'index.bin')
650
591
  });
651
592
  }
652
593
  if (this.options.draco) {
@@ -654,13 +595,13 @@ class I3SConverter {
654
595
  const slpkCompressedGeometryPath = (0, path_1.join)(childPath, 'geometries');
655
596
  await this.writeQueue.enqueue({
656
597
  archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
657
- writePromise: (0, file_utils_1.writeFileForSlpk)(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
598
+ writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
658
599
  });
659
600
  }
660
601
  else {
661
602
  const compressedGeometryPath = (0, path_1.join)(childPath, 'geometries/1/');
662
603
  await this.writeQueue.enqueue({
663
- writePromise: (0, file_utils_1.writeFile)(compressedGeometryPath, compressedGeometry, 'index.bin')
604
+ writePromise: () => (0, file_utils_1.writeFile)(compressedGeometryPath, compressedGeometry, 'index.bin')
664
605
  });
665
606
  }
666
607
  }
@@ -683,12 +624,12 @@ class I3SConverter {
683
624
  const slpkSharedPath = (0, path_1.join)(childPath, 'shared');
684
625
  await this.writeQueue.enqueue({
685
626
  archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
686
- writePromise: (0, file_utils_1.writeFileForSlpk)(slpkSharedPath, sharedDataStr, 'sharedResource.json')
627
+ writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkSharedPath, sharedDataStr, 'sharedResource.json')
687
628
  });
688
629
  }
689
630
  else {
690
631
  const sharedPath = (0, path_1.join)(childPath, 'shared/');
691
- await this.writeQueue.enqueue({ writePromise: (0, file_utils_1.writeFile)(sharedPath, sharedDataStr) });
632
+ await this.writeQueue.enqueue({ writePromise: () => (0, file_utils_1.writeFile)(sharedPath, sharedDataStr) });
692
633
  }
693
634
  }
694
635
  /**
@@ -709,7 +650,10 @@ class I3SConverter {
709
650
  await this.writeTextureFile(textureData, '0', format, childPath, slpkChildPath);
710
651
  if (this.generateTextures) {
711
652
  formats.push({ name: '1', format: 'ktx2' });
712
- const ktx2TextureData = (0, core_1.encode)(texture.image, textures_1.KTX2BasisWriterWorker, {
653
+ // For Node.js texture.image.data is type of Buffer
654
+ const copyArrayBuffer = texture.image.data.subarray();
655
+ const arrayToEncode = new Uint8Array(copyArrayBuffer);
656
+ const ktx2TextureData = (0, core_1.encode)({ ...texture.image, data: arrayToEncode }, textures_1.KTX2BasisWriterWorker, {
713
657
  ...textures_1.KTX2BasisWriterWorker.options,
714
658
  source: this.workerSource.ktx2,
715
659
  reuseWorkers: true,
@@ -731,6 +675,7 @@ class I3SConverter {
731
675
  }
732
676
  if (!this.layers0.textureSetDefinitions.length) {
733
677
  this.layers0.textureSetDefinitions.push({ formats });
678
+ this.layers0.textureSetDefinitions.push({ formats, atlas: true });
734
679
  }
735
680
  }
736
681
  }
@@ -748,13 +693,13 @@ class I3SConverter {
748
693
  const compress = false;
749
694
  await this.writeQueue.enqueue({
750
695
  archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
751
- writePromise: (0, file_utils_1.writeFileForSlpk)(slpkTexturePath, textureData, `${name}.${format}`, compress)
696
+ writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkTexturePath, textureData, `${name}.${format}`, compress)
752
697
  });
753
698
  }
754
699
  else {
755
700
  const texturePath = (0, path_1.join)(childPath, `textures/${name}/`);
756
701
  await this.writeQueue.enqueue({
757
- writePromise: (0, file_utils_1.writeFile)(texturePath, textureData, `index.${format}`)
702
+ writePromise: () => (0, file_utils_1.writeFile)(texturePath, textureData, `index.${format}`)
758
703
  });
759
704
  }
760
705
  }
@@ -773,13 +718,13 @@ class I3SConverter {
773
718
  const slpkAttributesPath = (0, path_1.join)(childPath, 'attributes', folderName);
774
719
  await this.writeQueue.enqueue({
775
720
  archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
776
- writePromise: (0, file_utils_1.writeFileForSlpk)(slpkAttributesPath, fileBuffer, '0.bin')
721
+ writePromise: () => (0, file_utils_1.writeFileForSlpk)(slpkAttributesPath, fileBuffer, '0.bin')
777
722
  });
778
723
  }
779
724
  else {
780
725
  const attributesPath = (0, path_1.join)(childPath, `attributes/${folderName}/0`);
781
726
  await this.writeQueue.enqueue({
782
- writePromise: (0, file_utils_1.writeFile)(attributesPath, fileBuffer, 'index.bin')
727
+ writePromise: () => (0, file_utils_1.writeFile)(attributesPath, fileBuffer, 'index.bin')
783
728
  });
784
729
  }
785
730
  }
@@ -809,127 +754,46 @@ class I3SConverter {
809
754
  _findOrCreateMaterial(material) {
810
755
  const hash = (0, md5_1.default)(JSON.stringify(material));
811
756
  if (this.materialMap.has(hash)) {
812
- return this.materialMap.get(hash);
757
+ return this.materialMap.get(hash) || 0;
813
758
  }
814
759
  const newMaterialId = this.materialDefinitions.push(material) - 1;
815
760
  this.materialMap.set(hash, newMaterialId);
816
761
  return newMaterialId;
817
762
  }
818
763
  /**
819
- * Generate storage attribute for map segmentation.
820
- * @param attributeIndex - order index of attribute (f_0, f_1 ...).
821
- * @param key - attribute key from batch table.\
822
- * @param attributeType - attribute type.
823
- * @return Updated storageAttribute.
824
- */
825
- _createdStorageAttribute(attributeIndex, key, attributeType) {
826
- const storageAttribute = {
827
- key: `f_${attributeIndex}`,
828
- name: key,
829
- ordering: ['attributeValues'],
830
- header: [{ property: 'count', valueType: 'UInt32' }],
831
- attributeValues: { valueType: 'Int32', valuesPerElement: 1 }
832
- };
833
- switch (attributeType) {
834
- case OBJECT_ID_TYPE:
835
- this._setupIdAttribute(storageAttribute);
836
- break;
837
- case STRING_TYPE:
838
- this._setupStringAttribute(storageAttribute);
839
- break;
840
- case DOUBLE_TYPE:
841
- this._setupDoubleAttribute(storageAttribute);
842
- break;
843
- case SHORT_INT_TYPE:
844
- break;
845
- default:
846
- this._setupStringAttribute(storageAttribute);
847
- }
848
- return storageAttribute;
849
- }
850
- /**
851
- * Get the attribute type for attributeStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
852
- * @param key - attribute's key
853
- * @param attribute - attribute's type in batchTable
764
+ * Get unique geometry configuration index
765
+ * In the end of conversion configurations will be transformed to geometryDefinitions array
766
+ * @param hasTexture
767
+ * @param hasUvRegions
768
+ * @returns
854
769
  */
855
- getAttributeType(key, attribute) {
856
- if (key === OBJECT_ID_TYPE) {
857
- return OBJECT_ID_TYPE;
770
+ findOrCreateGeometryDefinition(hasTexture, hasUvRegions) {
771
+ const geometryConfig = { hasTexture, hasUvRegions };
772
+ const hash = (0, md5_1.default)(JSON.stringify(geometryConfig));
773
+ if (this.geometryMap.has(hash)) {
774
+ return this.geometryMap.get(hash) || 0;
858
775
  }
859
- if (typeof attribute === STRING_TYPE) {
860
- return STRING_TYPE;
861
- }
862
- else if (typeof attribute === 'number') {
863
- return Number.isInteger(attribute) ? SHORT_INT_TYPE : DOUBLE_TYPE;
864
- }
865
- return STRING_TYPE;
866
- }
867
- /**
868
- * Setup storage attribute as string.
869
- * @param storageAttribute - attribute for map segmentation.
870
- */
871
- _setupStringAttribute(storageAttribute) {
872
- storageAttribute.ordering.unshift('attributeByteCounts');
873
- storageAttribute.header.push({ property: 'attributeValuesByteCount', valueType: 'UInt32' });
874
- storageAttribute.attributeValues = {
875
- valueType: 'String',
876
- encoding: 'UTF-8',
877
- valuesPerElement: 1
878
- };
879
- storageAttribute.attributeByteCounts = {
880
- valueType: 'UInt32',
881
- valuesPerElement: 1
882
- };
883
- }
884
- /**
885
- * Setup Id attribute for map segmentation.
886
- * @param storageAttribute - attribute for map segmentation .
887
- */
888
- _setupIdAttribute(storageAttribute) {
889
- storageAttribute.attributeValues = {
890
- valueType: 'Oid32',
891
- valuesPerElement: 1
892
- };
893
- }
894
- /**
895
- * Setup double attribute for map segmentation.
896
- * @param storageAttribute - attribute for map segmentation .
897
- */
898
- _setupDoubleAttribute(storageAttribute) {
899
- storageAttribute.attributeValues = {
900
- valueType: 'Float64',
901
- valuesPerElement: 1
902
- };
776
+ const newGeometryId = this.geometryConfigs.push(geometryConfig) - 1;
777
+ this.geometryMap.set(hash, newGeometryId);
778
+ return newGeometryId;
903
779
  }
904
780
  /**
905
- * Setup field attribute for map segmentation.
906
- * @param key - attribute for map segmentation.
907
- * @param fieldAttributeType - esri attribute type ('esriFieldTypeString' or 'esriFieldTypeOID').
781
+ * Do conversion of 3DTiles property table to I3s node attributes.
782
+ * @param propertyTable - Table with layer meta data.
908
783
  */
909
- _createFieldAttribute(key, fieldAttributeType) {
910
- return {
911
- name: key,
912
- type: fieldAttributeType,
913
- alias: key
914
- };
915
- }
916
- /**
917
- * Do conversion of 3DTiles batch table to I3s node attributes.
918
- * @param batchTable - Table with layer meta data.
919
- */
920
- _convertBatchTableInfoToNodeAttributes(batchTable) {
784
+ _convertPropertyTableToNodeAttributes(propertyTable) {
921
785
  let attributeIndex = 0;
922
- const batchTableWithObjectId = {
786
+ const propertyTableWithObjectId = {
923
787
  OBJECTID: [0],
924
- ...batchTable
788
+ ...propertyTable
925
789
  };
926
- for (const key in batchTableWithObjectId) {
927
- const firstAttribute = batchTableWithObjectId[key][0];
928
- const attributeType = this.getAttributeType(key, firstAttribute);
929
- const storageAttribute = this._createdStorageAttribute(attributeIndex, key, attributeType);
930
- const fieldAttributeType = this._getFieldAttributeType(attributeType);
931
- const fieldAttribute = this._createFieldAttribute(key, fieldAttributeType);
932
- const popupInfo = this._createPopupInfo(batchTableWithObjectId);
790
+ for (const key in propertyTableWithObjectId) {
791
+ const firstAttribute = propertyTableWithObjectId[key][0];
792
+ const attributeType = (0, feature_attributes_1.getAttributeType)(key, firstAttribute);
793
+ const storageAttribute = (0, feature_attributes_1.createdStorageAttribute)(attributeIndex, key, attributeType);
794
+ const fieldAttributeType = (0, feature_attributes_1.getFieldAttributeType)(attributeType);
795
+ const fieldAttribute = (0, feature_attributes_1.createFieldAttribute)(key, fieldAttributeType);
796
+ const popupInfo = (0, feature_attributes_1.createPopupInfo)(propertyTableWithObjectId);
933
797
  this.layers0.attributeStorageInfo.push(storageAttribute);
934
798
  this.layers0.fields.push(fieldAttribute);
935
799
  this.layers0.popupInfo = popupInfo;
@@ -937,55 +801,6 @@ class I3SConverter {
937
801
  attributeIndex += 1;
938
802
  }
939
803
  }
940
- /**
941
- * Find and return attribute type based on key form Batch table.
942
- * @param attributeType
943
- */
944
- _getFieldAttributeType(attributeType) {
945
- switch (attributeType) {
946
- case OBJECT_ID_TYPE:
947
- return 'esriFieldTypeOID';
948
- case STRING_TYPE:
949
- return 'esriFieldTypeString';
950
- case SHORT_INT_TYPE:
951
- return 'esriFieldTypeInteger';
952
- case DOUBLE_TYPE:
953
- return 'esriFieldTypeDouble';
954
- default:
955
- return 'esriFieldTypeString';
956
- }
957
- }
958
- /**
959
- * Generate popup info to show metadata on the map.
960
- * @param batchTable - Batch table data with OBJECTID.
961
- * @return data for correct rendering of popup.
962
- */
963
- _createPopupInfo(batchTable) {
964
- const title = '{OBJECTID}';
965
- const mediaInfos = [];
966
- const fieldInfos = [];
967
- const popupElements = [];
968
- const expressionInfos = [];
969
- for (const key in batchTable) {
970
- fieldInfos.push({
971
- fieldName: key,
972
- visible: true,
973
- isEditable: false,
974
- label: key
975
- });
976
- }
977
- popupElements.push({
978
- fieldInfos,
979
- type: 'fields'
980
- });
981
- return {
982
- title,
983
- mediaInfos,
984
- popupElements,
985
- fieldInfos,
986
- expressionInfos
987
- };
988
- }
989
804
  /**
990
805
  * Print statistics in the end of conversion
991
806
  * @param params - output files data