sdl-mcp 0.12.2 → 0.12.3

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 (276) hide show
  1. package/README.md +10 -0
  2. package/config/sdlmcp.config.example.json +53 -8
  3. package/config/sdlmcp.config.schema.json +530 -106
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/benchmark/external-manifest.d.ts +162 -0
  6. package/dist/benchmark/external-manifest.d.ts.map +1 -0
  7. package/dist/benchmark/external-manifest.js +336 -0
  8. package/dist/benchmark/external-manifest.js.map +1 -0
  9. package/dist/benchmark/external-runner.d.ts +100 -0
  10. package/dist/benchmark/external-runner.d.ts.map +1 -0
  11. package/dist/benchmark/external-runner.js +1171 -0
  12. package/dist/benchmark/external-runner.js.map +1 -0
  13. package/dist/benchmark/output-file.d.ts +3 -0
  14. package/dist/benchmark/output-file.d.ts.map +1 -0
  15. package/dist/benchmark/output-file.js +8 -0
  16. package/dist/benchmark/output-file.js.map +1 -0
  17. package/dist/cli/argParsing.d.ts.map +1 -1
  18. package/dist/cli/argParsing.js +6 -0
  19. package/dist/cli/argParsing.js.map +1 -1
  20. package/dist/cli/commands/benchmark.d.ts.map +1 -1
  21. package/dist/cli/commands/benchmark.js +3 -2
  22. package/dist/cli/commands/benchmark.js.map +1 -1
  23. package/dist/cli/commands/index.d.ts +1 -0
  24. package/dist/cli/commands/index.d.ts.map +1 -1
  25. package/dist/cli/commands/index.js +13 -7
  26. package/dist/cli/commands/index.js.map +1 -1
  27. package/dist/cli/commands/init.d.ts +5 -1
  28. package/dist/cli/commands/init.d.ts.map +1 -1
  29. package/dist/cli/commands/init.js +73 -3
  30. package/dist/cli/commands/init.js.map +1 -1
  31. package/dist/cli/commands/serve.d.ts.map +1 -1
  32. package/dist/cli/commands/serve.js +2 -0
  33. package/dist/cli/commands/serve.js.map +1 -1
  34. package/dist/cli/index.js +2 -0
  35. package/dist/cli/index.js.map +1 -1
  36. package/dist/cli/transport/http.d.ts +1 -35
  37. package/dist/cli/transport/http.d.ts.map +1 -1
  38. package/dist/cli/transport/http.js +151 -175
  39. package/dist/cli/transport/http.js.map +1 -1
  40. package/dist/cli/types.d.ts +1 -0
  41. package/dist/cli/types.d.ts.map +1 -1
  42. package/dist/config/constants.d.ts +30 -0
  43. package/dist/config/constants.d.ts.map +1 -1
  44. package/dist/config/constants.js +30 -0
  45. package/dist/config/constants.js.map +1 -1
  46. package/dist/config/types.d.ts +53 -1
  47. package/dist/config/types.d.ts.map +1 -1
  48. package/dist/config/types.js +62 -14
  49. package/dist/config/types.js.map +1 -1
  50. package/dist/db/ladybug-batching.d.ts +1 -0
  51. package/dist/db/ladybug-batching.d.ts.map +1 -1
  52. package/dist/db/ladybug-batching.js +1 -0
  53. package/dist/db/ladybug-batching.js.map +1 -1
  54. package/dist/db/ladybug-core.d.ts +3 -0
  55. package/dist/db/ladybug-core.d.ts.map +1 -1
  56. package/dist/db/ladybug-core.js +72 -2
  57. package/dist/db/ladybug-core.js.map +1 -1
  58. package/dist/db/ladybug-embeddings.d.ts +6 -1
  59. package/dist/db/ladybug-embeddings.d.ts.map +1 -1
  60. package/dist/db/ladybug-embeddings.js +6 -1
  61. package/dist/db/ladybug-embeddings.js.map +1 -1
  62. package/dist/db/ladybug-file-summaries.d.ts.map +1 -1
  63. package/dist/db/ladybug-file-summaries.js +23 -0
  64. package/dist/db/ladybug-file-summaries.js.map +1 -1
  65. package/dist/db/ladybug-queries.js +1 -1
  66. package/dist/db/ladybug-queries.js.map +1 -1
  67. package/dist/db/migrations/index.d.ts.map +1 -1
  68. package/dist/db/migrations/index.js +2 -0
  69. package/dist/db/migrations/index.js.map +1 -1
  70. package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts +5 -9
  71. package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts.map +1 -1
  72. package/dist/db/migrations/m007-copy-embeddings-to-symbol.js +24 -126
  73. package/dist/db/migrations/m007-copy-embeddings-to-symbol.js.map +1 -1
  74. package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts +5 -0
  75. package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts.map +1 -0
  76. package/dist/db/migrations/m021-remediate-symbol-embeddings.js +7 -0
  77. package/dist/db/migrations/m021-remediate-symbol-embeddings.js.map +1 -0
  78. package/dist/db/migrations/symbol-embedding-remediation.d.ts +57 -0
  79. package/dist/db/migrations/symbol-embedding-remediation.d.ts.map +1 -0
  80. package/dist/db/migrations/symbol-embedding-remediation.js +335 -0
  81. package/dist/db/migrations/symbol-embedding-remediation.js.map +1 -0
  82. package/dist/graph/layout/force-layout.d.ts +4 -0
  83. package/dist/graph/layout/force-layout.d.ts.map +1 -0
  84. package/dist/graph/layout/force-layout.js +127 -0
  85. package/dist/graph/layout/force-layout.js.map +1 -0
  86. package/dist/graph/layout/layout-service.d.ts +37 -0
  87. package/dist/graph/layout/layout-service.d.ts.map +1 -0
  88. package/dist/graph/layout/layout-service.js +172 -0
  89. package/dist/graph/layout/layout-service.js.map +1 -0
  90. package/dist/graph/layout/native-engine.d.ts +9 -0
  91. package/dist/graph/layout/native-engine.d.ts.map +1 -0
  92. package/dist/graph/layout/native-engine.js +59 -0
  93. package/dist/graph/layout/native-engine.js.map +1 -0
  94. package/dist/graph/layout/prng.d.ts +3 -0
  95. package/dist/graph/layout/prng.d.ts.map +1 -0
  96. package/dist/graph/layout/prng.js +19 -0
  97. package/dist/graph/layout/prng.js.map +1 -0
  98. package/dist/graph/layout/serializer.d.ts +3 -0
  99. package/dist/graph/layout/serializer.d.ts.map +1 -0
  100. package/dist/graph/layout/serializer.js +20 -0
  101. package/dist/graph/layout/serializer.js.map +1 -0
  102. package/dist/graph/layout/types.d.ts +30 -0
  103. package/dist/graph/layout/types.d.ts.map +1 -0
  104. package/dist/graph/layout/types.js +2 -0
  105. package/dist/graph/layout/types.js.map +1 -0
  106. package/dist/indexer/embeddings.d.ts +7 -0
  107. package/dist/indexer/embeddings.d.ts.map +1 -1
  108. package/dist/indexer/embeddings.js +44 -4
  109. package/dist/indexer/embeddings.js.map +1 -1
  110. package/dist/indexer/file-summary-embeddings.d.ts +12 -0
  111. package/dist/indexer/file-summary-embeddings.d.ts.map +1 -1
  112. package/dist/indexer/file-summary-embeddings.js +83 -21
  113. package/dist/indexer/file-summary-embeddings.js.map +1 -1
  114. package/dist/indexer/fileWalker.d.ts.map +1 -1
  115. package/dist/indexer/fileWalker.js +2 -1
  116. package/dist/indexer/fileWalker.js.map +1 -1
  117. package/dist/indexer/metrics-updater.d.ts.map +1 -1
  118. package/dist/indexer/metrics-updater.js +27 -4
  119. package/dist/indexer/metrics-updater.js.map +1 -1
  120. package/dist/indexer/watcher.d.ts.map +1 -1
  121. package/dist/indexer/watcher.js +2 -1
  122. package/dist/indexer/watcher.js.map +1 -1
  123. package/dist/mcp/context-response-projection.d.ts.map +1 -1
  124. package/dist/mcp/context-response-projection.js +49 -13
  125. package/dist/mcp/context-response-projection.js.map +1 -1
  126. package/dist/mcp/tools/search-edit/planner.d.ts.map +1 -1
  127. package/dist/mcp/tools/search-edit/planner.js +10 -3
  128. package/dist/mcp/tools/search-edit/planner.js.map +1 -1
  129. package/dist/observability/event-tap.d.ts +2 -1
  130. package/dist/observability/event-tap.d.ts.map +1 -1
  131. package/dist/observability/event-tap.js.map +1 -1
  132. package/dist/observability/service.d.ts +11 -4
  133. package/dist/observability/service.d.ts.map +1 -1
  134. package/dist/observability/service.js +83 -13
  135. package/dist/observability/service.js.map +1 -1
  136. package/dist/observability/types.d.ts +48 -2
  137. package/dist/observability/types.d.ts.map +1 -1
  138. package/dist/ui/.tsbuildinfo +1 -0
  139. package/dist/ui/vendor/fflate.js +2692 -0
  140. package/dist/ui/vendor/jsm/controls/ArcballControls.js +3543 -0
  141. package/dist/ui/vendor/jsm/controls/DragControls.js +452 -0
  142. package/dist/ui/vendor/jsm/controls/FirstPersonControls.js +488 -0
  143. package/dist/ui/vendor/jsm/controls/FlyControls.js +384 -0
  144. package/dist/ui/vendor/jsm/controls/MapControls.js +116 -0
  145. package/dist/ui/vendor/jsm/controls/OrbitControls.js +1963 -0
  146. package/dist/ui/vendor/jsm/controls/PointerLockControls.js +264 -0
  147. package/dist/ui/vendor/jsm/controls/TrackballControls.js +1001 -0
  148. package/dist/ui/vendor/jsm/controls/TransformControls.js +2003 -0
  149. package/dist/ui/vendor/jsm/loaders/3DMLoader.js +1836 -0
  150. package/dist/ui/vendor/jsm/loaders/3MFLoader.js +1621 -0
  151. package/dist/ui/vendor/jsm/loaders/AMFLoader.js +541 -0
  152. package/dist/ui/vendor/jsm/loaders/BVHLoader.js +484 -0
  153. package/dist/ui/vendor/jsm/loaders/ColladaLoader.js +153 -0
  154. package/dist/ui/vendor/jsm/loaders/DDSLoader.js +385 -0
  155. package/dist/ui/vendor/jsm/loaders/DRACOLoader.js +772 -0
  156. package/dist/ui/vendor/jsm/loaders/EXRLoader.js +3395 -0
  157. package/dist/ui/vendor/jsm/loaders/FBXLoader.js +4580 -0
  158. package/dist/ui/vendor/jsm/loaders/FontLoader.js +260 -0
  159. package/dist/ui/vendor/jsm/loaders/GCodeLoader.js +318 -0
  160. package/dist/ui/vendor/jsm/loaders/GLTFLoader.js +4860 -0
  161. package/dist/ui/vendor/jsm/loaders/HDRCubeTextureLoader.js +164 -0
  162. package/dist/ui/vendor/jsm/loaders/HDRLoader.js +463 -0
  163. package/dist/ui/vendor/jsm/loaders/IESLoader.js +379 -0
  164. package/dist/ui/vendor/jsm/loaders/KMZLoader.js +163 -0
  165. package/dist/ui/vendor/jsm/loaders/KTX2Loader.js +1276 -0
  166. package/dist/ui/vendor/jsm/loaders/KTXLoader.js +197 -0
  167. package/dist/ui/vendor/jsm/loaders/LDrawLoader.js +2510 -0
  168. package/dist/ui/vendor/jsm/loaders/LUT3dlLoader.js +205 -0
  169. package/dist/ui/vendor/jsm/loaders/LUTCubeLoader.js +190 -0
  170. package/dist/ui/vendor/jsm/loaders/LUTImageLoader.js +190 -0
  171. package/dist/ui/vendor/jsm/loaders/LWOLoader.js +1051 -0
  172. package/dist/ui/vendor/jsm/loaders/LottieLoader.js +130 -0
  173. package/dist/ui/vendor/jsm/loaders/MD2Loader.js +435 -0
  174. package/dist/ui/vendor/jsm/loaders/MDDLoader.js +147 -0
  175. package/dist/ui/vendor/jsm/loaders/MTLLoader.js +593 -0
  176. package/dist/ui/vendor/jsm/loaders/MaterialXLoader.js +1126 -0
  177. package/dist/ui/vendor/jsm/loaders/NRRDLoader.js +718 -0
  178. package/dist/ui/vendor/jsm/loaders/OBJLoader.js +955 -0
  179. package/dist/ui/vendor/jsm/loaders/PCDLoader.js +620 -0
  180. package/dist/ui/vendor/jsm/loaders/PDBLoader.js +272 -0
  181. package/dist/ui/vendor/jsm/loaders/PLYLoader.js +968 -0
  182. package/dist/ui/vendor/jsm/loaders/PVRLoader.js +270 -0
  183. package/dist/ui/vendor/jsm/loaders/RGBELoader.js +18 -0
  184. package/dist/ui/vendor/jsm/loaders/STLLoader.js +421 -0
  185. package/dist/ui/vendor/jsm/loaders/SVGLoader.js +3319 -0
  186. package/dist/ui/vendor/jsm/loaders/TDSLoader.js +1142 -0
  187. package/dist/ui/vendor/jsm/loaders/TGALoader.js +538 -0
  188. package/dist/ui/vendor/jsm/loaders/TIFFLoader.js +59 -0
  189. package/dist/ui/vendor/jsm/loaders/TTFLoader.js +261 -0
  190. package/dist/ui/vendor/jsm/loaders/USDLoader.js +303 -0
  191. package/dist/ui/vendor/jsm/loaders/USDZLoader.js +16 -0
  192. package/dist/ui/vendor/jsm/loaders/UltraHDRLoader.js +755 -0
  193. package/dist/ui/vendor/jsm/loaders/VOXLoader.js +919 -0
  194. package/dist/ui/vendor/jsm/loaders/VRMLLoader.js +3646 -0
  195. package/dist/ui/vendor/jsm/loaders/VTKLoader.js +1293 -0
  196. package/dist/ui/vendor/jsm/loaders/XYZLoader.js +143 -0
  197. package/dist/ui/vendor/jsm/loaders/collada/ColladaComposer.js +3044 -0
  198. package/dist/ui/vendor/jsm/loaders/collada/ColladaParser.js +1977 -0
  199. package/dist/ui/vendor/jsm/loaders/lwo/IFFParser.js +1217 -0
  200. package/dist/ui/vendor/jsm/loaders/lwo/LWO2Parser.js +414 -0
  201. package/dist/ui/vendor/jsm/loaders/lwo/LWO3Parser.js +373 -0
  202. package/dist/ui/vendor/jsm/loaders/usd/USDAParser.js +901 -0
  203. package/dist/ui/vendor/jsm/loaders/usd/USDCParser.js +1878 -0
  204. package/dist/ui/vendor/jsm/loaders/usd/USDComposer.js +4627 -0
  205. package/dist/ui/vendor/jsm/utils/BufferGeometryUtils.js +1501 -0
  206. package/dist/ui/vendor/jsm/utils/CameraUtils.js +82 -0
  207. package/dist/ui/vendor/jsm/utils/ColorUtils.js +76 -0
  208. package/dist/ui/vendor/jsm/utils/GeometryCompressionUtils.js +547 -0
  209. package/dist/ui/vendor/jsm/utils/GeometryUtils.js +226 -0
  210. package/dist/ui/vendor/jsm/utils/LDrawUtils.js +211 -0
  211. package/dist/ui/vendor/jsm/utils/SceneOptimizer.js +458 -0
  212. package/dist/ui/vendor/jsm/utils/SceneUtils.js +363 -0
  213. package/dist/ui/vendor/jsm/utils/ShadowMapViewer.js +244 -0
  214. package/dist/ui/vendor/jsm/utils/ShadowMapViewerGPU.js +233 -0
  215. package/dist/ui/vendor/jsm/utils/SkeletonUtils.js +496 -0
  216. package/dist/ui/vendor/jsm/utils/SortUtils.js +175 -0
  217. package/dist/ui/vendor/jsm/utils/UVsDebug.js +173 -0
  218. package/dist/ui/vendor/jsm/utils/WebGLTextureUtils.js +115 -0
  219. package/dist/ui/vendor/jsm/utils/WebGPUTextureUtils.js +81 -0
  220. package/dist/ui/vendor/jsm/utils/WorkerPool.js +167 -0
  221. package/dist/ui/vendor/three.core.min.js +6 -0
  222. package/dist/ui/vendor/three.module.min.js +6 -0
  223. package/dist/ui/viewer/ambient.js +39 -0
  224. package/dist/ui/viewer/api.js +93 -0
  225. package/dist/ui/viewer/chrome.js +36 -0
  226. package/dist/ui/viewer/edges.js +33 -0
  227. package/dist/ui/viewer/index.html +32 -0
  228. package/dist/ui/viewer/inspector.js +23 -0
  229. package/dist/ui/viewer/lenses/activity.js +24 -0
  230. package/dist/ui/viewer/lenses/community.js +5 -0
  231. package/dist/ui/viewer/lenses/edges.js +4 -0
  232. package/dist/ui/viewer/lenses/impact.js +6 -0
  233. package/dist/ui/viewer/lenses/search.js +69 -0
  234. package/dist/ui/viewer/lod.js +100 -0
  235. package/dist/ui/viewer/main.js +92 -0
  236. package/dist/ui/viewer/picking.js +45 -0
  237. package/dist/ui/viewer/scene.js +85 -0
  238. package/dist/ui/viewer/skins/default-skin.js +15 -0
  239. package/dist/ui/viewer/skins/loader.js +44 -0
  240. package/dist/ui/viewer/skins/manifest-schema.js +30 -0
  241. package/dist/ui/viewer/state.js +44 -0
  242. package/dist/ui/viewer/theme.js +23 -0
  243. package/dist/ui/viewer/universe.js +151 -0
  244. package/dist/ui/viewer/viewer.css +85 -0
  245. package/dist/util/safeRegex.d.ts.map +1 -1
  246. package/dist/util/safeRegex.js +221 -68
  247. package/dist/util/safeRegex.js.map +1 -1
  248. package/dist/viewer/legacy-graph.d.ts +40 -0
  249. package/dist/viewer/legacy-graph.d.ts.map +1 -0
  250. package/dist/viewer/legacy-graph.js +152 -0
  251. package/dist/viewer/legacy-graph.js.map +1 -0
  252. package/dist/viewer/routes.d.ts +10 -0
  253. package/dist/viewer/routes.d.ts.map +1 -0
  254. package/dist/viewer/routes.js +221 -0
  255. package/dist/viewer/routes.js.map +1 -0
  256. package/dist/viewer/service.d.ts +44 -0
  257. package/dist/viewer/service.d.ts.map +1 -0
  258. package/dist/viewer/service.js +160 -0
  259. package/dist/viewer/service.js.map +1 -0
  260. package/dist/viewer/types.d.ts +63 -0
  261. package/dist/viewer/types.d.ts.map +1 -0
  262. package/dist/viewer/types.js +2 -0
  263. package/dist/viewer/types.js.map +1 -0
  264. package/dist/viewer/viewer-config.d.ts +12 -0
  265. package/dist/viewer/viewer-config.d.ts.map +1 -0
  266. package/dist/viewer/viewer-config.js +36 -0
  267. package/dist/viewer/viewer-config.js.map +1 -0
  268. package/package.json +18 -9
  269. package/templates/SDL.md +19 -0
  270. package/templates/claude-code.json +8 -43
  271. package/dist/ui/graph.css +0 -108
  272. package/dist/ui/graph.d.ts +0 -2
  273. package/dist/ui/graph.d.ts.map +0 -1
  274. package/dist/ui/graph.html +0 -52
  275. package/dist/ui/graph.js +0 -259
  276. package/dist/ui/graph.js.map +0 -1
