@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.
- package/BVH/bvhFileLoader.d.ts +4 -67
- package/BVH/bvhFileLoader.js +6 -130
- package/BVH/bvhFileLoader.js.map +1 -1
- package/BVH/bvhFileLoader.pure.d.ts +75 -0
- package/BVH/bvhFileLoader.pure.js +154 -0
- package/BVH/bvhFileLoader.pure.js.map +1 -0
- package/BVH/bvhFileLoader.types.d.ts +11 -0
- package/BVH/bvhFileLoader.types.js +2 -0
- package/BVH/bvhFileLoader.types.js.map +1 -0
- package/BVH/pure.d.ts +3 -0
- package/BVH/pure.js +5 -0
- package/BVH/pure.js.map +1 -0
- package/FBX/fbxFileLoader.d.ts +4 -192
- package/FBX/fbxFileLoader.js +6 -2437
- package/FBX/fbxFileLoader.js.map +1 -1
- package/FBX/fbxFileLoader.pure.d.ts +190 -0
- package/FBX/fbxFileLoader.pure.js +2451 -0
- package/FBX/fbxFileLoader.pure.js.map +1 -0
- package/FBX/fbxFileLoader.types.d.ts +11 -0
- package/FBX/fbxFileLoader.types.js +2 -0
- package/FBX/fbxFileLoader.types.js.map +1 -0
- package/FBX/pure.d.ts +3 -0
- package/FBX/pure.js +4 -0
- package/FBX/pure.js.map +1 -0
- package/OBJ/objFileLoader.d.ts +4 -134
- package/OBJ/objFileLoader.js +6 -315
- package/OBJ/objFileLoader.js.map +1 -1
- package/OBJ/objFileLoader.pure.d.ts +132 -0
- package/OBJ/objFileLoader.pure.js +329 -0
- package/OBJ/objFileLoader.pure.js.map +1 -0
- package/OBJ/objFileLoader.types.d.ts +11 -0
- package/OBJ/objFileLoader.types.js +2 -0
- package/OBJ/objFileLoader.types.js.map +1 -0
- package/OBJ/pure.d.ts +5 -0
- package/OBJ/pure.js +6 -0
- package/OBJ/pure.js.map +1 -0
- package/OBJ/solidParser.js +4 -3
- package/OBJ/solidParser.js.map +1 -1
- package/SPLAT/gaussianSplattingBlockAllocator.d.ts +137 -0
- package/SPLAT/gaussianSplattingBlockAllocator.js +555 -0
- package/SPLAT/gaussianSplattingBlockAllocator.js.map +1 -0
- package/SPLAT/gaussianSplattingDownloadManager.d.ts +109 -0
- package/SPLAT/gaussianSplattingDownloadManager.js +241 -0
- package/SPLAT/gaussianSplattingDownloadManager.js.map +1 -0
- package/SPLAT/gaussianSplattingResidencyController.d.ts +133 -0
- package/SPLAT/gaussianSplattingResidencyController.js +222 -0
- package/SPLAT/gaussianSplattingResidencyController.js.map +1 -0
- package/SPLAT/gaussianSplattingStream.d.ts +122 -4
- package/SPLAT/gaussianSplattingStream.js +413 -42
- package/SPLAT/gaussianSplattingStream.js.map +1 -1
- package/SPLAT/gaussianSplattingWorkBuffer.d.ts +36 -0
- package/SPLAT/gaussianSplattingWorkBuffer.js +125 -13
- package/SPLAT/gaussianSplattingWorkBuffer.js.map +1 -1
- package/SPLAT/gaussianSplattingWorkBufferShaders.d.ts +15 -0
- package/SPLAT/gaussianSplattingWorkBufferShaders.js +82 -0
- package/SPLAT/gaussianSplattingWorkBufferShaders.js.map +1 -1
- package/SPLAT/pure.d.ts +5 -0
- package/SPLAT/pure.js +7 -0
- package/SPLAT/pure.js.map +1 -0
- package/SPLAT/sog.d.ts +1 -97
- package/SPLAT/sog.js +1 -501
- package/SPLAT/sog.js.map +1 -1
- package/SPLAT/sog.pure.d.ts +102 -0
- package/SPLAT/sog.pure.js +514 -0
- package/SPLAT/sog.pure.js.map +1 -0
- package/SPLAT/splatFileLoader.d.ts +5 -106
- package/SPLAT/splatFileLoader.js +9 -636
- package/SPLAT/splatFileLoader.js.map +1 -1
- package/SPLAT/splatFileLoader.pure.d.ts +104 -0
- package/SPLAT/splatFileLoader.pure.js +650 -0
- package/SPLAT/splatFileLoader.pure.js.map +1 -0
- package/SPLAT/splatFileLoader.types.d.ts +11 -0
- package/SPLAT/splatFileLoader.types.js +2 -0
- package/SPLAT/splatFileLoader.types.js.map +1 -0
- package/STL/pure.d.ts +2 -0
- package/STL/pure.js +3 -0
- package/STL/pure.js.map +1 -0
- package/STL/stlFileLoader.d.ts +5 -76
- package/STL/stlFileLoader.js +7 -236
- package/STL/stlFileLoader.js.map +1 -1
- package/STL/stlFileLoader.pure.d.ts +73 -0
- package/STL/stlFileLoader.pure.js +249 -0
- package/STL/stlFileLoader.pure.js.map +1 -0
- package/STL/stlFileLoader.types.d.ts +10 -0
- package/STL/stlFileLoader.types.js +2 -0
- package/STL/stlFileLoader.types.js.map +1 -0
- package/glTF/1.0/pure.d.ts +3 -0
- package/glTF/1.0/pure.js +4 -0
- package/glTF/1.0/pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_area.d.ts +4 -39
- package/glTF/2.0/Extensions/EXT_lights_area.js +6 -91
- package/glTF/2.0/Extensions/EXT_lights_area.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_lights_area.pure.d.ts +38 -0
- package/glTF/2.0/Extensions/EXT_lights_area.pure.js +106 -0
- package/glTF/2.0/Extensions/EXT_lights_area.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_area.types.d.ts +9 -0
- package/glTF/2.0/Extensions/EXT_lights_area.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_lights_area.types.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_ies.d.ts +4 -39
- package/glTF/2.0/Extensions/EXT_lights_ies.js +6 -81
- package/glTF/2.0/Extensions/EXT_lights_ies.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_lights_ies.pure.d.ts +38 -0
- package/glTF/2.0/Extensions/EXT_lights_ies.pure.js +96 -0
- package/glTF/2.0/Extensions/EXT_lights_ies.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_ies.types.d.ts +9 -0
- package/glTF/2.0/Extensions/EXT_lights_ies.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_lights_ies.types.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.d.ts +4 -46
- package/glTF/2.0/Extensions/EXT_lights_image_based.js +6 -113
- package/glTF/2.0/Extensions/EXT_lights_image_based.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_lights_image_based.pure.d.ts +37 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.pure.js +128 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.types.d.ts +17 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.types.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.d.ts +5 -37
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +7 -92
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.d.ts +35 -0
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.js +106 -0
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.types.d.ts +9 -0
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.types.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_meshopt_compression.d.ts +4 -37
- package/glTF/2.0/Extensions/EXT_meshopt_compression.js +6 -48
- package/glTF/2.0/Extensions/EXT_meshopt_compression.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_meshopt_compression.pure.d.ts +36 -0
- package/glTF/2.0/Extensions/EXT_meshopt_compression.pure.js +63 -0
- package/glTF/2.0/Extensions/EXT_meshopt_compression.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_meshopt_compression.types.d.ts +9 -0
- package/glTF/2.0/Extensions/EXT_meshopt_compression.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_meshopt_compression.types.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_texture_avif.d.ts +4 -32
- package/glTF/2.0/Extensions/EXT_texture_avif.js +6 -36
- package/glTF/2.0/Extensions/EXT_texture_avif.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_texture_avif.pure.d.ts +31 -0
- package/glTF/2.0/Extensions/EXT_texture_avif.pure.js +51 -0
- package/glTF/2.0/Extensions/EXT_texture_avif.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_texture_avif.types.d.ts +9 -0
- package/glTF/2.0/Extensions/EXT_texture_avif.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_texture_avif.types.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_texture_webp.d.ts +4 -31
- package/glTF/2.0/Extensions/EXT_texture_webp.js +6 -35
- package/glTF/2.0/Extensions/EXT_texture_webp.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_texture_webp.pure.d.ts +30 -0
- package/glTF/2.0/Extensions/EXT_texture_webp.pure.js +50 -0
- package/glTF/2.0/Extensions/EXT_texture_webp.pure.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_texture_webp.types.d.ts +9 -0
- package/glTF/2.0/Extensions/EXT_texture_webp.types.js +2 -0
- package/glTF/2.0/Extensions/EXT_texture_webp.types.js.map +1 -0
- package/glTF/2.0/Extensions/ExtrasAsMetadata.d.ts +4 -51
- package/glTF/2.0/Extensions/ExtrasAsMetadata.js +6 -71
- package/glTF/2.0/Extensions/ExtrasAsMetadata.js.map +1 -1
- package/glTF/2.0/Extensions/ExtrasAsMetadata.pure.d.ts +50 -0
- package/glTF/2.0/Extensions/ExtrasAsMetadata.pure.js +85 -0
- package/glTF/2.0/Extensions/ExtrasAsMetadata.pure.js.map +1 -0
- package/glTF/2.0/Extensions/ExtrasAsMetadata.types.d.ts +9 -0
- package/glTF/2.0/Extensions/ExtrasAsMetadata.types.js +2 -0
- package/glTF/2.0/Extensions/ExtrasAsMetadata.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_animation_pointer.d.ts +5 -45
- package/glTF/2.0/Extensions/KHR_animation_pointer.js +7 -75
- package/glTF/2.0/Extensions/KHR_animation_pointer.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_animation_pointer.pure.d.ts +43 -0
- package/glTF/2.0/Extensions/KHR_animation_pointer.pure.js +89 -0
- package/glTF/2.0/Extensions/KHR_animation_pointer.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_animation_pointer.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_animation_pointer.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_animation_pointer.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.d.ts +4 -45
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js +6 -90
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.d.ts +44 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.js +105 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/pure.d.ts +4 -0
- package/glTF/2.0/Extensions/KHR_interactivity/pure.js +5 -0
- package/glTF/2.0/Extensions/KHR_interactivity/pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity.d.ts +4 -36
- package/glTF/2.0/Extensions/KHR_interactivity.js +6 -148
- package/glTF/2.0/Extensions/KHR_interactivity.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity.pure.d.ts +35 -0
- package/glTF/2.0/Extensions/KHR_interactivity.pure.js +163 -0
- package/glTF/2.0/Extensions/KHR_interactivity.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_interactivity.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_interactivity.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_lights_punctual.d.ts +4 -39
- package/glTF/2.0/Extensions/KHR_lights_punctual.js +6 -89
- package/glTF/2.0/Extensions/KHR_lights_punctual.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_lights_punctual.pure.d.ts +38 -0
- package/glTF/2.0/Extensions/KHR_lights_punctual.pure.js +104 -0
- package/glTF/2.0/Extensions/KHR_lights_punctual.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_lights_punctual.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_lights_punctual.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_lights_punctual.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.js +6 -63
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.js +78 -0
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.js +6 -77
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.js +92 -0
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_coat.d.ts +4 -47
- package/glTF/2.0/Extensions/KHR_materials_coat.js +6 -117
- package/glTF/2.0/Extensions/KHR_materials_coat.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_coat.pure.d.ts +46 -0
- package/glTF/2.0/Extensions/KHR_materials_coat.pure.js +132 -0
- package/glTF/2.0/Extensions/KHR_materials_coat.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_coat.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_coat.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_coat.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.js +6 -56
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.js +71 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +6 -71
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.js +86 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_dispersion.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_dispersion.js +6 -54
- package/glTF/2.0/Extensions/KHR_materials_dispersion.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_dispersion.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_dispersion.pure.js +69 -0
- package/glTF/2.0/Extensions/KHR_materials_dispersion.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_dispersion.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_dispersion.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_dispersion.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js +6 -45
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.js +60 -0
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_fuzz.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_fuzz.js +6 -75
- package/glTF/2.0/Extensions/KHR_materials_fuzz.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_fuzz.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_fuzz.pure.js +90 -0
- package/glTF/2.0/Extensions/KHR_materials_fuzz.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_fuzz.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_fuzz.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_fuzz.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_ior.d.ts +4 -44
- package/glTF/2.0/Extensions/KHR_materials_ior.js +6 -52
- package/glTF/2.0/Extensions/KHR_materials_ior.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_ior.pure.d.ts +43 -0
- package/glTF/2.0/Extensions/KHR_materials_ior.pure.js +67 -0
- package/glTF/2.0/Extensions/KHR_materials_ior.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_ior.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_ior.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_ior.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_iridescence.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_iridescence.js +6 -66
- package/glTF/2.0/Extensions/KHR_materials_iridescence.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_iridescence.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_iridescence.pure.js +81 -0
- package/glTF/2.0/Extensions/KHR_materials_iridescence.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_iridescence.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_iridescence.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_iridescence.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.js +6 -72
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.js +87 -0
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_sheen.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_sheen.js +6 -71
- package/glTF/2.0/Extensions/KHR_materials_sheen.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_sheen.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_sheen.pure.js +86 -0
- package/glTF/2.0/Extensions/KHR_materials_sheen.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_sheen.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_sheen.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_sheen.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_specular.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_specular.js +6 -74
- package/glTF/2.0/Extensions/KHR_materials_specular.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_specular.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_specular.pure.js +89 -0
- package/glTF/2.0/Extensions/KHR_materials_specular.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_specular.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_specular.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_specular.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_transmission.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_transmission.js +6 -70
- package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_transmission.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_transmission.pure.js +85 -0
- package/glTF/2.0/Extensions/KHR_materials_transmission.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_transmission.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_transmission.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_transmission.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_unlit.d.ts +4 -40
- package/glTF/2.0/Extensions/KHR_materials_unlit.js +6 -64
- package/glTF/2.0/Extensions/KHR_materials_unlit.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_unlit.pure.d.ts +39 -0
- package/glTF/2.0/Extensions/KHR_materials_unlit.pure.js +79 -0
- package/glTF/2.0/Extensions/KHR_materials_unlit.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_unlit.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_unlit.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_unlit.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_variants.d.ts +4 -110
- package/glTF/2.0/Extensions/KHR_materials_variants.js +6 -260
- package/glTF/2.0/Extensions/KHR_materials_variants.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_variants.pure.d.ts +97 -0
- package/glTF/2.0/Extensions/KHR_materials_variants.pure.js +275 -0
- package/glTF/2.0/Extensions/KHR_materials_variants.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_variants.types.d.ts +29 -0
- package/glTF/2.0/Extensions/KHR_materials_variants.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_variants.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_volume.d.ts +4 -41
- package/glTF/2.0/Extensions/KHR_materials_volume.js +6 -77
- package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_volume.pure.d.ts +40 -0
- package/glTF/2.0/Extensions/KHR_materials_volume.pure.js +92 -0
- package/glTF/2.0/Extensions/KHR_materials_volume.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_volume.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_volume.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_volume.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.d.ts +4 -43
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js +6 -113
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.d.ts +42 -0
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.js +128 -0
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_mesh_quantization.d.ts +4 -27
- package/glTF/2.0/Extensions/KHR_mesh_quantization.js +6 -20
- package/glTF/2.0/Extensions/KHR_mesh_quantization.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_mesh_quantization.pure.d.ts +26 -0
- package/glTF/2.0/Extensions/KHR_mesh_quantization.pure.js +35 -0
- package/glTF/2.0/Extensions/KHR_mesh_quantization.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_mesh_quantization.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_mesh_quantization.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_mesh_quantization.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.d.ts +4 -29
- package/glTF/2.0/Extensions/KHR_node_hoverability.js +6 -187
- package/glTF/2.0/Extensions/KHR_node_hoverability.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_node_hoverability.pure.d.ts +28 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js +202 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.d.ts +4 -28
- package/glTF/2.0/Extensions/KHR_node_selectability.js +6 -121
- package/glTF/2.0/Extensions/KHR_node_selectability.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_node_selectability.pure.d.ts +27 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.pure.js +136 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.d.ts +4 -28
- package/glTF/2.0/Extensions/KHR_node_visibility.js +6 -64
- package/glTF/2.0/Extensions/KHR_node_visibility.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_node_visibility.pure.d.ts +27 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.pure.js +79 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_texture_basisu.d.ts +4 -31
- package/glTF/2.0/Extensions/KHR_texture_basisu.js +6 -35
- package/glTF/2.0/Extensions/KHR_texture_basisu.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_texture_basisu.pure.d.ts +30 -0
- package/glTF/2.0/Extensions/KHR_texture_basisu.pure.js +50 -0
- package/glTF/2.0/Extensions/KHR_texture_basisu.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_texture_basisu.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_texture_basisu.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_texture_basisu.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_texture_transform.d.ts +4 -35
- package/glTF/2.0/Extensions/KHR_texture_transform.js +6 -56
- package/glTF/2.0/Extensions/KHR_texture_transform.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_texture_transform.pure.d.ts +34 -0
- package/glTF/2.0/Extensions/KHR_texture_transform.pure.js +71 -0
- package/glTF/2.0/Extensions/KHR_texture_transform.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_texture_transform.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_texture_transform.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_texture_transform.types.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.d.ts +4 -37
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.js +6 -45
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.d.ts +36 -0
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.js +60 -0
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.types.d.ts +9 -0
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.types.js +2 -0
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.types.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_audio_emitter.d.ts +5 -54
- package/glTF/2.0/Extensions/MSFT_audio_emitter.js +7 -226
- package/glTF/2.0/Extensions/MSFT_audio_emitter.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_audio_emitter.pure.d.ts +52 -0
- package/glTF/2.0/Extensions/MSFT_audio_emitter.pure.js +240 -0
- package/glTF/2.0/Extensions/MSFT_audio_emitter.pure.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_audio_emitter.types.d.ts +9 -0
- package/glTF/2.0/Extensions/MSFT_audio_emitter.types.js +2 -0
- package/glTF/2.0/Extensions/MSFT_audio_emitter.types.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_lod.d.ts +4 -102
- package/glTF/2.0/Extensions/MSFT_lod.js +6 -335
- package/glTF/2.0/Extensions/MSFT_lod.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_lod.pure.d.ts +96 -0
- package/glTF/2.0/Extensions/MSFT_lod.pure.js +350 -0
- package/glTF/2.0/Extensions/MSFT_lod.pure.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_lod.types.d.ts +14 -0
- package/glTF/2.0/Extensions/MSFT_lod.types.js +2 -0
- package/glTF/2.0/Extensions/MSFT_lod.types.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.d.ts +6 -27
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.js +8 -40
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.d.ts +24 -0
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.js +53 -0
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.types.d.ts +9 -0
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.types.js +2 -0
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.types.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.d.ts +6 -27
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.js +8 -38
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.d.ts +24 -0
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.js +51 -0
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.js.map +1 -0
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.types.d.ts +9 -0
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.types.js +2 -0
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.types.js.map +1 -0
- package/glTF/2.0/Extensions/pure.d.ts +45 -0
- package/glTF/2.0/Extensions/pure.js +47 -0
- package/glTF/2.0/Extensions/pure.js.map +1 -0
- package/glTF/2.0/glTFLoader.d.ts +1 -471
- package/glTF/2.0/glTFLoader.js +3 -2539
- package/glTF/2.0/glTFLoader.js.map +1 -1
- package/glTF/2.0/glTFLoader.pure.d.ts +476 -0
- package/glTF/2.0/glTFLoader.pure.js +2563 -0
- package/glTF/2.0/glTFLoader.pure.js.map +1 -0
- package/glTF/2.0/pure.d.ts +8 -0
- package/glTF/2.0/pure.js +10 -0
- package/glTF/2.0/pure.js.map +1 -0
- package/glTF/glTFFileLoader.d.ts +5 -551
- package/glTF/glTFFileLoader.js +6 -996
- package/glTF/glTFFileLoader.js.map +1 -1
- package/glTF/glTFFileLoader.pure.d.ts +562 -0
- package/glTF/glTFFileLoader.pure.js +1024 -0
- package/glTF/glTFFileLoader.pure.js.map +1 -0
- package/glTF/glTFFileLoader.types.d.ts +11 -0
- package/glTF/glTFFileLoader.types.js +2 -0
- package/glTF/glTFFileLoader.types.js.map +1 -0
- package/glTF/pure.d.ts +6 -0
- package/glTF/pure.js +8 -0
- package/glTF/pure.js.map +1 -0
- package/package.json +56 -4
- package/pure.d.ts +8 -0
- package/pure.js +10 -0
- 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
|
+
}
|