@babylonjs/loaders 9.13.0 → 9.14.0

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 (489) hide show
  1. package/BVH/bvhFileLoader.d.ts +4 -67
  2. package/BVH/bvhFileLoader.js +6 -130
  3. package/BVH/bvhFileLoader.js.map +1 -1
  4. package/BVH/bvhFileLoader.pure.d.ts +75 -0
  5. package/BVH/bvhFileLoader.pure.js +154 -0
  6. package/BVH/bvhFileLoader.pure.js.map +1 -0
  7. package/BVH/bvhFileLoader.types.d.ts +11 -0
  8. package/BVH/bvhFileLoader.types.js +2 -0
  9. package/BVH/bvhFileLoader.types.js.map +1 -0
  10. package/BVH/pure.d.ts +3 -0
  11. package/BVH/pure.js +5 -0
  12. package/BVH/pure.js.map +1 -0
  13. package/FBX/fbxFileLoader.d.ts +4 -192
  14. package/FBX/fbxFileLoader.js +6 -2437
  15. package/FBX/fbxFileLoader.js.map +1 -1
  16. package/FBX/fbxFileLoader.pure.d.ts +190 -0
  17. package/FBX/fbxFileLoader.pure.js +2451 -0
  18. package/FBX/fbxFileLoader.pure.js.map +1 -0
  19. package/FBX/fbxFileLoader.types.d.ts +11 -0
  20. package/FBX/fbxFileLoader.types.js +2 -0
  21. package/FBX/fbxFileLoader.types.js.map +1 -0
  22. package/FBX/pure.d.ts +3 -0
  23. package/FBX/pure.js +4 -0
  24. package/FBX/pure.js.map +1 -0
  25. package/OBJ/objFileLoader.d.ts +4 -134
  26. package/OBJ/objFileLoader.js +6 -315
  27. package/OBJ/objFileLoader.js.map +1 -1
  28. package/OBJ/objFileLoader.pure.d.ts +132 -0
  29. package/OBJ/objFileLoader.pure.js +329 -0
  30. package/OBJ/objFileLoader.pure.js.map +1 -0
  31. package/OBJ/objFileLoader.types.d.ts +11 -0
  32. package/OBJ/objFileLoader.types.js +2 -0
  33. package/OBJ/objFileLoader.types.js.map +1 -0
  34. package/OBJ/pure.d.ts +5 -0
  35. package/OBJ/pure.js +6 -0
  36. package/OBJ/pure.js.map +1 -0
  37. package/OBJ/solidParser.js +4 -3
  38. package/OBJ/solidParser.js.map +1 -1
  39. package/SPLAT/gaussianSplattingBlockAllocator.d.ts +137 -0
  40. package/SPLAT/gaussianSplattingBlockAllocator.js +555 -0
  41. package/SPLAT/gaussianSplattingBlockAllocator.js.map +1 -0
  42. package/SPLAT/gaussianSplattingDownloadManager.d.ts +109 -0
  43. package/SPLAT/gaussianSplattingDownloadManager.js +241 -0
  44. package/SPLAT/gaussianSplattingDownloadManager.js.map +1 -0
  45. package/SPLAT/gaussianSplattingResidencyController.d.ts +133 -0
  46. package/SPLAT/gaussianSplattingResidencyController.js +222 -0
  47. package/SPLAT/gaussianSplattingResidencyController.js.map +1 -0
  48. package/SPLAT/gaussianSplattingStream.d.ts +122 -4
  49. package/SPLAT/gaussianSplattingStream.js +413 -42
  50. package/SPLAT/gaussianSplattingStream.js.map +1 -1
  51. package/SPLAT/gaussianSplattingWorkBuffer.d.ts +36 -0
  52. package/SPLAT/gaussianSplattingWorkBuffer.js +125 -13
  53. package/SPLAT/gaussianSplattingWorkBuffer.js.map +1 -1
  54. package/SPLAT/gaussianSplattingWorkBufferShaders.d.ts +15 -0
  55. package/SPLAT/gaussianSplattingWorkBufferShaders.js +82 -0
  56. package/SPLAT/gaussianSplattingWorkBufferShaders.js.map +1 -1
  57. package/SPLAT/pure.d.ts +5 -0
  58. package/SPLAT/pure.js +7 -0
  59. package/SPLAT/pure.js.map +1 -0
  60. package/SPLAT/sog.d.ts +1 -97
  61. package/SPLAT/sog.js +1 -501
  62. package/SPLAT/sog.js.map +1 -1
  63. package/SPLAT/sog.pure.d.ts +102 -0
  64. package/SPLAT/sog.pure.js +514 -0
  65. package/SPLAT/sog.pure.js.map +1 -0
  66. package/SPLAT/splatFileLoader.d.ts +5 -106
  67. package/SPLAT/splatFileLoader.js +9 -636
  68. package/SPLAT/splatFileLoader.js.map +1 -1
  69. package/SPLAT/splatFileLoader.pure.d.ts +104 -0
  70. package/SPLAT/splatFileLoader.pure.js +650 -0
  71. package/SPLAT/splatFileLoader.pure.js.map +1 -0
  72. package/SPLAT/splatFileLoader.types.d.ts +11 -0
  73. package/SPLAT/splatFileLoader.types.js +2 -0
  74. package/SPLAT/splatFileLoader.types.js.map +1 -0
  75. package/STL/pure.d.ts +2 -0
  76. package/STL/pure.js +3 -0
  77. package/STL/pure.js.map +1 -0
  78. package/STL/stlFileLoader.d.ts +5 -76
  79. package/STL/stlFileLoader.js +7 -236
  80. package/STL/stlFileLoader.js.map +1 -1
  81. package/STL/stlFileLoader.pure.d.ts +73 -0
  82. package/STL/stlFileLoader.pure.js +249 -0
  83. package/STL/stlFileLoader.pure.js.map +1 -0
  84. package/STL/stlFileLoader.types.d.ts +10 -0
  85. package/STL/stlFileLoader.types.js +2 -0
  86. package/STL/stlFileLoader.types.js.map +1 -0
  87. package/glTF/1.0/pure.d.ts +3 -0
  88. package/glTF/1.0/pure.js +4 -0
  89. package/glTF/1.0/pure.js.map +1 -0
  90. package/glTF/2.0/Extensions/EXT_lights_area.d.ts +4 -39
  91. package/glTF/2.0/Extensions/EXT_lights_area.js +6 -91
  92. package/glTF/2.0/Extensions/EXT_lights_area.js.map +1 -1
  93. package/glTF/2.0/Extensions/EXT_lights_area.pure.d.ts +38 -0
  94. package/glTF/2.0/Extensions/EXT_lights_area.pure.js +106 -0
  95. package/glTF/2.0/Extensions/EXT_lights_area.pure.js.map +1 -0
  96. package/glTF/2.0/Extensions/EXT_lights_area.types.d.ts +9 -0
  97. package/glTF/2.0/Extensions/EXT_lights_area.types.js +2 -0
  98. package/glTF/2.0/Extensions/EXT_lights_area.types.js.map +1 -0
  99. package/glTF/2.0/Extensions/EXT_lights_ies.d.ts +4 -39
  100. package/glTF/2.0/Extensions/EXT_lights_ies.js +6 -81
  101. package/glTF/2.0/Extensions/EXT_lights_ies.js.map +1 -1
  102. package/glTF/2.0/Extensions/EXT_lights_ies.pure.d.ts +38 -0
  103. package/glTF/2.0/Extensions/EXT_lights_ies.pure.js +96 -0
  104. package/glTF/2.0/Extensions/EXT_lights_ies.pure.js.map +1 -0
  105. package/glTF/2.0/Extensions/EXT_lights_ies.types.d.ts +9 -0
  106. package/glTF/2.0/Extensions/EXT_lights_ies.types.js +2 -0
  107. package/glTF/2.0/Extensions/EXT_lights_ies.types.js.map +1 -0
  108. package/glTF/2.0/Extensions/EXT_lights_image_based.d.ts +4 -46
  109. package/glTF/2.0/Extensions/EXT_lights_image_based.js +6 -113
  110. package/glTF/2.0/Extensions/EXT_lights_image_based.js.map +1 -1
  111. package/glTF/2.0/Extensions/EXT_lights_image_based.pure.d.ts +37 -0
  112. package/glTF/2.0/Extensions/EXT_lights_image_based.pure.js +128 -0
  113. package/glTF/2.0/Extensions/EXT_lights_image_based.pure.js.map +1 -0
  114. package/glTF/2.0/Extensions/EXT_lights_image_based.types.d.ts +17 -0
  115. package/glTF/2.0/Extensions/EXT_lights_image_based.types.js +2 -0
  116. package/glTF/2.0/Extensions/EXT_lights_image_based.types.js.map +1 -0
  117. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.d.ts +5 -37
  118. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +7 -92
  119. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -1
  120. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.d.ts +35 -0
  121. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.js +106 -0
  122. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.js.map +1 -0
  123. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.types.d.ts +9 -0
  124. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.types.js +2 -0
  125. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.types.js.map +1 -0
  126. package/glTF/2.0/Extensions/EXT_meshopt_compression.d.ts +4 -37
  127. package/glTF/2.0/Extensions/EXT_meshopt_compression.js +6 -48
  128. package/glTF/2.0/Extensions/EXT_meshopt_compression.js.map +1 -1
  129. package/glTF/2.0/Extensions/EXT_meshopt_compression.pure.d.ts +36 -0
  130. package/glTF/2.0/Extensions/EXT_meshopt_compression.pure.js +63 -0
  131. package/glTF/2.0/Extensions/EXT_meshopt_compression.pure.js.map +1 -0
  132. package/glTF/2.0/Extensions/EXT_meshopt_compression.types.d.ts +9 -0
  133. package/glTF/2.0/Extensions/EXT_meshopt_compression.types.js +2 -0
  134. package/glTF/2.0/Extensions/EXT_meshopt_compression.types.js.map +1 -0
  135. package/glTF/2.0/Extensions/EXT_texture_avif.d.ts +4 -32
  136. package/glTF/2.0/Extensions/EXT_texture_avif.js +6 -36
  137. package/glTF/2.0/Extensions/EXT_texture_avif.js.map +1 -1
  138. package/glTF/2.0/Extensions/EXT_texture_avif.pure.d.ts +31 -0
  139. package/glTF/2.0/Extensions/EXT_texture_avif.pure.js +51 -0
  140. package/glTF/2.0/Extensions/EXT_texture_avif.pure.js.map +1 -0
  141. package/glTF/2.0/Extensions/EXT_texture_avif.types.d.ts +9 -0
  142. package/glTF/2.0/Extensions/EXT_texture_avif.types.js +2 -0
  143. package/glTF/2.0/Extensions/EXT_texture_avif.types.js.map +1 -0
  144. package/glTF/2.0/Extensions/EXT_texture_webp.d.ts +4 -31
  145. package/glTF/2.0/Extensions/EXT_texture_webp.js +6 -35
  146. package/glTF/2.0/Extensions/EXT_texture_webp.js.map +1 -1
  147. package/glTF/2.0/Extensions/EXT_texture_webp.pure.d.ts +30 -0
  148. package/glTF/2.0/Extensions/EXT_texture_webp.pure.js +50 -0
  149. package/glTF/2.0/Extensions/EXT_texture_webp.pure.js.map +1 -0
  150. package/glTF/2.0/Extensions/EXT_texture_webp.types.d.ts +9 -0
  151. package/glTF/2.0/Extensions/EXT_texture_webp.types.js +2 -0
  152. package/glTF/2.0/Extensions/EXT_texture_webp.types.js.map +1 -0
  153. package/glTF/2.0/Extensions/ExtrasAsMetadata.d.ts +4 -51
  154. package/glTF/2.0/Extensions/ExtrasAsMetadata.js +6 -71
  155. package/glTF/2.0/Extensions/ExtrasAsMetadata.js.map +1 -1
  156. package/glTF/2.0/Extensions/ExtrasAsMetadata.pure.d.ts +50 -0
  157. package/glTF/2.0/Extensions/ExtrasAsMetadata.pure.js +85 -0
  158. package/glTF/2.0/Extensions/ExtrasAsMetadata.pure.js.map +1 -0
  159. package/glTF/2.0/Extensions/ExtrasAsMetadata.types.d.ts +9 -0
  160. package/glTF/2.0/Extensions/ExtrasAsMetadata.types.js +2 -0
  161. package/glTF/2.0/Extensions/ExtrasAsMetadata.types.js.map +1 -0
  162. package/glTF/2.0/Extensions/KHR_animation_pointer.d.ts +5 -45
  163. package/glTF/2.0/Extensions/KHR_animation_pointer.js +7 -75
  164. package/glTF/2.0/Extensions/KHR_animation_pointer.js.map +1 -1
  165. package/glTF/2.0/Extensions/KHR_animation_pointer.pure.d.ts +43 -0
  166. package/glTF/2.0/Extensions/KHR_animation_pointer.pure.js +89 -0
  167. package/glTF/2.0/Extensions/KHR_animation_pointer.pure.js.map +1 -0
  168. package/glTF/2.0/Extensions/KHR_animation_pointer.types.d.ts +9 -0
  169. package/glTF/2.0/Extensions/KHR_animation_pointer.types.js +2 -0
  170. package/glTF/2.0/Extensions/KHR_animation_pointer.types.js.map +1 -0
  171. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.d.ts +4 -45
  172. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js +6 -90
  173. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js.map +1 -1
  174. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.d.ts +44 -0
  175. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.js +105 -0
  176. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.js.map +1 -0
  177. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.types.d.ts +9 -0
  178. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.types.js +2 -0
  179. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.types.js.map +1 -0
  180. package/glTF/2.0/Extensions/KHR_interactivity/pure.d.ts +4 -0
  181. package/glTF/2.0/Extensions/KHR_interactivity/pure.js +5 -0
  182. package/glTF/2.0/Extensions/KHR_interactivity/pure.js.map +1 -0
  183. package/glTF/2.0/Extensions/KHR_interactivity.d.ts +4 -36
  184. package/glTF/2.0/Extensions/KHR_interactivity.js +6 -148
  185. package/glTF/2.0/Extensions/KHR_interactivity.js.map +1 -1
  186. package/glTF/2.0/Extensions/KHR_interactivity.pure.d.ts +35 -0
  187. package/glTF/2.0/Extensions/KHR_interactivity.pure.js +163 -0
  188. package/glTF/2.0/Extensions/KHR_interactivity.pure.js.map +1 -0
  189. package/glTF/2.0/Extensions/KHR_interactivity.types.d.ts +9 -0
  190. package/glTF/2.0/Extensions/KHR_interactivity.types.js +2 -0
  191. package/glTF/2.0/Extensions/KHR_interactivity.types.js.map +1 -0
  192. package/glTF/2.0/Extensions/KHR_lights_punctual.d.ts +4 -39
  193. package/glTF/2.0/Extensions/KHR_lights_punctual.js +6 -89
  194. package/glTF/2.0/Extensions/KHR_lights_punctual.js.map +1 -1
  195. package/glTF/2.0/Extensions/KHR_lights_punctual.pure.d.ts +38 -0
  196. package/glTF/2.0/Extensions/KHR_lights_punctual.pure.js +104 -0
  197. package/glTF/2.0/Extensions/KHR_lights_punctual.pure.js.map +1 -0
  198. package/glTF/2.0/Extensions/KHR_lights_punctual.types.d.ts +9 -0
  199. package/glTF/2.0/Extensions/KHR_lights_punctual.types.js +2 -0
  200. package/glTF/2.0/Extensions/KHR_lights_punctual.types.js.map +1 -0
  201. package/glTF/2.0/Extensions/KHR_materials_anisotropy.d.ts +4 -40
  202. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js +6 -63
  203. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js.map +1 -1
  204. package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.d.ts +39 -0
  205. package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.js +78 -0
  206. package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.js.map +1 -0
  207. package/glTF/2.0/Extensions/KHR_materials_anisotropy.types.d.ts +9 -0
  208. package/glTF/2.0/Extensions/KHR_materials_anisotropy.types.js +2 -0
  209. package/glTF/2.0/Extensions/KHR_materials_anisotropy.types.js.map +1 -0
  210. package/glTF/2.0/Extensions/KHR_materials_clearcoat.d.ts +4 -41
  211. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js +6 -77
  212. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js.map +1 -1
  213. package/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.d.ts +40 -0
  214. package/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.js +92 -0
  215. package/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.js.map +1 -0
  216. package/glTF/2.0/Extensions/KHR_materials_clearcoat.types.d.ts +9 -0
  217. package/glTF/2.0/Extensions/KHR_materials_clearcoat.types.js +2 -0
  218. package/glTF/2.0/Extensions/KHR_materials_clearcoat.types.js.map +1 -0
  219. package/glTF/2.0/Extensions/KHR_materials_coat.d.ts +4 -47
  220. package/glTF/2.0/Extensions/KHR_materials_coat.js +6 -117
  221. package/glTF/2.0/Extensions/KHR_materials_coat.js.map +1 -1
  222. package/glTF/2.0/Extensions/KHR_materials_coat.pure.d.ts +46 -0
  223. package/glTF/2.0/Extensions/KHR_materials_coat.pure.js +132 -0
  224. package/glTF/2.0/Extensions/KHR_materials_coat.pure.js.map +1 -0
  225. package/glTF/2.0/Extensions/KHR_materials_coat.types.d.ts +9 -0
  226. package/glTF/2.0/Extensions/KHR_materials_coat.types.js +2 -0
  227. package/glTF/2.0/Extensions/KHR_materials_coat.types.js.map +1 -0
  228. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.d.ts +4 -41
  229. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.js +6 -56
  230. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.js.map +1 -1
  231. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.d.ts +40 -0
  232. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.js +71 -0
  233. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.js.map +1 -0
  234. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.types.d.ts +9 -0
  235. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.types.js +2 -0
  236. package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.types.js.map +1 -0
  237. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.d.ts +4 -41
  238. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +6 -71
  239. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -1
  240. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.d.ts +40 -0
  241. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.js +86 -0
  242. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.js.map +1 -0
  243. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.types.d.ts +9 -0
  244. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.types.js +2 -0
  245. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.types.js.map +1 -0
  246. package/glTF/2.0/Extensions/KHR_materials_dispersion.d.ts +4 -41
  247. package/glTF/2.0/Extensions/KHR_materials_dispersion.js +6 -54
  248. package/glTF/2.0/Extensions/KHR_materials_dispersion.js.map +1 -1
  249. package/glTF/2.0/Extensions/KHR_materials_dispersion.pure.d.ts +40 -0
  250. package/glTF/2.0/Extensions/KHR_materials_dispersion.pure.js +69 -0
  251. package/glTF/2.0/Extensions/KHR_materials_dispersion.pure.js.map +1 -0
  252. package/glTF/2.0/Extensions/KHR_materials_dispersion.types.d.ts +9 -0
  253. package/glTF/2.0/Extensions/KHR_materials_dispersion.types.js +2 -0
  254. package/glTF/2.0/Extensions/KHR_materials_dispersion.types.js.map +1 -0
  255. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.d.ts +4 -40
  256. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js +6 -45
  257. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js.map +1 -1
  258. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.d.ts +39 -0
  259. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.js +60 -0
  260. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.js.map +1 -0
  261. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.types.d.ts +9 -0
  262. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.types.js +2 -0
  263. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.types.js.map +1 -0
  264. package/glTF/2.0/Extensions/KHR_materials_fuzz.d.ts +4 -41
  265. package/glTF/2.0/Extensions/KHR_materials_fuzz.js +6 -75
  266. package/glTF/2.0/Extensions/KHR_materials_fuzz.js.map +1 -1
  267. package/glTF/2.0/Extensions/KHR_materials_fuzz.pure.d.ts +40 -0
  268. package/glTF/2.0/Extensions/KHR_materials_fuzz.pure.js +90 -0
  269. package/glTF/2.0/Extensions/KHR_materials_fuzz.pure.js.map +1 -0
  270. package/glTF/2.0/Extensions/KHR_materials_fuzz.types.d.ts +9 -0
  271. package/glTF/2.0/Extensions/KHR_materials_fuzz.types.js +2 -0
  272. package/glTF/2.0/Extensions/KHR_materials_fuzz.types.js.map +1 -0
  273. package/glTF/2.0/Extensions/KHR_materials_ior.d.ts +4 -44
  274. package/glTF/2.0/Extensions/KHR_materials_ior.js +6 -52
  275. package/glTF/2.0/Extensions/KHR_materials_ior.js.map +1 -1
  276. package/glTF/2.0/Extensions/KHR_materials_ior.pure.d.ts +43 -0
  277. package/glTF/2.0/Extensions/KHR_materials_ior.pure.js +67 -0
  278. package/glTF/2.0/Extensions/KHR_materials_ior.pure.js.map +1 -0
  279. package/glTF/2.0/Extensions/KHR_materials_ior.types.d.ts +9 -0
  280. package/glTF/2.0/Extensions/KHR_materials_ior.types.js +2 -0
  281. package/glTF/2.0/Extensions/KHR_materials_ior.types.js.map +1 -0
  282. package/glTF/2.0/Extensions/KHR_materials_iridescence.d.ts +4 -40
  283. package/glTF/2.0/Extensions/KHR_materials_iridescence.js +6 -66
  284. package/glTF/2.0/Extensions/KHR_materials_iridescence.js.map +1 -1
  285. package/glTF/2.0/Extensions/KHR_materials_iridescence.pure.d.ts +39 -0
  286. package/glTF/2.0/Extensions/KHR_materials_iridescence.pure.js +81 -0
  287. package/glTF/2.0/Extensions/KHR_materials_iridescence.pure.js.map +1 -0
  288. package/glTF/2.0/Extensions/KHR_materials_iridescence.types.d.ts +9 -0
  289. package/glTF/2.0/Extensions/KHR_materials_iridescence.types.js +2 -0
  290. package/glTF/2.0/Extensions/KHR_materials_iridescence.types.js.map +1 -0
  291. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.d.ts +4 -40
  292. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.js +6 -72
  293. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.js.map +1 -1
  294. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.d.ts +39 -0
  295. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.js +87 -0
  296. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.js.map +1 -0
  297. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.types.d.ts +9 -0
  298. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.types.js +2 -0
  299. package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.types.js.map +1 -0
  300. package/glTF/2.0/Extensions/KHR_materials_sheen.d.ts +4 -41
  301. package/glTF/2.0/Extensions/KHR_materials_sheen.js +6 -71
  302. package/glTF/2.0/Extensions/KHR_materials_sheen.js.map +1 -1
  303. package/glTF/2.0/Extensions/KHR_materials_sheen.pure.d.ts +40 -0
  304. package/glTF/2.0/Extensions/KHR_materials_sheen.pure.js +86 -0
  305. package/glTF/2.0/Extensions/KHR_materials_sheen.pure.js.map +1 -0
  306. package/glTF/2.0/Extensions/KHR_materials_sheen.types.d.ts +9 -0
  307. package/glTF/2.0/Extensions/KHR_materials_sheen.types.js +2 -0
  308. package/glTF/2.0/Extensions/KHR_materials_sheen.types.js.map +1 -0
  309. package/glTF/2.0/Extensions/KHR_materials_specular.d.ts +4 -40
  310. package/glTF/2.0/Extensions/KHR_materials_specular.js +6 -74
  311. package/glTF/2.0/Extensions/KHR_materials_specular.js.map +1 -1
  312. package/glTF/2.0/Extensions/KHR_materials_specular.pure.d.ts +39 -0
  313. package/glTF/2.0/Extensions/KHR_materials_specular.pure.js +89 -0
  314. package/glTF/2.0/Extensions/KHR_materials_specular.pure.js.map +1 -0
  315. package/glTF/2.0/Extensions/KHR_materials_specular.types.d.ts +9 -0
  316. package/glTF/2.0/Extensions/KHR_materials_specular.types.js +2 -0
  317. package/glTF/2.0/Extensions/KHR_materials_specular.types.js.map +1 -0
  318. package/glTF/2.0/Extensions/KHR_materials_transmission.d.ts +4 -40
  319. package/glTF/2.0/Extensions/KHR_materials_transmission.js +6 -70
  320. package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -1
  321. package/glTF/2.0/Extensions/KHR_materials_transmission.pure.d.ts +39 -0
  322. package/glTF/2.0/Extensions/KHR_materials_transmission.pure.js +85 -0
  323. package/glTF/2.0/Extensions/KHR_materials_transmission.pure.js.map +1 -0
  324. package/glTF/2.0/Extensions/KHR_materials_transmission.types.d.ts +9 -0
  325. package/glTF/2.0/Extensions/KHR_materials_transmission.types.js +2 -0
  326. package/glTF/2.0/Extensions/KHR_materials_transmission.types.js.map +1 -0
  327. package/glTF/2.0/Extensions/KHR_materials_unlit.d.ts +4 -40
  328. package/glTF/2.0/Extensions/KHR_materials_unlit.js +6 -64
  329. package/glTF/2.0/Extensions/KHR_materials_unlit.js.map +1 -1
  330. package/glTF/2.0/Extensions/KHR_materials_unlit.pure.d.ts +39 -0
  331. package/glTF/2.0/Extensions/KHR_materials_unlit.pure.js +79 -0
  332. package/glTF/2.0/Extensions/KHR_materials_unlit.pure.js.map +1 -0
  333. package/glTF/2.0/Extensions/KHR_materials_unlit.types.d.ts +9 -0
  334. package/glTF/2.0/Extensions/KHR_materials_unlit.types.js +2 -0
  335. package/glTF/2.0/Extensions/KHR_materials_unlit.types.js.map +1 -0
  336. package/glTF/2.0/Extensions/KHR_materials_variants.d.ts +4 -110
  337. package/glTF/2.0/Extensions/KHR_materials_variants.js +6 -260
  338. package/glTF/2.0/Extensions/KHR_materials_variants.js.map +1 -1
  339. package/glTF/2.0/Extensions/KHR_materials_variants.pure.d.ts +97 -0
  340. package/glTF/2.0/Extensions/KHR_materials_variants.pure.js +275 -0
  341. package/glTF/2.0/Extensions/KHR_materials_variants.pure.js.map +1 -0
  342. package/glTF/2.0/Extensions/KHR_materials_variants.types.d.ts +29 -0
  343. package/glTF/2.0/Extensions/KHR_materials_variants.types.js +2 -0
  344. package/glTF/2.0/Extensions/KHR_materials_variants.types.js.map +1 -0
  345. package/glTF/2.0/Extensions/KHR_materials_volume.d.ts +4 -41
  346. package/glTF/2.0/Extensions/KHR_materials_volume.js +6 -77
  347. package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -1
  348. package/glTF/2.0/Extensions/KHR_materials_volume.pure.d.ts +40 -0
  349. package/glTF/2.0/Extensions/KHR_materials_volume.pure.js +92 -0
  350. package/glTF/2.0/Extensions/KHR_materials_volume.pure.js.map +1 -0
  351. package/glTF/2.0/Extensions/KHR_materials_volume.types.d.ts +9 -0
  352. package/glTF/2.0/Extensions/KHR_materials_volume.types.js +2 -0
  353. package/glTF/2.0/Extensions/KHR_materials_volume.types.js.map +1 -0
  354. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.d.ts +4 -43
  355. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js +6 -113
  356. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js.map +1 -1
  357. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.d.ts +42 -0
  358. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.js +128 -0
  359. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.js.map +1 -0
  360. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.types.d.ts +9 -0
  361. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.types.js +2 -0
  362. package/glTF/2.0/Extensions/KHR_materials_volume_scatter.types.js.map +1 -0
  363. package/glTF/2.0/Extensions/KHR_mesh_quantization.d.ts +4 -27
  364. package/glTF/2.0/Extensions/KHR_mesh_quantization.js +6 -20
  365. package/glTF/2.0/Extensions/KHR_mesh_quantization.js.map +1 -1
  366. package/glTF/2.0/Extensions/KHR_mesh_quantization.pure.d.ts +26 -0
  367. package/glTF/2.0/Extensions/KHR_mesh_quantization.pure.js +35 -0
  368. package/glTF/2.0/Extensions/KHR_mesh_quantization.pure.js.map +1 -0
  369. package/glTF/2.0/Extensions/KHR_mesh_quantization.types.d.ts +9 -0
  370. package/glTF/2.0/Extensions/KHR_mesh_quantization.types.js +2 -0
  371. package/glTF/2.0/Extensions/KHR_mesh_quantization.types.js.map +1 -0
  372. package/glTF/2.0/Extensions/KHR_node_hoverability.d.ts +4 -29
  373. package/glTF/2.0/Extensions/KHR_node_hoverability.js +6 -187
  374. package/glTF/2.0/Extensions/KHR_node_hoverability.js.map +1 -1
  375. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.d.ts +28 -0
  376. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js +202 -0
  377. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js.map +1 -0
  378. package/glTF/2.0/Extensions/KHR_node_hoverability.types.d.ts +9 -0
  379. package/glTF/2.0/Extensions/KHR_node_hoverability.types.js +2 -0
  380. package/glTF/2.0/Extensions/KHR_node_hoverability.types.js.map +1 -0
  381. package/glTF/2.0/Extensions/KHR_node_selectability.d.ts +4 -28
  382. package/glTF/2.0/Extensions/KHR_node_selectability.js +6 -121
  383. package/glTF/2.0/Extensions/KHR_node_selectability.js.map +1 -1
  384. package/glTF/2.0/Extensions/KHR_node_selectability.pure.d.ts +27 -0
  385. package/glTF/2.0/Extensions/KHR_node_selectability.pure.js +136 -0
  386. package/glTF/2.0/Extensions/KHR_node_selectability.pure.js.map +1 -0
  387. package/glTF/2.0/Extensions/KHR_node_selectability.types.d.ts +9 -0
  388. package/glTF/2.0/Extensions/KHR_node_selectability.types.js +2 -0
  389. package/glTF/2.0/Extensions/KHR_node_selectability.types.js.map +1 -0
  390. package/glTF/2.0/Extensions/KHR_node_visibility.d.ts +4 -28
  391. package/glTF/2.0/Extensions/KHR_node_visibility.js +6 -64
  392. package/glTF/2.0/Extensions/KHR_node_visibility.js.map +1 -1
  393. package/glTF/2.0/Extensions/KHR_node_visibility.pure.d.ts +27 -0
  394. package/glTF/2.0/Extensions/KHR_node_visibility.pure.js +79 -0
  395. package/glTF/2.0/Extensions/KHR_node_visibility.pure.js.map +1 -0
  396. package/glTF/2.0/Extensions/KHR_node_visibility.types.d.ts +9 -0
  397. package/glTF/2.0/Extensions/KHR_node_visibility.types.js +2 -0
  398. package/glTF/2.0/Extensions/KHR_node_visibility.types.js.map +1 -0
  399. package/glTF/2.0/Extensions/KHR_texture_basisu.d.ts +4 -31
  400. package/glTF/2.0/Extensions/KHR_texture_basisu.js +6 -35
  401. package/glTF/2.0/Extensions/KHR_texture_basisu.js.map +1 -1
  402. package/glTF/2.0/Extensions/KHR_texture_basisu.pure.d.ts +30 -0
  403. package/glTF/2.0/Extensions/KHR_texture_basisu.pure.js +50 -0
  404. package/glTF/2.0/Extensions/KHR_texture_basisu.pure.js.map +1 -0
  405. package/glTF/2.0/Extensions/KHR_texture_basisu.types.d.ts +9 -0
  406. package/glTF/2.0/Extensions/KHR_texture_basisu.types.js +2 -0
  407. package/glTF/2.0/Extensions/KHR_texture_basisu.types.js.map +1 -0
  408. package/glTF/2.0/Extensions/KHR_texture_transform.d.ts +4 -35
  409. package/glTF/2.0/Extensions/KHR_texture_transform.js +6 -56
  410. package/glTF/2.0/Extensions/KHR_texture_transform.js.map +1 -1
  411. package/glTF/2.0/Extensions/KHR_texture_transform.pure.d.ts +34 -0
  412. package/glTF/2.0/Extensions/KHR_texture_transform.pure.js +71 -0
  413. package/glTF/2.0/Extensions/KHR_texture_transform.pure.js.map +1 -0
  414. package/glTF/2.0/Extensions/KHR_texture_transform.types.d.ts +9 -0
  415. package/glTF/2.0/Extensions/KHR_texture_transform.types.js +2 -0
  416. package/glTF/2.0/Extensions/KHR_texture_transform.types.js.map +1 -0
  417. package/glTF/2.0/Extensions/KHR_xmp_json_ld.d.ts +4 -37
  418. package/glTF/2.0/Extensions/KHR_xmp_json_ld.js +6 -45
  419. package/glTF/2.0/Extensions/KHR_xmp_json_ld.js.map +1 -1
  420. package/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.d.ts +36 -0
  421. package/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.js +60 -0
  422. package/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.js.map +1 -0
  423. package/glTF/2.0/Extensions/KHR_xmp_json_ld.types.d.ts +9 -0
  424. package/glTF/2.0/Extensions/KHR_xmp_json_ld.types.js +2 -0
  425. package/glTF/2.0/Extensions/KHR_xmp_json_ld.types.js.map +1 -0
  426. package/glTF/2.0/Extensions/MSFT_audio_emitter.d.ts +5 -54
  427. package/glTF/2.0/Extensions/MSFT_audio_emitter.js +7 -226
  428. package/glTF/2.0/Extensions/MSFT_audio_emitter.js.map +1 -1
  429. package/glTF/2.0/Extensions/MSFT_audio_emitter.pure.d.ts +52 -0
  430. package/glTF/2.0/Extensions/MSFT_audio_emitter.pure.js +240 -0
  431. package/glTF/2.0/Extensions/MSFT_audio_emitter.pure.js.map +1 -0
  432. package/glTF/2.0/Extensions/MSFT_audio_emitter.types.d.ts +9 -0
  433. package/glTF/2.0/Extensions/MSFT_audio_emitter.types.js +2 -0
  434. package/glTF/2.0/Extensions/MSFT_audio_emitter.types.js.map +1 -0
  435. package/glTF/2.0/Extensions/MSFT_lod.d.ts +4 -102
  436. package/glTF/2.0/Extensions/MSFT_lod.js +6 -335
  437. package/glTF/2.0/Extensions/MSFT_lod.js.map +1 -1
  438. package/glTF/2.0/Extensions/MSFT_lod.pure.d.ts +96 -0
  439. package/glTF/2.0/Extensions/MSFT_lod.pure.js +350 -0
  440. package/glTF/2.0/Extensions/MSFT_lod.pure.js.map +1 -0
  441. package/glTF/2.0/Extensions/MSFT_lod.types.d.ts +14 -0
  442. package/glTF/2.0/Extensions/MSFT_lod.types.js +2 -0
  443. package/glTF/2.0/Extensions/MSFT_lod.types.js.map +1 -0
  444. package/glTF/2.0/Extensions/MSFT_minecraftMesh.d.ts +6 -27
  445. package/glTF/2.0/Extensions/MSFT_minecraftMesh.js +8 -40
  446. package/glTF/2.0/Extensions/MSFT_minecraftMesh.js.map +1 -1
  447. package/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.d.ts +24 -0
  448. package/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.js +53 -0
  449. package/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.js.map +1 -0
  450. package/glTF/2.0/Extensions/MSFT_minecraftMesh.types.d.ts +9 -0
  451. package/glTF/2.0/Extensions/MSFT_minecraftMesh.types.js +2 -0
  452. package/glTF/2.0/Extensions/MSFT_minecraftMesh.types.js.map +1 -0
  453. package/glTF/2.0/Extensions/MSFT_sRGBFactors.d.ts +6 -27
  454. package/glTF/2.0/Extensions/MSFT_sRGBFactors.js +8 -38
  455. package/glTF/2.0/Extensions/MSFT_sRGBFactors.js.map +1 -1
  456. package/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.d.ts +24 -0
  457. package/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.js +51 -0
  458. package/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.js.map +1 -0
  459. package/glTF/2.0/Extensions/MSFT_sRGBFactors.types.d.ts +9 -0
  460. package/glTF/2.0/Extensions/MSFT_sRGBFactors.types.js +2 -0
  461. package/glTF/2.0/Extensions/MSFT_sRGBFactors.types.js.map +1 -0
  462. package/glTF/2.0/Extensions/pure.d.ts +45 -0
  463. package/glTF/2.0/Extensions/pure.js +47 -0
  464. package/glTF/2.0/Extensions/pure.js.map +1 -0
  465. package/glTF/2.0/glTFLoader.d.ts +1 -471
  466. package/glTF/2.0/glTFLoader.js +3 -2539
  467. package/glTF/2.0/glTFLoader.js.map +1 -1
  468. package/glTF/2.0/glTFLoader.pure.d.ts +476 -0
  469. package/glTF/2.0/glTFLoader.pure.js +2563 -0
  470. package/glTF/2.0/glTFLoader.pure.js.map +1 -0
  471. package/glTF/2.0/pure.d.ts +8 -0
  472. package/glTF/2.0/pure.js +10 -0
  473. package/glTF/2.0/pure.js.map +1 -0
  474. package/glTF/glTFFileLoader.d.ts +5 -551
  475. package/glTF/glTFFileLoader.js +6 -996
  476. package/glTF/glTFFileLoader.js.map +1 -1
  477. package/glTF/glTFFileLoader.pure.d.ts +562 -0
  478. package/glTF/glTFFileLoader.pure.js +1024 -0
  479. package/glTF/glTFFileLoader.pure.js.map +1 -0
  480. package/glTF/glTFFileLoader.types.d.ts +11 -0
  481. package/glTF/glTFFileLoader.types.js +2 -0
  482. package/glTF/glTFFileLoader.types.js.map +1 -0
  483. package/glTF/pure.d.ts +6 -0
  484. package/glTF/pure.js +8 -0
  485. package/glTF/pure.js.map +1 -0
  486. package/package.json +56 -4
  487. package/pure.d.ts +8 -0
  488. package/pure.js +10 -0
  489. package/pure.js.map +1 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Options for {@link GaussianSplattingDownloadManager}.