@@ -0,0 +1,1276 @@
1
+ import {
2
+ CompressedArrayTexture,
3
+ CompressedCubeTexture,
4
+ CompressedTexture,
5
+ Data3DTexture,
6
+ DataTexture,
7
+ FileLoader,
8
+ FloatType,
9
+ HalfFloatType,
10
+ LinearFilter,
11
+ LinearMipmapLinearFilter,
12
+ NearestFilter,
13
+ NearestMipmapNearestFilter,
14
+ LinearSRGBColorSpace,
15
+ Loader,
16
+ NoColorSpace,
17
+ RGBAFormat,
18
+ RGBA_ASTC_4x4_Format,
19
+ RGBA_ASTC_6x6_Format,
20
+ RGBA_BPTC_Format,
21
+ RGBA_ETC2_EAC_Format,
22
+ R11_EAC_Format,
23
+ SIGNED_R11_EAC_Format,
24
+ RG11_EAC_Format,
25
+ SIGNED_RG11_EAC_Format,
26
+ RGBA_PVRTC_4BPPV1_Format,
27
+ RGBA_PVRTC_2BPPV1_Format,
28
+ RGBA_S3TC_DXT1_Format,
29
+ RGBA_S3TC_DXT5_Format,
30
+ RGB_BPTC_UNSIGNED_Format,
31
+ RGB_ETC1_Format,
32
+ RGB_ETC2_Format,
33
+ RGB_PVRTC_4BPPV1_Format,
34
+ RGB_S3TC_DXT1_Format,
35
+ SIGNED_RED_GREEN_RGTC2_Format,
36
+ SIGNED_RED_RGTC1_Format,
37
+ RED_GREEN_RGTC2_Format,
38
+ RED_RGTC1_Format,
39
+ RGBFormat,
40
+ RGFormat,
41
+ RedFormat,
42
+ SRGBColorSpace,
43
+ UnsignedByteType,
44
+ UnsignedInt5999Type,
45
+ UnsignedInt101111Type,
46
+ UnsignedShortType
47
+ } from 'three';
48
+ import { WorkerPool } from '../utils/WorkerPool.js';
49
+ import {
50
+ read,
51
+ KHR_DF_FLAG_ALPHA_PREMULTIPLIED,
52
+ KHR_DF_PRIMARIES_BT709,
53
+ KHR_DF_PRIMARIES_DISPLAYP3,
54
+ KHR_DF_PRIMARIES_UNSPECIFIED,
55
+ KHR_DF_TRANSFER_SRGB,
56
+ KHR_SUPERCOMPRESSION_NONE,
57
+ KHR_SUPERCOMPRESSION_ZSTD,
58
+ VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT,
59
+ VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT,
60
+ VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
61
+ VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
62
+ VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
63
+ VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
64
+ VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
65
+ VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
66
+ VK_FORMAT_BC1_RGB_SRGB_BLOCK,
67
+ VK_FORMAT_BC1_RGB_UNORM_BLOCK,
68
+ VK_FORMAT_BC3_SRGB_BLOCK,
69
+ VK_FORMAT_BC3_UNORM_BLOCK,
70
+ VK_FORMAT_BC4_SNORM_BLOCK,
71
+ VK_FORMAT_BC4_UNORM_BLOCK,
72
+ VK_FORMAT_BC5_SNORM_BLOCK,
73
+ VK_FORMAT_BC5_UNORM_BLOCK,
74
+ VK_FORMAT_BC7_SRGB_BLOCK,
75
+ VK_FORMAT_BC7_UNORM_BLOCK,
76
+ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
77
+ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
78
+ VK_FORMAT_EAC_R11_UNORM_BLOCK,
79
+ VK_FORMAT_EAC_R11_SNORM_BLOCK,
80
+ VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
81
+ VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
82
+ VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
83
+ VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
84
+ VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
85
+ VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
86
+ VK_FORMAT_R16G16B16A16_SFLOAT,
87
+ VK_FORMAT_R16G16B16A16_UNORM,
88
+ VK_FORMAT_R16G16_SFLOAT,
89
+ VK_FORMAT_R16_SFLOAT,
90
+ VK_FORMAT_R32G32B32A32_SFLOAT,
91
+ VK_FORMAT_R32G32_SFLOAT,
92
+ VK_FORMAT_R32_SFLOAT,
93
+ VK_FORMAT_R8G8B8A8_SRGB,
94
+ VK_FORMAT_R8G8B8A8_UNORM,
95
+ VK_FORMAT_R8G8_SRGB,
96
+ VK_FORMAT_R8G8_UNORM,
97
+ VK_FORMAT_R8_SRGB,
98
+ VK_FORMAT_R8_UNORM,
99
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
100
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32,
101
+ VK_FORMAT_UNDEFINED
102
+ } from '../libs/ktx-parse.module.js';
103
+ import { ZSTDDecoder } from '../libs/zstddec.module.js';
104
+ import { DisplayP3ColorSpace, LinearDisplayP3ColorSpace } from '../math/ColorSpaces.js';
105
+
106
+ const WASM_BIN_URL = new URL( '../libs/basis/basis_transcoder.wasm', import.meta.url ).toString();
107
+ const WASM_JS_URL = new URL( '../libs/basis/basis_transcoder.js', import.meta.url ).toString();
108
+
109
+ const _taskCache = new WeakMap();
110
+
111
+ let _activeLoaders = 0;
112
+
113
+ let _zstd;
114
+
115
+ /**
116
+ * A loader for KTX 2.0 GPU Texture containers.
117
+ *
118
+ * KTX 2.0 is a container format for various GPU texture formats. The loader supports Basis Universal GPU textures,
119
+ * which can be quickly transcoded to a wide variety of GPU texture compression formats. While KTX 2.0 also allows
120
+ * other hardware-specific formats, this loader does not yet parse them.
121
+ *
122
+ * This loader parses the KTX 2.0 container and transcodes to a supported GPU compressed texture format.
123
+ * The required WASM transcoder and JS wrapper are available from the `examples/jsm/libs/basis` directory.
124
+ *
125
+ * This loader relies on Web Assembly which is not supported in older browsers.
126
+ *
127
+ * References:
128
+ * - [KTX specification](http://github.khronos.org/KTX-Specification/)
129
+ * - [DFD](https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor)
130
+ * - [BasisU HDR](https://github.com/BinomialLLC/basis_universal/wiki/UASTC-HDR-Texture-Specification-v1.0)
131
+ *
132
+ * ```js
133
+ * const loader = new KTX2Loader();
134
+ * loader.setTranscoderPath( 'examples/jsm/libs/basis/' );
135
+ * loader.detectSupport( renderer );
136
+ * const texture = loader.loadAsync( 'diffuse.ktx2' );
137
+ * ```
138
+ *
139
+ * @augments Loader
140
+ * @three_import import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
141
+ */
142
+ class KTX2Loader extends Loader {
143
+
144
+ /**
145
+ * Constructs a new KTX2 loader.
146
+ *
147
+ * @param {LoadingManager} [manager] - The loading manager.
148
+ */
149
+ constructor( manager ) {
150
+
151
+ super( manager );
152
+
153
+ this.transcoderPath = '';
154
+ this.transcoderBinary = null;
155
+ this.transcoderPending = null;
156
+
157
+ this.workerPool = new WorkerPool();
158
+ this.workerSourceURL = '';
159
+ this.workerConfig = null;
160
+
161
+ if ( typeof MSC_TRANSCODER !== 'undefined' ) {
162
+
163
+ console.warn(
164
+
165
+ 'THREE.KTX2Loader: Please update to latest "basis_transcoder".'
166
+ + ' "msc_basis_transcoder" is no longer supported in three.js r125+.'
167
+
168
+ );
169
+
170
+ }
171
+
172
+ }
173
+
174
+ /**
175
+ * Sets the transcoder path to optionally set the decoder load path from a CDN.
176
+ *
177
+ * By default The WASM transcoder and JS wrapper are loaded from the `examples/jsm/libs/basis` directory.
178
+ *
179
+ * @param {string} path - The transcoder path to set.
180
+ * @return {KTX2Loader} A reference to this loader.
181
+ */
182
+ setTranscoderPath( path ) {
183
+
184
+ this.transcoderPath = path;
185
+
186
+ return this;
187
+
188
+ }
189
+
190
+ /**
191
+ * Sets the maximum number of Web Workers to be allocated by this instance.
192
+ *
193
+ * @param {number} workerLimit - The worker limit.
194
+ * @return {KTX2Loader} A reference to this loader.
195
+ */
196
+ setWorkerLimit( workerLimit ) {
197
+
198
+ this.workerPool.setWorkerLimit( workerLimit );
199
+
200
+ return this;
201
+
202
+ }
203
+
204
+
205
+ /**
206
+ * Async version of {@link KTX2Loader#detectSupport}.
207
+ *
208
+ * @async
209
+ * @deprecated
210
+ * @param {WebGPURenderer} renderer - The renderer.
211
+ * @return {Promise} A Promise that resolves when the support has been detected.
212
+ */
213
+ async detectSupportAsync( renderer ) {
214
+
215
+ console.warn( 'KTX2Loader: "detectSupportAsync()" has been deprecated. Use "detectSupport()" and "await renderer.init();" when creating the renderer.' ); // @deprecated r181
216
+
217
+ await renderer.init();
218
+
219
+ return this.detectSupport( renderer );
220
+
221
+ }
222
+
223
+ /**
224
+ * Detects hardware support for available compressed texture formats, to determine
225
+ * the output format for the transcoder. Must be called before loading a texture.
226
+ *
227
+ * @param {WebGPURenderer|WebGLRenderer} renderer - The renderer.
228
+ * @return {KTX2Loader} A reference to this loader.
229
+ */
230
+ detectSupport( renderer ) {
231
+
232
+ if ( renderer.isWebGPURenderer === true ) {
233
+
234
+ this.workerConfig = {
235
+ astcSupported: renderer.hasFeature( 'texture-compression-astc' ),
236
+ astcHDRSupported: false, // https://github.com/gpuweb/gpuweb/issues/3856
237
+ etc1Supported: renderer.hasFeature( 'texture-compression-etc1' ),
238
+ etc2Supported: renderer.hasFeature( 'texture-compression-etc2' ),
239
+ dxtSupported: renderer.hasFeature( 'texture-compression-s3tc' ),
240
+ bptcSupported: renderer.hasFeature( 'texture-compression-bc' ),
241
+ pvrtcSupported: renderer.hasFeature( 'texture-compression-pvrtc' )
242
+ };
243
+
244
+ } else {
245
+
246
+ this.workerConfig = {
247
+ astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ),
248
+ astcHDRSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' )
249
+ && renderer.extensions.get( 'WEBGL_compressed_texture_astc' ).getSupportedProfiles().includes( 'hdr' ),
250
+ etc1Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc1' ),
251
+ etc2Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc' ),
252
+ dxtSupported: renderer.extensions.has( 'WEBGL_compressed_texture_s3tc' ),
253
+ bptcSupported: renderer.extensions.has( 'EXT_texture_compression_bptc' ),
254
+ pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' )
255
+ || renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
256
+ };
257
+
258
+ if ( typeof navigator !== 'undefined' &&
259
+ typeof navigator.platform !== 'undefined' && typeof navigator.userAgent !== 'undefined' &&
260
+ navigator.platform.indexOf( 'Linux' ) >= 0 && navigator.userAgent.indexOf( 'Android' ) < 0 &&
261
+ this.workerConfig.astcSupported && this.workerConfig.etc2Supported &&
262
+ this.workerConfig.bptcSupported && this.workerConfig.dxtSupported ) {
263
+
264
+ // On Linux, Mesa drivers for AMD and Intel GPUs expose ETC1,ETC2 and ASTC even though the hardware doesn't support these.
265
+ // Using these extensions will result in expensive software decompression on the main thread inside the driver, causing performance issues.
266
+ // In general, browsers should not expose extensions for emulated formats, but Chrome and Firefox currently do so on Linux.
267
+ // Since a granular filter is a little too fragile and we can transcode into other GPU formats, disable formats that are likely to be emulated.
268
+
269
+ this.workerConfig.astcSupported = false;
270
+ this.workerConfig.etc1Supported = false;
271
+ this.workerConfig.etc2Supported = false;
272
+
273
+ }
274
+
275
+ }
276
+
277
+ return this;
278
+
279
+ }
280
+
281
+ // TODO: Make this method private
282
+
283
+ init() {
284
+
285
+ if ( ! this.transcoderPending ) {
286
+
287
+ const jsLoader = new FileLoader( this.manager );
288
+ jsLoader.setWithCredentials( this.withCredentials );
289
+
290
+ const binaryLoader = new FileLoader( this.manager );
291
+ binaryLoader.setWithCredentials( this.withCredentials );
292
+ binaryLoader.setResponseType( 'arraybuffer' );
293
+
294
+ let jsContent, binaryContent;
295
+ if ( this.transcoderPath === '' ) {
296
+
297
+ jsContent = jsLoader.loadAsync( WASM_JS_URL );
298
+ binaryContent = binaryLoader.loadAsync( WASM_BIN_URL );
299
+
300
+ } else {
301
+
302
+ // Load transcoder wrapper.
303
+ jsLoader.setPath( this.transcoderPath );
304
+ jsContent = jsLoader.loadAsync( 'basis_transcoder.js' );
305
+
306
+ // Load transcoder WASM binary.
307
+ binaryLoader.setPath( this.transcoderPath );
308
+ binaryContent = binaryLoader.loadAsync( 'basis_transcoder.wasm' );
309
+
310
+ }
311
+
312
+ this.transcoderPending = Promise.all( [ jsContent, binaryContent ] )
313
+ .then( ( [ jsContent, binaryContent ] ) => {
314
+
315
+ const fn = KTX2Loader.BasisWorker.toString();
316
+
317
+ const body = [
318
+ '/* constants */',
319
+ 'let _EngineFormat = ' + JSON.stringify( KTX2Loader.EngineFormat ),
320
+ 'let _EngineType = ' + JSON.stringify( KTX2Loader.EngineType ),
321
+ 'let _TranscoderFormat = ' + JSON.stringify( KTX2Loader.TranscoderFormat ),
322
+ 'let _BasisFormat = ' + JSON.stringify( KTX2Loader.BasisFormat ),
323
+ '/* basis_transcoder.js */',
324
+ jsContent,
325
+ '/* worker */',
326
+ fn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) )
327
+ ].join( '\n' );
328
+
329
+ this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );
330
+ this.transcoderBinary = binaryContent;
331
+
332
+ this.workerPool.setWorkerCreator( () => {
333
+
334
+ const worker = new Worker( this.workerSourceURL );
335
+ const transcoderBinary = this.transcoderBinary.slice( 0 );
336
+
337
+ worker.postMessage( { type: 'init', config: this.workerConfig, transcoderBinary }, [ transcoderBinary ] );
338
+
339
+ return worker;
340
+
341
+ } );
342
+
343
+ } );
344
+
345
+ if ( _activeLoaders > 0 ) {
346
+
347
+ // Each instance loads a transcoder and allocates workers, increasing network and memory cost.
348
+
349
+ console.warn(
350
+
351
+ 'THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues.'
352
+ + ' Use a single KTX2Loader instance, or call .dispose() on old instances.'
353
+
354
+ );
355
+
356
+ }
357
+
358
+ _activeLoaders ++;
359
+
360
+ }
361
+
362
+ return this.transcoderPending;
363
+
364
+ }
365
+
366
+ /**
367
+ * Starts loading from the given URL and passes the loaded KTX2 texture
368
+ * to the `onLoad()` callback.
369
+ *
370
+ * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
371
+ * @param {function(CompressedTexture)} onLoad - Executed when the loading process has been finished.
372
+ * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
373
+ * @param {onErrorCallback} onError - Executed when errors occur.
374
+ */
375
+ load( url, onLoad, onProgress, onError ) {
376
+
377
+ if ( this.workerConfig === null ) {
378
+
379
+ throw new Error( 'THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.' );
380
+
381
+ }
382
+
383
+ const loader = new FileLoader( this.manager );
384
+
385
+ loader.setPath( this.path );
386
+ loader.setCrossOrigin( this.crossOrigin );
387
+ loader.setWithCredentials( this.withCredentials );
388
+ loader.setRequestHeader( this.requestHeader );
389
+ loader.setResponseType( 'arraybuffer' );
390
+
391
+ loader.load( url, ( buffer ) => {
392
+
393
+ this.parse( buffer, onLoad, onError );
394
+
395
+ }, onProgress, onError );
396
+
397
+ }
398
+
399
+ /**
400
+ * Parses the given KTX2 data.
401
+ *
402
+ * @param {ArrayBuffer} buffer - The raw KTX2 data as an array buffer.
403
+ * @param {function(CompressedTexture)} onLoad - Executed when the loading/parsing process has been finished.
404
+ * @param {onErrorCallback} onError - Executed when errors occur.
405
+ * @returns {Promise} A Promise that resolves when the parsing has been finished.
406
+ */
407
+ parse( buffer, onLoad, onError ) {
408
+
409
+ if ( this.workerConfig === null ) {
410
+
411
+ throw new Error( 'THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.' );
412
+
413
+ }
414
+
415
+ // Check for an existing task using this buffer. A transferred buffer cannot be transferred
416
+ // again from this thread.
417
+ if ( _taskCache.has( buffer ) ) {
418
+
419
+ const cachedTask = _taskCache.get( buffer );
420
+
421
+ return cachedTask.promise.then( onLoad ).catch( onError );
422
+
423
+ }
424
+
425
+ this._createTexture( buffer )
426
+ .then( ( texture ) => onLoad ? onLoad( texture ) : null )
427
+ .catch( onError );
428
+
429
+ }
430
+
431
+ _createTextureFrom( transcodeResult, container ) {
432
+
433
+ const { type: messageType, error, data: { faces, width, height, format, type, dfdFlags } } = transcodeResult;
434
+
435
+ if ( messageType === 'error' ) return Promise.reject( error );
436
+
437
+ let texture;
438
+
439
+ if ( container.faceCount === 6 ) {
440
+
441
+ texture = new CompressedCubeTexture( faces, format, type );
442
+
443
+ } else {
444
+
445
+ const mipmaps = faces[ 0 ].mipmaps;
446
+
447
+ texture = container.layerCount > 1
448
+ ? new CompressedArrayTexture( mipmaps, width, height, container.layerCount, format, type )
449
+ : new CompressedTexture( mipmaps, width, height, format, type );
450
+
451
+ }
452
+
453
+ texture.minFilter = faces[ 0 ].mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
454
+ texture.magFilter = LinearFilter;
455
+ texture.generateMipmaps = false;
456
+
457
+ texture.needsUpdate = true;
458
+ texture.colorSpace = parseColorSpace( container );
459
+ texture.premultiplyAlpha = !! ( dfdFlags & KHR_DF_FLAG_ALPHA_PREMULTIPLIED );
460
+
461
+ return texture;
462
+
463
+ }
464
+
465
+ /**
466
+ * @private
467
+ * @param {ArrayBuffer} buffer
468
+ * @param {?Object} config
469
+ * @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
470
+ */
471
+ async _createTexture( buffer, config = {} ) {
472
+
473
+ const container = read( new Uint8Array( buffer ) );
474
+
475
+ // Basis UASTC HDR is a subset of ASTC, which can be transcoded efficiently
476
+ // to BC6H. To detect whether a KTX2 file uses Basis UASTC HDR, or default
477
+ // ASTC, inspect the DFD color model.
478
+ //
479
+ // Source: https://github.com/BinomialLLC/basis_universal/issues/381
480
+ const isBasisHDR = container.vkFormat === VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT
481
+ && container.dataFormatDescriptor[ 0 ].colorModel === 0xA7;
482
+
483
+ // If the device supports ASTC, Basis UASTC HDR requires no transcoder.
484
+ const needsTranscoder = container.vkFormat === VK_FORMAT_UNDEFINED
485
+ || isBasisHDR && ! this.workerConfig.astcHDRSupported;
486
+
487
+ if ( ! needsTranscoder ) {
488
+
489
+ return createRawTexture( container );
490
+
491
+ }
492
+
493
+ //
494
+ const taskConfig = config;
495
+ const texturePending = this.init().then( () => {
496
+
497
+ return this.workerPool.postMessage( { type: 'transcode', buffer, taskConfig: taskConfig }, [ buffer ] );
498
+
499
+ } ).then( ( e ) => this._createTextureFrom( e.data, container ) );
500
+
501
+ // Cache the task result.
502
+ _taskCache.set( buffer, { promise: texturePending } );
503
+
504
+ return texturePending;
505
+
506
+ }
507
+
508
+ /**
509
+ * Frees internal resources. This method should be called
510
+ * when the loader is no longer required.
511
+ */
512
+ dispose() {
513
+
514
+ this.workerPool.dispose();
515
+ if ( this.workerSourceURL ) URL.revokeObjectURL( this.workerSourceURL );
516
+
517
+ _activeLoaders --;
518
+
519
+ }
520
+
521
+ }
522
+
523
+
524
+ /* CONSTANTS */
525
+
526
+ KTX2Loader.BasisFormat = {
527
+ ETC1S: 0,
528
+ UASTC: 1,
529
+ UASTC_HDR: 2,
530
+ };
531
+
532
+ // Source: https://github.com/BinomialLLC/basis_universal/blob/master/webgl/texture_test/index.html
533
+ KTX2Loader.TranscoderFormat = {
534
+ ETC1: 0,
535
+ ETC2: 1,
536
+ BC1: 2,
537
+ BC3: 3,
538
+ BC4: 4,
539
+ BC5: 5,
540
+ BC7_M6_OPAQUE_ONLY: 6,
541
+ BC7_M5: 7,
542
+ PVRTC1_4_RGB: 8,
543
+ PVRTC1_4_RGBA: 9,
544
+ ASTC_4x4: 10,
545
+ ATC_RGB: 11,
546
+ ATC_RGBA_INTERPOLATED_ALPHA: 12,
547
+ RGBA32: 13,
548
+ RGB565: 14,
549
+ BGR565: 15,
550
+ RGBA4444: 16,
551
+ BC6H: 22,
552
+ RGB_HALF: 24,
553
+ RGBA_HALF: 25,
554
+ };
555
+
556
+ KTX2Loader.EngineFormat = {
557
+ RGBAFormat: RGBAFormat,
558
+ RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
559
+ RGB_BPTC_UNSIGNED_Format: RGB_BPTC_UNSIGNED_Format,
560
+ RGBA_BPTC_Format: RGBA_BPTC_Format,
561
+ RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
562
+ RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
563
+ RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format,
564
+ RGB_ETC1_Format: RGB_ETC1_Format,
565
+ RGB_ETC2_Format: RGB_ETC2_Format,
566
+ RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
567
+ RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format,
568
+ };
569
+
570
+ KTX2Loader.EngineType = {
571
+ UnsignedByteType: UnsignedByteType,
572
+ HalfFloatType: HalfFloatType,
573
+ FloatType: FloatType,
574
+ };
575
+
576
+ /* WEB WORKER */
577
+
578
+ KTX2Loader.BasisWorker = function () {
579
+
580
+ let config;
581
+ let transcoderPending;
582
+ let BasisModule;
583
+
584
+ const EngineFormat = _EngineFormat; // eslint-disable-line no-undef
585
+ const EngineType = _EngineType; // eslint-disable-line no-undef
586
+ const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
587
+ const BasisFormat = _BasisFormat; // eslint-disable-line no-undef
588
+
589
+ self.addEventListener( 'message', function ( e ) {
590
+
591
+ const message = e.data;
592
+
593
+ switch ( message.type ) {
594
+
595
+ case 'init':
596
+ config = message.config;
597
+ init( message.transcoderBinary );
598
+ break;
599
+
600
+ case 'transcode':
601
+ transcoderPending.then( () => {
602
+
603
+ try {
604
+
605
+ const { faces, buffers, width, height, hasAlpha, format, type, dfdFlags } = transcode( message.buffer );
606
+
607
+ self.postMessage( { type: 'transcode', id: message.id, data: { faces, width, height, hasAlpha, format, type, dfdFlags } }, buffers );
608
+
609
+ } catch ( error ) {
610
+
611
+ console.error( error );
612
+
613
+ self.postMessage( { type: 'error', id: message.id, error: error.message } );
614
+
615
+ }
616
+
617
+ } );
618
+ break;
619
+
620
+ }
621
+
622
+ } );
623
+
624
+ function init( wasmBinary ) {
625
+
626
+ transcoderPending = new Promise( ( resolve ) => {
627
+
628
+ BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
629
+ BASIS( BasisModule ); // eslint-disable-line no-undef
630
+
631
+ } ).then( () => {
632
+
633
+ BasisModule.initializeBasis();
634
+
635
+ if ( BasisModule.KTX2File === undefined ) {
636
+
637
+ console.warn( 'THREE.KTX2Loader: Please update Basis Universal transcoder.' );
638
+
639
+ }
640
+
641
+ } );
642
+
643
+ }
644
+
645
+ function transcode( buffer ) {
646
+
647
+ const ktx2File = new BasisModule.KTX2File( new Uint8Array( buffer ) );
648
+
649
+ function cleanup() {
650
+
651
+ ktx2File.close();
652
+ ktx2File.delete();
653
+
654
+ }
655
+
656
+ if ( ! ktx2File.isValid() ) {
657
+
658
+ cleanup();
659
+ throw new Error( 'THREE.KTX2Loader: Invalid or unsupported .ktx2 file' );
660
+
661
+ }
662
+
663
+ let basisFormat;
664
+
665
+ if ( ktx2File.isUASTC() ) {
666
+
667
+ basisFormat = BasisFormat.UASTC;
668
+
669
+ } else if ( ktx2File.isETC1S() ) {
670
+
671
+ basisFormat = BasisFormat.ETC1S;
672
+
673
+ } else if ( ktx2File.isHDR() ) {
674
+
675
+ basisFormat = BasisFormat.UASTC_HDR;
676
+
677
+ } else {
678
+
679
+ throw new Error( 'THREE.KTX2Loader: Unknown Basis encoding' );
680
+
681
+ }
682
+
683
+ const width = ktx2File.getWidth();
684
+ const height = ktx2File.getHeight();
685
+ const layerCount = ktx2File.getLayers() || 1;
686
+ const levelCount = ktx2File.getLevels();
687
+ const faceCount = ktx2File.getFaces();
688
+ const hasAlpha = ktx2File.getHasAlpha();
689
+ const dfdFlags = ktx2File.getDFDFlags();
690
+
691
+ const { transcoderFormat, engineFormat, engineType } = getTranscoderFormat( basisFormat, width, height, hasAlpha );
692
+
693
+ if ( ! width || ! height || ! levelCount ) {
694
+
695
+ cleanup();
696
+ throw new Error( 'THREE.KTX2Loader: Invalid texture' );
697
+
698
+ }
699
+
700
+ if ( ! ktx2File.startTranscoding() ) {
701
+
702
+ cleanup();
703
+ throw new Error( 'THREE.KTX2Loader: .startTranscoding failed' );
704
+
705
+ }
706
+
707
+ const faces = [];
708
+ const buffers = [];
709
+
710
+ for ( let face = 0; face < faceCount; face ++ ) {
711
+
712
+ const mipmaps = [];
713
+
714
+ for ( let mip = 0; mip < levelCount; mip ++ ) {
715
+
716
+ const layerMips = [];
717
+
718
+ let mipWidth, mipHeight;
719
+
720
+ for ( let layer = 0; layer < layerCount; layer ++ ) {
721
+
722
+ const levelInfo = ktx2File.getImageLevelInfo( mip, layer, face );
723
+
724
+ if ( face === 0 && mip === 0 && layer === 0 && ( levelInfo.origWidth % 4 !== 0 || levelInfo.origHeight % 4 !== 0 ) ) {
725
+
726
+ console.warn( 'THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions.' );
727
+
728
+ }
729
+
730
+ if ( levelCount > 1 ) {
731
+
732
+ mipWidth = levelInfo.origWidth;
733
+ mipHeight = levelInfo.origHeight;
734
+
735
+ } else {
736
+
737
+ // Handles non-multiple-of-four dimensions in textures without mipmaps. Textures with
738
+ // mipmaps must use multiple-of-four dimensions, for some texture formats and APIs.
739
+ // See mrdoob/three.js#25908.
740
+ mipWidth = levelInfo.width;
741
+ mipHeight = levelInfo.height;
742
+
743
+ }
744
+
745
+ let dst = new Uint8Array( ktx2File.getImageTranscodedSizeInBytes( mip, layer, 0, transcoderFormat ) );
746
+ const status = ktx2File.transcodeImage( dst, mip, layer, face, transcoderFormat, 0, - 1, - 1 );
747
+
748
+ if ( engineType === EngineType.HalfFloatType ) {
749
+
750
+ dst = new Uint16Array( dst.buffer, dst.byteOffset, dst.byteLength / Uint16Array.BYTES_PER_ELEMENT );
751
+
752
+ }
753
+
754
+ if ( ! status ) {
755
+
756
+ cleanup();
757
+ throw new Error( 'THREE.KTX2Loader: .transcodeImage failed.' );
758
+
759
+ }
760
+
761
+ layerMips.push( dst );
762
+
763
+ }
764
+
765
+ const mipData = concat( layerMips );
766
+
767
+ mipmaps.push( { data: mipData, width: mipWidth, height: mipHeight } );
768
+ buffers.push( mipData.buffer );
769
+
770
+ }
771
+
772
+ faces.push( { mipmaps, width, height, format: engineFormat, type: engineType } );
773
+
774
+ }
775
+
776
+ cleanup();
777
+
778
+ return { faces, buffers, width, height, hasAlpha, dfdFlags, format: engineFormat, type: engineType };
779
+
780
+ }
781
+
782
+ //
783
+
784
+ // Optimal choice of a transcoder target format depends on the Basis format (ETC1S, UASTC, or
785
+ // UASTC HDR), device capabilities, and texture dimensions. The list below ranks the formats
786
+ // separately for each format. Currently, priority is assigned based on:
787
+ //
788
+ // high quality > low quality > uncompressed
789
+ //
790
+ // Prioritization may be revisited, or exposed for configuration, in the future.
791
+ //
792
+ // Reference: https://github.com/KhronosGroup/3D-Formats-Guidelines/blob/main/KTXDeveloperGuide.md
793
+ const FORMAT_OPTIONS = [
794
+ {
795
+ if: 'astcSupported',
796
+ basisFormat: [ BasisFormat.UASTC ],
797
+ transcoderFormat: [ TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4 ],
798
+ engineFormat: [ EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format ],
799
+ engineType: [ EngineType.UnsignedByteType ],
800
+ priorityETC1S: Infinity,
801
+ priorityUASTC: 1,
802
+ needsPowerOfTwo: false,
803
+ },
804
+ {
805
+ if: 'bptcSupported',
806
+ basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC ],
807
+ transcoderFormat: [ TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5 ],
808
+ engineFormat: [ EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format ],
809
+ engineType: [ EngineType.UnsignedByteType ],
810
+ priorityETC1S: 3,
811
+ priorityUASTC: 2,
812
+ needsPowerOfTwo: false,
813
+ },
814
+ {
815
+ if: 'dxtSupported',
816
+ basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC ],
817
+ transcoderFormat: [ TranscoderFormat.BC1, TranscoderFormat.BC3 ],
818
+ engineFormat: [ EngineFormat.RGBA_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format ],
819
+ engineType: [ EngineType.UnsignedByteType ],
820
+ priorityETC1S: 4,
821
+ priorityUASTC: 5,
822
+ needsPowerOfTwo: false,
823
+ },
824
+ {
825
+ if: 'etc2Supported',
826
+ basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC ],
827
+ transcoderFormat: [ TranscoderFormat.ETC1, TranscoderFormat.ETC2 ],
828
+ engineFormat: [ EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format ],
829
+ engineType: [ EngineType.UnsignedByteType ],
830
+ priorityETC1S: 1,
831
+ priorityUASTC: 3,
832
+ needsPowerOfTwo: false,
833
+ },
834
+ {
835
+ if: 'etc1Supported',
836
+ basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC ],
837
+ transcoderFormat: [ TranscoderFormat.ETC1 ],
838
+ engineFormat: [ EngineFormat.RGB_ETC1_Format ],
839
+ engineType: [ EngineType.UnsignedByteType ],
840
+ priorityETC1S: 2,
841
+ priorityUASTC: 4,
842
+ needsPowerOfTwo: false,
843
+ },
844
+ {
845
+ if: 'pvrtcSupported',
846
+ basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC ],
847
+ transcoderFormat: [ TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA ],
848
+ engineFormat: [ EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format ],
849
+ engineType: [ EngineType.UnsignedByteType ],
850
+ priorityETC1S: 5,
851
+ priorityUASTC: 6,
852
+ needsPowerOfTwo: true,
853
+ },
854
+ {
855
+ if: 'bptcSupported',
856
+ basisFormat: [ BasisFormat.UASTC_HDR ],
857
+ transcoderFormat: [ TranscoderFormat.BC6H ],
858
+ engineFormat: [ EngineFormat.RGB_BPTC_UNSIGNED_Format ],
859
+ engineType: [ EngineType.HalfFloatType ],
860
+ priorityHDR: 1,
861
+ needsPowerOfTwo: false,
862
+ },
863
+
864
+ // Uncompressed fallbacks.
865
+
866
+ {
867
+ basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC ],
868
+ transcoderFormat: [ TranscoderFormat.RGBA32, TranscoderFormat.RGBA32 ],
869
+ engineFormat: [ EngineFormat.RGBAFormat, EngineFormat.RGBAFormat ],
870
+ engineType: [ EngineType.UnsignedByteType, EngineType.UnsignedByteType ],
871
+ priorityETC1S: 100,
872
+ priorityUASTC: 100,
873
+ needsPowerOfTwo: false,
874
+ },
875
+ {
876
+ basisFormat: [ BasisFormat.UASTC_HDR ],
877
+ transcoderFormat: [ TranscoderFormat.RGBA_HALF ],
878
+ engineFormat: [ EngineFormat.RGBAFormat ],
879
+ engineType: [ EngineType.HalfFloatType ],
880
+ priorityHDR: 100,
881
+ needsPowerOfTwo: false,
882
+ }
883
+ ];
884
+
885
+ const OPTIONS = {
886
+ [ BasisFormat.ETC1S ]: FORMAT_OPTIONS
887
+ .filter( ( opt ) => opt.basisFormat.includes( BasisFormat.ETC1S ) )
888
+ .sort( ( a, b ) => a.priorityETC1S - b.priorityETC1S ),
889
+
890
+ [ BasisFormat.UASTC ]: FORMAT_OPTIONS
891
+ .filter( ( opt ) => opt.basisFormat.includes( BasisFormat.UASTC ) )
892
+ .sort( ( a, b ) => a.priorityUASTC - b.priorityUASTC ),
893
+
894
+ [ BasisFormat.UASTC_HDR ]: FORMAT_OPTIONS
895
+ .filter( ( opt ) => opt.basisFormat.includes( BasisFormat.UASTC_HDR ) )
896
+ .sort( ( a, b ) => a.priorityHDR - b.priorityHDR ),
897
+ };
898
+
899
+ function getTranscoderFormat( basisFormat, width, height, hasAlpha ) {
900
+
901
+ const options = OPTIONS[ basisFormat ];
902
+
903
+ for ( let i = 0; i < options.length; i ++ ) {
904
+
905
+ const opt = options[ i ];
906
+
907
+ if ( opt.if && ! config[ opt.if ] ) continue;
908
+ if ( ! opt.basisFormat.includes( basisFormat ) ) continue;
909
+ if ( hasAlpha && opt.transcoderFormat.length < 2 ) continue;
910
+ if ( opt.needsPowerOfTwo && ! ( isPowerOfTwo( width ) && isPowerOfTwo( height ) ) ) continue;
911
+
912
+ const transcoderFormat = opt.transcoderFormat[ hasAlpha ? 1 : 0 ];
913
+ const engineFormat = opt.engineFormat[ hasAlpha ? 1 : 0 ];
914
+ const engineType = opt.engineType[ 0 ];
915
+
916
+ return { transcoderFormat, engineFormat, engineType };
917
+
918
+ }
919
+
920
+ throw new Error( 'THREE.KTX2Loader: Failed to identify transcoding target.' );
921
+
922
+ }
923
+
924
+ function isPowerOfTwo( value ) {
925
+
926
+ if ( value <= 2 ) return true;
927
+
928
+ return ( value & ( value - 1 ) ) === 0 && value !== 0;
929
+
930
+ }
931
+
932
+ /**
933
+ * Concatenates N byte arrays.
934
+ *
935
+ * @param {Uint8Array[]} arrays
936
+ * @return {Uint8Array}
937
+ */
938
+ function concat( arrays ) {
939
+
940
+ if ( arrays.length === 1 ) return arrays[ 0 ];
941
+
942
+ let totalByteLength = 0;
943
+
944
+ for ( let i = 0; i < arrays.length; i ++ ) {
945
+
946
+ const array = arrays[ i ];
947
+ totalByteLength += array.byteLength;
948
+
949
+ }
950
+
951
+ const result = new Uint8Array( totalByteLength );
952
+
953
+ let byteOffset = 0;
954
+
955
+ for ( let i = 0; i < arrays.length; i ++ ) {
956
+
957
+ const array = arrays[ i ];
958
+ result.set( array, byteOffset );
959
+
960
+ byteOffset += array.byteLength;
961
+
962
+ }
963
+
964
+ return result;
965
+
966
+ }
967
+
968
+ };
969
+
970
+ // Parsing for non-Basis textures. These textures may have supercompression
971
+ // like Zstd, but they do not require transcoding.
972
+
973
+ const UNCOMPRESSED_FORMATS = new Set( [ RGBAFormat, RGBFormat, RGFormat, RedFormat ] );
974
+
975
+ const NORMALIZED_VK_FORMATS = new Set( [ VK_FORMAT_R16G16B16A16_UNORM ] );
976
+
977
+ const FORMAT_MAP = {
978
+
979
+ [ VK_FORMAT_R32G32B32A32_SFLOAT ]: RGBAFormat,
980
+ [ VK_FORMAT_R32G32_SFLOAT ]: RGFormat,
981
+ [ VK_FORMAT_R32_SFLOAT ]: RedFormat,
982
+
983
+ [ VK_FORMAT_R16G16B16A16_SFLOAT ]: RGBAFormat,
984
+ [ VK_FORMAT_R16G16_SFLOAT ]: RGFormat,
985
+ [ VK_FORMAT_R16_SFLOAT ]: RedFormat,
986
+
987
+ [ VK_FORMAT_R16G16B16A16_UNORM ]: RGBAFormat,
988
+
989
+ [ VK_FORMAT_R8G8B8A8_SRGB ]: RGBAFormat,
990
+ [ VK_FORMAT_R8G8B8A8_UNORM ]: RGBAFormat,
991
+ [ VK_FORMAT_R8G8_SRGB ]: RGFormat,
992
+ [ VK_FORMAT_R8G8_UNORM ]: RGFormat,
993
+ [ VK_FORMAT_R8_SRGB ]: RedFormat,
994
+ [ VK_FORMAT_R8_UNORM ]: RedFormat,
995
+
996
+ [ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 ]: RGBFormat,
997
+ [ VK_FORMAT_B10G11R11_UFLOAT_PACK32 ]: RGBFormat,
998
+
999
+ [ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK ]: RGBA_ETC2_EAC_Format,
1000
+ [ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK ]: RGB_ETC2_Format,
1001
+ [ VK_FORMAT_EAC_R11_UNORM_BLOCK ]: R11_EAC_Format,
1002
+ [ VK_FORMAT_EAC_R11_SNORM_BLOCK ]: SIGNED_R11_EAC_Format,
1003
+ [ VK_FORMAT_EAC_R11G11_UNORM_BLOCK ]: RG11_EAC_Format,
1004
+ [ VK_FORMAT_EAC_R11G11_SNORM_BLOCK ]: SIGNED_RG11_EAC_Format,
1005
+
1006
+ [ VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT ]: RGBA_ASTC_4x4_Format,
1007
+ [ VK_FORMAT_ASTC_4x4_SRGB_BLOCK ]: RGBA_ASTC_4x4_Format,
1008
+ [ VK_FORMAT_ASTC_4x4_UNORM_BLOCK ]: RGBA_ASTC_4x4_Format,
1009
+ [ VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT ]: RGBA_ASTC_6x6_Format,
1010
+ [ VK_FORMAT_ASTC_6x6_SRGB_BLOCK ]: RGBA_ASTC_6x6_Format,
1011
+ [ VK_FORMAT_ASTC_6x6_UNORM_BLOCK ]: RGBA_ASTC_6x6_Format,
1012
+
1013
+ [ VK_FORMAT_BC1_RGBA_SRGB_BLOCK ]: RGBA_S3TC_DXT1_Format,
1014
+ [ VK_FORMAT_BC1_RGBA_UNORM_BLOCK ]: RGBA_S3TC_DXT1_Format,
1015
+ [ VK_FORMAT_BC1_RGB_SRGB_BLOCK ]: RGB_S3TC_DXT1_Format,
1016
+ [ VK_FORMAT_BC1_RGB_UNORM_BLOCK ]: RGB_S3TC_DXT1_Format,
1017
+
1018
+ [ VK_FORMAT_BC3_SRGB_BLOCK ]: RGBA_S3TC_DXT5_Format,
1019
+ [ VK_FORMAT_BC3_UNORM_BLOCK ]: RGBA_S3TC_DXT5_Format,
1020
+
1021
+ [ VK_FORMAT_BC4_SNORM_BLOCK ]: SIGNED_RED_RGTC1_Format,
1022
+ [ VK_FORMAT_BC4_UNORM_BLOCK ]: RED_RGTC1_Format,
1023
+
1024
+ [ VK_FORMAT_BC5_SNORM_BLOCK ]: SIGNED_RED_GREEN_RGTC2_Format,
1025
+ [ VK_FORMAT_BC5_UNORM_BLOCK ]: RED_GREEN_RGTC2_Format,
1026
+
1027
+ [ VK_FORMAT_BC7_SRGB_BLOCK ]: RGBA_BPTC_Format,
1028
+ [ VK_FORMAT_BC7_UNORM_BLOCK ]: RGBA_BPTC_Format,
1029
+
1030
+ [ VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG ]: RGBA_PVRTC_4BPPV1_Format,
1031
+ [ VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG ]: RGBA_PVRTC_4BPPV1_Format,
1032
+ [ VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG ]: RGBA_PVRTC_2BPPV1_Format,
1033
+ [ VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG ]: RGBA_PVRTC_2BPPV1_Format,
1034
+
1035
+ };
1036
+
1037
+ const TYPE_MAP = {
1038
+
1039
+ [ VK_FORMAT_R32G32B32A32_SFLOAT ]: FloatType,
1040
+ [ VK_FORMAT_R32G32_SFLOAT ]: FloatType,
1041
+ [ VK_FORMAT_R32_SFLOAT ]: FloatType,
1042
+
1043
+ [ VK_FORMAT_R16G16B16A16_SFLOAT ]: HalfFloatType,
1044
+ [ VK_FORMAT_R16G16_SFLOAT ]: HalfFloatType,
1045
+ [ VK_FORMAT_R16_SFLOAT ]: HalfFloatType,
1046
+
1047
+ [ VK_FORMAT_R16G16B16A16_UNORM ]: UnsignedShortType,
1048
+
1049
+ [ VK_FORMAT_R8G8B8A8_SRGB ]: UnsignedByteType,
1050
+ [ VK_FORMAT_R8G8B8A8_UNORM ]: UnsignedByteType,
1051
+ [ VK_FORMAT_R8G8_SRGB ]: UnsignedByteType,
1052
+ [ VK_FORMAT_R8G8_UNORM ]: UnsignedByteType,
1053
+ [ VK_FORMAT_R8_SRGB ]: UnsignedByteType,
1054
+ [ VK_FORMAT_R8_UNORM ]: UnsignedByteType,
1055
+
1056
+ [ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 ]: UnsignedInt5999Type,
1057
+ [ VK_FORMAT_B10G11R11_UFLOAT_PACK32 ]: UnsignedInt101111Type,
1058
+
1059
+ [ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK ]: UnsignedByteType,
1060
+ [ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK ]: UnsignedByteType,
1061
+ [ VK_FORMAT_EAC_R11_UNORM_BLOCK ]: UnsignedByteType,
1062
+ [ VK_FORMAT_EAC_R11_SNORM_BLOCK ]: UnsignedByteType,
1063
+ [ VK_FORMAT_EAC_R11G11_UNORM_BLOCK ]: UnsignedByteType,
1064
+ [ VK_FORMAT_EAC_R11G11_SNORM_BLOCK ]: UnsignedByteType,
1065
+
1066
+ [ VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT ]: HalfFloatType,
1067
+ [ VK_FORMAT_ASTC_4x4_SRGB_BLOCK ]: UnsignedByteType,
1068
+ [ VK_FORMAT_ASTC_4x4_UNORM_BLOCK ]: UnsignedByteType,
1069
+ [ VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT ]: HalfFloatType,
1070
+ [ VK_FORMAT_ASTC_6x6_SRGB_BLOCK ]: UnsignedByteType,
1071
+ [ VK_FORMAT_ASTC_6x6_UNORM_BLOCK ]: UnsignedByteType,
1072
+
1073
+ [ VK_FORMAT_BC1_RGBA_SRGB_BLOCK ]: UnsignedByteType,
1074
+ [ VK_FORMAT_BC1_RGBA_UNORM_BLOCK ]: UnsignedByteType,
1075
+ [ VK_FORMAT_BC1_RGB_SRGB_BLOCK ]: UnsignedByteType,
1076
+ [ VK_FORMAT_BC1_RGB_UNORM_BLOCK ]: UnsignedByteType,
1077
+
1078
+ [ VK_FORMAT_BC3_SRGB_BLOCK ]: UnsignedByteType,
1079
+ [ VK_FORMAT_BC3_UNORM_BLOCK ]: UnsignedByteType,
1080
+
1081
+ [ VK_FORMAT_BC4_SNORM_BLOCK ]: UnsignedByteType,
1082
+ [ VK_FORMAT_BC4_UNORM_BLOCK ]: UnsignedByteType,
1083
+
1084
+ [ VK_FORMAT_BC5_SNORM_BLOCK ]: UnsignedByteType,
1085
+ [ VK_FORMAT_BC5_UNORM_BLOCK ]: UnsignedByteType,
1086
+
1087
+ [ VK_FORMAT_BC7_SRGB_BLOCK ]: UnsignedByteType,
1088
+ [ VK_FORMAT_BC7_UNORM_BLOCK ]: UnsignedByteType,
1089
+
1090
+ [ VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG ]: UnsignedByteType,
1091
+ [ VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG ]: UnsignedByteType,
1092
+ [ VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG ]: UnsignedByteType,
1093
+ [ VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG ]: UnsignedByteType,
1094
+
1095
+ };
1096
+
1097
+ async function createRawTexture( container ) {
1098
+
1099
+ const { vkFormat } = container;
1100
+
1101
+ if ( FORMAT_MAP[ vkFormat ] === undefined ) {
1102
+
1103
+ throw new Error( 'THREE.KTX2Loader: Unsupported vkFormat: ' + vkFormat );
1104
+
1105
+ }
1106
+
1107
+ // TODO: Merge the TYPE_MAP warning into the thrown error above, after r190.
1108
+ if ( TYPE_MAP[ vkFormat ] === undefined ) {
1109
+
1110
+ console.warn( 'THREE.KTX2Loader: Missing ".type" for vkFormat: ' + vkFormat );
1111
+
1112
+ }
1113
+
1114
+ //
1115
+
1116
+ let zstd;
1117
+
1118
+ if ( container.supercompressionScheme === KHR_SUPERCOMPRESSION_ZSTD ) {
1119
+
1120
+ if ( ! _zstd ) {
1121
+
1122
+ _zstd = new Promise( async ( resolve ) => {
1123
+
1124
+ const zstd = new ZSTDDecoder();
1125
+ await zstd.init();
1126
+ resolve( zstd );
1127
+
1128
+ } );
1129
+
1130
+ }
1131
+
1132
+ zstd = await _zstd;
1133
+
1134
+ }
1135
+
1136
+ //
1137
+
1138
+ const mipmaps = [];
1139
+
1140
+ for ( let levelIndex = 0; levelIndex < container.levels.length; levelIndex ++ ) {
1141
+
1142
+ const levelWidth = Math.max( 1, container.pixelWidth >> levelIndex );
1143
+ const levelHeight = Math.max( 1, container.pixelHeight >> levelIndex );
1144
+ const levelDepth = container.pixelDepth ? Math.max( 1, container.pixelDepth >> levelIndex ) : 0;
1145
+
1146
+ const level = container.levels[ levelIndex ];
1147
+
1148
+ let levelData;
1149
+
1150
+ if ( container.supercompressionScheme === KHR_SUPERCOMPRESSION_NONE ) {
1151
+
1152
+ levelData = level.levelData;
1153
+
1154
+ } else if ( container.supercompressionScheme === KHR_SUPERCOMPRESSION_ZSTD ) {
1155
+
1156
+ levelData = zstd.decode( level.levelData, level.uncompressedByteLength );
1157
+
1158
+ } else {
1159
+
1160
+ throw new Error( 'THREE.KTX2Loader: Unsupported supercompressionScheme.' );
1161
+
1162
+ }
1163
+
1164
+ let data;
1165
+
1166
+ if ( TYPE_MAP[ vkFormat ] === FloatType ) {
1167
+
1168
+ data = new Float32Array(
1169
+
1170
+ levelData.buffer,
1171
+ levelData.byteOffset,
1172
+ levelData.byteLength / Float32Array.BYTES_PER_ELEMENT
1173
+
1174
+ );
1175
+
1176
+ } else if ( TYPE_MAP[ vkFormat ] === HalfFloatType || TYPE_MAP[ vkFormat ] === UnsignedShortType ) {
1177
+
1178
+ data = new Uint16Array(
1179
+
1180
+ levelData.buffer,
1181
+ levelData.byteOffset,
1182
+ levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT
1183
+
1184
+ );
1185
+
1186
+ } else if ( TYPE_MAP[ vkFormat ] === UnsignedInt5999Type || TYPE_MAP[ vkFormat ] === UnsignedInt101111Type ) {
1187
+
1188
+ data = new Uint32Array(
1189
+
1190
+ levelData.buffer,
1191
+ levelData.byteOffset,
1192
+ levelData.byteLength / Uint32Array.BYTES_PER_ELEMENT
1193
+
1194
+ );
1195
+
1196
+ } else {
1197
+
1198
+ data = levelData;
1199
+
1200
+ }
1201
+
1202
+ mipmaps.push( {
1203
+
1204
+ data: data,
1205
+ width: levelWidth,
1206
+ height: levelHeight,
1207
+ depth: levelDepth,
1208
+
1209
+ } );
1210
+
1211
+ }
1212
+
1213
+ // levelCount = 0 implies runtime-generated mipmaps.
1214
+ const useMipmaps = container.levelCount === 0 || mipmaps.length > 1;
1215
+
1216
+ let texture;
1217
+
1218
+ if ( UNCOMPRESSED_FORMATS.has( FORMAT_MAP[ vkFormat ] ) ) {
1219
+
1220
+ texture = container.pixelDepth === 0
1221
+ ? new DataTexture( mipmaps[ 0 ].data, container.pixelWidth, container.pixelHeight )
1222
+ : new Data3DTexture( mipmaps[ 0 ].data, container.pixelWidth, container.pixelHeight, container.pixelDepth );
1223
+ texture.minFilter = useMipmaps ? NearestMipmapNearestFilter : NearestFilter;
1224
+ texture.magFilter = NearestFilter;
1225
+ texture.generateMipmaps = container.levelCount === 0;
1226
+ texture.normalized = NORMALIZED_VK_FORMATS.has( vkFormat );
1227
+
1228
+ } else {
1229
+
1230
+ if ( container.pixelDepth > 0 ) throw new Error( 'THREE.KTX2Loader: Unsupported pixelDepth.' );
1231
+
1232
+ texture = new CompressedTexture( mipmaps, container.pixelWidth, container.pixelHeight );
1233
+ texture.minFilter = useMipmaps ? LinearMipmapLinearFilter : LinearFilter;
1234
+ texture.magFilter = LinearFilter;
1235
+
1236
+ }
1237
+
1238
+ texture.mipmaps = mipmaps;
1239
+
1240
+ texture.type = TYPE_MAP[ vkFormat ];
1241
+ texture.format = FORMAT_MAP[ vkFormat ];
1242
+ texture.colorSpace = parseColorSpace( container );
1243
+ texture.needsUpdate = true;
1244
+
1245
+ //
1246
+
1247
+ return Promise.resolve( texture );
1248
+
1249
+ }
1250
+
1251
+ function parseColorSpace( container ) {
1252
+
1253
+ const dfd = container.dataFormatDescriptor[ 0 ];
1254
+
1255
+ if ( dfd.colorPrimaries === KHR_DF_PRIMARIES_BT709 ) {
1256
+
1257
+ return dfd.transferFunction === KHR_DF_TRANSFER_SRGB ? SRGBColorSpace : LinearSRGBColorSpace;
1258
+
1259
+ } else if ( dfd.colorPrimaries === KHR_DF_PRIMARIES_DISPLAYP3 ) {
1260
+
1261
+ return dfd.transferFunction === KHR_DF_TRANSFER_SRGB ? DisplayP3ColorSpace : LinearDisplayP3ColorSpace;
1262
+
1263
+ } else if ( dfd.colorPrimaries === KHR_DF_PRIMARIES_UNSPECIFIED ) {
1264
+
1265
+ return NoColorSpace;
1266
+
1267
+ } else {
1268
+
1269
+ console.warn( `THREE.KTX2Loader: Unsupported color primaries, "${ dfd.colorPrimaries }"` );
1270
+ return NoColorSpace;
1271
+
1272
+ }
1273
+
1274
+ }
1275
+
1276
+ export { KTX2Loader };