3
+ */
4
+ export interface IGaussianSplattingDownloadManagerOptions {
5
+ /** Maximum number of downloads allowed to run at the same time. PlayCanvas default `2`. */
6
+ maxConcurrent?: number;
7
+ /** Number of times a failed download is retried before rejecting. PlayCanvas default `2` (3 attempts total). */
8
+ maxRetries?: number;
9
+ }
10
+ /** Identifies a group of related downloads so they can be cancelled together. */
11
+ export type DownloadGroupId = string | number;
12
+ /**
13
+ * Throttles the file downloads issued while streaming a Gaussian Splatting LOD scene.
14
+ *
15
+ * Mirrors the PlayCanvas gsplat asset loader: at most {@link maxConcurrent} downloads run at once, the
16
+ * rest wait in a FIFO queue, each failed download is retried up to {@link maxRetries} times, and requests
17
+ * are idempotent — concurrent (queued or in-flight) requests for the same URL share a single download.
18
+ *
19
+ * Downloads can be tagged with a group id and cancelled together via {@link cancelGroup}: when a node's
20
+ * target LOD changes before its file finishes loading, the streamer cancels that file's now-unneeded
21
+ * downloads. Cancellation aborts the underlying HTTP request (a queued download is dropped before it
22
+ * starts; an in-flight download is aborted and its concurrency slot freed), so no bandwidth is wasted on
23
+ * data that is no longer needed.
24
+ *
25
+ * Without this throttling, every on-demand LOD decode fans out into many parallel image fetches, so the
26
+ * browser opens dozens of simultaneous connections that compete for bandwidth and delay the splats the
27
+ * camera actually needs.
28
+ * @experimental
29
+ */
30
+ export declare class GaussianSplattingDownloadManager {
31
+ /** Maximum number of downloads allowed to run at the same time. */
32
+ readonly maxConcurrent: number;
33
+ /** Number of times a failed download is retried before rejecting. */
34
+ readonly maxRetries: number;
35
+ private _activeCount;
36
+ private readonly _queue;
37
+ private readonly _pending;
38
+ private readonly _groups;
39
+ private _disposed;
40
+ /**
41
+ * Creates a download manager.
42
+ * @param options concurrency and retry limits
43
+ */
44
+ constructor(options?: IGaussianSplattingDownloadManagerOptions);
45
+ /**
46
+ * Whether there are no downloads queued or in flight.
47
+ */
48
+ get isIdle(): boolean;
49
+ /**
50
+ * Downloads a file as an `ArrayBuffer`, queued behind the concurrency cap and retried on failure.
51
+ * Concurrent requests for the same URL resolve from a single shared download.
52
+ * @param url the file URL to download
53
+ * @param groupId optional group tag so related downloads can be cancelled together via {@link cancelGroup}
54
+ * @returns a promise resolving with the downloaded bytes
55
+ */
56
+ loadFileAsync(url: string, groupId?: DownloadGroupId): Promise<ArrayBuffer>;
57
+ /**
58
+ * Cancels a single pending download by URL. A queued download is dropped before it starts; an in-flight
59
+ * download has its underlying HTTP request aborted and its concurrency slot freed. No-op if the URL is
60
+ * not currently pending.
61
+ * @param url the URL to cancel
62
+ */
63
+ cancel(url: string): void;
64
+ /**
65
+ * Cancels every pending download tagged with the given group id.
66
+ * @param groupId the group whose downloads should be cancelled
67
+ */
68
+ cancelGroup(groupId: DownloadGroupId): void;
69
+ /**
70
+ * Cancels every queued download and aborts every in-flight download, preventing new downloads from
71
+ * starting.
72
+ */
73
+ dispose(): void;
74
+ /**
75
+ * Aborts a task: drops it from the queue (if not started), aborts its in-flight HTTP request (if started),
76
+ * unwinds its current attempt, settles its promise, and frees its concurrency slot.
77
+ * @param task the task to abort
78
+ * @param reason the rejection reason
79
+ */
80
+ private _abort;
81
+ /**
82
+ * Settles a task exactly once, removing it from the pending map and its group.
83
+ * @param task the task to settle
84
+ * @param settleFn resolves or rejects the task's promise
85
+ */
86
+ private _settle;
87
+ /**
88
+ * Releases a task's concurrency slot exactly once and pumps the queue.
89
+ * @param task the task whose slot to release
90
+ */
91
+ private _releaseSlot;
92
+ /**
93
+ * Starts as many queued downloads as the concurrency cap allows.
94
+ */
95
+ private _pump;
96
+ /**
97
+ * Runs a single download with retries, settling the task's shared promise. The idempotency entry is
98
+ * removed the moment the task settles so a later request for the same URL starts a fresh download.
99
+ * @param task the queued download to run
100
+ */
101
+ private _runTaskAsync;
102
+ /**
103
+ * Performs one download attempt, exposing the request handle (for abort) and an attempt-rejecter on the
104
+ * task so cancellation can both abort the HTTP request and unwind this awaited attempt.
105
+ * @param task the download task
106
+ * @returns a promise resolving with the downloaded bytes
107
+ */
108
+ private _downloadAttemptAsync;
109
+ }
@@ -0,0 +1,241 @@
1
+ import { Tools } from "@babylonjs/core/Misc/tools.js";
2
+ /**
3
+ * Throttles the file downloads issued while streaming a Gaussian Splatting LOD scene.
4
+ *
5
+ * Mirrors the PlayCanvas gsplat asset loader: at most {@link maxConcurrent} downloads run at once, the
6
+ * rest wait in a FIFO queue, each failed download is retried up to {@link maxRetries} times, and requests
7
+ * are idempotent — concurrent (queued or in-flight) requests for the same URL share a single download.
8
+ *
9
+ * Downloads can be tagged with a group id and cancelled together via {@link cancelGroup}: when a node's
10
+ * target LOD changes before its file finishes loading, the streamer cancels that file's now-unneeded
11
+ * downloads. Cancellation aborts the underlying HTTP request (a queued download is dropped before it
12
+ * starts; an in-flight download is aborted and its concurrency slot freed), so no bandwidth is wasted on
13
+ * data that is no longer needed.
14
+ *
15
+ * Without this throttling, every on-demand LOD decode fans out into many parallel image fetches, so the
16
+ * browser opens dozens of simultaneous connections that compete for bandwidth and delay the splats the
17
+ * camera actually needs.
18
+ * @experimental
19
+ */
20
+ export class GaussianSplattingDownloadManager {
21
+ /**
22
+ * Creates a download manager.
23
+ * @param options concurrency and retry limits
24
+ */
25
+ constructor(options) {
26
+ this._activeCount = 0;
27
+ this._queue = [];
28
+ // Idempotency: maps a URL to its task while the download is queued or in flight. The entry is removed
29
+ // once the download settles so a later request (after the bytes were consumed) downloads again.
30
+ this._pending = new Map();
31
+ // Maps a group id to the set of URLs currently downloading (or queued) under it, for bulk cancellation.
32
+ this._groups = new Map();
33
+ this._disposed = false;
34
+ this.maxConcurrent = Math.max(1, options?.maxConcurrent ?? 2);
35
+ this.maxRetries = Math.max(0, options?.maxRetries ?? 2);
36
+ }
37
+ /**
38
+ * Whether there are no downloads queued or in flight.
39
+ */
40
+ get isIdle() {
41
+ return this._pending.size === 0;
42
+ }
43
+ /**
44
+ * Downloads a file as an `ArrayBuffer`, queued behind the concurrency cap and retried on failure.
45
+ * Concurrent requests for the same URL resolve from a single shared download.
46
+ * @param url the file URL to download
47
+ * @param groupId optional group tag so related downloads can be cancelled together via {@link cancelGroup}
48
+ * @returns a promise resolving with the downloaded bytes
49
+ */
50
+ async loadFileAsync(url, groupId) {
51
+ if (this._disposed) {
52
+ throw new Error("GaussianSplattingDownloadManager has been disposed.");
53
+ }
54
+ const existing = this._pending.get(url);
55
+ if (existing) {
56
+ return await existing.promise;
57
+ }
58
+ const task = {
59
+ url,
60
+ groupId,
61
+ settled: false,
62
+ cancelled: false,
63
+ started: false,
64
+ slotReleased: false,
65
+ };
66
+ task.promise = new Promise((resolve, reject) => {
67
+ task.resolve = resolve;
68
+ task.reject = reject;
69
+ });
70
+ this._pending.set(url, task);
71
+ if (groupId !== undefined) {
72
+ let urls = this._groups.get(groupId);
73
+ if (!urls) {
74
+ urls = new Set();
75
+ this._groups.set(groupId, urls);
76
+ }
77
+ urls.add(url);
78
+ }
79
+ this._queue.push(task);
80
+ this._pump();
81
+ return await task.promise;
82
+ }
83
+ /**
84
+ * Cancels a single pending download by URL. A queued download is dropped before it starts; an in-flight
85
+ * download has its underlying HTTP request aborted and its concurrency slot freed. No-op if the URL is
86
+ * not currently pending.
87
+ * @param url the URL to cancel
88
+ */
89
+ cancel(url) {
90
+ const task = this._pending.get(url);
91
+ if (!task) {
92
+ return;
93
+ }
94
+ this._abort(task, new Error(`GaussianSplattingDownloadManager: download cancelled (${url}).`));
95
+ }
96
+ /**
97
+ * Cancels every pending download tagged with the given group id.
98
+ * @param groupId the group whose downloads should be cancelled
99
+ */
100
+ cancelGroup(groupId) {
101
+ const urls = this._groups.get(groupId);
102
+ if (!urls) {
103
+ return;
104
+ }
105
+ // Copy first: cancel() mutates the group set as each URL settles.
106
+ for (const url of Array.from(urls)) {
107
+ this.cancel(url);
108
+ }
109
+ this._groups.delete(groupId);
110
+ }
111
+ /**
112
+ * Cancels every queued download and aborts every in-flight download, preventing new downloads from
113
+ * starting.
114
+ */
115
+ dispose() {
116
+ if (this._disposed) {
117
+ return;
118
+ }
119
+ this._disposed = true;
120
+ this._queue.length = 0;
121
+ for (const task of Array.from(this._pending.values())) {
122
+ this._abort(task, new Error("GaussianSplattingDownloadManager has been disposed."));
123
+ }
124
+ }
125
+ /**
126
+ * Aborts a task: drops it from the queue (if not started), aborts its in-flight HTTP request (if started),
127
+ * unwinds its current attempt, settles its promise, and frees its concurrency slot.
128
+ * @param task the task to abort
129
+ * @param reason the rejection reason
130
+ */
131
+ _abort(task, reason) {
132
+ if (task.settled) {
133
+ return;
134
+ }
135
+ task.cancelled = true;
136
+ const queueIndex = this._queue.indexOf(task);
137
+ if (queueIndex !== -1) {
138
+ this._queue.splice(queueIndex, 1);
139
+ }
140
+ // Abort the underlying HTTP request (no-op for a queued task whose request has not been created).
141
+ task.request?.abort();
142
+ // abort() does not fire the error callback, so unwind the awaited attempt explicitly.
143
+ task.cancelAttempt?.(reason);
144
+ this._settle(task, () => task.reject(reason));
145
+ if (task.started) {
146
+ this._releaseSlot(task);
147
+ }
148
+ }
149
+ /**
150
+ * Settles a task exactly once, removing it from the pending map and its group.
151
+ * @param task the task to settle
152
+ * @param settleFn resolves or rejects the task's promise
153
+ */
154
+ _settle(task, settleFn) {
155
+ if (task.settled) {
156
+ return;
157
+ }
158
+ task.settled = true;
159
+ this._pending.delete(task.url);
160
+ if (task.groupId !== undefined) {
161
+ const urls = this._groups.get(task.groupId);
162
+ if (urls) {
163
+ urls.delete(task.url);
164
+ if (urls.size === 0) {
165
+ this._groups.delete(task.groupId);
166
+ }
167
+ }
168
+ }
169
+ settleFn();
170
+ }
171
+ /**
172
+ * Releases a task's concurrency slot exactly once and pumps the queue.
173
+ * @param task the task whose slot to release
174
+ */
175
+ _releaseSlot(task) {
176
+ if (task.slotReleased) {
177
+ return;
178
+ }
179
+ task.slotReleased = true;
180
+ this._activeCount--;
181
+ this._pump();
182
+ }
183
+ /**
184
+ * Starts as many queued downloads as the concurrency cap allows.
185
+ */
186
+ _pump() {
187
+ while (!this._disposed && this._activeCount < this.maxConcurrent && this._queue.length > 0) {
188
+ const task = this._queue.shift();
189
+ if (task.settled) {
190
+ continue;
191
+ }
192
+ task.started = true;
193
+ this._activeCount++;
194
+ void this._runTaskAsync(task).finally(() => {
195
+ this._releaseSlot(task);
196
+ });
197
+ }
198
+ }
199
+ /**
200
+ * Runs a single download with retries, settling the task's shared promise. The idempotency entry is
201
+ * removed the moment the task settles so a later request for the same URL starts a fresh download.
202
+ * @param task the queued download to run
203
+ */
204
+ async _runTaskAsync(task) {
205
+ let lastError;
206
+ // attempt 0 is the initial try; attempts 1..maxRetries are retries (PlayCanvas retries immediately).
207
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
208
+ if (this._disposed || task.cancelled) {
209
+ return;
210
+ }
211
+ try {
212
+ // eslint-disable-next-line no-await-in-loop
213
+ const buffer = await this._downloadAttemptAsync(task);
214
+ this._settle(task, () => task.resolve(buffer));
215
+ return;
216
+ }
217
+ catch (e) {
218
+ task.cancelAttempt = undefined;
219
+ if (this._disposed || task.cancelled) {
220
+ // The task was already settled by cancel()/dispose(); just stop retrying.
221
+ return;
222
+ }
223
+ lastError = e;
224
+ }
225
+ }
226
+ this._settle(task, () => task.reject(lastError));
227
+ }
228
+ /**
229
+ * Performs one download attempt, exposing the request handle (for abort) and an attempt-rejecter on the
230
+ * task so cancellation can both abort the HTTP request and unwind this awaited attempt.
231
+ * @param task the download task
232
+ * @returns a promise resolving with the downloaded bytes
233
+ */
234
+ async _downloadAttemptAsync(task) {
235
+ return await new Promise((resolve, reject) => {
236
+ task.cancelAttempt = reject;
237
+ task.request = Tools.LoadFile(task.url, (data) => resolve(data), undefined, undefined, true, (_request, exception) => reject(exception instanceof Error ? exception : new Error(`GaussianSplattingDownloadManager: failed to load ${task.url}.`)));
238
+ });
239
+ }
240
+ }
241
+ //# sourceMappingURL=gaussianSplattingDownloadManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gaussianSplattingDownloadManager.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/gaussianSplattingDownloadManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { Tools } from \"core/Misc/tools\";\r\nimport { type IFileRequest } from \"core/Misc/fileRequest\";\r\n\r\n/**\r\n * Options for {@link GaussianSplattingDownloadManager}.\r\n */\r\nexport interface IGaussianSplattingDownloadManagerOptions {\r\n /** Maximum number of downloads allowed to run at the same time. PlayCanvas default `2`. */\r\n maxConcurrent?: number;\r\n /** Number of times a failed download is retried before rejecting. PlayCanvas default `2` (3 attempts total). */\r\n maxRetries?: number;\r\n}\r\n\r\n/** Identifies a group of related downloads so they can be cancelled together. */\r\nexport type DownloadGroupId = string | number;\r\n\r\n/**\r\n * A queued, concurrency-capped download task.\r\n */\r\ninterface IDownloadTask {\r\n url: string;\r\n groupId?: DownloadGroupId;\r\n promise: Promise<ArrayBuffer>;\r\n resolve: (data: ArrayBuffer) => void;\r\n reject: (reason: any) => void;\r\n // Set once the task is settled (resolved/rejected/cancelled) so it is never settled twice.\r\n settled: boolean;\r\n // Set when the task has been cancelled so an in-flight download discards its eventual result.\r\n cancelled: boolean;\r\n // True once the task has been pulled from the queue and counted against the concurrency cap.\r\n started: boolean;\r\n // True once the task's concurrency slot has been released (so it is released exactly once).\r\n slotReleased: boolean;\r\n // The in-flight HTTP request for the current attempt, used to abort the download on cancellation.\r\n request?: IFileRequest;\r\n // Rejects the current attempt's promise so an aborted download unwinds immediately (abort() does not\r\n // fire the error callback, so the awaited attempt would otherwise hang).\r\n cancelAttempt?: (reason: any) => void;\r\n}\r\n\r\n/**\r\n * Throttles the file downloads issued while streaming a Gaussian Splatting LOD scene.\r\n *\r\n * Mirrors the PlayCanvas gsplat asset loader: at most {@link maxConcurrent} downloads run at once, the\r\n * rest wait in a FIFO queue, each failed download is retried up to {@link maxRetries} times, and requests\r\n * are idempotent — concurrent (queued or in-flight) requests for the same URL share a single download.\r\n *\r\n * Downloads can be tagged with a group id and cancelled together via {@link cancelGroup}: when a node's\r\n * target LOD changes before its file finishes loading, the streamer cancels that file's now-unneeded\r\n * downloads. Cancellation aborts the underlying HTTP request (a queued download is dropped before it\r\n * starts; an in-flight download is aborted and its concurrency slot freed), so no bandwidth is wasted on\r\n * data that is no longer needed.\r\n *\r\n * Without this throttling, every on-demand LOD decode fans out into many parallel image fetches, so the\r\n * browser opens dozens of simultaneous connections that compete for bandwidth and delay the splats the\r\n * camera actually needs.\r\n * @experimental\r\n */\r\nexport class GaussianSplattingDownloadManager {\r\n /** Maximum number of downloads allowed to run at the same time. */\r\n public readonly maxConcurrent: number;\r\n /** Number of times a failed download is retried before rejecting. */\r\n public readonly maxRetries: number;\r\n\r\n private _activeCount = 0;\r\n private readonly _queue: IDownloadTask[] = [];\r\n // Idempotency: maps a URL to its task while the download is queued or in flight. The entry is removed\r\n // once the download settles so a later request (after the bytes were consumed) downloads again.\r\n private readonly _pending = new Map<string, IDownloadTask>();\r\n // Maps a group id to the set of URLs currently downloading (or queued) under it, for bulk cancellation.\r\n private readonly _groups = new Map<DownloadGroupId, Set<string>>();\r\n private _disposed = false;\r\n\r\n /**\r\n * Creates a download manager.\r\n * @param options concurrency and retry limits\r\n */\r\n public constructor(options?: IGaussianSplattingDownloadManagerOptions) {\r\n this.maxConcurrent = Math.max(1, options?.maxConcurrent ?? 2);\r\n this.maxRetries = Math.max(0, options?.maxRetries ?? 2);\r\n }\r\n\r\n /**\r\n * Whether there are no downloads queued or in flight.\r\n */\r\n public get isIdle(): boolean {\r\n return this._pending.size === 0;\r\n }\r\n\r\n /**\r\n * Downloads a file as an `ArrayBuffer`, queued behind the concurrency cap and retried on failure.\r\n * Concurrent requests for the same URL resolve from a single shared download.\r\n * @param url the file URL to download\r\n * @param groupId optional group tag so related downloads can be cancelled together via {@link cancelGroup}\r\n * @returns a promise resolving with the downloaded bytes\r\n */\r\n public async loadFileAsync(url: string, groupId?: DownloadGroupId): Promise<ArrayBuffer> {\r\n if (this._disposed) {\r\n throw new Error(\"GaussianSplattingDownloadManager has been disposed.\");\r\n }\r\n const existing = this._pending.get(url);\r\n if (existing) {\r\n return await existing.promise;\r\n }\r\n const task: IDownloadTask = {\r\n url,\r\n groupId,\r\n settled: false,\r\n cancelled: false,\r\n started: false,\r\n slotReleased: false,\r\n } as IDownloadTask;\r\n task.promise = new Promise<ArrayBuffer>((resolve, reject) => {\r\n task.resolve = resolve;\r\n task.reject = reject;\r\n });\r\n this._pending.set(url, task);\r\n if (groupId !== undefined) {\r\n let urls = this._groups.get(groupId);\r\n if (!urls) {\r\n urls = new Set<string>();\r\n this._groups.set(groupId, urls);\r\n }\r\n urls.add(url);\r\n }\r\n this._queue.push(task);\r\n this._pump();\r\n return await task.promise;\r\n }\r\n\r\n /**\r\n * Cancels a single pending download by URL. A queued download is dropped before it starts; an in-flight\r\n * download has its underlying HTTP request aborted and its concurrency slot freed. No-op if the URL is\r\n * not currently pending.\r\n * @param url the URL to cancel\r\n */\r\n public cancel(url: string): void {\r\n const task = this._pending.get(url);\r\n if (!task) {\r\n return;\r\n }\r\n this._abort(task, new Error(`GaussianSplattingDownloadManager: download cancelled (${url}).`));\r\n }\r\n\r\n /**\r\n * Cancels every pending download tagged with the given group id.\r\n * @param groupId the group whose downloads should be cancelled\r\n */\r\n public cancelGroup(groupId: DownloadGroupId): void {\r\n const urls = this._groups.get(groupId);\r\n if (!urls) {\r\n return;\r\n }\r\n // Copy first: cancel() mutates the group set as each URL settles.\r\n for (const url of Array.from(urls)) {\r\n this.cancel(url);\r\n }\r\n this._groups.delete(groupId);\r\n }\r\n\r\n /**\r\n * Cancels every queued download and aborts every in-flight download, preventing new downloads from\r\n * starting.\r\n */\r\n public dispose(): void {\r\n if (this._disposed) {\r\n return;\r\n }\r\n this._disposed = true;\r\n this._queue.length = 0;\r\n for (const task of Array.from(this._pending.values())) {\r\n this._abort(task, new Error(\"GaussianSplattingDownloadManager has been disposed.\"));\r\n }\r\n }\r\n\r\n /**\r\n * Aborts a task: drops it from the queue (if not started), aborts its in-flight HTTP request (if started),\r\n * unwinds its current attempt, settles its promise, and frees its concurrency slot.\r\n * @param task the task to abort\r\n * @param reason the rejection reason\r\n */\r\n private _abort(task: IDownloadTask, reason: any): void {\r\n if (task.settled) {\r\n return;\r\n }\r\n task.cancelled = true;\r\n const queueIndex = this._queue.indexOf(task);\r\n if (queueIndex !== -1) {\r\n this._queue.splice(queueIndex, 1);\r\n }\r\n // Abort the underlying HTTP request (no-op for a queued task whose request has not been created).\r\n task.request?.abort();\r\n // abort() does not fire the error callback, so unwind the awaited attempt explicitly.\r\n task.cancelAttempt?.(reason);\r\n this._settle(task, () => task.reject(reason));\r\n if (task.started) {\r\n this._releaseSlot(task);\r\n }\r\n }\r\n\r\n /**\r\n * Settles a task exactly once, removing it from the pending map and its group.\r\n * @param task the task to settle\r\n * @param settleFn resolves or rejects the task's promise\r\n */\r\n private _settle(task: IDownloadTask, settleFn: () => void): void {\r\n if (task.settled) {\r\n return;\r\n }\r\n task.settled = true;\r\n this._pending.delete(task.url);\r\n if (task.groupId !== undefined) {\r\n const urls = this._groups.get(task.groupId);\r\n if (urls) {\r\n urls.delete(task.url);\r\n if (urls.size === 0) {\r\n this._groups.delete(task.groupId);\r\n }\r\n }\r\n }\r\n settleFn();\r\n }\r\n\r\n /**\r\n * Releases a task's concurrency slot exactly once and pumps the queue.\r\n * @param task the task whose slot to release\r\n */\r\n private _releaseSlot(task: IDownloadTask): void {\r\n if (task.slotReleased) {\r\n return;\r\n }\r\n task.slotReleased = true;\r\n this._activeCount--;\r\n this._pump();\r\n }\r\n\r\n /**\r\n * Starts as many queued downloads as the concurrency cap allows.\r\n */\r\n private _pump(): void {\r\n while (!this._disposed && this._activeCount < this.maxConcurrent && this._queue.length > 0) {\r\n const task = this._queue.shift()!;\r\n if (task.settled) {\r\n continue;\r\n }\r\n task.started = true;\r\n this._activeCount++;\r\n void this._runTaskAsync(task).finally(() => {\r\n this._releaseSlot(task);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Runs a single download with retries, settling the task's shared promise. The idempotency entry is\r\n * removed the moment the task settles so a later request for the same URL starts a fresh download.\r\n * @param task the queued download to run\r\n */\r\n private async _runTaskAsync(task: IDownloadTask): Promise<void> {\r\n let lastError: any;\r\n // attempt 0 is the initial try; attempts 1..maxRetries are retries (PlayCanvas retries immediately).\r\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\r\n if (this._disposed || task.cancelled) {\r\n return;\r\n }\r\n try {\r\n // eslint-disable-next-line no-await-in-loop\r\n const buffer = await this._downloadAttemptAsync(task);\r\n this._settle(task, () => task.resolve(buffer));\r\n return;\r\n } catch (e) {\r\n task.cancelAttempt = undefined;\r\n if (this._disposed || task.cancelled) {\r\n // The task was already settled by cancel()/dispose(); just stop retrying.\r\n return;\r\n }\r\n lastError = e;\r\n }\r\n }\r\n this._settle(task, () => task.reject(lastError));\r\n }\r\n\r\n /**\r\n * Performs one download attempt, exposing the request handle (for abort) and an attempt-rejecter on the\r\n * task so cancellation can both abort the HTTP request and unwind this awaited attempt.\r\n * @param task the download task\r\n * @returns a promise resolving with the downloaded bytes\r\n */\r\n private async _downloadAttemptAsync(task: IDownloadTask): Promise<ArrayBuffer> {\r\n return await new Promise<ArrayBuffer>((resolve, reject) => {\r\n task.cancelAttempt = reject;\r\n task.request = Tools.LoadFile(\r\n task.url,\r\n (data) => resolve(data as ArrayBuffer),\r\n undefined,\r\n undefined,\r\n true,\r\n (_request, exception) => reject(exception instanceof Error ? exception : new Error(`GaussianSplattingDownloadManager: failed to load ${task.url}.`))\r\n );\r\n });\r\n }\r\n}\r\n"]}
@@ -0,0 +1,133 @@
1
+ import { type Nullable } from "@babylonjs/core/types.js";
2
+ /**
3
+ * One resident block relocation produced by {@link GaussianSplattingResidencyController.compact}: the file's
4
+ * splat data must be moved from `oldOffset` to `newOffset` (`count` splats) in the work buffer.
5
+ */
6
+ export interface IResidencyMove {
7
+ /** File index whose splat data must move. */
8
+ file: number;
9
+ /** The file's previous splat offset in the work buffer. */
10
+ oldOffset: number;
11
+ /** The file's new splat offset after compaction. */
12
+ newOffset: number;
13
+ /** Number of splats in the file. */
14
+ count: number;
15
+ }
16
+ /**
17
+ * Tracks which streamed Gaussian Splatting files are resident in the GPU work buffer and where, evicting
18
+ * unreferenced files after a cooldown to keep the resident set within a fixed budget.
19
+ *
20
+ * Built on {@link GaussianSplattingBlockAllocator}: each resident file owns a contiguous block of the work
21
+ * buffer's splat-index address space. A file with no remaining references is scheduled for eviction; after
22
+ * `cooldownFrames` ticks (or sooner, if the space is needed by a new allocation — "evict-to-fit") its block
23
+ * is freed and reused. Pinned files (e.g. the always-rendered environment and the padding splat) are never
24
+ * evicted. The {@link onEvict} callback fires for every file the controller evicts so the owner can drop its
25
+ * own bookkeeping (e.g. mark it no longer decoded).
26
+ *
27
+ * This controller owns only memory/residency bookkeeping — it has no knowledge of the scene, GPU, downloads,
28
+ * or reference counting (the caller decides when a file's reference count reaches zero and calls
29
+ * {@link scheduleEviction}).
30
+ * @experimental
31
+ */
32
+ export declare class GaussianSplattingResidencyController {
33
+ private readonly _allocator;
34
+ private readonly _blocks;
35
+ private readonly _cooldown;
36
+ private readonly _pinned;
37
+ private readonly _cooldownFrames;
38
+ private readonly _onEvict;
39
+ /**
40
+ * Creates a residency controller.
41
+ * @param capacity total splat-index capacity of the work buffer
42
+ * @param cooldownFrames number of ticks an unreferenced file stays resident before being evicted
43
+ * @param onEvict called with the file index whenever the controller evicts a file (via tick or evict-to-fit)
44
+ */
45
+ constructor(capacity: number, cooldownFrames: number, onEvict: (file: number) => void);
46
+ /**
47
+ * Total splat-index capacity.
48
+ */
49
+ get capacity(): number;
50
+ /**
51
+ * Number of files currently resident.
52
+ */
53
+ get residentCount(): number;
54
+ /**
55
+ * Total free splat capacity (sum of all gaps, which may be fragmented). After {@link compact} an
56
+ * allocation of up to this size is guaranteed to fit.
57
+ */
58
+ get freeSize(): number;
59
+ /**
60
+ * Whether the given file currently has a block in the work buffer.
61
+ * @param file file index
62
+ * @returns true if resident
63
+ */
64
+ has(file: number): boolean;
65
+ /**
66
+ * The work-buffer splat offset of a resident file, or undefined if not resident.
67
+ * @param file file index
68
+ * @returns the splat offset, or undefined
69
+ */
70
+ offset(file: number): number | undefined;
71
+ /**
72
+ * Allocates a contiguous block for a file about to be decoded. If there is no room, evicts files whose
73
+ * eviction cooldown is pending (they are unreferenced) and retries once. Returns the splat offset, or null
74
+ * if it still does not fit (the caller should refuse the decode and keep the node's current LOD).
75
+ * @param file file index
76
+ * @param count number of splats the file needs
77
+ * @returns the allocated splat offset, or null if it cannot fit
78
+ */
79
+ allocate(file: number, count: number): Nullable<number>;
80
+ /**
81
+ * Allocates a block for a file that must never be evicted (e.g. the environment or padding splat).
82
+ * @param file file index (use a sentinel that cannot collide with real file indices)
83
+ * @param count number of splats
84
+ * @returns the allocated splat offset, or null if it cannot fit
85
+ */
86
+ pin(file: number, count: number): Nullable<number>;
87
+ /**
88
+ * Frees a file's block immediately (e.g. when a decode was cancelled before completing). Does not fire
89
+ * {@link onEvict}. No-op for pinned or non-resident files.
90
+ * @param file file index
91
+ */
92
+ free(file: number): void;
93
+ /**
94
+ * Compacts the resident blocks to defragment free space (capacity is unchanged), returning every block
95
+ * that moved so the caller can relocate the corresponding GPU/CPU splat data. Call when an allocation
96
+ * fails despite sufficient total free space ({@link freeSize}); afterwards that allocation will fit.
97
+ * @returns the relocations to apply (empty when nothing moved)
98
+ */
99
+ compact(): IResidencyMove[];
100
+ /**
101
+ * Returns the current resident blocks (file index, splat offset, splat count). Used to relocate GPU/CPU
102
+ * data after {@link compact}.
103
+ * @returns one entry per resident file
104
+ */
105
+ getResidentBlocks(): Array<{
106
+ file: number;
107
+ offset: number;
108
+ count: number;
109
+ }>;
110
+ /**
111
+ * Schedules an unreferenced resident file for eviction after the cooldown. No-op for pinned or
112
+ * non-resident files.
113
+ * @param file file index
114
+ */
115
+ scheduleEviction(file: number): void;
116
+ /**
117
+ * Cancels a pending eviction because the file was referenced again.
118
+ * @param file file index
119
+ */
120
+ cancelEviction(file: number): void;
121
+ /**
122
+ * Advances all eviction cooldowns by one frame, evicting any that expire. Each evicted file fires
123
+ * {@link onEvict}.
124
+ * @returns the file indices evicted this tick
125
+ */
126
+ tick(): number[];
127
+ /**
128
+ * Releases all bookkeeping. The allocator and maps are cleared.
129
+ */
130
+ dispose(): void;
131
+ private _evictAllCooled;
132
+ private _evict;
133
+ }