{"version":3,"file":"babylonjs.loaders.min.js","sources":["file:///home/vsts/work/1/s/packages/dev/loaders/src/BVH/bvhLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/BVH/bvhFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/BVH/bvhFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/BVH/bvhFileLoader.ts","file:///home/vsts/work/1/s/node_modules/tslib/tslib.es6.js","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/parsers/zlibInflate.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/parsers/fbxBinaryParser.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/parsers/fbxAsciiParser.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/types/fbxTypes.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/propertyTemplates.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/nodeTransform.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/connections.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/geometry.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/nurbs.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/legacyDocument.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/constraints.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/materialModel.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/materials.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/skeleton.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/rig.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/animationCurve.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/animation.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/blendShapes.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/sceneDiagnostics.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/fbxInterpreter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/interpreter/transform.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/fbxConstraintBehavior.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/fbxFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/fbxFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/glTFValidation.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/FBX/fbxFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/glTFFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/glTFFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/glTFFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFLoaderUtils.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFBinaryExtension.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFBinaryExtension.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFMaterialsCommonExtension.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/1.0/glTFMaterialsCommonExtension.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtensionRegistry.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/gltfPathToObjectConverter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/objectModelMapping.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/glTFLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/glTFLoaderAnimation.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/glTFLoaderAnimation.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/openpbrMaterialLoadingAdapter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/pbrMaterialLoadingAdapter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_lights_image_based.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_lights_image_based.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_meshopt_compression.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_meshopt_compression.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_webp.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_webp.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_avif.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_avif.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_lights_ies.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_lights_ies.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_gaussian_splatting.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_gaussian_splatting.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_lights_area.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_lights_area.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_coat.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_coat.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_fuzz.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_fuzz.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_variants.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_variants.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/transmissionHelper.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume_scatter.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume_scatter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_roughness.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_mesh_quantization.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_mesh_quantization.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_texture_basisu.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_texture_basisu.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_texture_transform.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_xmp_json_ld.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_xmp_json_ld.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_lod.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_lod.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityReferences.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/compositePathToObjectConverter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/babylonScenePathToObjectConverter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/interactivityAssetPathToObjectConverter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_visibility.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_visibility.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_selectability.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_selectability.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_hoverability.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_node_hoverability.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/ExtrasAsMetadata.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/ExtrasAsMetadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/OBJ/mtlFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/OBJ/solidParser.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/OBJ/objFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/OBJ/objFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/OBJ/objFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/STL/stlFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/STL/stlFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/STL/stlFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/splatFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/sog.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/gaussianSplattingWorkBufferShaders.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/gaussianSplattingWorkBuffer.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/gaussianSplattingDownloadManager.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/gaussianSplattingBlockAllocator.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/gaussianSplattingResidencyController.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/gaussianSplattingStream.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/spz.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/splatFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/SPLAT/splatFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/USD/usdFileLoader.metadata.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/USD/usdCommandProtocol.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/USD/usdSceneMaterializer.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/USD/usdFileLoader.pure.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/dynamic.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/glTF/2.0/Extensions/dynamic.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/USD/usdFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-bvhFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-dynamic.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-glTF.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-glTF1.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-glTF2.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-objFileLoader.ts","file:///home/vsts/work/1/s/packages/dev/loaders/src/legacy/legacy-stlFileLoader.ts"],"sourcesContent":["import { type IAnimationKey } from \"core/Animations\";\nimport { Animation } from \"core/Animations/animation\";\nimport { Bone } from \"core/Bones/bone\";\nimport { Skeleton } from \"core/Bones/skeleton\";\nimport { Matrix, Quaternion, Vector3 } from \"core/Maths/math.vector\";\nimport { type Scene } from \"core/scene\";\nimport { type Nullable } from \"core/types\";\nimport { type BVHLoadingOptions } from \"./bvhLoadingOptions\";\nimport { Tools } from \"core/Misc/tools\";\nimport { type AssetContainer } from \"core/assetContainer\";\n\nconst _XPosition = \"Xposition\";\nconst _YPosition = \"Yposition\";\nconst _ZPosition = \"Zposition\";\nconst _XRotation = \"Xrotation\";\nconst _YRotation = \"Yrotation\";\nconst _ZRotation = \"Zrotation\";\n\nconst _HierarchyNode = \"HIERARCHY\";\nconst _MotionNode = \"MOTION\";\n\nclass LoaderContext {\n    loopMode: number = Animation.ANIMATIONLOOPMODE_CYCLE;\n    list: IBVHNode[] = [];\n    root: IBVHNode = CreateBVHNode();\n    numFrames: number = 0;\n    frameRate: number = 0;\n    skeleton: Skeleton;\n\n    constructor(skeleton: Skeleton) {\n        this.skeleton = skeleton;\n    }\n}\n\ninterface IBVHNode {\n    name: string;\n    type: string;\n    offset: Vector3;\n    channels: string[];\n    children: IBVHNode[];\n    frames: IBVHKeyFrame[];\n    parent: Nullable<IBVHNode>;\n}\n\ninterface IBVHKeyFrame {\n    frame: number;\n    position: Vector3;\n    rotation: Quaternion;\n}\n\nfunction CreateBVHNode(): IBVHNode {\n    return {\n        name: \"\",\n        type: \"\",\n        offset: new Vector3(),\n        channels: [],\n        children: [],\n        frames: [],\n        parent: null,\n    };\n}\n\nfunction CreateBVHKeyFrame(): IBVHKeyFrame {\n    return {\n        frame: 0,\n        position: new Vector3(),\n        rotation: new Quaternion(),\n    };\n}\n\n/**\n * Converts the BVH node's offset to a Babylon matrix\n * @param node - The BVH node to convert\n * @returns The converted matrix\n */\nfunction BoneOffset(node: IBVHNode): Matrix {\n    const x = node.offset.x;\n    const y = node.offset.y;\n    const z = node.offset.z;\n    return Matrix.Translation(x, y, z);\n}\n\n/**\n * Creates animations for the BVH node\n * @param node - The BVH node to create animations for\n * @param context - The loader context\n * @returns The created animations\n */\nfunction CreateAnimations(node: IBVHNode, context: LoaderContext): Animation[] {\n    if (node.frames.length === 0) {\n        return [];\n    }\n\n    const animations: Animation[] = [];\n\n    // Create position animation if there are position channels\n    const hasPosition = node.channels.some((c) => c === _XPosition || c === _YPosition || c === _ZPosition);\n\n    // Create rotation animation if there are rotation channels\n    const hasRotation = node.channels.some((c) => c === _XRotation || c === _YRotation || c === _ZRotation);\n\n    const posAnim = new Animation(`${node.name}_pos`, \"position\", context.frameRate, Animation.ANIMATIONTYPE_VECTOR3, context.loopMode);\n\n    const rotAnim = new Animation(`${node.name}_rot`, \"rotationQuaternion\", context.frameRate, Animation.ANIMATIONTYPE_QUATERNION, context.loopMode);\n\n    const posKeys: IAnimationKey[] = [];\n    const rotKeys: IAnimationKey[] = [];\n\n    for (let i = 0; i < node.frames.length; i++) {\n        const frame = node.frames[i];\n\n        if (hasPosition && frame.position) {\n            posKeys.push({\n                frame: frame.frame,\n                value: frame.position.clone(),\n            });\n        }\n\n        if (hasRotation) {\n            rotKeys.push({\n                frame: frame.frame,\n                value: frame.rotation.clone(),\n            });\n        }\n    }\n\n    if (posKeys.length > 0) {\n        posAnim.setKeys(posKeys);\n        animations.push(posAnim);\n    }\n\n    if (rotKeys.length > 0) {\n        rotAnim.setKeys(rotKeys);\n        animations.push(rotAnim);\n    }\n\n    return animations;\n}\n\n/**\n * Converts a BVH node to a Babylon bone\n * @param node - The BVH node to convert\n * @param parent - The parent bone\n * @param context - The loader context\n */\nfunction ConvertNode(node: IBVHNode, parent: Nullable<Bone>, context: LoaderContext) {\n    const matrix = BoneOffset(node);\n    const bone = new Bone(node.name, context.skeleton, parent, matrix);\n\n    // Create animation for this bone\n    const animations = CreateAnimations(node, context);\n    for (const animation of animations) {\n        if (animation.getKeys() && animation.getKeys().length > 0) {\n            bone.animations.push(animation);\n        }\n    }\n\n    for (const child of node.children) {\n        ConvertNode(child, bone, context);\n    }\n}\n\n/**\n * Recursively reads data from a single frame into the bone hierarchy.\n * The bone hierarchy has to be structured in the same order as the BVH file.\n * keyframe data is stored in bone.frames.\n * @param data - splitted string array (frame values), values are shift()ed\n * @param frameNumber - playback time for this keyframe\n * @param bone - the bone to read frame data from\n * @param tokenIndex - the index of the token to read\n */\nfunction ReadFrameData(data: string[], frameNumber: number, bone: IBVHNode, tokenIndex: { i: number }) {\n    if (bone.type === \"ENDSITE\") {\n        // end sites have no motion data\n        return;\n    }\n\n    // add keyframe\n    const keyframe = CreateBVHKeyFrame();\n    keyframe.frame = frameNumber;\n    keyframe.position = new Vector3();\n    keyframe.rotation = new Quaternion();\n\n    bone.frames.push(keyframe);\n\n    let combinedRotation = Matrix.Identity();\n\n    // parse values for each channel in node\n    for (let i = 0; i < bone.channels.length; ++i) {\n        const channel = bone.channels[i];\n        const value = data[tokenIndex.i++];\n        if (!value) {\n            continue;\n        }\n        const parsedValue = parseFloat(value.trim());\n        if (channel.endsWith(\"position\")) {\n            switch (channel) {\n                case _XPosition:\n                    keyframe.position.x = parsedValue;\n                    break;\n                case _YPosition:\n                    keyframe.position.y = parsedValue;\n                    break;\n                case _ZPosition:\n                    keyframe.position.z = parsedValue;\n                    break;\n            }\n        } else if (channel.endsWith(\"rotation\")) {\n            const angle = Tools.ToRadians(parsedValue);\n            let rotationMatrix: Matrix;\n            switch (channel) {\n                case _XRotation:\n                    rotationMatrix = Matrix.RotationX(angle);\n                    break;\n                case _YRotation:\n                    rotationMatrix = Matrix.RotationY(angle);\n                    break;\n                case _ZRotation:\n                    rotationMatrix = Matrix.RotationZ(angle);\n                    break;\n            }\n            combinedRotation = rotationMatrix!.multiply(combinedRotation);\n        }\n    }\n\n    Quaternion.FromRotationMatrixToRef(combinedRotation, keyframe.rotation);\n\n    // parse child nodes\n    for (const child of bone.children) {\n        ReadFrameData(data, frameNumber, child, tokenIndex);\n    }\n}\n\n/**\n * Recursively parses the HIERARCHY section of the BVH file\n * @param lines - all lines of the file. lines are consumed as we go along\n * @param firstLine - line containing the node type and name e.g. \"JOINT hip\"\n * @param parent - the parent node for hierarchy\n * @param context - the loader context containing the list of nodes and other data\n * @returns a BVH node including children\n */\nfunction ReadNode(lines: string[], firstLine: string, parent: Nullable<IBVHNode>, context: LoaderContext): IBVHNode {\n    const node = CreateBVHNode();\n    node.parent = parent;\n    context.list.push(node);\n\n    // parse node type and name.\n    let tokens: string[] | undefined = firstLine.trim().split(/\\s+/);\n\n    if (tokens[0].toUpperCase() === \"END\" && tokens[1].toUpperCase() === \"SITE\") {\n        node.type = \"ENDSITE\";\n        node.name = \"ENDSITE\"; // bvh end sites have no name\n    } else {\n        node.name = tokens[1];\n        node.type = tokens[0].toUpperCase();\n    }\n\n    // opening bracket\n    if (lines.shift()?.trim() != \"{\") {\n        throw new Error(\"Expected opening { after type & name\");\n    }\n\n    // parse OFFSET\n    const tokensSplit = lines.shift()?.trim().split(/\\s+/);\n    if (!tokensSplit) {\n        throw new Error(\"Unexpected end of file: missing OFFSET\");\n    }\n    tokens = tokensSplit;\n\n    if (tokens[0].toUpperCase() != \"OFFSET\") {\n        throw new Error(\"Expected OFFSET, but got: \" + tokens[0]);\n    }\n    if (tokens.length != 4) {\n        throw new Error(\"OFFSET: Invalid number of values\");\n    }\n\n    const offset = new Vector3(parseFloat(tokens[1]), parseFloat(tokens[2]), parseFloat(tokens[3]));\n\n    if (isNaN(offset.x) || isNaN(offset.y) || isNaN(offset.z)) {\n        throw new Error(\"OFFSET: Invalid values\");\n    }\n\n    node.offset = offset;\n\n    // parse CHANNELS definitions\n    if (node.type != \"ENDSITE\") {\n        tokens = lines.shift()?.trim().split(/\\s+/);\n        if (!tokens) {\n            throw new Error(\"Unexpected end of file: missing CHANNELS\");\n        }\n\n        if (tokens[0].toUpperCase() != \"CHANNELS\") {\n            throw new Error(\"Expected CHANNELS definition\");\n        }\n\n        const numChannels = parseInt(tokens[1]);\n        // Skip CHANNELS and the number of channels\n        node.channels = tokens.splice(2, numChannels);\n        node.children = [];\n    }\n\n    // read children\n    while (lines.length > 0) {\n        const line = lines.shift()?.trim();\n\n        if (line === \"}\") {\n            // Finish reading the node\n            return node;\n        } else if (line) {\n            node.children.push(ReadNode(lines, line, node, context));\n        }\n    }\n\n    throw new Error(\"Unexpected end of file: missing closing brace\");\n}\n\n/**\n * Reads a BVH file, returns a skeleton\n * @param text - The BVH file content\n * @param scene - The scene to add the skeleton to\n * @param assetContainer - The asset container to add the skeleton to\n * @param loadingOptions - The loading options\n * @returns The skeleton\n */\nexport function ReadBvh(text: string, scene: Scene, assetContainer: Nullable<AssetContainer>, loadingOptions: BVHLoadingOptions): Skeleton {\n    const lines = text.split(\"\\n\");\n\n    const { loopMode } = loadingOptions;\n\n    scene._blockEntityCollection = !!assetContainer;\n    const skeleton = new Skeleton(\"\", \"\", scene);\n    skeleton._parentContainer = assetContainer;\n    scene._blockEntityCollection = false;\n\n    const context = new LoaderContext(skeleton);\n    context.loopMode = loopMode;\n\n    // read model structure\n    const firstLine = lines.shift();\n    if (!firstLine || firstLine.trim().toUpperCase() !== _HierarchyNode) {\n        throw new Error(\"HIERARCHY expected\");\n    }\n\n    const nodeLine = lines.shift();\n    if (!nodeLine) {\n        throw new Error(\"Unexpected end of file after HIERARCHY\");\n    }\n    const root = ReadNode(lines, nodeLine.trim(), null, context);\n\n    // read motion data\n    const motionLine = lines.shift();\n    if (!motionLine || motionLine.trim().toUpperCase() !== _MotionNode) {\n        throw new Error(\"MOTION expected\");\n    }\n\n    const framesLine = lines.shift();\n    if (!framesLine) {\n        throw new Error(\"Unexpected end of file before frame count\");\n    }\n    const framesTokens = framesLine.trim().split(/[\\s]+/);\n    if (framesTokens.length < 2) {\n        throw new Error(\"Invalid frame count line\");\n    }\n\n    // number of frames\n    const numFrames = parseInt(framesTokens[1]);\n    if (isNaN(numFrames)) {\n        throw new Error(\"Failed to read number of frames.\");\n    }\n    context.numFrames = numFrames;\n\n    // frame time\n    const frameTimeLine = lines.shift();\n    if (!frameTimeLine) {\n        throw new Error(\"Unexpected end of file before frame time\");\n    }\n    const frameTimeTokens = frameTimeLine.trim().split(/[\\s]+/);\n    if (frameTimeTokens.length < 3) {\n        throw new Error(\"Invalid frame time line\");\n    }\n    const frameTime = parseFloat(frameTimeTokens[2]);\n    if (isNaN(frameTime)) {\n        throw new Error(\"Failed to read frame time.\");\n    }\n    if (frameTime <= 0) {\n        throw new Error(\"Failed to read frame time. Invalid value \" + frameTime);\n    }\n\n    context.frameRate = 1 / frameTime;\n\n    // read frame data line by line\n    for (let i = 0; i < numFrames; ++i) {\n        const frameLine = lines.shift();\n        if (!frameLine) {\n            continue;\n        }\n        const tokens = frameLine.trim().split(/[\\s]+/) || [];\n        ReadFrameData(tokens, i, root, { i: 0 });\n    }\n\n    context.root = root;\n\n    ConvertNode(context.root, null, context);\n\n    context.skeleton.returnToRest();\n    return context.skeleton;\n}\n","import { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const BVHFileLoaderMetadata = {\r\n    name: \"bvh\",\r\n    extensions: {\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".bvh\": { isBinary: false },\r\n    } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n","import {\r\n    type ISceneLoaderPluginAsync,\r\n    type ISceneLoaderPluginFactory,\r\n    type ISceneLoaderAsyncResult,\r\n    type SceneLoaderPluginOptions,\r\n    RegisterSceneLoaderPlugin,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { Animation } from \"core/Animations/animation.pure\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type BVHLoadingOptions } from \"./bvhLoadingOptions\";\r\nimport { BVHFileLoaderMetadata } from \"./bvhFileLoader.metadata\";\r\nimport { ReadBvh } from \"./bvhLoader\";\r\n\r\n/**\r\n * @experimental\r\n * BVH file type loader.\r\n * This is a babylon scene loader plugin.\r\n */\r\nexport class BVHFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\r\n    /**\r\n     * Name of the loader (\"bvh\")\r\n     */\r\n    public readonly name = BVHFileLoaderMetadata.name;\r\n\r\n    /** @internal */\r\n    public readonly extensions = BVHFileLoaderMetadata.extensions;\r\n\r\n    private readonly _loadingOptions: BVHLoadingOptions;\r\n\r\n    /**\r\n     * Creates loader for bvh motion files\r\n     * @param loadingOptions - Options for the bvh loader\r\n     */\r\n    constructor(loadingOptions?: Partial<Readonly<BVHLoadingOptions>>) {\r\n        this._loadingOptions = { ...BVHFileLoader._DefaultLoadingOptions, ...(loadingOptions ?? {}) };\r\n    }\r\n\r\n    private static get _DefaultLoadingOptions(): BVHLoadingOptions {\r\n        return {\r\n            loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,\r\n        };\r\n    }\r\n\r\n    /** @internal */\r\n    public createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\r\n        return new BVHFileLoader(options[BVHFileLoaderMetadata.name]);\r\n    }\r\n\r\n    /**\r\n     * If the data string can be loaded directly.\r\n     * @param data - direct load data\r\n     * @returns if the data can be loaded directly\r\n     */\r\n    public canDirectLoad(data: string): boolean {\r\n        return this.isBvhHeader(data);\r\n    }\r\n\r\n    /**\r\n     * Returns whether the provided text starts with a BVH HIERARCHY header.\r\n     * @param text - the text to inspect\r\n     * @returns true if the text is a BVH header\r\n     */\r\n    public isBvhHeader(text: string): boolean {\r\n        return text.split(\"\\n\")[0] == \"HIERARCHY\";\r\n    }\r\n\r\n    /**\r\n     * Returns whether the provided text does not start with a BVH HIERARCHY header.\r\n     * @param text - the text to inspect\r\n     * @returns true if the text is not a BVH header\r\n     */\r\n    public isNotBvhHeader(text: string): boolean {\r\n        return !this.isBvhHeader(text);\r\n    }\r\n\r\n    /**\r\n     * Imports  from the loaded gaussian splatting data and adds them to the scene\r\n     * @param _meshesNames a string or array of strings of the mesh names that should be loaded from the file\r\n     * @param scene the scene the meshes should be added to\r\n     * @param data the bvh data to load\r\n     * @returns a promise containing the loaded skeletons and animations\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    public importMeshAsync(_meshesNames: string | readonly string[] | null | undefined, scene: Scene, data: unknown): Promise<ISceneLoaderAsyncResult> {\r\n        if (typeof data !== \"string\") {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(\"BVH loader expects string data.\");\r\n        }\r\n        if (this.isNotBvhHeader(data as string)) {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(\"BVH loader expects HIERARCHY header.\");\r\n        }\r\n        try {\r\n            const skeleton = ReadBvh(data, scene, null, this._loadingOptions);\r\n            return Promise.resolve({\r\n                meshes: [],\r\n                particleSystems: [],\r\n                skeletons: [skeleton],\r\n                animationGroups: [],\r\n                transformNodes: [],\r\n                geometries: [],\r\n                lights: [],\r\n                spriteManagers: [],\r\n            } as ISceneLoaderAsyncResult);\r\n        } catch (e) {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(e);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Imports all objects from the loaded bvh data and adds them to the scene\r\n     * @param scene the scene the objects should be added to\r\n     * @param data the bvh data to load\r\n     * @returns a promise which completes when objects have been loaded to the scene\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async\r\n    public loadAsync(scene: Scene, data: unknown): Promise<void> {\r\n        if (typeof data !== \"string\") {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(\"BVH loader expects string data.\");\r\n        }\r\n        if (this.isNotBvhHeader(data as string)) {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(\"BVH loader expects HIERARCHY header.\");\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return this.importMeshAsync(null, scene, data).then(() => {\r\n            // return void\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Load into an asset container.\r\n     * @param scene The scene to load into\r\n     * @param data The data to import\r\n     * @returns The loaded asset container\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    public loadAssetContainerAsync(scene: Scene, data: unknown): Promise<AssetContainer> {\r\n        if (typeof data !== \"string\") {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(\"BVH loader expects string data.\");\r\n        }\r\n        if (this.isNotBvhHeader(data as string)) {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(\"BVH loader expects HIERARCHY header.\");\r\n        }\r\n        const assetContainer = new AssetContainer(scene);\r\n        try {\r\n            const skeleton = ReadBvh(data, scene, assetContainer, this._loadingOptions);\r\n            assetContainer.skeletons.push(skeleton);\r\n            return Promise.resolve(assetContainer);\r\n        } catch (e) {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            return Promise.reject(e);\r\n        }\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the BVHFileLoader scene loader plugin.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterBVHFileLoader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    RegisterSceneLoaderPlugin(new BVHFileLoader());\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./bvhFileLoader.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./bvhFileLoader.types\";\r\nexport * from \"./bvhFileLoader.pure\";\r\n\r\nimport { RegisterBVHFileLoader } from \"./bvhFileLoader.pure\";\r\nRegisterBVHFileLoader();\r\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n    extendStatics = Object.setPrototypeOf ||\r\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n        function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n    return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n    if (typeof b !== \"function\" && b !== null)\r\n        throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n    extendStatics(d, b);\r\n    function __() { this.constructor = d; }\r\n    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n    __assign = Object.assign || function __assign(t) {\r\n        for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n            s = arguments[i];\r\n            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n        }\r\n        return t;\r\n    }\r\n    return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n    var t = {};\r\n    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n        t[p] = s[p];\r\n    if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n                t[p[i]] = s[p[i]];\r\n        }\r\n    return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n    return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n    return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n    function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n    var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n    var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n    var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n    var _, done = false;\r\n    for (var i = decorators.length - 1; i >= 0; i--) {\r\n        var context = {};\r\n        for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n        for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n        context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n        var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n        if (kind === \"accessor\") {\r\n            if (result === void 0) continue;\r\n            if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n            if (_ = accept(result.get)) descriptor.get = _;\r\n            if (_ = accept(result.set)) descriptor.set = _;\r\n            if (_ = accept(result.init)) initializers.unshift(_);\r\n        }\r\n        else if (_ = accept(result)) {\r\n            if (kind === \"field\") initializers.unshift(_);\r\n            else descriptor[key] = _;\r\n        }\r\n    }\r\n    if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n    done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n    var useValue = arguments.length > 2;\r\n    for (var i = 0; i < initializers.length; i++) {\r\n        value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n    }\r\n    return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n    return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n    if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n    return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n    if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n    return new (P || (P = Promise))(function (resolve, reject) {\r\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n    });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n    return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n    function verb(n) { return function (v) { return step([n, v]); }; }\r\n    function step(op) {\r\n        if (f) throw new TypeError(\"Generator is already executing.\");\r\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n            if (y = 0, t) op = [op[0] & 2, t.value];\r\n            switch (op[0]) {\r\n                case 0: case 1: t = op; break;\r\n                case 4: _.label++; return { value: op[1], done: false };\r\n                case 5: _.label++; y = op[1]; op = [0]; continue;\r\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n                default:\r\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n                    if (t[2]) _.ops.pop();\r\n                    _.trys.pop(); continue;\r\n            }\r\n            op = body.call(thisArg, _);\r\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n    }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n    if (k2 === undefined) k2 = k;\r\n    var desc = Object.getOwnPropertyDescriptor(m, k);\r\n    if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n        desc = { enumerable: true, get: function() { return m[k]; } };\r\n    }\r\n    Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n    if (k2 === undefined) k2 = k;\r\n    o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n    for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n    var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n    if (m) return m.call(o);\r\n    if (o && typeof o.length === \"number\") return {\r\n        next: function () {\r\n            if (o && i >= o.length) o = void 0;\r\n            return { value: o && o[i++], done: !o };\r\n        }\r\n    };\r\n    throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n    var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n    if (!m) return o;\r\n    var i = m.call(o), r, ar = [], e;\r\n    try {\r\n        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n    }\r\n    catch (error) { e = { error: error }; }\r\n    finally {\r\n        try {\r\n            if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n        }\r\n        finally { if (e) throw e.error; }\r\n    }\r\n    return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n    for (var ar = [], i = 0; i < arguments.length; i++)\r\n        ar = ar.concat(__read(arguments[i]));\r\n    return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n    for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n            r[k] = a[j];\r\n    return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n        if (ar || !(i in from)) {\r\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n            ar[i] = from[i];\r\n        }\r\n    }\r\n    return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n    return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n    if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n    var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n    return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n    function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n    function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n    function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n    function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n    function fulfill(value) { resume(\"next\", value); }\r\n    function reject(value) { resume(\"throw\", value); }\r\n    function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n    var i, p;\r\n    return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n    function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n    if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n    var m = o[Symbol.asyncIterator], i;\r\n    return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n    if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n    return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n    Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n    o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n    ownKeys = Object.getOwnPropertyNames || function (o) {\r\n        var ar = [];\r\n        for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n        return ar;\r\n    };\r\n    return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n    if (mod && mod.__esModule) return mod;\r\n    var result = {};\r\n    if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n    __setModuleDefault(result, mod);\r\n    return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n    return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n    if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n    if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n    return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n    if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n    if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n    if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n    return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n    if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n    return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n    if (value !== null && value !== void 0) {\r\n        if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n        var dispose, inner;\r\n        if (async) {\r\n            if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n            dispose = value[Symbol.asyncDispose];\r\n        }\r\n        if (dispose === void 0) {\r\n            if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n            dispose = value[Symbol.dispose];\r\n            if (async) inner = dispose;\r\n        }\r\n        if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n        if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n        env.stack.push({ value: value, dispose: dispose, async: async });\r\n    }\r\n    else if (async) {\r\n        env.stack.push({ async: true });\r\n    }\r\n    return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n    var e = new Error(message);\r\n    return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n    function fail(e) {\r\n        env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n        env.hasError = true;\r\n    }\r\n    var r, s = 0;\r\n    function next() {\r\n        while (r = env.stack.pop()) {\r\n            try {\r\n                if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n                if (r.dispose) {\r\n                    var result = r.dispose.call(r.value);\r\n                    if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n                }\r\n                else s |= 1;\r\n            }\r\n            catch (e) {\r\n                fail(e);\r\n            }\r\n        }\r\n        if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n        if (env.hasError) throw env.error;\r\n    }\r\n    return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n    if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n        return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n            return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n        });\r\n    }\r\n    return path;\r\n}\r\n\r\nexport default {\r\n    __extends: __extends,\r\n    __assign: __assign,\r\n    __rest: __rest,\r\n    __decorate: __decorate,\r\n    __param: __param,\r\n    __esDecorate: __esDecorate,\r\n    __runInitializers: __runInitializers,\r\n    __propKey: __propKey,\r\n    __setFunctionName: __setFunctionName,\r\n    __metadata: __metadata,\r\n    __awaiter: __awaiter,\r\n    __generator: __generator,\r\n    __createBinding: __createBinding,\r\n    __exportStar: __exportStar,\r\n    __values: __values,\r\n    __read: __read,\r\n    __spread: __spread,\r\n    __spreadArrays: __spreadArrays,\r\n    __spreadArray: __spreadArray,\r\n    __await: __await,\r\n    __asyncGenerator: __asyncGenerator,\r\n    __asyncDelegator: __asyncDelegator,\r\n    __asyncValues: __asyncValues,\r\n    __makeTemplateObject: __makeTemplateObject,\r\n    __importStar: __importStar,\r\n    __importDefault: __importDefault,\r\n    __classPrivateFieldGet: __classPrivateFieldGet,\r\n    __classPrivateFieldSet: __classPrivateFieldSet,\r\n    __classPrivateFieldIn: __classPrivateFieldIn,\r\n    __addDisposableResource: __addDisposableResource,\r\n    __disposeResources: __disposeResources,\r\n    __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nconst ADLER_MOD = 65521;\r\nconst MAX_BITS = 15;\r\n\r\nconst LENGTH_BASE = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258];\r\nconst LENGTH_EXTRA_BITS = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];\r\nconst DISTANCE_BASE = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577];\r\nconst DISTANCE_EXTRA_BITS = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];\r\nconst CODE_LENGTH_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\r\n\r\n/**\r\n * Inflate a zlib-wrapped deflate stream.\r\n *\r\n * This implementation is intentionally scoped to FBX binary array payloads: one-shot,\r\n * synchronous zlib streams with the exact uncompressed length known up front.\r\n */\r\nexport function inflateZlib(input: Uint8Array, expectedLength: number): Uint8Array {\r\n    if (!Number.isInteger(expectedLength) || expectedLength < 0) {\r\n        throw new Error(\"zlib: invalid expected length\");\r\n    }\r\n    if (input.byteLength < 6) {\r\n        throw new Error(\"zlib: unexpected end of input\");\r\n    }\r\n\r\n    const cmf = input[0];\r\n    const flg = input[1];\r\n    if ((cmf & 0x0f) !== 8 || cmf >> 4 > 7 || ((cmf << 8) + flg) % 31 !== 0) {\r\n        throw new Error(\"zlib: invalid header\");\r\n    }\r\n    if ((flg & 0x20) !== 0) {\r\n        throw new Error(\"zlib: preset dictionary not supported\");\r\n    }\r\n\r\n    const reader = new BitReader(input, 2, input.byteLength - 4);\r\n    const output = new OutputWriter(expectedLength);\r\n\r\n    let isFinalBlock = false;\r\n    while (!isFinalBlock) {\r\n        isFinalBlock = reader.readBits(1) === 1;\r\n        const blockType = reader.readBits(2);\r\n        switch (blockType) {\r\n            case 0:\r\n                inflateStoredBlock(reader, output);\r\n                break;\r\n            case 1:\r\n                inflateCompressedBlock(reader, output, getFixedLiteralLengthTree(), getFixedDistanceTree());\r\n                break;\r\n            case 2: {\r\n                const { literalLengthTree, distanceTree } = readDynamicTrees(reader);\r\n                inflateCompressedBlock(reader, output, literalLengthTree, distanceTree);\r\n                break;\r\n            }\r\n            default:\r\n                throw new Error(\"deflate: invalid block type\");\r\n        }\r\n    }\r\n\r\n    if (reader.byteOffset < input.byteLength - 4) {\r\n        throw new Error(\"zlib: trailing deflate data\");\r\n    }\r\n\r\n    output.finish();\r\n    const expectedAdler = ((input[input.byteLength - 4] << 24) | (input[input.byteLength - 3] << 16) | (input[input.byteLength - 2] << 8) | input[input.byteLength - 1]) >>> 0;\r\n    if (output.adler32() !== expectedAdler) {\r\n        throw new Error(\"zlib: adler32 mismatch\");\r\n    }\r\n\r\n    return output.bytes;\r\n}\r\n\r\nclass BitReader {\r\n    private bitBuffer = 0;\r\n    private bitCount = 0;\r\n\r\n    public constructor(\r\n        private readonly input: Uint8Array,\r\n        public byteOffset: number,\r\n        private readonly endOffset: number\r\n    ) {}\r\n\r\n    public readBits(count: number): number {\r\n        this.ensureBits(count);\r\n        const value = this.bitBuffer & ((1 << count) - 1);\r\n        this.bitBuffer >>>= count;\r\n        this.bitCount -= count;\r\n        return value;\r\n    }\r\n\r\n    public readBit(): number {\r\n        if (this.bitCount === 0) {\r\n            if (this.byteOffset >= this.endOffset) {\r\n                throw new Error(\"zlib: unexpected end of input\");\r\n            }\r\n            this.bitBuffer = this.input[this.byteOffset++];\r\n            this.bitCount = 8;\r\n        }\r\n        const bit = this.bitBuffer & 1;\r\n        this.bitBuffer >>>= 1;\r\n        this.bitCount--;\r\n        return bit;\r\n    }\r\n\r\n    public alignToByte(): void {\r\n        this.bitBuffer = 0;\r\n        this.bitCount = 0;\r\n    }\r\n\r\n    public readUint16LE(): number {\r\n        this.ensureByteAligned();\r\n        if (this.byteOffset + 2 > this.endOffset) {\r\n            throw new Error(\"zlib: unexpected end of input\");\r\n        }\r\n        const value = this.input[this.byteOffset] | (this.input[this.byteOffset + 1] << 8);\r\n        this.byteOffset += 2;\r\n        return value;\r\n    }\r\n\r\n    public readByte(): number {\r\n        this.ensureByteAligned();\r\n        if (this.byteOffset >= this.endOffset) {\r\n            throw new Error(\"zlib: unexpected end of input\");\r\n        }\r\n        return this.input[this.byteOffset++];\r\n    }\r\n\r\n    private ensureByteAligned(): void {\r\n        if (this.bitCount !== 0) {\r\n            throw new Error(\"deflate: expected byte alignment\");\r\n        }\r\n    }\r\n\r\n    private ensureBits(count: number): void {\r\n        while (this.bitCount < count) {\r\n            if (this.byteOffset >= this.endOffset) {\r\n                throw new Error(\"zlib: unexpected end of input\");\r\n            }\r\n            this.bitBuffer |= this.input[this.byteOffset++] << this.bitCount;\r\n            this.bitCount += 8;\r\n        }\r\n    }\r\n}\r\n\r\nclass OutputWriter {\r\n    private offset = 0;\r\n    private adlerA = 1;\r\n    private adlerB = 0;\r\n\r\n    public readonly bytes: Uint8Array;\r\n\r\n    public constructor(expectedLength: number) {\r\n        this.bytes = new Uint8Array(expectedLength);\r\n    }\r\n\r\n    public writeByte(value: number): void {\r\n        if (this.offset >= this.bytes.byteLength) {\r\n            throw new Error(\"zlib: output length mismatch\");\r\n        }\r\n        const byte = value & 0xff;\r\n        this.bytes[this.offset++] = byte;\r\n        this.adlerA += byte;\r\n        this.adlerB += this.adlerA;\r\n        this.adlerA %= ADLER_MOD;\r\n        this.adlerB %= ADLER_MOD;\r\n    }\r\n\r\n    public copy(distance: number, length: number): void {\r\n        if (distance <= 0 || distance > this.offset) {\r\n            throw new Error(\"deflate: distance out of range\");\r\n        }\r\n        for (let i = 0; i < length; i++) {\r\n            this.writeByte(this.bytes[this.offset - distance]);\r\n        }\r\n    }\r\n\r\n    public finish(): void {\r\n        if (this.offset !== this.bytes.byteLength) {\r\n            throw new Error(\"zlib: output length mismatch\");\r\n        }\r\n    }\r\n\r\n    public adler32(): number {\r\n        return ((this.adlerB << 16) | this.adlerA) >>> 0;\r\n    }\r\n}\r\n\r\nclass HuffmanTree {\r\n    private readonly symbolsByLength: Array<Int16Array | undefined>;\r\n    private readonly maxCodeLength: number;\r\n\r\n    public constructor(codeLengths: readonly number[], options: { allowEmpty?: boolean } = {}) {\r\n        const counts = new Array<number>(MAX_BITS + 1).fill(0);\r\n        let nonZeroCount = 0;\r\n        let maxCodeLength = 0;\r\n\r\n        for (const length of codeLengths) {\r\n            if (!Number.isInteger(length) || length < 0 || length > MAX_BITS) {\r\n                throw new Error(\"deflate: invalid huffman code lengths\");\r\n            }\r\n            if (length > 0) {\r\n                counts[length]++;\r\n                nonZeroCount++;\r\n                maxCodeLength = Math.max(maxCodeLength, length);\r\n            }\r\n        }\r\n\r\n        if (nonZeroCount === 0) {\r\n            if (options.allowEmpty) {\r\n                this.symbolsByLength = [];\r\n                this.maxCodeLength = 0;\r\n                return;\r\n            }\r\n            throw new Error(\"deflate: invalid huffman code lengths\");\r\n        }\r\n\r\n        let remaining = 1;\r\n        for (let bits = 1; bits <= MAX_BITS; bits++) {\r\n            remaining = (remaining << 1) - counts[bits];\r\n            if (remaining < 0) {\r\n                throw new Error(\"deflate: invalid huffman code lengths\");\r\n            }\r\n        }\r\n        if (remaining !== 0 && nonZeroCount !== 1) {\r\n            throw new Error(\"deflate: invalid huffman code lengths\");\r\n        }\r\n\r\n        const nextCode = new Array<number>(MAX_BITS + 1).fill(0);\r\n        let code = 0;\r\n        for (let bits = 1; bits <= MAX_BITS; bits++) {\r\n            code = (code + counts[bits - 1]) << 1;\r\n            nextCode[bits] = code;\r\n        }\r\n\r\n        this.symbolsByLength = Array.from({ length: MAX_BITS + 1 }, (_, length) => {\r\n            if (counts[length] === 0) {\r\n                return undefined;\r\n            }\r\n            const symbols = new Int16Array(1 << length);\r\n            symbols.fill(-1);\r\n            return symbols;\r\n        });\r\n        for (let symbol = 0; symbol < codeLengths.length; symbol++) {\r\n            const length = codeLengths[symbol];\r\n            if (length === 0) {\r\n                continue;\r\n            }\r\n            this.symbolsByLength[length]![nextCode[length]++] = symbol;\r\n        }\r\n        this.maxCodeLength = maxCodeLength;\r\n    }\r\n\r\n    public decode(reader: BitReader): number {\r\n        if (this.maxCodeLength === 0) {\r\n            throw new Error(\"deflate: invalid huffman code\");\r\n        }\r\n\r\n        let code = 0;\r\n        for (let length = 1; length <= this.maxCodeLength; length++) {\r\n            code = (code << 1) | reader.readBit();\r\n            const symbol = this.symbolsByLength[length]?.[code] ?? -1;\r\n            if (symbol >= 0) {\r\n                return symbol;\r\n            }\r\n        }\r\n        throw new Error(\"deflate: invalid huffman code\");\r\n    }\r\n}\r\n\r\nlet fixedLiteralLengthTree: HuffmanTree | undefined;\r\nlet fixedDistanceTree: HuffmanTree | undefined;\r\n\r\nfunction getFixedLiteralLengthTree(): HuffmanTree {\r\n    if (!fixedLiteralLengthTree) {\r\n        const lengths = new Array<number>(288);\r\n        for (let symbol = 0; symbol <= 143; symbol++) {\r\n            lengths[symbol] = 8;\r\n        }\r\n        for (let symbol = 144; symbol <= 255; symbol++) {\r\n            lengths[symbol] = 9;\r\n        }\r\n        for (let symbol = 256; symbol <= 279; symbol++) {\r\n            lengths[symbol] = 7;\r\n        }\r\n        for (let symbol = 280; symbol <= 287; symbol++) {\r\n            lengths[symbol] = 8;\r\n        }\r\n        fixedLiteralLengthTree = new HuffmanTree(lengths);\r\n    }\r\n    return fixedLiteralLengthTree;\r\n}\r\n\r\nfunction getFixedDistanceTree(): HuffmanTree {\r\n    if (!fixedDistanceTree) {\r\n        fixedDistanceTree = new HuffmanTree(new Array<number>(32).fill(5));\r\n    }\r\n    return fixedDistanceTree;\r\n}\r\n\r\nfunction inflateStoredBlock(reader: BitReader, output: OutputWriter): void {\r\n    reader.alignToByte();\r\n    const length = reader.readUint16LE();\r\n    const inverseLength = reader.readUint16LE();\r\n    if (((length ^ inverseLength) & 0xffff) !== 0xffff) {\r\n        throw new Error(\"deflate: invalid stored block length\");\r\n    }\r\n\r\n    for (let i = 0; i < length; i++) {\r\n        output.writeByte(reader.readByte());\r\n    }\r\n}\r\n\r\nfunction inflateCompressedBlock(reader: BitReader, output: OutputWriter, literalLengthTree: HuffmanTree, distanceTree: HuffmanTree): void {\r\n    while (true) {\r\n        const symbol = literalLengthTree.decode(reader);\r\n        if (symbol < 256) {\r\n            output.writeByte(symbol);\r\n            continue;\r\n        }\r\n        if (symbol === 256) {\r\n            return;\r\n        }\r\n        if (symbol > 285) {\r\n            throw new Error(\"deflate: invalid literal/length symbol\");\r\n        }\r\n\r\n        const lengthIndex = symbol - 257;\r\n        const length = LENGTH_BASE[lengthIndex] + reader.readBits(LENGTH_EXTRA_BITS[lengthIndex]);\r\n        const distanceSymbol = distanceTree.decode(reader);\r\n        if (distanceSymbol > 29) {\r\n            throw new Error(\"deflate: invalid distance symbol\");\r\n        }\r\n        const distance = DISTANCE_BASE[distanceSymbol] + reader.readBits(DISTANCE_EXTRA_BITS[distanceSymbol]);\r\n        output.copy(distance, length);\r\n    }\r\n}\r\n\r\nfunction readDynamicTrees(reader: BitReader): {\r\n    literalLengthTree: HuffmanTree;\r\n    distanceTree: HuffmanTree;\r\n} {\r\n    const literalLengthCount = reader.readBits(5) + 257;\r\n    const distanceCount = reader.readBits(5) + 1;\r\n    const codeLengthCount = reader.readBits(4) + 4;\r\n\r\n    const codeLengthLengths = new Array<number>(19).fill(0);\r\n    for (let i = 0; i < codeLengthCount; i++) {\r\n        codeLengthLengths[CODE_LENGTH_ORDER[i]] = reader.readBits(3);\r\n    }\r\n\r\n    const codeLengthTree = new HuffmanTree(codeLengthLengths);\r\n    const lengths = readCodeLengths(reader, codeLengthTree, literalLengthCount + distanceCount);\r\n    const literalLengthLengths = lengths.slice(0, literalLengthCount);\r\n    const distanceLengths = lengths.slice(literalLengthCount);\r\n\r\n    if (literalLengthLengths[256] === 0) {\r\n        throw new Error(\"deflate: missing end-of-block code\");\r\n    }\r\n\r\n    return {\r\n        literalLengthTree: new HuffmanTree(literalLengthLengths),\r\n        distanceTree: new HuffmanTree(distanceLengths, { allowEmpty: true }),\r\n    };\r\n}\r\n\r\nfunction readCodeLengths(reader: BitReader, codeLengthTree: HuffmanTree, count: number): number[] {\r\n    const lengths: number[] = [];\r\n    while (lengths.length < count) {\r\n        const symbol = codeLengthTree.decode(reader);\r\n        if (symbol <= 15) {\r\n            lengths.push(symbol);\r\n            continue;\r\n        }\r\n\r\n        let repeatLength: number;\r\n        let repeatedValue: number;\r\n        switch (symbol) {\r\n            case 16:\r\n                if (lengths.length === 0) {\r\n                    throw new Error(\"deflate: invalid code length repeat\");\r\n                }\r\n                repeatedValue = lengths[lengths.length - 1];\r\n                repeatLength = reader.readBits(2) + 3;\r\n                break;\r\n            case 17:\r\n                repeatedValue = 0;\r\n                repeatLength = reader.readBits(3) + 3;\r\n                break;\r\n            case 18:\r\n                repeatedValue = 0;\r\n                repeatLength = reader.readBits(7) + 11;\r\n                break;\r\n            default:\r\n                throw new Error(\"deflate: invalid code length symbol\");\r\n        }\r\n\r\n        if (lengths.length + repeatLength > count) {\r\n            throw new Error(\"deflate: invalid code length repeat\");\r\n        }\r\n        for (let i = 0; i < repeatLength; i++) {\r\n            lengths.push(repeatedValue);\r\n        }\r\n    }\r\n    return lengths;\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXProperty, type FBXPropertyType } from \"../types/fbxTypes\";\nimport { inflateZlib } from \"./zlibInflate\";\n\nconst FBX_MAGIC = \"Kaydara FBX Binary  \\0\";\nconst HEADER_SIZE = 27; // 21 magic + 1 (0x1A) + 1 endianness flag + 4 version uint32\n\n// Byte order of the file being parsed. Big-endian FBX files exist (e.g. old Maya exports); the flag byte after the\n// magic is non-zero for them. Parsing is synchronous so a module-level flag is safe.\nlet littleEndian = true;\n\n/**\n * Parse a binary FBX file into an FBXDocument.\n * Supports FBX versions 7.0–7.7 (v7.5+ uses 64-bit node headers).\n */\nexport function parseBinaryFBX(buffer: ArrayBuffer): FBXDocument {\n    const view = new DataView(buffer);\n    const bytes = new Uint8Array(buffer);\n    littleEndian = bytes.length > 22 ? bytes[22] === 0 : true;\n\n    // Validate magic\n    const magic = decodeASCII(bytes, 0, 21);\n    if (magic !== FBX_MAGIC) {\n        throw new Error(\"Not a valid binary FBX file\");\n    }\n    if (buffer.byteLength < HEADER_SIZE) {\n        throw new Error(\"Truncated binary FBX header\");\n    }\n\n    const version = view.getUint32(23, littleEndian);\n    // v7.5+ uses 64-bit offsets in node records\n    const is64Bit = version >= 7500;\n\n    const nodes: FBXNode[] = [];\n    let offset = HEADER_SIZE;\n\n    while (offset < buffer.byteLength) {\n        const result = parseNode(view, bytes, offset, is64Bit, buffer.byteLength);\n        if (result === null) {\n            break; // null sentinel node\n        }\n        nodes.push(result.node);\n        offset = result.endOffset;\n    }\n\n    return { version, nodes };\n}\n\ninterface ParsedNode {\n    node: FBXNode;\n    endOffset: number;\n}\n\nfunction parseNode(view: DataView, bytes: Uint8Array, offset: number, is64Bit: boolean, limit: number): ParsedNode | null {\n    // Read node header\n    let endOffset: number;\n    let numProperties: number;\n    let propertyListLen: number;\n    let headerSize: number;\n\n    if (is64Bit) {\n        ensureRange(bytes, offset, 25, limit, \"FBX node header\");\n        endOffset = readUint64AsNumber(view, offset);\n        numProperties = readUint64AsNumber(view, offset + 8);\n        propertyListLen = readUint64AsNumber(view, offset + 16);\n        headerSize = 25; // 8+8+8+1 (nameLen byte)\n    } else {\n        ensureRange(bytes, offset, 13, limit, \"FBX node header\");\n        endOffset = view.getUint32(offset, littleEndian);\n        numProperties = view.getUint32(offset + 4, littleEndian);\n        propertyListLen = view.getUint32(offset + 8, littleEndian);\n        headerSize = 13; // 4+4+4+1 (nameLen byte)\n    }\n\n    // Null sentinel: all header fields are zero\n    if (endOffset === 0) {\n        return null;\n    }\n    if (endOffset <= offset || endOffset > limit) {\n        throw new Error(`Invalid FBX node end offset ${endOffset} at offset ${offset}`);\n    }\n\n    const nameLen = bytes[offset + headerSize - 1];\n    ensureRange(bytes, offset + headerSize, nameLen, endOffset, \"FBX node name\");\n    const name = decodeASCII(bytes, offset + headerSize, nameLen);\n\n    let cursor = offset + headerSize + nameLen;\n    const propertiesStart = cursor;\n    const propertiesEnd = propertiesStart + propertyListLen;\n    if (propertiesEnd > endOffset) {\n        throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\n    }\n\n    // Parse properties\n    const properties: FBXProperty[] = [];\n    for (let i = 0; i < numProperties; i++) {\n        const result = parseProperty(view, bytes, cursor, propertiesEnd);\n        properties.push(result.property);\n        cursor = result.nextOffset;\n    }\n    if (cursor !== propertiesEnd) {\n        throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\n    }\n\n    // Parse nested child nodes (between end of properties and endOffset)\n    const children: FBXNode[] = [];\n    if (cursor < endOffset) {\n        while (cursor < endOffset) {\n            const child = parseNode(view, bytes, cursor, is64Bit, endOffset);\n            if (child === null) {\n                break;\n            }\n            if (child.endOffset <= cursor || child.endOffset > endOffset) {\n                throw new Error(`Invalid FBX child node end offset ${child.endOffset} at offset ${cursor}`);\n            }\n            children.push(child.node);\n            cursor = child.endOffset;\n        }\n    }\n\n    return {\n        node: { name, properties, children },\n        endOffset,\n    };\n}\n\ninterface ParsedProperty {\n    property: FBXProperty;\n    nextOffset: number;\n}\n\nfunction parseProperty(view: DataView, bytes: Uint8Array, offset: number, limit: number): ParsedProperty {\n    ensureRange(bytes, offset, 1, limit, \"FBX property type\");\n    const typeCode = String.fromCharCode(bytes[offset]);\n    offset += 1;\n\n    switch (typeCode) {\n        case \"C\": {\n            // Boolean (1 byte). Legacy (pre-7000) files also use 'C' for bare characters such as key modes\n            // ('U', 's', 'n'); those are surfaced as small integers so consumers can read the character code.\n            ensureRange(bytes, offset, 1, limit, \"FBX boolean property\");\n            const byte = bytes[offset];\n            if (byte > 1) {\n                return { property: { type: \"int32\", value: byte }, nextOffset: offset + 1 };\n            }\n            return { property: { type: \"boolean\", value: byte !== 0 }, nextOffset: offset + 1 };\n        }\n        case \"Z\": {\n            // Single byte integer (rare, emitted by some exporters); ufbx reads it as an unsigned byte number.\n            ensureRange(bytes, offset, 1, limit, \"FBX byte property\");\n            const value = bytes[offset];\n            return { property: { type: \"int32\", value }, nextOffset: offset + 1 };\n        }\n        case \"Y\": {\n            // Int16\n            ensureRange(bytes, offset, 2, limit, \"FBX int16 property\");\n            const value = view.getInt16(offset, littleEndian);\n            return { property: { type: \"int16\", value }, nextOffset: offset + 2 };\n        }\n        case \"I\": {\n            // Int32\n            ensureRange(bytes, offset, 4, limit, \"FBX int32 property\");\n            const value = view.getInt32(offset, littleEndian);\n            return { property: { type: \"int32\", value }, nextOffset: offset + 4 };\n        }\n        case \"F\": {\n            // Float32\n            ensureRange(bytes, offset, 4, limit, \"FBX float32 property\");\n            const value = view.getFloat32(offset, littleEndian);\n            return { property: { type: \"float32\", value }, nextOffset: offset + 4 };\n        }\n        case \"D\": {\n            // Float64\n            ensureRange(bytes, offset, 8, limit, \"FBX float64 property\");\n            const value = view.getFloat64(offset, littleEndian);\n            return { property: { type: \"float64\", value }, nextOffset: offset + 8 };\n        }\n        case \"L\": {\n            // Int64\n            ensureRange(bytes, offset, 8, limit, \"FBX int64 property\");\n            const value = readInt64AsNumber(view, offset);\n            const property: FBXProperty = { type: \"int64\", value };\n            if (!Number.isSafeInteger(value)) {\n                property.raw = int64ToDecimalString(view, offset);\n            }\n            return { property, nextOffset: offset + 8 };\n        }\n        case \"S\": {\n            // String (uint32 length + data)\n            ensureRange(bytes, offset, 4, limit, \"FBX string property length\");\n            const len = view.getUint32(offset, littleEndian);\n            ensureRange(bytes, offset + 4, len, limit, \"FBX string property data\");\n            const value = decodeUTF8(bytes, offset + 4, len);\n            return { property: { type: \"string\", value }, nextOffset: offset + 4 + len };\n        }\n        case \"R\": {\n            // Raw binary data (uint32 length + data)\n            ensureRange(bytes, offset, 4, limit, \"FBX raw property length\");\n            const len = view.getUint32(offset, littleEndian);\n            ensureRange(bytes, offset + 4, len, limit, \"FBX raw property data\");\n            const value = bytes.slice(offset + 4, offset + 4 + len);\n            return { property: { type: \"raw\", value }, nextOffset: offset + 4 + len };\n        }\n        // Array types\n        case \"f\":\n            return parseArrayProperty(view, bytes, offset, \"float32[]\", 4, limit);\n        case \"d\":\n            return parseArrayProperty(view, bytes, offset, \"float64[]\", 8, limit);\n        case \"i\":\n            return parseArrayProperty(view, bytes, offset, \"int32[]\", 4, limit);\n        case \"l\":\n            return parseArrayProperty(view, bytes, offset, \"int64[]\", 8, limit);\n        case \"b\":\n            return parseArrayProperty(view, bytes, offset, \"boolean[]\", 1, limit);\n        case \"c\":\n            // Byte array (same layout as 'b'); consumers treat it as small integers.\n            return parseArrayProperty(view, bytes, offset, \"boolean[]\", 1, limit);\n        default:\n            throw new Error(`Unknown FBX property type: '${typeCode}' at offset ${offset - 1}`);\n    }\n}\n\nfunction parseArrayProperty(view: DataView, bytes: Uint8Array, offset: number, type: FBXPropertyType, elementSize: number, limit: number): ParsedProperty {\n    ensureRange(bytes, offset, 12, limit, `FBX array property header for ${type}`);\n    const arrayLength = view.getUint32(offset, littleEndian);\n    const encoding = view.getUint32(offset + 4, littleEndian); // 0=raw, 1=zlib\n    const compressedLength = view.getUint32(offset + 8, littleEndian);\n    offset += 12;\n    const expectedByteLength = arrayLength * elementSize;\n    ensureRange(bytes, offset, compressedLength, limit, `FBX array property data for ${type}`);\n\n    let arrayData: Uint8Array;\n    if (encoding === 1) {\n        // zlib compressed\n        const compressed = bytes.subarray(offset, offset + compressedLength);\n        arrayData = inflateZlib(compressed, expectedByteLength);\n    } else {\n        if (encoding !== 0) {\n            throw new Error(`Unsupported FBX array encoding: ${encoding}`);\n        }\n        if (compressedLength !== expectedByteLength) {\n            throw new Error(`Invalid FBX array byte length for ${type}`);\n        }\n        arrayData = bytes.slice(offset, offset + compressedLength);\n    }\n\n    if (!littleEndian && elementSize > 1 && type !== \"int64[]\") {\n        swapBytesInPlace(arrayData, elementSize);\n    }\n    const arrayBuffer = arrayData.buffer.slice(arrayData.byteOffset, arrayData.byteOffset + arrayData.byteLength);\n\n    let value: Float32Array | Float64Array | Int32Array | Uint8Array;\n    switch (type) {\n        case \"float32[]\":\n            value = new Float32Array(arrayBuffer);\n            break;\n        case \"float64[]\":\n            value = new Float64Array(arrayBuffer);\n            break;\n        case \"int32[]\":\n            value = new Int32Array(arrayBuffer);\n            break;\n        case \"boolean[]\":\n            value = arrayData;\n            break;\n        case \"int64[]\":\n            value = readInt64ArrayData(arrayData);\n            break;\n        default:\n            throw new Error(`Unexpected array type: ${type}`);\n    }\n\n    return {\n        property: { type, value },\n        nextOffset: offset + compressedLength,\n    };\n}\n\nfunction ensureRange(bytes: Uint8Array, offset: number, byteLength: number, limit: number, context: string): void {\n    if (offset < 0 || byteLength < 0 || offset + byteLength > limit || offset + byteLength > bytes.byteLength) {\n        throw new Error(`${context}: unexpected end of input`);\n    }\n}\n\nfunction swapBytesInPlace(data: Uint8Array, elementSize: number): void {\n    for (let i = 0; i + elementSize <= data.length; i += elementSize) {\n        for (let a = i, b = i + elementSize - 1; a < b; a++, b--) {\n            const t = data[a];\n            data[a] = data[b];\n            data[b] = t;\n        }\n    }\n}\n\nfunction readUint64AsNumber(view: DataView, offset: number): number {\n    const low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);\n    const high = view.getUint32(littleEndian ? offset + 4 : offset, littleEndian);\n    return high * 0x100000000 + low;\n}\n\nfunction readInt64AsNumber(view: DataView, offset: number): number {\n    const low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);\n    const high = view.getInt32(littleEndian ? offset + 4 : offset, littleEndian);\n    return high * 0x100000000 + low;\n}\n\n/** Exact decimal text of a 64-bit two's complement integer, for values a double cannot represent. */\nfunction int64ToDecimalString(view: DataView, offset: number): string {\n    let low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);\n    let high = view.getUint32(littleEndian ? offset + 4 : offset, littleEndian);\n    const negative = (high & 0x80000000) !== 0;\n    if (negative) {\n        low = (~low + 1) >>> 0;\n        high = (~high + (low === 0 ? 1 : 0)) >>> 0;\n    }\n    const digits: number[] = [];\n    while (high !== 0 || low !== 0) {\n        const highQuotient = Math.floor(high / 10);\n        const carried = (high % 10) * 4294967296 + low;\n        digits.push(carried % 10);\n        high = highQuotient;\n        low = Math.floor(carried / 10);\n    }\n    return (negative ? \"-\" : \"\") + (digits.length > 0 ? digits.reverse().join(\"\") : \"0\");\n}\n\nfunction readInt64ArrayData(arrayData: Uint8Array): Float64Array {\n    const view = new DataView(arrayData.buffer, arrayData.byteOffset, arrayData.byteLength);\n    const values = new Float64Array(arrayData.byteLength / 8);\n    for (let i = 0; i < values.length; i++) {\n        values[i] = readInt64AsNumber(view, i * 8);\n    }\n    return values;\n}\n\nfunction decodeASCII(bytes: Uint8Array, offset: number, length: number): string {\n    let result = \"\";\n    for (let i = 0; i < length; i++) {\n        result += String.fromCharCode(bytes[offset + i]);\n    }\n    return result;\n}\n\nfunction decodeUTF8(bytes: Uint8Array, offset: number, length: number): string {\n    const decoder = new TextDecoder(\"utf-8\");\n    return decoder.decode(bytes.subarray(offset, offset + length));\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXProperty } from \"../types/fbxTypes\";\n\n/**\n * Parse an ASCII FBX file into an FBXDocument.\n */\nexport function parseAsciiFBX(text: string): FBXDocument {\n    const tokenizer = new Tokenizer(text);\n    const version = parseVersion(text);\n    const nodes: FBXNode[] = [];\n\n    while (!tokenizer.isEOF()) {\n        tokenizer.skipWhitespaceAndComments();\n        if (tokenizer.isEOF()) {\n            break;\n        }\n        const node = parseNodeFromTokens(tokenizer);\n        if (node) {\n            nodes.push(node);\n        }\n    }\n\n    if (version >= 7200) {\n        reinterpretKeyAttrDataFloat(nodes);\n    }\n    return { version, nodes };\n}\n\n/**\n * In ASCII files of version 7.2+, `KeyAttrDataFloat` holds the raw 32-bit float bit patterns written as integers\n * (some elements are genuinely integers). Reinterpret them so tangent data reads like the binary format.\n */\nfunction reinterpretKeyAttrDataFloat(nodes: FBXNode[]): void {\n    for (const node of nodes) {\n        if (node.name === \"KeyAttrDataFloat\" && node.properties.length === 1 && node.properties[0].value instanceof Float64Array) {\n            const raw = node.properties[0].value;\n            const bits = new Int32Array(raw.length);\n            for (let i = 0; i < raw.length; i++) {\n                bits[i] = raw[i] | 0;\n            }\n            node.properties[0] = { type: \"float32[]\", value: new Float32Array(bits.buffer) };\n        }\n        if (node.children.length > 0) {\n            reinterpretKeyAttrDataFloat(node.children);\n        }\n    }\n}\n\n/** Extract FBX version from the header comment (e.g. \"; FBX 7.7.0 project file\") */\nfunction parseVersion(text: string): number {\n    const match = text.match(/;\\s*FBX\\s+(\\d+)\\.(\\d+)\\.(\\d+)/);\n    if (match) {\n        return parseInt(match[1]) * 1000 + parseInt(match[2]) * 100 + parseInt(match[3]);\n    }\n    // Some files lack the header comment. The FBXHeaderExtension block carries the version too.\n    const ext = text.match(/FBXVersion:\\s*(\\d+)/);\n    if (ext) {\n        return parseInt(ext[1]);\n    }\n    // Fall back to the layout heuristic: Properties70 blocks only exist in 7.x files.\n    return text.includes(\"Properties70\") ? 7000 : 6000;\n}\n\n// ── Tokenizer ──────────────────────────────────────────────────────────────────\n\nconst enum TokenType {\n    Identifier,\n    Number,\n    String,\n    OpenBrace,\n    CloseBrace,\n    Colon,\n    Comma,\n    Star,\n    EOF,\n}\n\ninterface Token {\n    type: TokenType;\n    value: string;\n    pos: number;\n}\n\nclass Tokenizer {\n    private pos = 0;\n    private readonly len: number;\n\n    constructor(private readonly text: string) {\n        this.len = text.length;\n    }\n\n    isEOF(): boolean {\n        this.skipWhitespaceAndComments();\n        return this.pos >= this.len;\n    }\n\n    peek(): Token {\n        const saved = this.pos;\n        const tok = this.next();\n        this.pos = saved;\n        return tok;\n    }\n\n    next(): Token {\n        this.skipWhitespaceAndComments();\n        if (this.pos >= this.len) {\n            return { type: TokenType.EOF, value: \"\", pos: this.pos };\n        }\n\n        const ch = this.text[this.pos];\n        const startPos = this.pos;\n\n        switch (ch) {\n            case \"{\":\n                this.pos++;\n                return { type: TokenType.OpenBrace, value: \"{\", pos: startPos };\n            case \"}\":\n                this.pos++;\n                return { type: TokenType.CloseBrace, value: \"}\", pos: startPos };\n            case \":\":\n                this.pos++;\n                return { type: TokenType.Colon, value: \":\", pos: startPos };\n            case \",\":\n                this.pos++;\n                return { type: TokenType.Comma, value: \",\", pos: startPos };\n            case \"*\":\n                this.pos++;\n                return { type: TokenType.Star, value: \"*\", pos: startPos };\n            case '\"':\n                return this.readString();\n            default:\n                if (this.isNumberStart(ch)) {\n                    return this.readNumber();\n                }\n                if (this.isIdentStart(ch)) {\n                    return this.readIdentifier();\n                }\n                throw new Error(`Unexpected character '${ch}' at position ${this.pos}`);\n        }\n    }\n\n    expect(type: TokenType): Token {\n        const tok = this.next();\n        if (tok.type !== type) {\n            throw new Error(`Expected token type ${type} but got ${tok.type} ('${tok.value}') at pos ${tok.pos}`);\n        }\n        return tok;\n    }\n\n    /** Look ahead to see if the next identifier + colon is a child node start */\n    isNextNodeStart(): boolean {\n        const saved = this.pos;\n        this.skipWhitespaceAndComments();\n        // Read the identifier\n        if (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\n            while (this.pos < this.len && this.isIdentChar(this.text[this.pos])) {\n                this.pos++;\n            }\n            // Skip whitespace between identifier and potential colon\n            while (this.pos < this.len && (this.text[this.pos] === \" \" || this.text[this.pos] === \"\\t\")) {\n                this.pos++;\n            }\n            const isNode = this.pos < this.len && this.text[this.pos] === \":\";\n            this.pos = saved;\n            return isNode;\n        }\n        this.pos = saved;\n        return false;\n    }\n\n    skipWhitespaceAndComments(): void {\n        while (this.pos < this.len) {\n            const ch = this.text[this.pos];\n            if (ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\") {\n                this.pos++;\n            } else if (ch === \";\") {\n                // Skip comment to end of line\n                while (this.pos < this.len && this.text[this.pos] !== \"\\n\") {\n                    this.pos++;\n                }\n            } else {\n                break;\n            }\n        }\n    }\n\n    private readString(): Token {\n        const startPos = this.pos;\n        this.pos++; // skip opening quote\n        let value = \"\";\n        while (this.pos < this.len && this.text[this.pos] !== '\"') {\n            if (this.text[this.pos] === \"\\\\\" && this.pos + 1 < this.len) {\n                this.pos++;\n                value += this.text[this.pos];\n            } else {\n                value += this.text[this.pos];\n            }\n            this.pos++;\n        }\n        if (this.pos < this.len) {\n            this.pos++; // skip closing quote\n        }\n        // The SDK writes double quotes inside strings as &quot;\n        if (value.includes(\"&quot;\")) {\n            value = value.split(\"&quot;\").join('\"');\n        }\n        return { type: TokenType.String, value, pos: startPos };\n    }\n\n    private readNumber(): Token {\n        const startPos = this.pos;\n        // Handle leading sign\n        if (this.text[this.pos] === \"-\" || this.text[this.pos] === \"+\") {\n            this.pos++;\n        }\n        // Word-form specials: inf, infinity, nan, ind (any case), optionally signed, optionally with a\n        // parenthesised payload such as nan(ind) or nan(12345).\n        if (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\n            while (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\n                this.pos++;\n            }\n            this.skipSpecialNumberSuffix();\n            return { type: TokenType.Number, value: this.text.substring(startPos, this.pos), pos: startPos };\n        }\n        while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\n            this.pos++;\n        }\n        if (this.pos < this.len && this.text[this.pos] === \".\") {\n            this.pos++;\n            while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\n                this.pos++;\n            }\n        }\n        // Scientific notation\n        if (this.pos < this.len && (this.text[this.pos] === \"e\" || this.text[this.pos] === \"E\")) {\n            this.pos++;\n            if (this.pos < this.len && (this.text[this.pos] === \"+\" || this.text[this.pos] === \"-\")) {\n                this.pos++;\n            }\n            while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\n                this.pos++;\n            }\n        }\n        // MSVC-style specials: 1.#INF, -1.#IND, 1.#QNAN, 1.#SNAN, 2.#IND12345678\n        if (this.pos < this.len && this.text[this.pos] === \"#\") {\n            this.pos++;\n            while (this.pos < this.len && (this.isIdentStart(this.text[this.pos]) || this.isDigit(this.text[this.pos]))) {\n                this.pos++;\n            }\n            this.skipSpecialNumberSuffix();\n        }\n        return { type: TokenType.Number, value: this.text.substring(startPos, this.pos), pos: startPos };\n    }\n\n    private readIdentifier(): Token {\n        const startPos = this.pos;\n        while (this.pos < this.len && this.isIdentChar(this.text[this.pos])) {\n            this.pos++;\n        }\n        // Malformed special numbers such as \"snan(\" or \"Nan((\" lex as identifiers; swallow their parenthesised tail.\n        this.skipSpecialNumberSuffix();\n        return { type: TokenType.Identifier, value: this.text.substring(startPos, this.pos), pos: startPos };\n    }\n\n    /** Consumes a run of parentheses and alphanumerics that some writers append to nan/inf tokens. */\n    private skipSpecialNumberSuffix(): void {\n        if (this.pos < this.len && this.text[this.pos] === \"(\") {\n            while (this.pos < this.len) {\n                const ch = this.text[this.pos];\n                if (ch === \"(\" || ch === \")\" || this.isIdentChar(ch)) {\n                    this.pos++;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    private isDigit(ch: string): boolean {\n        return ch >= \"0\" && ch <= \"9\";\n    }\n\n    private isNumberStart(ch: string): boolean {\n        if (this.isDigit(ch) || ch === \".\") {\n            return true;\n        }\n        if ((ch === \"-\" || ch === \"+\") && this.pos + 1 < this.len) {\n            const next = this.text[this.pos + 1];\n            return this.isDigit(next) || next === \".\" || isSpecialNumberWord(this.text.substring(this.pos + 1, this.pos + 10));\n        }\n        if (isSpecialNumberWord(this.text.substring(this.pos, this.pos + 9))) {\n            // Bare inf/nan words in value position; identifiers followed by ':' are node names and never match.\n            return !this.isFollowedByColon(this.pos);\n        }\n        return false;\n    }\n\n    private isFollowedByColon(from: number): boolean {\n        let p = from;\n        while (p < this.len && this.isIdentChar(this.text[p])) {\n            p++;\n        }\n        while (p < this.len && (this.text[p] === \" \" || this.text[p] === \"\\t\")) {\n            p++;\n        }\n        return p < this.len && this.text[p] === \":\";\n    }\n\n    private isIdentStart(ch: string): boolean {\n        return (ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\";\n    }\n\n    private isIdentChar(ch: string): boolean {\n        // '-' appears inside node names such as \"Pre-Extrapolation\" / \"Post-Extrapolation\".\n        return this.isIdentStart(ch) || this.isDigit(ch) || ch === \"|\" || ch === \"-\";\n    }\n}\n\n// ── Node Parsing ───────────────────────────────────────────────────────────────\n\nfunction parseNodeFromTokens(tokenizer: Tokenizer): FBXNode | null {\n    const nameTok = tokenizer.peek();\n    if (nameTok.type === TokenType.CloseBrace || nameTok.type === TokenType.EOF) {\n        return null;\n    }\n\n    // Node name\n    const identTok = tokenizer.next();\n    if (identTok.type !== TokenType.Identifier) {\n        throw new Error(`Expected identifier for node name, got '${identTok.value}' at pos ${identTok.pos}`);\n    }\n    const name = identTok.value;\n    tokenizer.expect(TokenType.Colon);\n\n    // Parse properties until we hit '{' or end-of-line content\n    const properties: FBXProperty[] = [];\n    const children: FBXNode[] = [];\n\n    // Check for array shorthand: *count { a: ... }\n    let peek = tokenizer.peek();\n    if (peek.type === TokenType.Star) {\n        // Array node like \"Vertices: *25959 {\"\n        tokenizer.next(); // consume *\n        const countTok = tokenizer.expect(TokenType.Number);\n        const count = parseInt(countTok.value);\n        tokenizer.expect(TokenType.OpenBrace);\n\n        // Expect \"a:\" followed by comma-separated values\n        const aTok = tokenizer.next();\n        if (aTok.type === TokenType.Identifier && aTok.value === \"a\") {\n            tokenizer.expect(TokenType.Colon);\n            const values = parseArrayValues(tokenizer, count);\n            properties.push({ type: \"float64[]\", value: new Float64Array(values) });\n        }\n\n        tokenizer.expect(TokenType.CloseBrace);\n        return { name, properties, children };\n    }\n\n    // Parse inline properties (comma-separated values on the same logical line)\n    // Values can be: numbers, strings, or bare identifiers (e.g. \"T\", \"Y\", \"CullingOff\")\n    peek = tokenizer.peek();\n    while (peek.type !== TokenType.OpenBrace && peek.type !== TokenType.CloseBrace && peek.type !== TokenType.EOF) {\n        if (peek.type === TokenType.Number) {\n            const tok = tokenizer.next();\n            const numVal = parseNumericValue(tok.value);\n            if (Number.isInteger(numVal) && !tok.value.includes(\".\") && !tok.value.includes(\"e\") && !tok.value.includes(\"E\")) {\n                const property: FBXProperty = { type: isInt32(numVal) ? \"int32\" : \"int64\", value: numVal };\n                if (!Number.isSafeInteger(numVal)) {\n                    property.raw = canonicalIntegerText(tok.value);\n                }\n                properties.push(property);\n            } else {\n                properties.push({ type: \"float64\", value: numVal });\n            }\n        } else if (peek.type === TokenType.String) {\n            const tok = tokenizer.next();\n            properties.push({ type: \"string\", value: tok.value });\n        } else if (peek.type === TokenType.Identifier) {\n            // Check if this is a property value or the start of a new child node.\n            // If the next non-whitespace after the identifier is ':', it's a child node name — stop.\n            if (tokenizer.isNextNodeStart()) {\n                break;\n            }\n            // Bare identifier as a property value (e.g. \"T\", \"Y\", \"CullingOff\")\n            const tok = tokenizer.next();\n            properties.push({ type: \"string\", value: tok.value });\n        } else if (peek.type === TokenType.Comma) {\n            tokenizer.next(); // consume comma\n        } else {\n            break;\n        }\n        peek = tokenizer.peek();\n    }\n\n    // Check for block body { ... }\n    peek = tokenizer.peek();\n    if (peek.type === TokenType.OpenBrace) {\n        tokenizer.next(); // consume '{'\n        // Parse child nodes\n        while (true) {\n            peek = tokenizer.peek();\n            if (peek.type === TokenType.CloseBrace || peek.type === TokenType.EOF) {\n                break;\n            }\n            const child = parseNodeFromTokens(tokenizer);\n            if (child) {\n                children.push(child);\n            } else {\n                break;\n            }\n        }\n        tokenizer.expect(TokenType.CloseBrace);\n    }\n\n    return { name, properties, children };\n}\n\nfunction parseArrayValues(tokenizer: Tokenizer, count: number): number[] {\n    const values: number[] = [];\n    while (true) {\n        const peek = tokenizer.peek();\n        if (peek.type === TokenType.CloseBrace || peek.type === TokenType.EOF) {\n            break;\n        }\n        if (peek.type === TokenType.Comma) {\n            tokenizer.next();\n            continue;\n        }\n        if (peek.type === TokenType.Number) {\n            const tok = tokenizer.next();\n            values.push(parseNumericValue(tok.value));\n        } else if (peek.type === TokenType.Identifier && !tokenizer.isNextNodeStart()) {\n            // Unrecognised nan/inf spellings (\"snan\", \"infty\", \"ind\") still count as values.\n            const tok = tokenizer.next();\n            values.push(parseNumericValue(tok.value));\n        } else {\n            break;\n        }\n    }\n    if (values.length !== count) {\n        throw new Error(`ASCII FBX array declared ${count} values but parsed ${values.length}`);\n    }\n    return values;\n}\n\n/** Matches a leading inf/infinity/nan/ind word (case-insensitive) at the start of the string. */\nfunction isSpecialNumberWord(str: string): boolean {\n    return /^(?:inf(?:inity)?|nan|ind)(?![A-Za-z0-9_|])/i.test(str);\n}\n\nfunction parseNumericValue(str: string): number {\n    const n = Number(str);\n    if (!Number.isNaN(n)) {\n        return n;\n    }\n    // \"1.#INF\", \"-1.#IND\", \"1.#QNAN\", \"inf\", \"-Infinity\", \"nan\", \"nan(ind)\", \"infty\"\n    const sign = str.startsWith(\"-\") ? -1 : 1;\n    const body = str.replace(/^[+-]/, \"\").replace(/\\(.*$/, \"\");\n    if (/#INF/i.test(body) || /^inf/i.test(body)) {\n        return sign * Infinity;\n    }\n    return NaN;\n}\n\n/** Integer text without sign prefix noise or leading zeros, so equal values produce equal keys. */\nfunction canonicalIntegerText(text: string): string {\n    const negative = text.startsWith(\"-\");\n    const digits = text.replace(/^[+-]/, \"\").replace(/^0+(?=\\d)/, \"\");\n    return negative && digits !== \"0\" ? `-${digits}` : digits;\n}\n\nfunction isInt32(value: number): boolean {\n    return value >= -2147483648 && value <= 2147483647;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * Intermediate representation for parsed FBX data.\n * Both binary and ASCII parsers produce this same structure.\n */\n\n/** Individual property value within an FBX node */\nexport type FBXPropertyValue = boolean | number | string | Float32Array | Float64Array | Int32Array | Uint8Array;\n\n/** Parsed FBX property type identifier. */\nexport type FBXPropertyType =\n    | \"boolean\" // 'C'\n    | \"int16\" // 'Y'\n    | \"int32\" // 'I'\n    | \"int64\" // 'L'\n    | \"float32\" // 'F'\n    | \"float64\" // 'D'\n    | \"string\" // 'S'\n    | \"raw\" // 'R'\n    | \"float32[]\" // 'f'\n    | \"float64[]\" // 'd'\n    | \"int32[]\" // 'i'\n    | \"int64[]\" // 'l'\n    | \"boolean[]\"; // 'b' (stored as Uint8Array where 0=false, 1=true)\n\n/** Individual property within an FBX node. */\nexport interface FBXProperty {\n    /** Parsed property type. */\n    type: FBXPropertyType;\n    /** Parsed property value. */\n    value: FBXPropertyValue;\n    /**\n     * Exact decimal text of an int64 whose magnitude exceeds 2^53; `value` then holds the rounded double. Object\n     * ids are the only int64 values where the last bits matter, and `resolveConnections` keys them by this text.\n     */\n    raw?: string;\n}\n\n/** A node in the FBX document tree */\nexport interface FBXNode {\n    /** Node name. */\n    name: string;\n    /** Node properties. */\n    properties: FBXProperty[];\n    /** Child nodes. */\n    children: FBXNode[];\n}\n\n/** Top-level parsed FBX document */\nexport interface FBXDocument {\n    /** FBX file version. */\n    version: number;\n    /** Top-level document nodes. */\n    nodes: FBXNode[];\n}\n\n/** Helper to find a child node by name */\nexport function findChildByName(node: FBXNode, name: string): FBXNode | undefined {\n    return node.children.find((c) => c.name === name);\n}\n\n/** Helper to find all children with a given name */\nexport function findChildrenByName(node: FBXNode, name: string): FBXNode[] {\n    return node.children.filter((c) => c.name === name);\n}\n\n/** Helper to find a top-level node in a document */\nexport function findDocumentNode(doc: FBXDocument, name: string): FBXNode | undefined {\n    return doc.nodes.find((n) => n.name === name);\n}\n\n/** Extract a property value by index, with type narrowing */\nexport function getPropertyValue<T extends FBXPropertyValue>(node: FBXNode, index: number): T | undefined {\n    if (index < node.properties.length) {\n        return node.properties[index].value as T;\n    }\n    return undefined;\n}\n\n/**\n * Validates an FBX object ID value: IDs are 64-bit integers, so anything non-numeric, non-finite or fractional is\n * rejected. IDs beyond 2^53 are carried losslessly through the property's `raw` text by `resolveConnections`.\n * @param value - Parsed FBX object ID value\n * @returns The object ID, or undefined when the value cannot be an ID\n */\nexport function getSafeFBXObjectId(value: unknown): number | undefined {\n    if (typeof value !== \"number\" || !Number.isFinite(value) || !Number.isInteger(value)) {\n        return undefined;\n    }\n    return value;\n}\n\n/** Typed array payload types produced by the parsers. */\nexport type FBXArrayValue = Float32Array | Float64Array | Int32Array | Uint8Array;\n\n/**\n * Returns the array payload of a node.\n * FBX 7.x stores arrays as a single array property. FBX 6.x (and some 7.x ASCII exporters) store them as a run of\n * scalar properties, and a one-element array degenerates to a single scalar. All of these are coalesced here.\n * @param node - Node whose properties hold the array\n * @returns The array, or null when the node has no numeric payload\n */\nexport function getNodeArray(node: FBXNode | undefined | null): FBXArrayValue | null {\n    if (!node || node.properties.length === 0) {\n        return null;\n    }\n    const first = node.properties[0].value;\n    if (node.properties.length === 1 && (first instanceof Float32Array || first instanceof Float64Array || first instanceof Int32Array || first instanceof Uint8Array)) {\n        return first;\n    }\n    const out = new Float64Array(node.properties.length);\n    for (let i = 0; i < node.properties.length; i++) {\n        const v = node.properties[i].value;\n        if (typeof v === \"number\") {\n            out[i] = v;\n        } else if (typeof v === \"boolean\") {\n            out[i] = v ? 1 : 0;\n        } else {\n            return null;\n        }\n    }\n    return out;\n}\n\n/** Get the numeric ID from a node (first property is typically the int64 UID) */\nexport function getNodeId(node: FBXNode): number | undefined {\n    const prop = node.properties[0];\n    if (prop && (prop.type === \"int64\" || prop.type === \"int32\")) {\n        return getSafeFBXObjectId(prop.value);\n    }\n    return undefined;\n}\n\n/**\n * Clean FBX object names.\n * FBX names may contain:\n *   - A \"Class::\" prefix (e.g. \"Model::valkyrie_mesh\") — strip it\n *   - A binary null/control-character class suffix — strip it\n */\nexport function cleanFBXName(fbxName: string): string {\n    // Binary FBX: \"Name\\x00\\x01Class\" — the name is everything before the separator and may itself contain \"::\".\n    const sepIdx = fbxName.indexOf(\"\\0\\x01\");\n    if (sepIdx >= 0) {\n        return fbxName.substring(0, sepIdx);\n    }\n\n    // ASCII FBX: \"Class::Name\" — strip only the leading class prefix (\"Model::Cube::Model\" -> \"Cube::Model\").\n    const colonIdx = fbxName.indexOf(\"::\");\n    if (colonIdx >= 0) {\n        return fbxName.substring(colonIdx + 2);\n    }\n\n    return fbxName;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXPropertyValue, findChildByName, findDocumentNode, getPropertyValue } from \"../types/fbxTypes\";\n\nexport interface FBXTemplateProperty {\n    name: string;\n    propertyType: string;\n    label: string;\n    flags: string;\n    values: FBXPropertyValue[];\n}\n\nexport interface FBXPropertyTemplate {\n    objectType: string;\n    templateName: string;\n    properties: Map<string, FBXTemplateProperty>;\n}\n\nexport type FBXPropertyTemplateMap = Map<string, Map<string, FBXPropertyTemplate>>;\n\nexport function extractPropertyTemplates(doc: FBXDocument): FBXPropertyTemplateMap {\n    const templates: FBXPropertyTemplateMap = new Map();\n    const definitions = findDocumentNode(doc, \"Definitions\");\n    if (!definitions) {\n        return templates;\n    }\n\n    for (const objectTypeNode of definitions.children) {\n        if (objectTypeNode.name !== \"ObjectType\") {\n            continue;\n        }\n\n        const objectType = getPropertyValue<string>(objectTypeNode, 0);\n        if (!objectType) {\n            continue;\n        }\n\n        for (const templateNode of objectTypeNode.children) {\n            if (templateNode.name !== \"PropertyTemplate\") {\n                continue;\n            }\n\n            const templateName = getPropertyValue<string>(templateNode, 0);\n            if (!templateName) {\n                continue;\n            }\n\n            const template = extractPropertyTemplate(objectType, templateName, templateNode);\n            let templatesByName = templates.get(objectType);\n            if (!templatesByName) {\n                templatesByName = new Map();\n                templates.set(objectType, templatesByName);\n            }\n            templatesByName.set(templateName, template);\n        }\n    }\n\n    return templates;\n}\n\nexport function getPropertyTemplate(templates: FBXPropertyTemplateMap, objectType: string, templateName?: string): FBXPropertyTemplate | undefined {\n    const templatesByName = templates.get(objectType);\n    if (!templatesByName) {\n        return undefined;\n    }\n    if (templateName) {\n        return templatesByName.get(templateName);\n    }\n    return templatesByName.values().next().value;\n}\n\nexport function getTemplatePropertyValue<T extends FBXPropertyValue>(template: FBXPropertyTemplate | undefined, propertyName: string, valueIndex = 0): T | undefined {\n    return template?.properties.get(propertyName)?.values[valueIndex] as T | undefined;\n}\n\nexport function resolvePropertyValue<T extends FBXPropertyValue>(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, valueIndex = 0): T | undefined {\n    return resolvePropertyValues(node, template, propertyName)?.[valueIndex] as T | undefined;\n}\n\nexport function resolveNumberProperty(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, fallback: number): number {\n    return toNumber(resolvePropertyValue(node, template, propertyName)) ?? fallback;\n}\n\nexport function resolveVector2Property(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, fallback: [number, number]): [number, number] {\n    const values = resolvePropertyValues(node, template, propertyName);\n    if (!values) {\n        return fallback;\n    }\n    const x = toNumber(values[0]);\n    const y = toNumber(values[1]);\n    return x !== undefined && y !== undefined ? [x, y] : fallback;\n}\n\nexport function resolveVector3Property(\n    node: FBXNode,\n    template: FBXPropertyTemplate | undefined,\n    propertyName: string,\n    fallback: [number, number, number]\n): [number, number, number] {\n    const values = resolvePropertyValues(node, template, propertyName);\n    if (!values) {\n        return fallback;\n    }\n    const x = toNumber(values[0]);\n    const y = toNumber(values[1]);\n    const z = toNumber(values[2]);\n    return x !== undefined && y !== undefined && z !== undefined ? [x, y, z] : fallback;\n}\n\nexport function resolvePropertyValues(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string): FBXPropertyValue[] | undefined {\n    return findLocalPropertyValues(node, propertyName) ?? template?.properties.get(propertyName)?.values;\n}\n\nfunction toNumber(value: FBXPropertyValue | undefined): number | undefined {\n    if (typeof value === \"number\") {\n        return value;\n    }\n    return undefined;\n}\n\nfunction extractPropertyTemplate(objectType: string, templateName: string, templateNode: FBXNode): FBXPropertyTemplate {\n    const properties = new Map<string, FBXTemplateProperty>();\n    const properties70 = findChildByName(templateNode, \"Properties70\");\n\n    for (const propertyNode of properties70?.children ?? []) {\n        if (propertyNode.name !== \"P\") {\n            continue;\n        }\n\n        const property = extractPropertyNode(propertyNode);\n        if (property) {\n            properties.set(property.name, property);\n        }\n    }\n\n    return { objectType, templateName, properties };\n}\n\n/** A property from a Properties70 (\"P\") or Properties60 (\"Property\") block. */\nexport interface FBXPropertyEntry {\n    name: string;\n    type: string;\n    flags: string;\n    values: FBXPropertyValue[];\n}\n\n/**\n * Lists the properties declared directly on an object, from both the 7.x and 6.x property blocks.\n * @param node - Object node\n * @returns Property entries in declaration order (empty when the node has no property block)\n */\nexport function getPropertyEntries(node: FBXNode | undefined): FBXPropertyEntry[] {\n    const out: FBXPropertyEntry[] = [];\n    if (!node) {\n        return out;\n    }\n    for (const container of node.children) {\n        if (container.name !== \"Properties70\" && container.name !== \"Properties60\") {\n            continue;\n        }\n        for (const p of container.children) {\n            if (p.name !== \"P\" && p.name !== \"PS\" && p.name !== \"Property\") {\n                continue;\n            }\n            const name = getPropertyValue<string>(p, 0);\n            if (typeof name !== \"string\") {\n                continue;\n            }\n            // The layout follows the entry node, not its container: `P` / `PS` carry name, type, label and flags,\n            // `Property` carries name, type and flags. Transitional 6.x files write `P` entries inside Properties60.\n            const hasLabel = p.name !== \"Property\";\n            const type = getPropertyValue<string>(p, 1);\n            const flags = getPropertyValue<string>(p, hasLabel ? 3 : 2);\n            out.push({\n                name,\n                type: typeof type === \"string\" ? type : \"\",\n                flags: typeof flags === \"string\" ? flags : \"\",\n                values: p.properties.slice(hasLabel ? 4 : 3).map((property) => property.value),\n            });\n        }\n    }\n    return out;\n}\n\n/** Value of a user property: scalars as-is, vectors and colours as number arrays. */\nexport type FBXUserPropertyValue = string | number | boolean | number[];\n\n/**\n * User-defined properties of an object: those flagged \"U\" (user) in the property flags. Every DCC exports custom\n * attributes this way (Maya extra attributes, 3ds Max user properties, Blender custom properties).\n * @param node - Object node\n * @returns Map of property name to value, or undefined when the object has none\n */\nexport function extractUserProperties(node: FBXNode): Record<string, FBXUserPropertyValue> | undefined {\n    const result: Record<string, FBXUserPropertyValue> = {};\n    let any = false;\n    for (const entry of getPropertyEntries(node)) {\n        if (!entry.flags.includes(\"U\")) {\n            continue;\n        }\n        const value = userPropertyValue(entry.values, entry.type);\n        if (value !== undefined) {\n            result[entry.name] = value;\n            any = true;\n        }\n    }\n    return any ? result : undefined;\n}\n\n/** Property types whose extra values are limits or labels rather than components (value, min, max). */\nconst SCALAR_PROPERTY_TYPES = new Set([\n    \"Integer\",\n    \"int\",\n    \"Number\",\n    \"double\",\n    \"Float\",\n    \"float\",\n    \"Bool\",\n    \"bool\",\n    \"Enum\",\n    \"enum\",\n    \"Visibility\",\n    \"Roll\",\n    \"Weight\",\n    \"Distance\",\n    \"KTime\",\n    \"Time\",\n]);\n\nexport function userPropertyValue(values: FBXPropertyValue[], typeName?: string): FBXUserPropertyValue | undefined {\n    if (values.length === 0) {\n        return undefined;\n    }\n    const first = values[0];\n    if (typeName !== undefined && SCALAR_PROPERTY_TYPES.has(typeName) && (typeof first === \"number\" || typeof first === \"boolean\")) {\n        return typeof first === \"boolean\" ? first : first;\n    }\n    if (values.length === 1) {\n        return typeof first === \"string\" || typeof first === \"number\" || typeof first === \"boolean\" ? first : undefined;\n    }\n    const numbers: number[] = [];\n    for (const v of values) {\n        if (typeof v === \"number\") {\n            numbers.push(v);\n        } else if (typeof v === \"boolean\") {\n            numbers.push(v ? 1 : 0);\n        } else {\n            break;\n        }\n    }\n    if (numbers.length === values.length) {\n        return numbers;\n    }\n    return typeof first === \"string\" ? first : undefined;\n}\n\nfunction findLocalPropertyValues(node: FBXNode, propertyName: string): FBXPropertyValue[] | undefined {\n    const propertyContainers = [findChildByName(node, \"Properties70\"), findChildByName(node, \"Properties60\")].filter((child): child is FBXNode => child !== undefined);\n\n    // When a property is declared more than once the SDK keeps the last declaration.\n    let found: FBXPropertyValue[] | undefined;\n    for (const container of propertyContainers) {\n        for (const propertyNode of container.children) {\n            if (propertyNode.name !== \"P\" && propertyNode.name !== \"Property\") {\n                continue;\n            }\n            if (getPropertyValue<string>(propertyNode, 0) !== propertyName) {\n                continue;\n            }\n            found = propertyNode.properties.slice(propertyNode.name === \"Property\" ? 3 : 4).map((property) => property.value);\n        }\n    }\n\n    return found;\n}\n\nfunction extractPropertyNode(node: FBXNode): FBXTemplateProperty | null {\n    const name = getPropertyValue<string>(node, 0);\n    if (!name) {\n        return null;\n    }\n\n    return {\n        name,\n        propertyType: getPropertyValue<string>(node, 1) ?? \"\",\n        label: getPropertyValue<string>(node, 2) ?? \"\",\n        flags: getPropertyValue<string>(node, 3) ?? \"\",\n        values: node.properties.slice(4).map((property) => property.value),\n    };\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXNode } from \"../types/fbxTypes\";\nimport { resolveNumberProperty, resolveVector3Property, type FBXPropertyTemplate } from \"./propertyTemplates\";\n\n/** Transform properties resolved from an FBX Model, with template defaults applied. */\nexport interface FBXNodeTransformData {\n    translation: [number, number, number];\n    rotation: [number, number, number];\n    scale: [number, number, number];\n    preRotation: [number, number, number];\n    postRotation: [number, number, number];\n    rotationPivot: [number, number, number];\n    scalingPivot: [number, number, number];\n    rotationOffset: [number, number, number];\n    scalingOffset: [number, number, number];\n    geometricTranslation: [number, number, number];\n    geometricRotation: [number, number, number];\n    geometricScaling: [number, number, number];\n    /** Rotation order: 0=XYZ, 1=XZY, 2=YZX, 3=YXZ, 4=ZXY, 5=ZYX, 6=SphericXYZ */\n    rotationOrder: number;\n    /** FBX transform inheritance mode. 0=RrSs, 1=RSrs, 2=Rrs */\n    inheritType: number;\n    /** Whether the rotation space (rotation order, pre/post rotation) is active for this node */\n    rotationActive: boolean;\n    diagnostics: string[];\n}\n\n/**\n * Resolves the transform properties of a Model node the way the FBX SDK evaluates them.\n *\n * `RotationActive` gates the whole rotation space: when it is false (the FbxNode template default), the SDK\n * composes `Lcl Rotation` in plain XYZ order and ignores `RotationOrder`, `PreRotation` and `PostRotation`.\n * `RotationSpaceForLimitOnly` restricts the rotation space to limits, which has the same effect for us.\n */\nexport function extractNodeTransform(modelNode: FBXNode, template?: FBXPropertyTemplate): FBXNodeTransformData {\n    const translation = resolveVector3Property(modelNode, template, \"Lcl Translation\", [0, 0, 0]);\n    const rotation = resolveVector3Property(modelNode, template, \"Lcl Rotation\", [0, 0, 0]);\n    const scale = resolveVector3Property(modelNode, template, \"Lcl Scaling\", [1, 1, 1]);\n    let preRotation = resolveVector3Property(modelNode, template, \"PreRotation\", [0, 0, 0]);\n    let postRotation = resolveVector3Property(modelNode, template, \"PostRotation\", [0, 0, 0]);\n    const rotationPivot = resolveVector3Property(modelNode, template, \"RotationPivot\", [0, 0, 0]);\n    const scalingPivot = resolveVector3Property(modelNode, template, \"ScalingPivot\", [0, 0, 0]);\n    const rotationOffset = resolveVector3Property(modelNode, template, \"RotationOffset\", [0, 0, 0]);\n    const scalingOffset = resolveVector3Property(modelNode, template, \"ScalingOffset\", [0, 0, 0]);\n    const geometricTranslation = resolveVector3Property(modelNode, template, \"GeometricTranslation\", [0, 0, 0]);\n    const geometricRotation = resolveVector3Property(modelNode, template, \"GeometricRotation\", [0, 0, 0]);\n    const geometricScaling = resolveVector3Property(modelNode, template, \"GeometricScaling\", [1, 1, 1]);\n    let rotationOrder = resolveNumberProperty(modelNode, template, \"RotationOrder\", 0);\n    const inheritType = resolveNumberProperty(modelNode, template, \"InheritType\", 1);\n\n    // The SDK default when the property is absent everywhere is \"active\"; the FbxNode template usually sets 0.\n    const rotationActiveValue = resolveNumberProperty(modelNode, template, \"RotationActive\", 1);\n    const rotationSpaceForLimitOnly = resolveNumberProperty(modelNode, template, \"RotationSpaceForLimitOnly\", 0);\n    const rotationActive = rotationActiveValue !== 0 && rotationSpaceForLimitOnly === 0;\n    if (!rotationActive) {\n        rotationOrder = 0;\n        preRotation = [0, 0, 0];\n        postRotation = [0, 0, 0];\n    }\n\n    // Inherit modes 0 (RrSs), 1 (RSrs) and 2 (Rrs) are all evaluated by the loader; anything else is unknown.\n    const diagnostics = inheritType === 0 || inheritType === 1 || inheritType === 2 ? [] : [`InheritType ${inheritType} is unknown; treated as RSrs.`];\n\n    return {\n        translation,\n        rotation,\n        scale,\n        preRotation,\n        postRotation,\n        rotationPivot,\n        scalingPivot,\n        rotationOffset,\n        scalingOffset,\n        geometricTranslation,\n        geometricRotation,\n        geometricScaling,\n        rotationOrder,\n        inheritType,\n        rotationActive,\n        diagnostics,\n    };\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXProperty, cleanFBXName, findDocumentNode, getPropertyValue, getSafeFBXObjectId } from \"../types/fbxTypes\";\n\n/** Connection type: OO = object-to-object, OP = object-to-property */\nexport type ConnectionType = \"OO\" | \"OP\";\n\n/** A resolved FBX object connection. */\nexport interface FBXConnection {\n    /** Connection type. */\n    type: ConnectionType;\n    /** Child object ID. */\n    childId: number;\n    /** Parent object ID. */\n    parentId: number;\n    /** For OP connections, the property name on the parent (e.g. \"DiffuseColor\") */\n    propertyName?: string;\n}\n\n/** Object table entry used by the FBX connection graph. */\nexport interface FBXObjectEntry {\n    /** Object ID. */\n    id: number;\n    /** Object node. */\n    node: FBXNode;\n    /** Source of the object entry. */\n    source: \"Objects\" | \"legacySyntheticGeometry\" | \"legacySyntheticAttribute\" | \"legacySyntheticBlendShape\";\n    /** Legacy string object name, when applicable. */\n    legacyName?: string;\n    /** True if the object was synthesized for legacy compatibility. */\n    synthetic: boolean;\n}\n\n/** Raw connection-table entry and import status. */\nexport interface FBXConnectionEntry {\n    /** Source node name. */\n    source: \"C\" | \"Connect\";\n    /** Raw connection type. */\n    rawType?: string;\n    /** Child object ID, when resolved. */\n    childId?: number;\n    /** Parent object ID, when resolved. */\n    parentId?: number;\n    /** OP connection property name, when present. */\n    propertyName?: string;\n    /** True if the connection was accepted into the resolved graph. */\n    accepted: boolean;\n}\n\n/** Reason a connection produced a diagnostic. */\nexport type FBXConnectionDiagnosticReason =\n    \"unsupported-connection-type\" | \"missing-connection-endpoint\" | \"unresolved-legacy-endpoint\" | \"unresolved-object-reference\" | \"duplicate-parent\" | \"self-loop\";\n\n/** Recoverable connection graph issue. */\nexport interface FBXConnectionDiagnostic {\n    /** Diagnostic reason. */\n    reason: FBXConnectionDiagnosticReason;\n    /** Human-readable diagnostic message. */\n    message: string;\n    /** Connection-table index associated with the diagnostic, if applicable. */\n    connectionIndex?: number;\n    /** Connection type associated with the diagnostic, if applicable. */\n    type?: string;\n    /** Child object ID associated with the diagnostic, if applicable. */\n    childId?: number;\n    /** Parent object ID associated with the diagnostic, if applicable. */\n    parentId?: number;\n    /** OP connection property name associated with the diagnostic, if applicable. */\n    propertyName?: string;\n}\n\n/** Resolved FBX object and connection graph. */\nexport interface FBXObjectMap {\n    /** All objects by their unique ID */\n    objects: Map<number, FBXNode>;\n    /** Object table entries, including synthetic compatibility objects */\n    objectEntries: FBXObjectEntry[];\n    /** Children of each object ID */\n    childrenOf: Map<number, { id: number; propertyName?: string }[]>;\n    /** Parent of each object ID */\n    parentOf: Map<number, { id: number; propertyName?: string }>;\n    /** Raw connection list */\n    connections: FBXConnection[];\n    /** Raw connection-table entries and whether they were accepted into the graph */\n    connectionEntries: FBXConnectionEntry[];\n    /** Unsupported or suspicious connection shapes encountered while preserving graph behavior */\n    diagnostics: FBXConnectionDiagnostic[];\n}\n\n/**\n * Build a connection graph from a parsed FBX document.\n * Maps object IDs to their FBXNode and resolves parent-child relationships.\n */\nexport function resolveConnections(doc: FBXDocument): FBXObjectMap {\n    const objects = new Map<number, FBXNode>();\n    const objectEntries: FBXObjectEntry[] = [];\n    const childrenOf = new Map<number, { id: number; propertyName?: string }[]>();\n    const parentOf = new Map<number, { id: number; propertyName?: string }>();\n    const connections: FBXConnection[] = [];\n    const connectionEntries: FBXConnectionEntry[] = [];\n    const diagnostics: FBXConnectionDiagnostic[] = [];\n    // Legacy (6.x and older) objects are identified by their full \"Class::Name\" string, exactly as the SDK does,\n    // so that a material, texture and video sharing a base name stay distinct. Connections that only carry the\n    // bare name fall back to the first object with that name.\n    const legacyIds = new Map<string, number>();\n    const legacyIdsByCleanName = new Map<string, number>();\n    const syntheticLegacyIds = new Map<string, Map<string, number>>();\n    const legacyGeometryByModelId = new Map<number, number>();\n\n    // Every numeric id the file uses is reserved up front so that synthetic ids (legacy objects, inline shapes)\n    // and the stand-ins for ids beyond 2^53 never collide with a real object.\n    const objectsNode = findDocumentNode(doc, \"Objects\");\n    const connectionsNode = findDocumentNode(doc, \"Connections\");\n    const usedIds = new Set<number>();\n    const reserve = (property: FBXProperty | undefined): void => {\n        const value = property?.value;\n        if (typeof value === \"number\" && Number.isSafeInteger(value)) {\n            usedIds.add(value);\n        }\n    };\n    for (const obj of objectsNode?.children ?? []) {\n        reserve(obj.properties[0]);\n    }\n    for (const c of connectionsNode?.children ?? []) {\n        reserve(c.properties[1]);\n        reserve(c.properties[2]);\n        reserve(c.properties[3]);\n    }\n    let nextSyntheticId = -1;\n    const allocateId = (): number => {\n        while (usedIds.has(nextSyntheticId)) {\n            nextSyntheticId--;\n        }\n        const id = nextSyntheticId--;\n        usedIds.add(id);\n        return id;\n    };\n    // Ids whose magnitude exceeds 2^53 are keyed by their exact decimal text; distinct texts get distinct ids.\n    const remappedIds = new Map<string, number>();\n    const numericIdOf = (property: FBXProperty | undefined): number | undefined => {\n        if (!property) {\n            return undefined;\n        }\n        if (property.raw !== undefined) {\n            let id = remappedIds.get(property.raw);\n            if (id === undefined) {\n                id = allocateId();\n                remappedIds.set(property.raw, id);\n            }\n            return id;\n        }\n        return getSafeFBXObjectId(property.value);\n    };\n    const toObjectId = (property: FBXProperty | undefined): number | undefined => {\n        const numericId = numericIdOf(property);\n        if (numericId !== undefined) {\n            return numericId;\n        }\n        const value = property?.value;\n        if (typeof value !== \"string\") {\n            return undefined;\n        }\n        const direct = legacyIds.get(value);\n        if (direct !== undefined) {\n            return direct;\n        }\n        const legacyName = cleanFBXName(value);\n        if (legacyName === \"Scene\") {\n            return 0;\n        }\n        return legacyIdsByCleanName.get(legacyName);\n    };\n\n    const getLegacyId = (rawName: string): number => {\n        let id = legacyIds.get(rawName);\n        if (id === undefined) {\n            id = allocateId();\n            legacyIds.set(rawName, id);\n            const clean = cleanFBXName(rawName);\n            if (!legacyIdsByCleanName.has(clean)) {\n                legacyIdsByCleanName.set(clean, id);\n            }\n        }\n        return id;\n    };\n\n    const getSyntheticLegacyId = (role: string, name: string): number => {\n        let idsByName = syntheticLegacyIds.get(role);\n        if (!idsByName) {\n            idsByName = new Map();\n            syntheticLegacyIds.set(role, idsByName);\n        }\n\n        let id = idsByName.get(name);\n        if (id === undefined) {\n            id = allocateId();\n            idsByName.set(name, id);\n        }\n        return id;\n    };\n\n    /** Turns `Shape` children of a geometry into a BlendShape deformer with one channel and shape geometry each. */\n    const synthesizeInlineShapes = (owner: FBXNode, geometryId: number, key: string): void => {\n        const shapes = owner.children.filter((c) => c.name === \"Shape\");\n        if (shapes.length === 0) {\n            return;\n        }\n        const deformerId = getSyntheticLegacyId(\"BlendShape\", key);\n        const deformer = createLegacyObject(\"Deformer\", deformerId, `Deformer::${cleanFBXName(key)}`, \"BlendShape\", [createVersionNode(100)]);\n        objects.set(deformerId, deformer);\n        objectEntries.push({ id: deformerId, node: deformer, source: \"legacySyntheticBlendShape\", legacyName: key, synthetic: true });\n        addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", deformerId, geometryId);\n        for (const shape of shapes) {\n            const shapeName = cleanFBXName(getPropertyValue<string>(shape, 0) ?? \"Shape\");\n            const channelId = getSyntheticLegacyId(\"BlendShapeChannel\", `${key}|${shapeName}`);\n            const channel = createLegacyObject(\"Deformer\", channelId, `SubDeformer::${shapeName}`, \"BlendShapeChannel\", [\n                createVersionNode(100),\n                { name: \"DeformPercent\", properties: [{ type: \"float64\", value: 0 }], children: [] },\n                {\n                    name: \"Properties60\",\n                    properties: [],\n                    children: [\n                        {\n                            name: \"Property\",\n                            properties: [\n                                { type: \"string\", value: \"DeformPercent\" },\n                                { type: \"string\", value: \"Number\" },\n                                { type: \"string\", value: \"A\" },\n                                { type: \"float64\", value: 0 },\n                            ],\n                            children: [],\n                        },\n                    ],\n                },\n            ]);\n            objects.set(channelId, channel);\n            objectEntries.push({ id: channelId, node: channel, source: \"legacySyntheticBlendShape\", legacyName: `${key}|${shapeName}`, synthetic: true });\n            addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", channelId, deformerId);\n            const shapeId = getSyntheticLegacyId(\"Shape\", `${key}|${shapeName}`);\n            const shapeGeometry = createLegacyObject(\"Geometry\", shapeId, `Geometry::${shapeName}`, \"Shape\", shape.children);\n            objects.set(shapeId, shapeGeometry);\n            objectEntries.push({ id: shapeId, node: shapeGeometry, source: \"legacySyntheticBlendShape\", legacyName: `${key}|${shapeName}`, synthetic: true });\n            addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", shapeId, channelId);\n        }\n    };\n\n    // Build object map from Objects section\n    if (objectsNode) {\n        for (const obj of objectsNode.children) {\n            const idProp = obj.properties[0];\n            if (idProp) {\n                const id = numericIdOf(idProp);\n                if (id !== undefined) {\n                    objects.set(id, obj);\n                    objectEntries.push({ id, node: obj, source: \"Objects\", synthetic: false });\n                    if (obj.name === \"Geometry\" && getPropertyValue<string>(obj, 2) === \"Mesh\") {\n                        // FBX 7.1 stores blend shapes inline in the geometry, like 6.x files.\n                        synthesizeInlineShapes(obj, id, String(id));\n                    }\n                } else if (typeof idProp.value === \"string\") {\n                    const legacyName = idProp.value;\n                    const id = getLegacyId(legacyName);\n                    const normalized = normalizeLegacyObject(obj, id);\n                    objects.set(id, normalized);\n                    objectEntries.push({ id, node: normalized, source: \"Objects\", legacyName, synthetic: false });\n\n                    const legacySubType = obj.name === \"Model\" ? getPropertyValue<string>(obj, 1) : undefined;\n                    if (legacySubType === \"Mesh\") {\n                        const geometryId = getSyntheticLegacyId(\"Geometry\", legacyName);\n                        const geometry = createLegacyGeometry(obj, geometryId);\n                        objects.set(geometryId, geometry);\n                        objectEntries.push({ id: geometryId, node: geometry, source: \"legacySyntheticGeometry\", legacyName, synthetic: true });\n                        addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", geometryId, id);\n                        legacyGeometryByModelId.set(id, geometryId);\n\n                        // Inline blend shapes become a BlendShape deformer with one channel and one shape geometry each.\n                        synthesizeInlineShapes(obj, geometryId, legacyName);\n                    } else if (legacySubType === \"Light\" || legacySubType === \"Camera\") {\n                        // 6.x lights and cameras keep their attribute properties on the model; expose them as a NodeAttribute.\n                        const attributeId = getSyntheticLegacyId(\"NodeAttribute\", legacyName);\n                        const attribute = createLegacyObject(\"NodeAttribute\", attributeId, `NodeAttribute::${cleanFBXName(legacyName)}`, legacySubType, obj.children);\n                        objects.set(attributeId, attribute);\n                        objectEntries.push({ id: attributeId, node: attribute, source: \"legacySyntheticAttribute\", legacyName, synthetic: true });\n                        addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", attributeId, id);\n                    }\n                }\n            }\n        }\n    }\n\n    // Parse connections\n    if (connectionsNode) {\n        for (const c of connectionsNode.children) {\n            if (c.name !== \"C\" && c.name !== \"Connect\") {\n                continue;\n            }\n\n            const connectionIndex = connectionEntries.length;\n            let type = getPropertyValue<string>(c, 0);\n            let childIdRaw = c.properties[1];\n            let parentIdRaw = c.properties[2];\n            let poPropertyName: string | undefined;\n            // \"PO\" connects a property of the first object to the second object (6.x constraints use it for\n            // \"Constrained Object\"); it is the mirror image of \"OP\", so store it as OP from the object to the owner.\n            if (type === \"PO\" && typeof c.properties[2]?.value === \"string\" && c.properties.length > 3) {\n                type = \"OP\";\n                poPropertyName = c.properties[2].value as string;\n                childIdRaw = c.properties[3];\n                parentIdRaw = c.properties[1];\n            }\n            const entry: FBXConnectionEntry = {\n                source: c.name,\n                rawType: type,\n                accepted: false,\n            };\n            connectionEntries.push(entry);\n\n            if (type !== \"OO\" && type !== \"OP\") {\n                const childId = toObjectId(childIdRaw);\n                const parentId = toObjectId(parentIdRaw);\n                diagnostics.push({\n                    reason: \"unsupported-connection-type\",\n                    message: `Unsupported FBX connection type '${type ?? \"\"}' was not added to the graph.`,\n                    connectionIndex,\n                    type,\n                    childId,\n                    parentId,\n                });\n                continue;\n            }\n\n            if (childIdRaw === undefined || parentIdRaw === undefined) {\n                diagnostics.push({\n                    reason: \"missing-connection-endpoint\",\n                    message: \"FBX connection is missing a child or parent endpoint.\",\n                    connectionIndex,\n                    type,\n                });\n                continue;\n            }\n\n            const childId = toObjectId(childIdRaw);\n            let parentId = toObjectId(parentIdRaw);\n            // 6.x deformers connect to the model; the importer expects them on the geometry.\n            if (childId !== undefined && parentId !== undefined && objects.get(childId)?.name === \"Deformer\") {\n                parentId = legacyGeometryByModelId.get(parentId) ?? parentId;\n            }\n            if (childId === undefined || parentId === undefined) {\n                diagnostics.push({\n                    reason: \"unresolved-legacy-endpoint\",\n                    message: \"FBX connection references a legacy string endpoint that is not present in the object table.\",\n                    connectionIndex,\n                    type,\n                });\n                continue;\n            }\n\n            const propertyName = poPropertyName ?? (type === \"OP\" && c.properties.length > 3 ? getPropertyValue<string>(c, 3) : undefined);\n\n            entry.childId = childId;\n            entry.parentId = parentId;\n            entry.propertyName = propertyName;\n\n            if (childId === parentId) {\n                diagnostics.push({\n                    reason: \"self-loop\",\n                    message: \"FBX connection references the same object as child and parent.\",\n                    connectionIndex,\n                    type,\n                    childId,\n                    parentId,\n                    propertyName,\n                });\n            }\n            if (!objects.has(childId)) {\n                diagnostics.push({\n                    reason: \"unresolved-object-reference\",\n                    message: \"FBX connection child ID is not present in the object table.\",\n                    connectionIndex,\n                    type,\n                    childId,\n                    parentId,\n                    propertyName,\n                });\n            }\n            if (parentId !== 0 && !objects.has(parentId)) {\n                diagnostics.push({\n                    reason: \"unresolved-object-reference\",\n                    message: \"FBX connection parent ID is not present in the object table.\",\n                    connectionIndex,\n                    type,\n                    childId,\n                    parentId,\n                    propertyName,\n                });\n            }\n\n            addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex);\n            entry.accepted = true;\n        }\n    }\n\n    return { objects, objectEntries, childrenOf, parentOf, connections, connectionEntries, diagnostics };\n}\n\n/** Get all child objects of a given parent ID, optionally filtered by node name */\nexport function getChildren(map: FBXObjectMap, parentId: number, nodeName?: string): { id: number; node: FBXNode; propertyName?: string }[] {\n    const children = map.childrenOf.get(parentId) ?? [];\n    const result: { id: number; node: FBXNode; propertyName?: string }[] = [];\n\n    for (const child of children) {\n        const node = map.objects.get(child.id);\n        if (node && (!nodeName || node.name === nodeName)) {\n            result.push({ id: child.id, node, propertyName: child.propertyName });\n        }\n    }\n\n    return result;\n}\n\nfunction createVersionNode(version: number): FBXNode {\n    return { name: \"Version\", properties: [{ type: \"int32\", value: version }], children: [] };\n}\n\nfunction createLegacyObject(nodeName: string, id: number, name: string, subType: string, children: FBXNode[]): FBXNode {\n    return {\n        name: nodeName,\n        properties: [\n            { type: \"int64\", value: id },\n            { type: \"string\", value: name },\n            { type: \"string\", value: subType },\n        ],\n        children,\n    };\n}\n\nfunction addConnection(\n    connections: FBXConnection[],\n    childrenOf: Map<number, { id: number; propertyName?: string }[]>,\n    parentOf: Map<number, { id: number; propertyName?: string }>,\n    diagnostics: FBXConnectionDiagnostic[],\n    type: ConnectionType,\n    childId: number,\n    parentId: number,\n    propertyName?: string,\n    connectionIndex?: number\n): void {\n    connections.push({ type, childId, parentId, propertyName });\n\n    if (!childrenOf.has(parentId)) {\n        childrenOf.set(parentId, []);\n    }\n    childrenOf.get(parentId)!.push({ id: childId, propertyName });\n    const existingParent = parentOf.get(childId);\n    if (existingParent) {\n        diagnostics.push({\n            reason: \"duplicate-parent\",\n            message: \"FBX object has multiple parents; preserving the existing last-parent behavior.\",\n            connectionIndex,\n            type,\n            childId,\n            parentId,\n            propertyName,\n        });\n    }\n    parentOf.set(childId, { id: parentId, propertyName });\n}\n\nfunction normalizeLegacyObject(node: FBXNode, id: number): FBXNode {\n    const name = cleanFBXName(getPropertyValue<string>(node, 0) ?? node.name);\n    const subType = getPropertyValue<string>(node, 1) ?? \"\";\n    return {\n        ...node,\n        properties: [\n            { type: \"int64\", value: id },\n            { type: \"string\", value: name },\n            { type: \"string\", value: subType },\n        ],\n    };\n}\n\nfunction createLegacyGeometry(modelNode: FBXNode, geometryId: number): FBXNode {\n    const name = cleanFBXName(getPropertyValue<string>(modelNode, 0) ?? \"Geometry\");\n    return {\n        name: \"Geometry\",\n        properties: [\n            { type: \"int64\", value: geometryId },\n            { type: \"string\", value: name },\n            { type: \"string\", value: \"Mesh\" },\n        ],\n        children: modelNode.children,\n    };\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXNode, findChildByName, findChildrenByName, getPropertyValue, cleanFBXName, getNodeArray } from \"../types/fbxTypes\";\n\n/** A named UV set */\nexport interface FBXUVSet {\n    /** UV set name (e.g. \"UVMap\", \"lightmap\") */\n    name: string;\n    /** Per-vertex UV data [u,v, ...] (expanded to match triangle vertices) */\n    data: Float64Array;\n}\n\n/** Recoverable geometry import issue. */\nexport interface FBXGeometryDiagnostic {\n    /** Diagnostic category. */\n    type:\n        \"degenerate-polygon\" | \"triangulation-fallback\" | \"layer-index-out-of-bounds\" | \"layer-data-too-short\" | \"nurbs-invalid\" | \"nurbs-trim-ignored\" | \"nurbs-deformer-ignored\";\n    /** Human-readable diagnostic message. */\n    message: string;\n    /** Polygon index associated with the diagnostic, if applicable. */\n    polygonIndex?: number;\n    /** Layer element name associated with the diagnostic, if applicable. */\n    layerName?: string;\n    /** Source data index associated with the diagnostic, if applicable. */\n    index?: number;\n}\n\n/** Parsed geometry data ready for Babylon consumption */\nexport interface FBXGeometryData {\n    /** Node ID from the FBX document */\n    id: number;\n    /** Geometry name */\n    name: string;\n    /** Flat array of vertex positions [x,y,z, x,y,z, ...] */\n    positions: Float64Array;\n    /** Triangle indices (already triangulated from n-gons) */\n    indices: Uint32Array;\n    /** Per-vertex normals [x,y,z, ...] (expanded to match triangle vertices) */\n    normals: Float64Array | null;\n    /** Per-vertex UVs [u,v, ...] (expanded to match triangle vertices) — first UV set for convenience */\n    uvs: Float64Array | null;\n    /** All UV sets (including the first) */\n    uvSets: FBXUVSet[];\n    /** Per-vertex colors [r,g,b,a, ...] (expanded to match triangle vertices) */\n    colors: Float32Array | null;\n    /** Per-vertex tangents [x,y,z,w, ...] expanded to match triangle vertices */\n    tangents: Float64Array | null;\n    /** Per-vertex binormals [x,y,z, ...] expanded to match triangle vertices */\n    binormals: Float64Array | null;\n    /** Control point index for each polygon-vertex (for skinning lookup) */\n    controlPointIndices: Uint32Array | null;\n    /** Per-triangle material index (which material each triangle belongs to) */\n    materialIndices: Int32Array | null;\n    /** Recoverable geometry import issues */\n    diagnostics: FBXGeometryDiagnostic[];\n}\n\n/**\n * Extract geometry data from an FBX Geometry node.\n * Handles polygon triangulation and layer element expansion.\n */\nexport function extractGeometry(geometryNode: FBXNode, nodeId: number): FBXGeometryData {\n    const name = cleanFBXName(getPropertyValue<string>(geometryNode, 1) ?? \"Geometry\");\n\n    // Extract raw vertices\n    // Edge-only meshes (e.g. Blender edge circles) and empty placeholders have no vertices or polygons; they\n    // become geometry with zero triangles rather than errors.\n    const verticesNode = findChildByName(geometryNode, \"Vertices\");\n    const rawPositions = verticesNode ? toFloat64Array(getNodeArrayValue(verticesNode)) : new Float64Array(0);\n\n    // Extract polygon vertex indices\n    const pviNode = findChildByName(geometryNode, \"PolygonVertexIndex\");\n    const rawIndices = pviNode ? toInt32Array(getNodeArrayValue(pviNode)) : new Int32Array(0);\n    const diagnostics: FBXGeometryDiagnostic[] = [];\n\n    // Parse polygons from the FBX negative-index convention\n    const polygons = parsePolygons(rawIndices);\n\n    // Triangulate polygons while preserving polygon-vertex indices for layer data.\n    const triangles = triangulatePolygons(polygons, rawPositions, diagnostics);\n\n    // Build the list of polygon-vertex pairs for layer element expansion\n    const polyVertexList = buildPolygonVertexList(polygons);\n\n    // Extract normals\n    const normalNode = findChildByName(geometryNode, \"LayerElementNormal\");\n    let normals: Float64Array | null = null;\n    if (normalNode) {\n        normals = expandLayerElement(normalNode, \"Normals\", \"NormalsIndex\", polyVertexList, rawPositions.length / 3, 3, diagnostics);\n    }\n\n    // Extract all UV sets\n    const uvNodes = findChildrenByName(geometryNode, \"LayerElementUV\");\n    const uvSets: FBXUVSet[] = [];\n    for (const uvNode of uvNodes) {\n        const nameNode = findChildByName(uvNode, \"Name\");\n        const setName = nameNode ? (getPropertyValue<string>(nameNode, 0) ?? `UVSet${uvSets.length}`) : `UVSet${uvSets.length}`;\n        const data = expandLayerElement(uvNode, \"UV\", \"UVIndex\", polyVertexList, rawPositions.length / 3, 2, diagnostics);\n        if (data) {\n            uvSets.push({ name: setName, data });\n        }\n    }\n    const uvs = uvSets.length > 0 ? uvSets[0].data : null;\n\n    // Extract vertex colors\n    const colorNode = findChildByName(geometryNode, \"LayerElementColor\");\n    let colors: Float32Array | null = null;\n    if (colorNode) {\n        const colorData = expandLayerElement(colorNode, \"Colors\", \"ColorIndex\", polyVertexList, rawPositions.length / 3, 4, diagnostics);\n        if (colorData) {\n            colors = new Float32Array(colorData.length);\n            for (let i = 0; i < colorData.length; i++) {\n                colors[i] = colorData[i];\n            }\n        }\n    }\n\n    const tangentNode = findChildByName(geometryNode, \"LayerElementTangent\");\n    const binormalNode = findChildByName(geometryNode, \"LayerElementBinormal\");\n    const binormals = binormalNode ? expandLayerElement(binormalNode, \"Binormals\", \"BinormalsIndex\", polyVertexList, rawPositions.length / 3, 3, diagnostics) : null;\n    const tangents = tangentNode ? expandTangentLayer(tangentNode, polyVertexList, rawPositions.length / 3, normals, binormals, diagnostics) : null;\n\n    // Extract per-polygon material indices\n    const matNode = findChildByName(geometryNode, \"LayerElementMaterial\");\n    let polyMaterialIndices: Int32Array | null = null;\n    if (matNode) {\n        polyMaterialIndices = extractMaterialIndices(matNode, polygons.length);\n    }\n\n    // Build final indexed mesh with expanded per-triangle-vertex attributes\n    const result = buildTriangleMesh(rawPositions, triangles, polyVertexList, normals, uvs, uvSets, colors, tangents, binormals);\n\n    // Expand per-polygon material indices to per-triangle\n    let materialIndices: Int32Array | null = null;\n    if (polyMaterialIndices) {\n        // Check if all polygons use the same material (optimization)\n        let allSame = true;\n        const firstMat = polyMaterialIndices[0];\n        for (let i = 1; i < polyMaterialIndices.length; i++) {\n            if (polyMaterialIndices[i] !== firstMat) {\n                allSame = false;\n                break;\n            }\n        }\n\n        if (!allSame || firstMat !== 0) {\n            const triCount = result.indices.length / 3;\n            materialIndices = new Int32Array(triCount);\n            for (let ti = 0; ti < triangles.length; ti++) {\n                materialIndices[ti] = polyMaterialIndices[triangles[ti].polyIndex] ?? 0;\n            }\n        }\n    }\n\n    return {\n        id: nodeId,\n        name,\n        positions: result.positions,\n        indices: result.indices,\n        normals: result.normals,\n        uvs: result.uvs,\n        uvSets: result.uvSets,\n        colors: result.colors,\n        tangents: result.tangents,\n        binormals: result.binormals,\n        controlPointIndices: result.controlPointIndices,\n        materialIndices,\n        diagnostics,\n    };\n}\n\n// ── Polygon Parsing ────────────────────────────────────────────────────────────\n\ninterface Polygon {\n    /** Control point indices for this polygon */\n    indices: number[];\n    /** Starting index in the original PolygonVertexIndex array */\n    startIndex: number;\n}\n\ninterface Triangle {\n    vertices: [number, number, number];\n    polyIndex: number;\n}\n\nfunction parsePolygons(rawIndices: Int32Array): Polygon[] {\n    const polygons: Polygon[] = [];\n    let currentPoly: number[] = [];\n    let startIndex = 0;\n\n    for (let i = 0; i < rawIndices.length; i++) {\n        const idx = rawIndices[i];\n        if (idx < 0) {\n            // End of polygon: actual index is -(idx + 1)\n            currentPoly.push(-(idx + 1));\n            polygons.push({ indices: currentPoly, startIndex });\n            currentPoly = [];\n            startIndex = i + 1;\n        } else {\n            currentPoly.push(idx);\n        }\n    }\n\n    return polygons;\n}\n\nfunction triangulatePolygons(polygons: Polygon[], rawPositions: Float64Array, diagnostics: FBXGeometryDiagnostic[]): Triangle[] {\n    const triangles: Triangle[] = [];\n\n    for (let polyIndex = 0; polyIndex < polygons.length; polyIndex++) {\n        const poly = polygons[polyIndex];\n        triangles.push(...triangulatePolygon(poly, polyIndex, rawPositions, diagnostics));\n    }\n\n    return triangles;\n}\n\nfunction triangulatePolygon(poly: Polygon, polyIndex: number, rawPositions: Float64Array, diagnostics: FBXGeometryDiagnostic[]): Triangle[] {\n    if (poly.indices.length < 3) {\n        diagnostics.push({\n            type: \"degenerate-polygon\",\n            message: `Polygon ${polyIndex} has fewer than three vertices.`,\n            polygonIndex: polyIndex,\n        });\n        return [];\n    }\n    if (poly.indices.length === 3) {\n        return [{ vertices: [poly.startIndex, poly.startIndex + 1, poly.startIndex + 2], polyIndex }];\n    }\n\n    const projected = projectPolygonTo2D(poly, rawPositions);\n    if (!projected) {\n        diagnostics.push({\n            type: \"degenerate-polygon\",\n            message: `Polygon ${polyIndex} has a near-zero normal; using fan triangulation.`,\n            polygonIndex: polyIndex,\n        });\n        return fanTriangulate(poly, polyIndex);\n    }\n\n    const polygonArea = signedArea2D(projected);\n    if (Math.abs(polygonArea) < 1e-12) {\n        diagnostics.push({\n            type: \"degenerate-polygon\",\n            message: `Polygon ${polyIndex} projects to near-zero area; using fan triangulation.`,\n            polygonIndex: polyIndex,\n        });\n        return fanTriangulate(poly, polyIndex);\n    }\n\n    const isCCW = polygonArea > 0;\n    const clipped = earClip(projected, isCCW, polygonArea);\n    if (!clipped) {\n        diagnostics.push({\n            type: \"triangulation-fallback\",\n            message: `Polygon ${polyIndex} could not be fully ear-clipped; using fan triangulation.`,\n            polygonIndex: polyIndex,\n        });\n        return fanTriangulate(poly, polyIndex);\n    }\n    return clipped.map(([a, b, c]) => ({ vertices: [poly.startIndex + a, poly.startIndex + b, poly.startIndex + c] as [number, number, number], polyIndex }));\n}\n\n/**\n * Ear clipping on a doubly linked vertex ring. Only reflex vertices can lie inside a candidate ear, so the\n * containment test walks the reflex vertices alone, and the scan resumes after the last clipped ear instead of\n * restarting, which keeps large n-gons (thousands of vertices) at roughly quadratic cost in the reflex count.\n * @returns triangles as local vertex indices, or null when no ear can be found (self-intersecting input)\n */\nfunction earClip(points: [number, number][], isCCW: boolean, polygonArea: number): [number, number, number][] | null {\n    const n = points.length;\n    const prev = new Int32Array(n);\n    const next = new Int32Array(n);\n    for (let i = 0; i < n; i++) {\n        prev[i] = (i + n - 1) % n;\n        next[i] = (i + 1) % n;\n    }\n    // Tolerances scale with the polygon so huge and tiny coordinates behave the same.\n    const eps = Math.abs(polygonArea) * 1e-12 + 1e-300;\n    const sign = isCCW ? 1 : -1;\n    const turn = (i: number): number => sign * cross2D(points[prev[i]], points[i], points[next[i]]);\n    const reflex = new Uint8Array(n);\n    for (let i = 0; i < n; i++) {\n        reflex[i] = turn(i) < -eps ? 1 : 0;\n    }\n    const inside = (p: [number, number], a: [number, number], b: [number, number], c: [number, number]): boolean => {\n        // Inside or on the boundary of the (consistently oriented) triangle\n        return sign * cross2D(a, b, p) >= -eps && sign * cross2D(b, c, p) >= -eps && sign * cross2D(c, a, p) >= -eps;\n    };\n\n    const triangles: [number, number, number][] = [];\n    let remaining = n;\n    let i = 0;\n    let visitedSinceClip = 0;\n    while (remaining > 3) {\n        const a = prev[i];\n        const c = next[i];\n        let clip = false;\n        if (!reflex[i]) {\n            const t = turn(i);\n            if (t <= eps) {\n                // Collinear vertex: its ear is a zero-area sliver, kept so every n-gon still yields n - 2 triangles.\n                clip = true;\n                triangles.push([a, i, c]);\n            } else {\n                clip = true;\n                for (let j = next[c]; j !== a; j = next[j]) {\n                    if (reflex[j] && inside(points[j], points[a], points[i], points[c])) {\n                        clip = false;\n                        break;\n                    }\n                }\n                if (clip) {\n                    triangles.push([a, i, c]);\n                }\n            }\n        }\n        if (clip) {\n            next[a] = c;\n            prev[c] = a;\n            remaining--;\n            reflex[a] = turn(a) < -eps ? 1 : 0;\n            reflex[c] = turn(c) < -eps ? 1 : 0;\n            i = c;\n            visitedSinceClip = 0;\n            continue;\n        }\n        i = c;\n        if (++visitedSinceClip > remaining) {\n            return null;\n        }\n    }\n    const last = i;\n    triangles.push([prev[last], last, next[last]]);\n    return triangles;\n}\n\nfunction fanTriangulate(poly: Polygon, polyIndex: number): Triangle[] {\n    const triangles: Triangle[] = [];\n    for (let i = 1; i < poly.indices.length - 1; i++) {\n        triangles.push({\n            vertices: [poly.startIndex, poly.startIndex + i, poly.startIndex + i + 1],\n            polyIndex,\n        });\n    }\n    return triangles;\n}\n\nfunction projectPolygonTo2D(poly: Polygon, rawPositions: Float64Array): [number, number][] | null {\n    const normal = computeNewellNormal(poly, rawPositions);\n    const ax = Math.abs(normal[0]);\n    const ay = Math.abs(normal[1]);\n    const az = Math.abs(normal[2]);\n    if (ax + ay + az < 1e-12) {\n        return null;\n    }\n\n    const dropAxis = ax > ay && ax > az ? 0 : ay > az ? 1 : 2;\n    return poly.indices.map((cp) => {\n        const x = rawPositions[cp * 3];\n        const y = rawPositions[cp * 3 + 1];\n        const z = rawPositions[cp * 3 + 2];\n        if (dropAxis === 0) {\n            return normal[0] >= 0 ? [y, z] : [z, y];\n        }\n        if (dropAxis === 1) {\n            return normal[1] >= 0 ? [z, x] : [x, z];\n        }\n        return normal[2] >= 0 ? [x, y] : [y, x];\n    });\n}\n\nfunction computeNewellNormal(poly: Polygon, rawPositions: Float64Array): [number, number, number] {\n    let nx = 0;\n    let ny = 0;\n    let nz = 0;\n    for (let i = 0; i < poly.indices.length; i++) {\n        const current = poly.indices[i] * 3;\n        const next = poly.indices[(i + 1) % poly.indices.length] * 3;\n        const x0 = rawPositions[current];\n        const y0 = rawPositions[current + 1];\n        const z0 = rawPositions[current + 2];\n        const x1 = rawPositions[next];\n        const y1 = rawPositions[next + 1];\n        const z1 = rawPositions[next + 2];\n        nx += (y0 - y1) * (z0 + z1);\n        ny += (z0 - z1) * (x0 + x1);\n        nz += (x0 - x1) * (y0 + y1);\n    }\n    return [nx, ny, nz];\n}\n\nfunction signedArea2D(points: [number, number][]): number {\n    let area = 0;\n    for (let i = 0; i < points.length; i++) {\n        const a = points[i];\n        const b = points[(i + 1) % points.length];\n        area += a[0] * b[1] - b[0] * a[1];\n    }\n    return area / 2;\n}\n\nfunction cross2D(a: [number, number], b: [number, number], c: [number, number]): number {\n    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);\n}\n\n/** Build a flat list of (polygonIndex, vertexInPolygon, controlPointIndex) for each polygon vertex */\ninterface PolyVertex {\n    polyIndex: number;\n    vertexInPoly: number;\n    controlPointIndex: number;\n    /** Global polygon-vertex index (position in the original PolygonVertexIndex array) */\n    globalIndex: number;\n}\n\nfunction buildPolygonVertexList(polygons: Polygon[]): PolyVertex[] {\n    const list: PolyVertex[] = [];\n    for (let pi = 0; pi < polygons.length; pi++) {\n        const poly = polygons[pi];\n        for (let vi = 0; vi < poly.indices.length; vi++) {\n            list.push({\n                polyIndex: pi,\n                vertexInPoly: vi,\n                controlPointIndex: poly.indices[vi],\n                globalIndex: poly.startIndex + vi,\n            });\n        }\n    }\n    return list;\n}\n\n// ── Layer Element Expansion ────────────────────────────────────────────────────\n\n/**\n * Extract per-polygon material indices from LayerElementMaterial.\n * Returns an Int32Array with one material index per polygon.\n */\nfunction extractMaterialIndices(matNode: FBXNode, polygonCount: number): Int32Array | null {\n    const mappingNode = findChildByName(matNode, \"MappingInformationType\");\n    const referenceNode = findChildByName(matNode, \"ReferenceInformationType\");\n\n    if (!mappingNode || !referenceNode) {\n        return null;\n    }\n\n    const mapping = getPropertyValue<string>(mappingNode, 0) ?? \"\";\n    const reference = getPropertyValue<string>(referenceNode, 0) ?? \"\";\n\n    if (mapping === \"AllSame\") {\n        const materialsNode = findChildByName(matNode, \"Materials\");\n        const rawIndices = materialsNode ? toInt32Array(getNodeArrayValue(materialsNode)) : null;\n        const materialIndex = rawIndices && rawIndices.length > 0 ? rawIndices[0] : 0;\n        const indices = new Int32Array(polygonCount);\n        if (materialIndex !== 0) {\n            indices.fill(materialIndex);\n        }\n        return indices;\n    }\n\n    if (mapping === \"ByPolygon\") {\n        const materialsNode = findChildByName(matNode, \"Materials\");\n        if (!materialsNode) {\n            return null;\n        }\n        const rawIndices = toInt32Array(getNodeArrayValue(materialsNode));\n        // For Direct reference, the Materials array has one index per polygon\n        if (reference === \"Direct\" || reference === \"IndexToDirect\") {\n            return rawIndices;\n        }\n    }\n\n    return null;\n}\n\nfunction expandLayerElement(\n    layerNode: FBXNode,\n    dataChildName: string,\n    indexChildName: string,\n    polyVertexList: PolyVertex[],\n    controlPointCount: number,\n    stride: number,\n    diagnostics: FBXGeometryDiagnostic[]\n): Float64Array | null {\n    const mappingNode = findChildByName(layerNode, \"MappingInformationType\");\n    const referenceNode = findChildByName(layerNode, \"ReferenceInformationType\");\n\n    if (!mappingNode || !referenceNode) {\n        return null;\n    }\n\n    const mapping = getPropertyValue<string>(mappingNode, 0) ?? \"\";\n    const reference = getPropertyValue<string>(referenceNode, 0) ?? \"\";\n\n    const dataNode = findChildByName(layerNode, dataChildName);\n    if (!dataNode) {\n        return null;\n    }\n    const data = toFloat64Array(getNodeArrayValue(dataNode));\n\n    let indexData: Int32Array | null = null;\n    if (reference === \"IndexToDirect\") {\n        const indexNode = findChildByName(layerNode, indexChildName);\n        if (indexNode) {\n            indexData = toInt32Array(getNodeArrayValue(indexNode));\n        }\n    }\n\n    // Expand to per-polygon-vertex\n    const result = new Float64Array(polyVertexList.length * stride);\n\n    for (let i = 0; i < polyVertexList.length; i++) {\n        const pv = polyVertexList[i];\n        let dataIndex: number;\n\n        if (mapping === \"ByPolygonVertex\") {\n            if (reference === \"IndexToDirect\" && indexData) {\n                dataIndex = indexData[pv.globalIndex];\n            } else {\n                // Direct\n                dataIndex = pv.globalIndex;\n            }\n        } else if (mapping === \"ByControlPoint\" || mapping === \"ByVertice\") {\n            if (reference === \"IndexToDirect\" && indexData) {\n                dataIndex = indexData[pv.controlPointIndex];\n            } else {\n                dataIndex = pv.controlPointIndex;\n            }\n        } else if (mapping === \"ByPolygon\") {\n            if (reference === \"IndexToDirect\" && indexData) {\n                dataIndex = indexData[pv.polyIndex];\n            } else {\n                dataIndex = pv.polyIndex;\n            }\n        } else if (mapping === \"AllSame\") {\n            dataIndex = 0;\n        } else {\n            dataIndex = pv.globalIndex;\n        }\n\n        for (let s = 0; s < stride; s++) {\n            const sourceIndex = dataIndex * stride + s;\n            if (dataIndex < 0 || sourceIndex >= data.length) {\n                diagnostics.push({\n                    type: sourceIndex >= data.length ? \"layer-data-too-short\" : \"layer-index-out-of-bounds\",\n                    message: `Layer '${layerNode.name}' references unavailable element ${dataIndex}.`,\n                    layerName: layerNode.name,\n                    index: dataIndex,\n                });\n                result[i * stride + s] = 0;\n            } else {\n                result[i * stride + s] = data[sourceIndex];\n            }\n        }\n    }\n\n    return result;\n}\n\nfunction expandTangentLayer(\n    tangentNode: FBXNode,\n    polyVertexList: PolyVertex[],\n    controlPointCount: number,\n    normals: Float64Array | null,\n    binormals: Float64Array | null,\n    diagnostics: FBXGeometryDiagnostic[]\n): Float64Array | null {\n    const sourceStride = inferLayerElementStride(tangentNode, \"Tangents\", \"TangentsIndex\", polyVertexList, controlPointCount, diagnostics);\n    const expanded = expandLayerElement(tangentNode, \"Tangents\", \"TangentsIndex\", polyVertexList, controlPointCount, sourceStride, diagnostics);\n    if (!expanded) {\n        return null;\n    }\n\n    const tangents = new Float64Array(polyVertexList.length * 4);\n    for (let i = 0; i < polyVertexList.length; i++) {\n        const sourceOffset = i * sourceStride;\n        const destOffset = i * 4;\n        tangents[destOffset] = expanded[sourceOffset];\n        tangents[destOffset + 1] = expanded[sourceOffset + 1];\n        tangents[destOffset + 2] = expanded[sourceOffset + 2];\n        tangents[destOffset + 3] = sourceStride >= 4 ? expanded[sourceOffset + 3] : computeTangentHandedness(i, tangents, normals, binormals);\n    }\n    return tangents;\n}\n\nfunction inferLayerElementStride(\n    layerNode: FBXNode,\n    dataChildName: string,\n    indexChildName: string,\n    polyVertexList: PolyVertex[],\n    controlPointCount: number,\n    diagnostics: FBXGeometryDiagnostic[]\n): number {\n    const dataNode = findChildByName(layerNode, dataChildName);\n    if (!dataNode) {\n        return 3;\n    }\n    const data = toFloat64Array(getNodeArrayValue(dataNode));\n    const mapping = getPropertyValue<string>(findChildByName(layerNode, \"MappingInformationType\") ?? { name: \"\", properties: [], children: [] }, 0) ?? \"\";\n    const reference = getPropertyValue<string>(findChildByName(layerNode, \"ReferenceInformationType\") ?? { name: \"\", properties: [], children: [] }, 0) ?? \"\";\n    const indexNode = findChildByName(layerNode, indexChildName);\n    const indexData = indexNode ? toInt32Array(getNodeArrayValue(indexNode)) : null;\n    const directCount =\n        reference === \"IndexToDirect\" && indexData\n            ? Math.max(...Array.from(indexData), 0) + 1\n            : mapping === \"ByControlPoint\" || mapping === \"ByVertice\"\n              ? controlPointCount\n              : mapping === \"AllSame\"\n                ? 1\n                : polyVertexList.length;\n\n    if (directCount > 0 && data.length % directCount === 0) {\n        const stride = data.length / directCount;\n        if (stride === 3 || stride === 4) {\n            return stride;\n        }\n    }\n\n    diagnostics.push({\n        type: \"layer-data-too-short\",\n        message: `Could not infer stride for layer '${layerNode.name}', defaulting to 3.`,\n        layerName: layerNode.name,\n    });\n    return 3;\n}\n\nfunction computeTangentHandedness(vertexIndex: number, tangents: Float64Array, normals: Float64Array | null, binormals: Float64Array | null): number {\n    if (!normals || !binormals) {\n        return 1;\n    }\n    const to = vertexIndex * 4;\n    const no = vertexIndex * 3;\n    const nx = normals[no];\n    const ny = normals[no + 1];\n    const nz = normals[no + 2];\n    const tx = tangents[to];\n    const ty = tangents[to + 1];\n    const tz = tangents[to + 2];\n    const bx = binormals[no];\n    const by = binormals[no + 1];\n    const bz = binormals[no + 2];\n    const cx = ny * tz - nz * ty;\n    const cy = nz * tx - nx * tz;\n    const cz = nx * ty - ny * tx;\n    return cx * bx + cy * by + cz * bz < 0 ? -1 : 1;\n}\n\n// ── Final Mesh Assembly ────────────────────────────────────────────────────────\n\ninterface TriangleMeshData {\n    positions: Float64Array;\n    indices: Uint32Array;\n    normals: Float64Array | null;\n    uvs: Float64Array | null;\n    uvSets: FBXUVSet[];\n    colors: Float32Array | null;\n    tangents: Float64Array | null;\n    binormals: Float64Array | null;\n    controlPointIndices: Uint32Array;\n}\n\n/**\n * Build the final triangle mesh. Since normals/UVs are per-polygon-vertex,\n * we need to create unique vertices for each polygon-vertex combination.\n */\nfunction buildTriangleMesh(\n    rawPositions: Float64Array,\n    triangles: Triangle[],\n    polyVertexList: PolyVertex[],\n    expandedNormals: Float64Array | null,\n    expandedUVs: Float64Array | null,\n    expandedUVSets: FBXUVSet[],\n    expandedColors: Float32Array | null,\n    expandedTangents: Float64Array | null,\n    expandedBinormals: Float64Array | null\n): TriangleMeshData {\n    // FBX stores every attribute per polygon-vertex. Polygon-vertices that share the control point and all attribute\n    // values are welded into one output vertex (this is what every DCC does on import); polygon-vertices that differ\n    // in any attribute (hard edges, UV seams) stay separate. Skinning and blend shapes index by control point, so\n    // welding is transparent to them.\n    const polyVertexCount = polyVertexList.length;\n    const remap = new Uint32Array(polyVertexCount);\n    const unique: number[] = [];\n    const keyToIndex = new Map<string, number>();\n    const uvSetCount = expandedUVSets.length;\n    for (let i = 0; i < polyVertexCount; i++) {\n        let key = String(polyVertexList[i].controlPointIndex);\n        if (expandedNormals) {\n            key += `|${expandedNormals[i * 3]},${expandedNormals[i * 3 + 1]},${expandedNormals[i * 3 + 2]}`;\n        }\n        for (let u = 0; u < uvSetCount; u++) {\n            const d = expandedUVSets[u].data;\n            key += `|${d[i * 2]},${d[i * 2 + 1]}`;\n        }\n        if (expandedColors) {\n            key += `|${expandedColors[i * 4]},${expandedColors[i * 4 + 1]},${expandedColors[i * 4 + 2]},${expandedColors[i * 4 + 3]}`;\n        }\n        if (expandedTangents) {\n            key += `|${expandedTangents[i * 4]},${expandedTangents[i * 4 + 1]},${expandedTangents[i * 4 + 2]},${expandedTangents[i * 4 + 3]}`;\n        }\n        let index = keyToIndex.get(key);\n        if (index === undefined) {\n            index = unique.length;\n            keyToIndex.set(key, index);\n            unique.push(i);\n        }\n        remap[i] = index;\n    }\n\n    const vertexCount = unique.length;\n    const positions = new Float64Array(vertexCount * 3);\n    const controlPointIndices = new Uint32Array(vertexCount);\n    const gather = (src: Float64Array | Float32Array | null, stride: number, ctor: typeof Float64Array | typeof Float32Array) => {\n        if (!src) {\n            return null;\n        }\n        const out = new ctor(vertexCount * stride);\n        for (let v = 0; v < vertexCount; v++) {\n            const srcIndex = unique[v] * stride;\n            for (let k = 0; k < stride; k++) {\n                out[v * stride + k] = src[srcIndex + k];\n            }\n        }\n        return out;\n    };\n\n    // Positions come from control points — keep in original RH space (root node handles RH→LH conversion)\n    for (let v = 0; v < vertexCount; v++) {\n        const cp = polyVertexList[unique[v]].controlPointIndex;\n        positions[v * 3] = rawPositions[cp * 3];\n        positions[v * 3 + 1] = rawPositions[cp * 3 + 1];\n        positions[v * 3 + 2] = rawPositions[cp * 3 + 2];\n        controlPointIndices[v] = cp;\n    }\n\n    // Keep original winding order — Z negation handles handedness\n    const indexCount = triangles.length * 3;\n    const indices = new Uint32Array(indexCount);\n    for (let i = 0; i < triangles.length; i++) {\n        indices[i * 3] = remap[triangles[i].vertices[0]];\n        indices[i * 3 + 1] = remap[triangles[i].vertices[1]];\n        indices[i * 3 + 2] = remap[triangles[i].vertices[2]];\n    }\n\n    const uvSets: FBXUVSet[] = expandedUVSets.map((set) => ({ name: set.name, data: gather(set.data, 2, Float64Array) as Float64Array }));\n\n    return {\n        positions,\n        indices,\n        normals: gather(expandedNormals, 3, Float64Array) as Float64Array | null,\n        uvs: uvSets.length > 0 ? uvSets[0].data : (gather(expandedUVs, 2, Float64Array) as Float64Array | null),\n        uvSets,\n        colors: gather(expandedColors, 4, Float32Array) as Float32Array | null,\n        tangents: gather(expandedTangents, 4, Float64Array) as Float64Array | null,\n        binormals: gather(expandedBinormals, 3, Float64Array) as Float64Array | null,\n        controlPointIndices,\n    };\n}\n\n// ── Utilities ──────────────────────────────────────────────────────────────────\n\nfunction toFloat64Array(value: unknown): Float64Array {\n    if (value instanceof Float64Array) {\n        return value;\n    }\n    if (value instanceof Float32Array) {\n        return new Float64Array(value);\n    }\n    if (value instanceof Int32Array || value instanceof Uint8Array) {\n        return new Float64Array(value);\n    }\n    if (Array.isArray(value)) {\n        const result = new Float64Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = Number(value[i]);\n        }\n        return result;\n    }\n    throw new Error(`Cannot convert ${typeof value} to Float64Array`);\n}\n\nfunction toInt32Array(value: unknown): Int32Array {\n    if (value instanceof Int32Array) {\n        return value;\n    }\n    if (value instanceof Float64Array) {\n        const result = new Int32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = Math.round(value[i]);\n        }\n        return result;\n    }\n    if (value instanceof Float32Array || value instanceof Uint8Array) {\n        const result = new Int32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = Math.round(value[i]);\n        }\n        return result;\n    }\n    if (Array.isArray(value)) {\n        const result = new Int32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = Math.round(Number(value[i]));\n        }\n        return result;\n    }\n    throw new Error(`Cannot convert ${typeof value} to Int32Array`);\n}\n\nfunction getNodeArrayValue(node: FBXNode): unknown {\n    return getNodeArray(node) ?? new Float64Array(0);\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * NURBS curves and surfaces, and polyline (\"Line\") geometry.\n *\n * The basis evaluation and tessellation follow the FBX SDK conventions as implemented by ufbx: knot spans are\n * subdivided uniformly, closed and periodic curves wrap their control points, and surfaces are tessellated into\n * quads (degenerate quads at poles become triangles) with welded positions along the wrapped edges.\n */\nimport { type FBXNode, findChildByName, getPropertyValue, cleanFBXName, getNodeArray } from \"../types/fbxTypes\";\nimport { type FBXGeometryData, type FBXGeometryDiagnostic } from \"./geometry\";\nimport { getPropertyEntries } from \"./propertyTemplates\";\n\nexport type FBXNurbsTopology = \"open\" | \"closed\" | \"periodic\";\n\n/** Knot vector and derived data of one parametric direction. */\nexport interface FBXNurbsBasis {\n    order: number;\n    topology: FBXNurbsTopology;\n    knots: Float64Array;\n    /** Parameter range that the curve is defined on */\n    tMin: number;\n    tMax: number;\n    /** Distinct knot values inside [tMin, tMax], i.e. the boundaries of the non-empty spans */\n    spans: Float64Array;\n    /** False when the knot vector is too short or not monotonic */\n    valid: boolean;\n}\n\n/** NURBS curve: homogeneous control points (x, y, z, w) and a basis. */\nexport interface FBXNurbsCurveData {\n    basis: FBXNurbsBasis;\n    /** Control points as x,y,z,w */\n    controlPoints: Float64Array;\n    numControlPoints: number;\n}\n\n/** NURBS surface: control points laid out as `v * numU + u`. */\nexport interface FBXNurbsSurfaceData {\n    basisU: FBXNurbsBasis;\n    basisV: FBXNurbsBasis;\n    numU: number;\n    numV: number;\n    /** Control points as x,y,z,w */\n    controlPoints: Float64Array;\n    flipNormals: boolean;\n    /** Span subdivision stored in the file (Step), 0 when absent */\n    stepU: number;\n    stepV: number;\n}\n\n/** Polyline geometry ready for a lines mesh: one or more open or closed point runs. */\nexport interface FBXCurveGeometryData {\n    id: number;\n    name: string;\n    kind: \"line\" | \"nurbsCurve\";\n    /** Each polyline as x,y,z triples; closed runs repeat their first point at the end */\n    polylines: Float64Array[];\n    /** Display colour from the geometry's Color property */\n    color: [number, number, number] | null;\n    diagnostics: FBXGeometryDiagnostic[];\n}\n\nconst MAX_NURBS_ORDER = 128;\nconst DEFAULT_SPAN_SUBDIVISION = 4;\nconst MAX_FILE_SPAN_SUBDIVISION = 16;\nconst MAX_SPAN_SUBDIVISION = 64;\n\nfunction readTopology(form: string | undefined): FBXNurbsTopology {\n    return form === \"Closed\" ? \"closed\" : form === \"Periodic\" ? \"periodic\" : \"open\";\n}\n\nexport function createNurbsBasis(order: number, form: string | undefined, knots: Float64Array): FBXNurbsBasis {\n    const basis: FBXNurbsBasis = { order, topology: readTopology(form), knots, tMin: 0, tMax: 0, spans: new Float64Array(0), valid: false };\n    if (order > 1 && order <= MAX_NURBS_ORDER) {\n        const degree = order - 1;\n        if (knots.length >= 2 * degree + 1) {\n            basis.tMin = knots[degree];\n            basis.tMax = knots[knots.length - degree - 1];\n            const maxSpans = knots.length - 2 * degree;\n            const spans: number[] = [];\n            let prev = -Infinity;\n            for (let i = 0; i < maxSpans; i++) {\n                const t = knots[degree + i];\n                if (t !== prev) {\n                    spans.push(t);\n                    prev = t;\n                }\n            }\n            basis.spans = Float64Array.from(spans);\n            basis.valid = true;\n            for (let i = 1; i < knots.length; i++) {\n                if (!(knots[i - 1] <= knots[i])) {\n                    basis.valid = false;\n                    break;\n                }\n            }\n        }\n    }\n    return basis;\n}\n\nfunction nurbsWeight(knots: Float64Array, knot: number, degree: number, u: number): number {\n    if (knot < 0 || knot >= knots.length || knots.length - knot < degree) {\n        return 0;\n    }\n    const prevU = knots[knot];\n    const nextU = knots[knot + degree];\n    if (prevU >= nextU) {\n        return 0;\n    }\n    if (u <= prevU) {\n        return 0;\n    }\n    if (u >= nextU) {\n        return 1;\n    }\n    return (u - prevU) / (nextU - prevU);\n}\n\nfunction nurbsDeriv(knots: Float64Array, knot: number, degree: number): number {\n    if (knot < 0 || knot >= knots.length || knots.length - knot < degree) {\n        return 0;\n    }\n    const prevU = knots[knot];\n    const nextU = knots[knot + degree];\n    if (prevU >= nextU) {\n        return 0;\n    }\n    return degree / (nextU - prevU);\n}\n\n/**\n * Evaluates the basis functions (and their derivatives) that are non-zero at `u`.\n * @returns index of the first influencing control point, or -1 when the basis cannot be evaluated\n */\nexport function evaluateNurbsBasis(basis: FBXNurbsBasis, u: number, weights: Float64Array, derivatives: Float64Array | null): number {\n    if (basis.order <= 1 || !basis.valid) {\n        return -1;\n    }\n    const degree = basis.order - 1;\n    const knots = basis.knots;\n    let knot: number;\n    if (u <= basis.tMin) {\n        knot = degree;\n        u = basis.tMin;\n    } else if (u >= basis.tMax) {\n        knot = knots.length - degree - 2;\n        u = basis.tMax;\n    } else {\n        // Knot span [knots[knot], knots[knot + 1]) containing u\n        let lo = 0;\n        let hi = knots.length - 1;\n        while (lo < hi) {\n            const mid = (lo + hi) >> 1;\n            if (knots[mid + 1] <= u) {\n                lo = mid + 1;\n            } else {\n                hi = mid;\n            }\n        }\n        if (!(knots[lo] <= u && u < knots[lo + 1])) {\n            return -1;\n        }\n        knot = lo;\n    }\n    if (knot < degree) {\n        return -1;\n    }\n\n    weights[0] = 1;\n    for (let p = 1; p <= degree; p++) {\n        let prev = 0;\n        let g = 1 - nurbsWeight(knots, knot - p + 1, p, u);\n        let dg = 0;\n        const last = derivatives !== null && p === degree;\n        if (last) {\n            dg = nurbsDeriv(knots, knot - p + 1, p);\n        }\n        for (let i = p; i > 0; i--) {\n            const f = nurbsWeight(knots, knot - p + i, p, u);\n            const weight = weights[i - 1];\n            weights[i] = f * weight + g * prev;\n            if (last) {\n                const df = nurbsDeriv(knots, knot - p + i, p);\n                derivatives![i] = df * weight - dg * prev;\n                dg = df;\n            }\n            prev = weight;\n            g = 1 - f;\n        }\n        weights[0] = g * prev;\n        if (last) {\n            derivatives![0] = -dg * prev;\n        }\n    }\n    return knot - degree;\n}\n\n/** Evaluates a curve point; `out` receives position (0..2) and derivative (3..5). */\nexport function evaluateNurbsCurve(curve: FBXNurbsCurveData, u: number, out: Float64Array, weights: Float64Array, derivs: Float64Array): boolean {\n    const base = evaluateNurbsBasis(curve.basis, u, weights, derivs);\n    if (base < 0 || curve.numControlPoints === 0) {\n        return false;\n    }\n    const order = curve.basis.order;\n    let px = 0,\n        py = 0,\n        pz = 0,\n        pw = 0,\n        dx = 0,\n        dy = 0,\n        dz = 0,\n        dw = 0;\n    const cp = curve.controlPoints;\n    for (let i = 0; i < order; i++) {\n        const ix = ((base + i) % curve.numControlPoints) * 4;\n        const w = weights[i] * cp[ix + 3];\n        const d = derivs[i] * cp[ix + 3];\n        px += cp[ix] * w;\n        py += cp[ix + 1] * w;\n        pz += cp[ix + 2] * w;\n        pw += w;\n        dx += cp[ix] * d;\n        dy += cp[ix + 1] * d;\n        dz += cp[ix + 2] * d;\n        dw += d;\n    }\n    const rcp = pw !== 0 ? 1 / pw : 0;\n    out[0] = px * rcp;\n    out[1] = py * rcp;\n    out[2] = pz * rcp;\n    out[3] = (dx - dw * out[0]) * rcp;\n    out[4] = (dy - dw * out[1]) * rcp;\n    out[5] = (dz - dw * out[2]) * rcp;\n    return true;\n}\n\n/** Evaluates a surface point; `out` receives position (0..2), du (3..5) and dv (6..8). */\nexport function evaluateNurbsSurface(\n    surface: FBXNurbsSurfaceData,\n    u: number,\n    v: number,\n    out: Float64Array,\n    scratch: { wu: Float64Array; wv: Float64Array; du: Float64Array; dv: Float64Array }\n): boolean {\n    const baseU = evaluateNurbsBasis(surface.basisU, u, scratch.wu, scratch.du);\n    const baseV = evaluateNurbsBasis(surface.basisV, v, scratch.wv, scratch.dv);\n    if (baseU < 0 || baseV < 0 || surface.numU === 0 || surface.numV === 0) {\n        return false;\n    }\n    const orderU = surface.basisU.order;\n    const orderV = surface.basisV.order;\n    const cp = surface.controlPoints;\n    let px = 0,\n        py = 0,\n        pz = 0,\n        pw = 0;\n    let ux = 0,\n        uy = 0,\n        uz = 0,\n        uw = 0;\n    let vx = 0,\n        vy = 0,\n        vz = 0,\n        vw = 0;\n    for (let vi = 0; vi < orderV; vi++) {\n        const vix = (baseV + vi) % surface.numV;\n        const weightV = scratch.wv[vi];\n        const derivV = scratch.dv[vi];\n        for (let ui = 0; ui < orderU; ui++) {\n            const uix = (baseU + ui) % surface.numU;\n            const weightU = scratch.wu[ui];\n            const derivU = scratch.du[ui];\n            const ix = (vix * surface.numU + uix) * 4;\n            const cw = cp[ix + 3];\n            const w = weightU * weightV * cw;\n            const wdu = derivU * weightV * cw;\n            const wdv = derivV * weightU * cw;\n            const x = cp[ix],\n                y = cp[ix + 1],\n                z = cp[ix + 2];\n            px += x * w;\n            py += y * w;\n            pz += z * w;\n            pw += w;\n            ux += x * wdu;\n            uy += y * wdu;\n            uz += z * wdu;\n            uw += wdu;\n            vx += x * wdv;\n            vy += y * wdv;\n            vz += z * wdv;\n            vw += wdv;\n        }\n    }\n    const rcp = pw !== 0 ? 1 / pw : 0;\n    out[0] = px * rcp;\n    out[1] = py * rcp;\n    out[2] = pz * rcp;\n    out[3] = (ux - uw * out[0]) * rcp;\n    out[4] = (uy - uw * out[1]) * rcp;\n    out[5] = (uz - uw * out[2]) * rcp;\n    out[6] = (vx - vw * out[0]) * rcp;\n    out[7] = (vy - vw * out[1]) * rcp;\n    out[8] = (vz - vw * out[2]) * rcp;\n    return true;\n}\n\n/**\n * Tessellates a curve into a polyline with `subdivision` segments per knot span. Closed and periodic curves\n * end on a copy of their first point.\n */\nexport function tessellateNurbsCurve(curve: FBXNurbsCurveData, subdivision: number = DEFAULT_SPAN_SUBDIVISION): Float64Array | null {\n    const basis = curve.basis;\n    if (!basis.valid || curve.numControlPoints === 0 || basis.spans.length === 0) {\n        return null;\n    }\n    const numSub = Math.max(1, Math.floor(subdivision));\n    const numSpans = basis.spans.length;\n    const isOpen = basis.topology === \"open\";\n    const numIndices = numSpans + (numSpans - 1) * (numSub - 1);\n    const numVertices = numIndices - (isOpen ? 0 : 1);\n    const points = new Float64Array(numIndices * 3);\n    const weights = new Float64Array(basis.order + 1);\n    const derivs = new Float64Array(basis.order + 1);\n    const out = new Float64Array(6);\n    for (let spanIx = 0; spanIx < numSpans; spanIx++) {\n        const numSplits = spanIx + 1 === numSpans ? 1 : numSub;\n        for (let subIx = 0; subIx < numSplits; subIx++) {\n            const ix = spanIx * numSub + subIx;\n            if (ix < numVertices) {\n                let u = basis.spans[spanIx];\n                if (subIx > 0) {\n                    const t = subIx / numSub;\n                    u = u * (1 - t) + t * basis.spans[spanIx + 1];\n                }\n                if (evaluateNurbsCurve(curve, u, out, weights, derivs)) {\n                    points[ix * 3] = out[0];\n                    points[ix * 3 + 1] = out[1];\n                    points[ix * 3 + 2] = out[2];\n                }\n            } else {\n                points[ix * 3] = points[0];\n                points[ix * 3 + 1] = points[1];\n                points[ix * 3 + 2] = points[2];\n            }\n        }\n    }\n    return points;\n}\n\n/** Span subdivision to use for a surface direction: an explicit override, else the file's Step, else 4. */\nexport function resolveSpanSubdivision(fileStep: number, override: number | undefined): number {\n    if (override !== undefined && Number.isFinite(override) && override > 0) {\n        return Math.min(MAX_SPAN_SUBDIVISION, Math.max(1, Math.floor(override)));\n    }\n    if (fileStep > 0) {\n        return Math.min(MAX_FILE_SPAN_SUBDIVISION, Math.floor(fileStep));\n    }\n    return DEFAULT_SPAN_SUBDIVISION;\n}\n\n/**\n * Tessellates a surface into triangles. Positions on wrapped (closed/periodic) edges and at poles are welded\n * exactly like the FBX SDK does, so degenerate quads collapse into triangles.\n */\nexport function tessellateNurbsSurface(\n    surface: FBXNurbsSurfaceData,\n    subU: number,\n    subV: number\n): { positions: Float64Array; indices: Uint32Array; normals: Float64Array; uvs: Float64Array } | null {\n    const basisU = surface.basisU;\n    const basisV = surface.basisV;\n    if (!basisU.valid || !basisV.valid || surface.numU === 0 || surface.numV === 0 || basisU.spans.length < 2 || basisV.spans.length < 2) {\n        return null;\n    }\n    const openU = basisU.topology === \"open\";\n    const openV = basisV.topology === \"open\";\n    const spansU = basisU.spans.length;\n    const spansV = basisV.spans.length;\n    const facesU = (spansU - 1) * subU;\n    const facesV = (spansV - 1) * subV;\n    const indicesU = spansU + (spansU - 1) * (subU - 1);\n    const indicesV = spansV + (spansV - 1) * (subV - 1);\n    const numAttribs = indicesU * indicesV;\n    const numFaces = facesU * facesV;\n    if (numAttribs > 0x3fffffff || numFaces > 0x3fffffff) {\n        return null;\n    }\n\n    // Unique (welded) positions and per-attribute-vertex data\n    const positionIx = new Uint32Array(numAttribs);\n    const welded = new Float64Array(numAttribs * 3);\n    let numPositions = 0;\n    const attribUv = new Float64Array(numAttribs * 2);\n    const scratch = {\n        wu: new Float64Array(basisU.order + 1),\n        wv: new Float64Array(basisV.order + 1),\n        du: new Float64Array(basisU.order + 1),\n        dv: new Float64Array(basisV.order + 1),\n    };\n    const out = new Float64Array(9);\n\n    for (let spanV = 0; spanV < spansV; spanV++) {\n        const splitsV = spanV + 1 === spansV ? 1 : subV;\n        for (let splitV = 0; splitV < splitsV; splitV++) {\n            const ixV = spanV * subV + splitV;\n            let v = basisV.spans[spanV];\n            if (splitV > 0) {\n                const t = splitV / splitsV;\n                v = v * (1 - t) + t * basisV.spans[spanV + 1];\n            }\n            const originalV = v;\n            if (spanV + 1 === spansV && !openV) {\n                v = basisV.spans[0];\n            }\n            for (let spanU = 0; spanU < spansU; spanU++) {\n                const splitsU = spanU + 1 === spansU ? 1 : subU;\n                for (let splitU = 0; splitU < splitsU; splitU++) {\n                    const ixU = spanU * subU + splitU;\n                    let u = basisU.spans[spanU];\n                    if (splitU > 0) {\n                        const t = splitU / splitsU;\n                        u = u * (1 - t) + t * basisU.spans[spanU + 1];\n                    }\n                    const originalU = u;\n                    if (spanU + 1 === spansU && !openU) {\n                        u = basisU.spans[0];\n                    }\n\n                    let px = 0,\n                        py = 0,\n                        pz = 0;\n                    if (evaluateNurbsSurface(surface, u, v, out, scratch)) {\n                        px = out[0];\n                        py = out[1];\n                        pz = out[2];\n                    }\n\n                    // Positions that wrap around to an already emitted neighbour are welded.\n                    const neighbors: number[] = [];\n                    if ((spanV === 0 && (spanU > 0 || splitU > 0)) || (spanU === 0 && (spanV > 0 || splitV > 0))) {\n                        neighbors.push(0);\n                    }\n                    if (spanV + 1 === spansV) {\n                        neighbors.push(ixU);\n                        if (spanU > 0 || splitU > 0) {\n                            neighbors.push(ixV * indicesU);\n                        }\n                    }\n                    if (spanU + 1 === spansU) {\n                        neighbors.push(ixV * indicesU);\n                        if (spanV > 0 || splitV > 0) {\n                            neighbors.push(indicesU - 1);\n                        }\n                    }\n\n                    const ix = ixV * indicesU + ixU;\n                    let posIx = numPositions;\n                    for (const nb of neighbors) {\n                        if (nb >= ix) {\n                            continue;\n                        }\n                        const nbPos = positionIx[nb];\n                        const dx = welded[nbPos * 3] - px;\n                        const dy = welded[nbPos * 3 + 1] - py;\n                        const dz = welded[nbPos * 3 + 2] - pz;\n                        if (dx * dx + dy * dy + dz * dz < 0.0000001) {\n                            posIx = nbPos;\n                            break;\n                        }\n                    }\n                    positionIx[ix] = posIx;\n                    if (posIx === numPositions) {\n                        welded[posIx * 3] = px;\n                        welded[posIx * 3 + 1] = py;\n                        welded[posIx * 3 + 2] = pz;\n                        numPositions++;\n                    }\n                    attribUv[ix * 2] = originalU;\n                    attribUv[ix * 2 + 1] = originalV;\n                }\n            }\n        }\n    }\n\n    // Faces: quads, or triangles where two consecutive corners share a welded position\n    const triangles: number[] = [];\n    const faceCorners = [0, 0, 0, 0];\n    const faceVerts = [0, 0, 0, 0];\n    for (let faceV = 0; faceV < facesV; faceV++) {\n        for (let faceU = 0; faceU < facesU; faceU++) {\n            faceCorners[0] = faceV * indicesU + faceU;\n            faceCorners[1] = faceV * indicesU + faceU + 1;\n            faceCorners[2] = (faceV + 1) * indicesU + faceU + 1;\n            faceCorners[3] = (faceV + 1) * indicesU + faceU;\n            for (let i = 0; i < 4; i++) {\n                faceVerts[i] = positionIx[faceCorners[i]];\n            }\n            let count = 4;\n            for (let prev = 0; prev < 4; prev++) {\n                const next = (prev + 1) % 4;\n                if (faceVerts[prev] === faceVerts[next]) {\n                    for (let i = next; i < 3; i++) {\n                        faceCorners[i] = faceCorners[i + 1];\n                        faceVerts[i] = faceVerts[i + 1];\n                    }\n                    count = 3;\n                    break;\n                }\n            }\n            triangles.push(faceCorners[0], faceCorners[1], faceCorners[2]);\n            if (count === 4) {\n                triangles.push(faceCorners[0], faceCorners[2], faceCorners[3]);\n            }\n        }\n    }\n\n    // Smooth normals: area-weighted face normals accumulated per welded position\n    const posNormals = new Float64Array(numPositions * 3);\n    for (let t = 0; t < triangles.length; t += 3) {\n        const a = positionIx[triangles[t]] * 3;\n        const b = positionIx[triangles[t + 1]] * 3;\n        const c = positionIx[triangles[t + 2]] * 3;\n        const e1x = welded[b] - welded[a],\n            e1y = welded[b + 1] - welded[a + 1],\n            e1z = welded[b + 2] - welded[a + 2];\n        const e2x = welded[c] - welded[a],\n            e2y = welded[c + 1] - welded[a + 1],\n            e2z = welded[c + 2] - welded[a + 2];\n        const nx = e1y * e2z - e1z * e2y;\n        const ny = e1z * e2x - e1x * e2z;\n        const nz = e1x * e2y - e1y * e2x;\n        for (const p of [a, b, c]) {\n            posNormals[p] += nx;\n            posNormals[p + 1] += ny;\n            posNormals[p + 2] += nz;\n        }\n    }\n    const flip = surface.flipNormals ? -1 : 1;\n    for (let p = 0; p < numPositions; p++) {\n        const x = posNormals[p * 3],\n            y = posNormals[p * 3 + 1],\n            z = posNormals[p * 3 + 2];\n        const len = Math.hypot(x, y, z);\n        if (len > 0) {\n            posNormals[p * 3] = (x / len) * flip;\n            posNormals[p * 3 + 1] = (y / len) * flip;\n            posNormals[p * 3 + 2] = (z / len) * flip;\n        }\n    }\n\n    const positions = new Float64Array(numAttribs * 3);\n    const normals = new Float64Array(numAttribs * 3);\n    for (let ix = 0; ix < numAttribs; ix++) {\n        const p = positionIx[ix] * 3;\n        positions[ix * 3] = welded[p];\n        positions[ix * 3 + 1] = welded[p + 1];\n        positions[ix * 3 + 2] = welded[p + 2];\n        normals[ix * 3] = posNormals[p];\n        normals[ix * 3 + 1] = posNormals[p + 1];\n        normals[ix * 3 + 2] = posNormals[p + 2];\n    }\n    return { positions, indices: Uint32Array.from(triangles), normals, uvs: attribUv };\n}\n\nfunction readFloatArray(node: FBXNode, name: string): Float64Array | null {\n    const child = findChildByName(node, name);\n    if (!child) {\n        return null;\n    }\n    const array = getNodeArray(child);\n    if (!array) {\n        return null;\n    }\n    return array instanceof Float64Array ? array : Float64Array.from(array as ArrayLike<number>);\n}\n\nfunction readColor(node: FBXNode): [number, number, number] | null {\n    const entry = getPropertyEntries(node).find((e) => e.name === \"Color\");\n    if (!entry || typeof entry.values[0] !== \"number\" || typeof entry.values[1] !== \"number\" || typeof entry.values[2] !== \"number\") {\n        return null;\n    }\n    return [entry.values[0], entry.values[1], entry.values[2]];\n}\n\n/** Reads a NurbsCurve geometry node. */\nexport function extractNurbsCurve(node: FBXNode): FBXNurbsCurveData | null {\n    const orderNode = findChildByName(node, \"Order\");\n    const formNode = findChildByName(node, \"Form\");\n    const order = orderNode ? (getPropertyValue<number>(orderNode, 0) ?? 0) : 0;\n    const form = formNode ? getPropertyValue<string>(formNode, 0) : undefined;\n    const points = readFloatArray(node, \"Points\");\n    const knots = readFloatArray(node, \"KnotVector\");\n    if (!points || !knots || points.length % 4 !== 0) {\n        return null;\n    }\n    return { basis: createNurbsBasis(order, form, knots), controlPoints: points, numControlPoints: points.length / 4 };\n}\n\n/** Reads a NurbsSurface geometry node. */\nexport function extractNurbsSurface(node: FBXNode): FBXNurbsSurfaceData | null {\n    const orderNode = findChildByName(node, \"NurbsSurfaceOrder\");\n    const dimensionsNode = findChildByName(node, \"Dimensions\");\n    const stepNode = findChildByName(node, \"Step\");\n    const formNode = findChildByName(node, \"Form\");\n    const flipNode = findChildByName(node, \"FlipNormals\");\n    const orderU = orderNode ? (getPropertyValue<number>(orderNode, 0) ?? 0) : 0;\n    const orderV = orderNode ? (getPropertyValue<number>(orderNode, 1) ?? 0) : 0;\n    const numU = dimensionsNode ? (getPropertyValue<number>(dimensionsNode, 0) ?? 0) : 0;\n    const numV = dimensionsNode ? (getPropertyValue<number>(dimensionsNode, 1) ?? 0) : 0;\n    const stepU = stepNode ? (getPropertyValue<number>(stepNode, 0) ?? 0) : 0;\n    const stepV = stepNode ? (getPropertyValue<number>(stepNode, 1) ?? 0) : 0;\n    const formU = formNode ? getPropertyValue<string>(formNode, 0) : undefined;\n    const formV = formNode ? getPropertyValue<string>(formNode, 1) : undefined;\n    const flipValue = flipNode ? getPropertyValue<number | boolean>(flipNode, 0) : 0;\n    const points = readFloatArray(node, \"Points\");\n    const knotsU = readFloatArray(node, \"KnotVectorU\");\n    const knotsV = readFloatArray(node, \"KnotVectorV\");\n    if (!points || !knotsU || !knotsV || points.length % 4 !== 0 || points.length / 4 !== numU * numV || numU <= 0 || numV <= 0) {\n        return null;\n    }\n    return {\n        basisU: createNurbsBasis(orderU, formU, knotsU),\n        basisV: createNurbsBasis(orderV, formV, knotsV),\n        numU,\n        numV,\n        controlPoints: points,\n        flipNormals: flipValue === true || flipValue === 1,\n        stepU: typeof stepU === \"number\" ? stepU : 0,\n        stepV: typeof stepV === \"number\" ? stepV : 0,\n    };\n}\n\n/** Tessellates a NurbsSurface geometry node into mesh geometry. */\nexport function nurbsSurfaceToGeometry(node: FBXNode, geometryId: number, subdivisionOverride: number | undefined): FBXGeometryData | null {\n    const name = cleanFBXName(getPropertyValue<string>(node, 1) ?? \"NurbsSurface\");\n    const surface = extractNurbsSurface(node);\n    const diagnostics: FBXGeometryDiagnostic[] = [];\n    if (!surface) {\n        return null;\n    }\n    const subU = resolveSpanSubdivision(surface.stepU, subdivisionOverride);\n    const subV = resolveSpanSubdivision(surface.stepV, subdivisionOverride);\n    const tess = tessellateNurbsSurface(surface, subU, subV);\n    if (!tess) {\n        diagnostics.push({ type: \"nurbs-invalid\", message: `NURBS surface '${name}' has an invalid basis and was skipped.` });\n        return {\n            id: geometryId,\n            name,\n            positions: new Float64Array(0),\n            indices: new Uint32Array(0),\n            normals: null,\n            uvs: null,\n            uvSets: [],\n            colors: null,\n            tangents: null,\n            binormals: null,\n            controlPointIndices: null,\n            materialIndices: null,\n            diagnostics,\n        };\n    }\n    return {\n        id: geometryId,\n        name,\n        positions: tess.positions,\n        indices: tess.indices,\n        normals: tess.normals,\n        uvs: tess.uvs,\n        uvSets: [{ name: \"map1\", data: tess.uvs }],\n        colors: null,\n        tangents: null,\n        binormals: null,\n        controlPointIndices: null,\n        materialIndices: null,\n        diagnostics,\n    };\n}\n\n/** Reads a NurbsCurve geometry node into a tessellated polyline. */\nexport function extractNurbsCurveGeometry(node: FBXNode, geometryId: number, subdivision: number = DEFAULT_SPAN_SUBDIVISION): FBXCurveGeometryData {\n    const name = cleanFBXName(getPropertyValue<string>(node, 1) ?? \"NurbsCurve\");\n    const diagnostics: FBXGeometryDiagnostic[] = [];\n    const curve = extractNurbsCurve(node);\n    const polyline = curve ? tessellateNurbsCurve(curve, subdivision) : null;\n    if (!polyline) {\n        diagnostics.push({ type: \"nurbs-invalid\", message: `NURBS curve '${name}' has an invalid basis and was skipped.` });\n    }\n    return { id: geometryId, name, kind: \"nurbsCurve\", polylines: polyline ? [polyline] : [], color: readColor(node), diagnostics };\n}\n\n/**\n * Reads a Line geometry node: Points plus PointsIndex where a negative index (~index) ends a segment, as in\n * polygon vertex indices.\n */\nexport function extractLineGeometry(node: FBXNode, geometryId: number): FBXCurveGeometryData {\n    const name = cleanFBXName(getPropertyValue<string>(node, 1) ?? \"Line\");\n    const diagnostics: FBXGeometryDiagnostic[] = [];\n    const points = readFloatArray(node, \"Points\");\n    const indexNode = findChildByName(node, \"PointsIndex\");\n    const rawIndices = indexNode ? getNodeArray(indexNode) : null;\n    const polylines: Float64Array[] = [];\n    if (points && points.length % 3 === 0) {\n        const numPoints = points.length / 3;\n        const indices: number[] = rawIndices ? Array.from(rawIndices as ArrayLike<number>) : Array.from({ length: numPoints }, (_, i) => i);\n        let current: number[] = [];\n        const flush = () => {\n            if (current.length >= 2) {\n                polylines.push(Float64Array.from(current));\n            } else if (current.length === 1) {\n                diagnostics.push({ type: \"degenerate-polygon\", message: `Line '${name}' has a single-point segment that was skipped.` });\n            }\n            current = [];\n        };\n        for (let i = 0; i < indices.length; i++) {\n            let ix = indices[i];\n            const ends = ix < 0;\n            if (ends) {\n                ix = ~ix;\n            }\n            if (ix >= 0 && ix < numPoints) {\n                current.push(points[ix * 3], points[ix * 3 + 1], points[ix * 3 + 2]);\n            } else {\n                diagnostics.push({ type: \"layer-index-out-of-bounds\", message: `Line '${name}' references point ${ix} outside its ${numPoints} points.`, index: i });\n            }\n            if (ends) {\n                flush();\n            }\n        }\n        flush();\n    }\n    return { id: geometryId, name, kind: \"line\", polylines, color: readColor(node), diagnostics };\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * FBX 5.x (and older) documents store everything at the top level: one `Model` node per object with inline\n * geometry, materials, skin links, lights and cameras, and `Children` lists instead of connections. This module\n * rewrites such a document into the 6.x layout (`Objects`, `Connections`, `Takes`) so the rest of the importer\n * can treat both the same way. The rules follow the FBX SDK's legacy reader as implemented by ufbx.\n */\nimport { type FBXDocument, type FBXNode, type FBXProperty, findChildByName, findDocumentNode, getPropertyValue, getNodeArray, cleanFBXName } from \"../types/fbxTypes\";\n\nconst str = (value: string): FBXProperty => ({ type: \"string\", value });\nconst num = (value: number): FBXProperty => ({ type: \"float64\", value });\nconst int = (value: number): FBXProperty => ({ type: \"int32\", value });\nconst makeNode = (name: string, properties: FBXProperty[] = [], children: FBXNode[] = []): FBXNode => ({ name, properties, children });\nfunction property60(name: string, typeName: string, flags: string, ...values: (number | string)[]): FBXNode {\n    return makeNode(\"Property\", [str(name), str(typeName), str(flags), ...values.map((v) => (typeof v === \"string\" ? str(v) : num(v)))]);\n}\nfunction property70(name: string, typeName: string, flags: string, ...values: (number | string)[]): FBXNode {\n    return makeNode(\"P\", [str(name), str(typeName), str(\"\"), str(flags), ...values.map((v) => (typeof v === \"string\" ? str(v) : num(v)))]);\n}\nconst arrayNode = (name: string, array: Float64Array | Int32Array): FBXNode => makeNode(name, [{ type: array instanceof Int32Array ? \"int32[]\" : \"float64[]\", value: array }]);\n\n/** True for pre-6000 files: no `Objects` section but top-level `Model` nodes. */\nexport function isLegacyDocument(doc: FBXDocument): boolean {\n    return !findDocumentNode(doc, \"Objects\") && doc.nodes.some((n) => n.name === \"Model\");\n}\n\nfunction numberAt(node: FBXNode | undefined, index = 0): number | undefined {\n    const v = node?.properties[index]?.value;\n    return typeof v === \"number\" ? v : typeof v === \"boolean\" ? (v ? 1 : 0) : undefined;\n}\n\nfunction numbers(node: FBXNode | undefined): number[] {\n    if (!node) {\n        return [];\n    }\n    const array = getNodeArray(node);\n    return array ? Array.from(array as ArrayLike<number>) : [];\n}\n\nfunction toFloat64(node: FBXNode | undefined): Float64Array | null {\n    const array = node ? getNodeArray(node) : null;\n    if (!array) {\n        return null;\n    }\n    return array instanceof Float64Array ? array : Float64Array.from(array as ArrayLike<number>);\n}\n\nfunction toInt32(node: FBXNode | undefined): Int32Array | null {\n    const array = node ? getNodeArray(node) : null;\n    if (!array) {\n        return null;\n    }\n    return array instanceof Int32Array ? array : Int32Array.from(array as ArrayLike<number>, (v) => Math.trunc(v));\n}\n\n/** Default (rest) value of a `Channel` tree: T/R/S each with X/Y/Z sub channels carrying `Default`. */\nfunction readTransformChannelDefaults(transformChannel: FBXNode | undefined, out: { t?: number[]; r?: number[]; s?: number[] }): void {\n    if (!transformChannel) {\n        return;\n    }\n    for (const sub of transformChannel.children) {\n        if (sub.name !== \"Channel\") {\n            continue;\n        }\n        const kind = getPropertyValue<string>(sub, 0);\n        const key = kind === \"T\" ? \"t\" : kind === \"R\" ? \"r\" : kind === \"S\" ? \"s\" : undefined;\n        if (!key || out[key]) {\n            continue;\n        }\n        const values = [0, 0, 0];\n        let any = false;\n        for (const axis of sub.children) {\n            if (axis.name !== \"Channel\") {\n                continue;\n            }\n            const axisName = getPropertyValue<string>(axis, 0);\n            const index = axisName === \"X\" ? 0 : axisName === \"Y\" ? 1 : axisName === \"Z\" ? 2 : -1;\n            const value = numberAt(findChildByName(axis, \"Default\"));\n            if (index >= 0 && value !== undefined) {\n                values[index] = value;\n                any = true;\n            }\n        }\n        if (any) {\n            out[key] = values;\n        }\n    }\n}\n\nfunction channelHasKeys(channel: FBXNode): boolean {\n    const keys = findChildByName(channel, \"Key\");\n    if (keys && keys.properties.length > 0) {\n        return true;\n    }\n    return channel.children.some((c) => c.name === \"Channel\" && channelHasKeys(c));\n}\n\ninterface LegacyContext {\n    version: number;\n    objects: FBXNode[];\n    connections: FBXNode[];\n    usedNames: Map<string, number>;\n    /** Model raw name → transform channel defaults from the takes */\n    takeDefaults: Map<string, FBXNode>;\n}\n\nfunction uniqueName(ctx: LegacyContext, name: string): string {\n    const count = ctx.usedNames.get(name) ?? 0;\n    ctx.usedNames.set(name, count + 1);\n    return count === 0 ? name : `${name} (${count + 1})`;\n}\n\nfunction connect(ctx: LegacyContext, child: string, parent: string): void {\n    ctx.connections.push(makeNode(\"C\", [str(\"OO\"), str(child), str(parent)]));\n}\n\nfunction normalize3(array: Float64Array): Float64Array {\n    const out = new Float64Array(array.length);\n    for (let i = 0; i + 2 < array.length; i += 3) {\n        const x = array[i],\n            y = array[i + 1],\n            z = array[i + 2];\n        const len = Math.hypot(x, y, z);\n        if (len > 0) {\n            out[i] = x / len;\n            out[i + 1] = y / len;\n            out[i + 2] = z / len;\n        }\n    }\n    return out;\n}\n\n/** Converts the inline polygon mesh of a legacy model into 6.x-style geometry children. */\nfunction convertMesh(model: FBXNode, version: number): FBXNode[] {\n    const vertices = toFloat64(findChildByName(model, \"Vertices\"));\n    const indices = toInt32(findChildByName(model, \"PolygonVertexIndex\"));\n    if (!vertices || !indices) {\n        return [];\n    }\n    const numVertices = Math.floor(vertices.length / 3);\n    const numIndices = indices.length;\n    if (numIndices > 0 && indices[numIndices - 1] >= 0) {\n        indices[numIndices - 1] = ~indices[numIndices - 1];\n    }\n    const out: FBXNode[] = [makeNode(\"GeometryVersion\", [int(124)]), arrayNode(\"Vertices\", vertices), arrayNode(\"PolygonVertexIndex\", indices)];\n\n    // Normals are per vertex or per polygon-vertex, decided by their count (5000 files prefer per vertex).\n    const normals = toFloat64(findChildByName(model, \"Normals\"));\n    if (normals) {\n        const count = Math.floor(normals.length / 3);\n        const perVertex = count === numVertices;\n        const perIndex = count === numIndices;\n        const mapping = perVertex && (!perIndex || version === 5000) ? \"ByVertice\" : perIndex ? \"ByPolygonVertex\" : undefined;\n        if (mapping) {\n            out.push(\n                makeNode(\n                    \"LayerElementNormal\",\n                    [int(0)],\n                    [\n                        makeNode(\"Version\", [int(101)]),\n                        makeNode(\"Name\", [str(\"\")]),\n                        makeNode(\"MappingInformationType\", [str(mapping)]),\n                        makeNode(\"ReferenceInformationType\", [str(\"Direct\")]),\n                        arrayNode(\"Normals\", normalize3(normals)),\n                    ]\n                )\n            );\n        }\n    }\n\n    const uvInfo = findChildByName(model, \"GeometryUVInfo\");\n    const uv = uvInfo ? toFloat64(findChildByName(uvInfo, \"TextureUV\")) : null;\n    if (uvInfo && uv) {\n        const uvIndex = toInt32(findChildByName(uvInfo, \"TextureUVVerticeIndex\"));\n        const numUV = Math.floor(uv.length / 2);\n        let element: FBXNode | undefined;\n        const base = [makeNode(\"Version\", [int(101)]), makeNode(\"Name\", [str(\"\")])];\n        if (uvIndex && uvIndex.length === numIndices) {\n            element = makeNode(\n                \"LayerElementUV\",\n                [int(0)],\n                [\n                    ...base,\n                    makeNode(\"MappingInformationType\", [str(\"ByPolygonVertex\")]),\n                    makeNode(\"ReferenceInformationType\", [str(\"IndexToDirect\")]),\n                    arrayNode(\"UV\", uv),\n                    arrayNode(\"UVIndex\", uvIndex),\n                ]\n            );\n        } else if (numUV === numIndices) {\n            element = makeNode(\n                \"LayerElementUV\",\n                [int(0)],\n                [...base, makeNode(\"MappingInformationType\", [str(\"ByPolygonVertex\")]), makeNode(\"ReferenceInformationType\", [str(\"Direct\")]), arrayNode(\"UV\", uv)]\n            );\n        } else if (numUV === numVertices) {\n            element = makeNode(\n                \"LayerElementUV\",\n                [int(0)],\n                [...base, makeNode(\"MappingInformationType\", [str(\"ByVertice\")]), makeNode(\"ReferenceInformationType\", [str(\"Direct\")]), arrayNode(\"UV\", uv)]\n            );\n        }\n        if (element) {\n            out.push(element);\n        }\n    }\n\n    const assignation = getPropertyValue<string>(findChildByName(model, \"MaterialAssignation\") ?? makeNode(\"x\"), 0);\n    const materials = toInt32(findChildByName(model, \"Materials\"));\n    if (materials && materials.length > 0) {\n        const mapping = assignation === \"ByPolygon\" ? \"ByPolygon\" : \"AllSame\";\n        out.push(\n            makeNode(\n                \"LayerElementMaterial\",\n                [int(0)],\n                [\n                    makeNode(\"Version\", [int(101)]),\n                    makeNode(\"Name\", [str(\"\")]),\n                    makeNode(\"MappingInformationType\", [str(mapping)]),\n                    makeNode(\"ReferenceInformationType\", [str(\"IndexToDirect\")]),\n                    arrayNode(\"Materials\", mapping === \"AllSame\" ? Int32Array.of(materials[0]) : materials),\n                ]\n            )\n        );\n    }\n\n    // Blend shapes keep the 6.x inline form; the connection resolver turns them into deformers.\n    for (const child of model.children) {\n        if (child.name === \"Shape\") {\n            out.push(child);\n        }\n    }\n    return out;\n}\n\n/** Legacy materials are embedded in the model; each becomes its own object connected to the model. */\nfunction convertMaterials(ctx: LegacyContext, model: FBXNode, modelName: string): void {\n    for (const child of model.children) {\n        if (child.name !== \"Material\") {\n            continue;\n        }\n        const rawName = getPropertyValue<string>(child, 0) ?? \"Material\";\n        const name = uniqueName(ctx, rawName.includes(\"::\") ? rawName : `Material::${rawName}`);\n        const color = (source: string, target: string): FBXNode | null => {\n            const values = numbers(findChildByName(child, source));\n            return values.length >= 3 ? property60(target, \"ColorRGB\", \"\", values[0], values[1], values[2]) : null;\n        };\n        const scalar = (source: string, target: string): FBXNode | null => {\n            const value = numberAt(findChildByName(child, source));\n            return value !== undefined ? property60(target, \"double\", \"\", value) : null;\n        };\n        const properties = [\n            color(\"Ambient\", \"AmbientColor\"),\n            color(\"Diffuse\", \"DiffuseColor\"),\n            color(\"Specular\", \"SpecularColor\"),\n            color(\"Emissive\", \"EmissiveColor\"),\n            scalar(\"Shininess\", \"Shininess\"),\n            scalar(\"Alpha\", \"Opacity\"),\n            scalar(\"Reflectivity\", \"ReflectionFactor\"),\n        ].filter((p): p is FBXNode => p !== null);\n        const shading = findChildByName(child, \"ShadingModel\");\n        ctx.objects.push(\n            makeNode(\n                \"Material\",\n                [str(name), str(\"\")],\n                [makeNode(\"Version\", [int(100)]), shading ?? makeNode(\"ShadingModel\", [str(\"phong\")]), makeNode(\"Properties60\", [], properties)]\n            )\n        );\n        connect(ctx, name, modelName);\n    }\n}\n\n/** `Link` children are skin clusters bound to other models. */\nfunction convertLinks(ctx: LegacyContext, model: FBXNode, modelName: string): void {\n    const links = model.children.filter((c) => c.name === \"Link\");\n    if (links.length === 0) {\n        return;\n    }\n    const skinName = uniqueName(ctx, `Deformer::Skin ${cleanFBXName(modelName)}`);\n    ctx.objects.push(makeNode(\"Deformer\", [str(skinName), str(\"Skin\")], [makeNode(\"Version\", [int(100)]), makeNode(\"Link_DeformAcuracy\", [num(50)])]));\n    connect(ctx, skinName, modelName);\n    for (const link of links) {\n        const boneName = getPropertyValue<string>(link, 0) ?? \"\";\n        const clusterName = uniqueName(ctx, `SubDeformer::Cluster ${cleanFBXName(modelName)} ${cleanFBXName(boneName)}`);\n        const children: FBXNode[] = [makeNode(\"Version\", [int(100)]), makeNode(\"Mode\", [str(\"Normalize\")])];\n        for (const arrayName of [\"Indexes\", \"Weights\", \"Transform\", \"TransformLink\"]) {\n            const child = findChildByName(link, arrayName);\n            if (!child) {\n                continue;\n            }\n            const array = arrayName === \"Indexes\" ? toInt32(child) : toFloat64(child);\n            if (array) {\n                children.push(arrayNode(arrayName, array));\n            }\n        }\n        ctx.objects.push(makeNode(\"Deformer\", [str(clusterName), str(\"Cluster\")], children));\n        connect(ctx, clusterName, skinName);\n        connect(ctx, boneName, clusterName);\n    }\n}\n\nfunction lightProperties(model: FBXNode): FBXNode[] {\n    const out: FBXNode[] = [];\n    const lightType = numberAt(findChildByName(model, \"LightType\"));\n    if (lightType !== undefined) {\n        out.push(property60(\"LightType\", \"enum\", \"\", lightType));\n    }\n    const color = numbers(findChildByName(model, \"Color\"));\n    if (color.length >= 3) {\n        out.push(property60(\"Color\", \"ColorRGB\", \"\", color[0], color[1], color[2]));\n    }\n    const scalars: [string, string][] = [\n        [\"Intensity\", \"Intensity\"],\n        [\"ConeAngle\", \"OuterAngle\"],\n        [\"HotSpot\", \"InnerAngle\"],\n    ];\n    for (const [source, target] of scalars) {\n        const value = numberAt(findChildByName(model, source));\n        if (value !== undefined) {\n            out.push(property60(target, \"double\", \"\", value));\n        }\n    }\n    const castShadows = numberAt(findChildByName(model, \"CastShadows\"));\n    if (castShadows !== undefined) {\n        out.push(property60(\"CastShadows\", \"bool\", \"\", castShadows));\n    }\n    return out;\n}\n\nfunction cameraProperties(model: FBXNode): FBXNode[] {\n    const out: FBXNode[] = [];\n    const scalars: [string, string][] = [\n        [\"Aperture\", \"FieldOfView\"],\n        [\"FieldOfViewXProperty\", \"FieldOfViewX\"],\n        [\"FieldOfViewYProperty\", \"FieldOfViewY\"],\n        [\"SqueezeRatio\", \"FilmSqueezeRatio\"],\n        [\"FocalLength\", \"FocalLength\"],\n        [\"AspectType\", \"AspectRatioMode\"],\n        [\"AspectW\", \"AspectWidth\"],\n        [\"AspectH\", \"AspectHeight\"],\n        [\"ApertureMode\", \"ApertureMode\"],\n        [\"NearPlane\", \"NearPlane\"],\n        [\"FarPlane\", \"FarPlane\"],\n        [\"Roll\", \"Roll\"],\n    ];\n    for (const [source, target] of scalars) {\n        const value = numberAt(findChildByName(model, source));\n        if (value !== undefined) {\n            out.push(property60(target, target === \"AspectRatioMode\" || target === \"ApertureMode\" ? \"enum\" : \"double\", \"\", value));\n        }\n    }\n    const aperture = numbers(findChildByName(model, \"CameraAperture\"));\n    if (aperture.length >= 2) {\n        out.push(property60(\"FilmWidth\", \"double\", \"\", aperture[0]));\n        out.push(property60(\"FilmHeight\", \"double\", \"\", aperture[1]));\n    }\n    return out;\n}\n\nfunction convertModel(ctx: LegacyContext, model: FBXNode): void {\n    const rawName = getPropertyValue<string>(model, 0) ?? \"Model\";\n    const typeName = getPropertyValue<string>(findChildByName(model, \"Type\") ?? makeNode(\"x\"), 0);\n    const hasVertices = !!findChildByName(model, \"Vertices\");\n    const subType = typeName === \"Light\" ? \"Light\" : typeName === \"Camera\" ? \"Camera\" : typeName === \"LimbNode\" ? \"LimbNode\" : hasVertices ? \"Mesh\" : \"Null\";\n\n    // Rest transform: defaults of the model's own channels, else of the take channels.\n    const defaults: { t?: number[]; r?: number[]; s?: number[] } = {};\n    const ownTransform = model.children.find((c) => c.name === \"Channel\" && getPropertyValue<string>(c, 0) === \"Transform\");\n    readTransformChannelDefaults(ownTransform, defaults);\n    readTransformChannelDefaults(ctx.takeDefaults.get(rawName), defaults);\n    const t = defaults.t ?? [0, 0, 0];\n    const r = defaults.r ?? [0, 0, 0];\n    const s = defaults.s ?? [1, 1, 1];\n    const properties: FBXNode[] = [\n        property60(\"Lcl Translation\", \"Lcl Translation\", \"A+\", t[0], t[1], t[2]),\n        property60(\"Lcl Rotation\", \"Lcl Rotation\", \"A+\", r[0], r[1], r[2]),\n        property60(\"Lcl Scaling\", \"Lcl Scaling\", \"A+\", s[0], s[1], s[2]),\n    ];\n    const visibilityChannel = model.children.find((c) => c.name === \"Channel\" && getPropertyValue<string>(c, 0) === \"Visibility\");\n    const visibility = numberAt(findChildByName(visibilityChannel ?? makeNode(\"x\"), \"Default\"));\n    if (visibility !== undefined && visibility <= 0) {\n        properties.push(property60(\"Visibility\", \"Visibility\", \"A+\", 0));\n    }\n    if (subType === \"Light\") {\n        properties.push(...lightProperties(model));\n    } else if (subType === \"Camera\") {\n        properties.push(...cameraProperties(model));\n    } else if (subType === \"LimbNode\") {\n        const size = numberAt(findChildByName(findChildByName(model, \"Properties\") ?? makeNode(\"x\"), \"Size\"));\n        if (size !== undefined) {\n            properties.push(property60(\"Size\", \"double\", \"\", size));\n        }\n    }\n\n    const children: FBXNode[] = [makeNode(\"Version\", [int(232)]), makeNode(\"Properties60\", [], properties)];\n    for (const name of [\"Culling\", \"Position\", \"Up\", \"LookAt\"]) {\n        const child = findChildByName(model, name);\n        if (child) {\n            children.push(child);\n        }\n    }\n    if (subType === \"Mesh\") {\n        children.push(...convertMesh(model, ctx.version));\n    }\n    ctx.objects.push(makeNode(\"Model\", [str(rawName), str(subType)], children));\n\n    convertMaterials(ctx, model, rawName);\n    convertLinks(ctx, model, rawName);\n\n    const childNames = findChildByName(model, \"Children\");\n    for (const p of childNames?.properties ?? []) {\n        if (typeof p.value === \"string\") {\n            connect(ctx, p.value, rawName);\n        }\n    }\n}\n\n/** Rewrites a legacy document into the 6.x object/connection layout. */\nexport function upgradeLegacyDocument(doc: FBXDocument): FBXDocument {\n    const headerVersion = numberAt(findChildByName(findDocumentNode(doc, \"FBXHeaderExtension\") ?? makeNode(\"x\"), \"FBXVersion\"));\n    const version = Math.max(doc.version, headerVersion ?? 0);\n    const ctx: LegacyContext = { version, objects: [], connections: [], usedNames: new Map(), takeDefaults: new Map() };\n\n    // Takes keep their format; their Transform channels also provide rest values for models without own channels.\n    const takes = findDocumentNode(doc, \"Takes\");\n    for (const take of takes?.children ?? []) {\n        if (take.name !== \"Take\") {\n            continue;\n        }\n        for (const model of take.children) {\n            if (model.name !== \"Model\") {\n                continue;\n            }\n            const name = getPropertyValue<string>(model, 0);\n            const transform = model.children.find((c) => c.name === \"Channel\" && getPropertyValue<string>(c, 0) === \"Transform\");\n            if (name && transform && !ctx.takeDefaults.has(name)) {\n                ctx.takeDefaults.set(name, transform);\n            }\n        }\n    }\n\n    const models = doc.nodes.filter((n) => n.name === \"Model\");\n    for (const model of models) {\n        convertModel(ctx, model);\n    }\n\n    // Animation stored directly on models (pre-5800) becomes an implicit take, as in the SDK.\n    const implicitModels: FBXNode[] = [];\n    for (const model of models) {\n        const channels = model.children.filter((c) => c.name === \"Channel\" && channelHasKeys(c));\n        if (channels.length > 0) {\n            implicitModels.push(makeNode(\"Model\", [str(getPropertyValue<string>(model, 0) ?? \"\")], channels));\n        }\n    }\n    let takesNode = takes;\n    if (implicitModels.length > 0) {\n        const implicitTake = makeNode(\"Take\", [str(\"(internal)\")], implicitModels);\n        takesNode = takes ? makeNode(\"Takes\", takes.properties, [...takes.children, implicitTake]) : makeNode(\"Takes\", [], [implicitTake]);\n    }\n\n    // Frame rate from the legacy settings block.\n    const settings = findDocumentNode(doc, \"Settings\") ?? findChildByName(findDocumentNode(doc, \"Version5\") ?? makeNode(\"x\"), \"Settings\");\n    const frameRateNode = settings ? findChildByName(settings, \"FrameRate\") : undefined;\n    const frameRateValue = frameRateNode?.properties[0]?.value;\n    const fps = typeof frameRateValue === \"number\" ? frameRateValue : typeof frameRateValue === \"string\" ? Number.parseFloat(frameRateValue) : NaN;\n    const extra: FBXNode[] = [];\n    let replacedGlobalSettings = false;\n    if (Number.isFinite(fps) && fps > 0) {\n        const existing = findDocumentNode(doc, \"GlobalSettings\");\n        if (existing) {\n            // Keep the file's axis, unit and other settings; only add the frame rate when the block lacks one.\n            const props70 = findChildByName(existing, \"Properties70\");\n            const container = props70 ?? findChildByName(existing, \"Properties60\") ?? makeNode(\"Properties60\");\n            const hasTimeMode = container.children.some((c) => getPropertyValue<string>(c, 0) === \"TimeMode\");\n            const property = props70 ? property70 : property60;\n            const frameRate = hasTimeMode ? [] : [property(\"TimeMode\", \"enum\", \"\", 14), property(\"CustomFrameRate\", \"double\", \"\", fps)];\n            const children = existing.children.filter((c) => c !== container);\n            extra.push(makeNode(\"GlobalSettings\", existing.properties, [...children, makeNode(container.name, container.properties, [...container.children, ...frameRate])]));\n        } else {\n            extra.push(\n                makeNode(\n                    \"GlobalSettings\",\n                    [],\n                    [makeNode(\"Version\", [int(1000)]), makeNode(\"Properties60\", [], [property60(\"TimeMode\", \"enum\", \"\", 14), property60(\"CustomFrameRate\", \"double\", \"\", fps)])]\n                )\n            );\n        }\n        replacedGlobalSettings = true;\n    }\n\n    const kept = doc.nodes.filter((n) => n.name !== \"Model\" && n.name !== \"Takes\" && n.name !== \"Settings\" && (n.name !== \"GlobalSettings\" || !replacedGlobalSettings));\n    const nodes = [...kept, ...extra, makeNode(\"Objects\", [], ctx.objects), makeNode(\"Connections\", [], ctx.connections)];\n    if (takesNode) {\n        nodes.push(takesNode);\n    }\n    return { ...doc, version, nodes };\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * FBX constraints (FbxConstraint): aim, parent, position, rotation, scale and single chain IK. The property and\n * connection conventions follow the FBX SDK (target weights are `<TargetName>.Weight`, parent offsets\n * `<TargetName>.Offset T/R/S`, the constrained node arrives through the \"Constrained Object\" connection).\n */\nimport { type FBXNode, getPropertyValue, cleanFBXName } from \"../types/fbxTypes\";\nimport { type FBXObjectMap } from \"./connections\";\nimport { getPropertyEntries } from \"./propertyTemplates\";\n\nexport type FBXConstraintType = \"aim\" | \"parent\" | \"position\" | \"rotation\" | \"scale\" | \"singleChainIK\" | \"unknown\";\n\nexport type Vec3 = [number, number, number];\nexport type Bool3 = [boolean, boolean, boolean];\n\n/** One weighted target of a constraint. */\nexport interface FBXConstraintTarget {\n    /** Model id of the target node */\n    modelId: number;\n    /** Normalized weight (file value / 100, or as-is for IK pole targets) */\n    weight: number;\n    /** Parent constraint translation offset expressed in the target's space */\n    offsetTranslation: Vec3;\n    /** Parent constraint rotation offset in degrees, expressed in the target's space */\n    offsetRotation: Vec3;\n    /** Parent constraint scale offset expressed in the target's space */\n    offsetScale: Vec3;\n}\n\n/** A constraint object of the file, with its targets and parameters resolved. */\nexport interface FBXConstraintData {\n    /** Constraint object id */\n    id: number;\n    /** Constraint name */\n    name: string;\n    /** Resolved constraint kind */\n    type: FBXConstraintType;\n    /** Constraint type name as written in the file (e.g. \"Parent-Child\") */\n    typeName: string;\n    /** Constrained model */\n    nodeId?: number;\n    /** Weighted targets in file order */\n    targets: FBXConstraintTarget[];\n    /** Global weight (file value / 100) */\n    weight: number;\n    /** False when the constraint is switched off in the file */\n    active: boolean;\n    /** Which translation axes the constraint drives */\n    affectTranslation: Bool3;\n    /** Which rotation axes the constraint drives */\n    affectRotation: Bool3;\n    /** Which scale axes the constraint drives */\n    affectScale: Bool3;\n    /** Translation offset of the constrained node */\n    offsetTranslation: Vec3;\n    /** Rotation offset of the constrained node, in degrees */\n    offsetRotation: Vec3;\n    /** Scale offset of the constrained node */\n    offsetScale: Vec3;\n    /** Aim: local axis that points at the target */\n    aimVector: Vec3;\n    /** Aim: local axis aligned with the up direction */\n    upVector: Vec3;\n    /** Aim: world up direction (world up modes 2 and 3) */\n    worldUpVector: Vec3;\n    /** Aim: 0 scene up, 1 aim up node, 2 align to node, 3 vector, 4 none */\n    worldUpType: number;\n    /** Aim: model id of the world up object (world up modes 1 and 2) */\n    worldUpNodeId?: number;\n    /** Single chain IK: model id of the first joint of the chain */\n    ikFirstJointId?: number;\n    /** Single chain IK: model id of the last joint of the chain */\n    ikEndJointId?: number;\n    /** Single chain IK: model id of the effector */\n    ikEffectorId?: number;\n    /** Single chain IK: pole vector */\n    ikPoleVector: Vec3;\n}\n\nconst TYPE_NAMES: Record<string, FBXConstraintType> = {\n    Aim: \"aim\",\n    \"Parent-Child\": \"parent\",\n    \"Position From Positions\": \"position\",\n    \"Rotation From Rotations\": \"rotation\",\n    \"Scale From Scales\": \"scale\",\n    \"Single Chain IK\": \"singleChainIK\",\n};\n\nfunction vec3(values: unknown[] | undefined, fallback: Vec3): Vec3 {\n    if (values && typeof values[0] === \"number\" && typeof values[1] === \"number\" && typeof values[2] === \"number\") {\n        return [values[0], values[1], values[2]];\n    }\n    return fallback;\n}\n\nfunction num(values: unknown[] | undefined, fallback: number): number {\n    const v = values?.[0];\n    return typeof v === \"number\" ? v : typeof v === \"boolean\" ? (v ? 1 : 0) : fallback;\n}\n\n/** Reads every constraint object of the scene. */\nexport function extractConstraints(objectMap: FBXObjectMap): FBXConstraintData[] {\n    const constraints: FBXConstraintData[] = [];\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name !== \"Constraint\") {\n            continue;\n        }\n        constraints.push(extractConstraint(id, node, objectMap));\n    }\n    return constraints;\n}\n\nfunction extractConstraint(id: number, node: FBXNode, objectMap: FBXObjectMap): FBXConstraintData {\n    const typeChild = node.children.find((c) => c.name === \"Type\");\n    const typeName = (typeChild ? getPropertyValue<string>(typeChild, 0) : undefined) ?? getPropertyValue<string>(node, 2) ?? \"\";\n    const type = TYPE_NAMES[typeName] ?? \"unknown\";\n    const props = new Map<string, unknown[]>();\n    for (const entry of getPropertyEntries(node)) {\n        props.set(entry.name, entry.values);\n    }\n    const bool3 = (prefix: string, fallback: boolean): Bool3 => [\n        num(props.get(`${prefix}X`), fallback ? 1 : 0) !== 0,\n        num(props.get(`${prefix}Y`), fallback ? 1 : 0) !== 0,\n        num(props.get(`${prefix}Z`), fallback ? 1 : 0) !== 0,\n    ];\n\n    const constraint: FBXConstraintData = {\n        id,\n        name: cleanFBXName(getPropertyValue<string>(node, 1) ?? \"Constraint\"),\n        type,\n        typeName,\n        targets: [],\n        weight: num(props.get(\"Weight\"), 100) / 100,\n        active: num(props.get(\"Active\"), 1) !== 0,\n        affectTranslation: [true, true, true],\n        affectRotation: [true, true, true],\n        affectScale: [false, false, false],\n        offsetTranslation: [0, 0, 0],\n        offsetRotation: [0, 0, 0],\n        offsetScale: [1, 1, 1],\n        aimVector: vec3(props.get(\"AimVector\"), [1, 0, 0]),\n        upVector: vec3(props.get(\"UpVector\"), [0, 1, 0]),\n        worldUpVector: vec3(props.get(\"WorldUpVector\"), [0, 1, 0]),\n        worldUpType: num(props.get(\"WorldUpType\"), 0),\n        ikPoleVector: vec3(props.get(\"PoleVector\"), [0, 0, 0]),\n    };\n\n    switch (type) {\n        case \"aim\":\n            constraint.affectRotation = bool3(\"Affect\", true);\n            constraint.offsetRotation = vec3(props.get(\"RotationOffset\"), [0, 0, 0]);\n            break;\n        case \"parent\":\n            constraint.affectTranslation = bool3(\"AffectTranslation\", true);\n            constraint.affectRotation = bool3(\"AffectRotation\", true);\n            constraint.affectScale = bool3(\"AffectScale\", false);\n            break;\n        case \"position\":\n            constraint.affectTranslation = bool3(\"Affect\", true);\n            constraint.offsetTranslation = vec3(props.get(\"Translation\"), [0, 0, 0]);\n            break;\n        case \"rotation\":\n            constraint.affectRotation = bool3(\"Affect\", true);\n            constraint.offsetRotation = vec3(props.get(\"Rotation\"), [0, 0, 0]);\n            break;\n        case \"scale\":\n            constraint.affectScale = bool3(\"Affect\", true);\n            constraint.offsetScale = vec3(props.get(\"Scaling\"), [1, 1, 1]);\n            break;\n        default:\n            break;\n    }\n\n    // Connected objects: the child of each OP connection is the model, the property names its role.\n    const weightScale = type === \"singleChainIK\" ? 1 : 100;\n    for (const conn of objectMap.connections) {\n        if (conn.parentId !== id || conn.type !== \"OP\" || !conn.propertyName) {\n            continue;\n        }\n        const modelNode = objectMap.objects.get(conn.childId);\n        if (!modelNode || modelNode.name !== \"Model\") {\n            continue;\n        }\n        const role = conn.propertyName;\n        const targetName = cleanFBXName(getPropertyValue<string>(modelNode, 1) ?? \"\");\n        switch (role) {\n            case \"Constrained Object\":\n            case \"Constrained object (Child)\":\n                constraint.nodeId = conn.childId;\n                break;\n            case \"Source\":\n            case \"Source (Parent)\":\n            case \"Aim At Object\":\n            case \"Pole Vector Object\":\n                constraint.targets.push({\n                    modelId: conn.childId,\n                    weight: num(props.get(`${targetName}.Weight`), weightScale) / weightScale,\n                    offsetTranslation: vec3(props.get(`${targetName}.Offset T`), [0, 0, 0]),\n                    offsetRotation: vec3(props.get(`${targetName}.Offset R`), [0, 0, 0]),\n                    offsetScale: vec3(props.get(`${targetName}.Offset S`), [1, 1, 1]),\n                });\n                break;\n            case \"World Up Object\":\n                constraint.worldUpNodeId = conn.childId;\n                break;\n            case \"First Joint\":\n                constraint.ikFirstJointId = conn.childId;\n                break;\n            case \"End Joint\":\n                constraint.ikEndJointId = conn.childId;\n                break;\n            case \"Effector\":\n                constraint.ikEffectorId = conn.childId;\n                break;\n            default:\n                break;\n        }\n    }\n    return constraint;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * Unified material model.\n *\n * FBX materials come in many vendor flavours: the classic FbxSurfaceLambert / FbxSurfacePhong, Autodesk Standard\n * Surface (OSL), Arnold aiStandardSurface, 3ds Max Physical Material, 3ds Max PBR (metal/rough and spec/gloss),\n * the 3ds Max glTF material, OpenPBR, and Maya's Stingray PBS ShaderFX graph. Each stores its parameters under\n * different property names, sometimes behind a shader binding table.\n *\n * This module resolves any of them into two parameter sets, mirroring how the FBX SDK / ufbx expose materials:\n * `fbx` (the classic Lambert/Phong parameters) and `pbr` (a physically based parameter set), plus feature flags.\n */\nimport { type FBXPropertyValue } from \"../types/fbxTypes\";\n\nexport type FBXShaderType =\n    | \"unknown\"\n    | \"fbxLambert\"\n    | \"fbxPhong\"\n    | \"oslStandardSurface\"\n    | \"arnoldStandardSurface\"\n    | \"3dsMaxPhysicalMaterial\"\n    | \"3dsMaxPbrMetalRough\"\n    | \"3dsMaxPbrSpecGloss\"\n    | \"gltfMaterial\"\n    | \"openPbrMaterial\"\n    | \"shaderFxGraph\";\n\n/** One resolved material parameter: a constant value and/or a texture. */\nexport interface FBXMaterialMap<TTexture> {\n    /** Constant value (r,g,b,a for colours, x for scalars) */\n    value?: number[];\n    /** Number of meaningful components in `value` (1 for scalars, 3 or 4 for colours) */\n    valueComponents: number;\n    /** Texture bound to the parameter */\n    texture?: TTexture;\n    /** Whether the texture is enabled (some vendors carry an explicit toggle) */\n    textureEnabled: boolean;\n}\n\nexport type FBXFbxMapName =\n    | \"diffuseFactor\"\n    | \"diffuseColor\"\n    | \"specularFactor\"\n    | \"specularColor\"\n    | \"specularExponent\"\n    | \"reflectionFactor\"\n    | \"reflectionColor\"\n    | \"transparencyFactor\"\n    | \"transparencyColor\"\n    | \"emissionFactor\"\n    | \"emissionColor\"\n    | \"ambientFactor\"\n    | \"ambientColor\"\n    | \"normalMap\"\n    | \"bump\"\n    | \"bumpFactor\"\n    | \"displacement\"\n    | \"displacementFactor\"\n    | \"vectorDisplacement\"\n    | \"vectorDisplacementFactor\";\n\nexport type FBXPbrMapName =\n    | \"baseFactor\"\n    | \"baseColor\"\n    | \"roughness\"\n    | \"metalness\"\n    | \"diffuseRoughness\"\n    | \"specularFactor\"\n    | \"specularColor\"\n    | \"specularIor\"\n    | \"specularAnisotropy\"\n    | \"specularRotation\"\n    | \"transmissionFactor\"\n    | \"transmissionColor\"\n    | \"transmissionDepth\"\n    | \"transmissionScatter\"\n    | \"transmissionScatterAnisotropy\"\n    | \"transmissionDispersion\"\n    | \"transmissionRoughness\"\n    | \"transmissionExtraRoughness\"\n    | \"transmissionPriority\"\n    | \"transmissionEnableInAov\"\n    | \"subsurfaceFactor\"\n    | \"subsurfaceColor\"\n    | \"subsurfaceRadius\"\n    | \"subsurfaceScale\"\n    | \"subsurfaceAnisotropy\"\n    | \"subsurfaceTintColor\"\n    | \"subsurfaceType\"\n    | \"sheenFactor\"\n    | \"sheenColor\"\n    | \"sheenRoughness\"\n    | \"coatFactor\"\n    | \"coatColor\"\n    | \"coatRoughness\"\n    | \"coatIor\"\n    | \"coatAnisotropy\"\n    | \"coatRotation\"\n    | \"coatNormal\"\n    | \"coatAffectBaseColor\"\n    | \"coatAffectBaseRoughness\"\n    | \"thinFilmFactor\"\n    | \"thinFilmThickness\"\n    | \"thinFilmIor\"\n    | \"emissionFactor\"\n    | \"emissionColor\"\n    | \"opacity\"\n    | \"indirectDiffuse\"\n    | \"indirectSpecular\"\n    | \"normalMap\"\n    | \"tangentMap\"\n    | \"displacementMap\"\n    | \"matteFactor\"\n    | \"matteColor\"\n    | \"ambientOcclusion\"\n    | \"glossiness\"\n    | \"coatGlossiness\"\n    | \"transmissionGlossiness\";\n\nexport type FBXMaterialFeatureName =\n    | \"pbr\"\n    | \"metalness\"\n    | \"diffuse\"\n    | \"specular\"\n    | \"emission\"\n    | \"transmission\"\n    | \"coat\"\n    | \"sheen\"\n    | \"opacity\"\n    | \"ambientOcclusion\"\n    | \"matte\"\n    | \"unlit\"\n    | \"ior\"\n    | \"diffuseRoughness\"\n    | \"transmissionRoughness\"\n    | \"thinWalled\"\n    | \"caustics\"\n    | \"exitToBackground\"\n    | \"internalReflections\"\n    | \"doubleSided\"\n    | \"roughnessAsGlossiness\"\n    | \"coatRoughnessAsGlossiness\"\n    | \"transmissionRoughnessAsGlossiness\";\n\nexport interface FBXMaterialModel<TTexture> {\n    shaderType: FBXShaderType;\n    /** Prefix material property names carry for this shader (e.g. \"3dsMax|Parameters|\") */\n    shaderPropPrefix: string;\n    fbx: Partial<Record<FBXFbxMapName, FBXMaterialMap<TTexture>>>;\n    pbr: Partial<Record<FBXPbrMapName, FBXMaterialMap<TTexture>>>;\n    features: Partial<Record<FBXMaterialFeatureName, { enabled: boolean; explicit: boolean }>>;\n}\n\n/** Inputs needed to resolve a material, independent of the parse representation. */\nexport interface FBXMaterialSource<TTexture> {\n    /** \"lambert\", \"phong\", \"unknown\", ... as written in the file */\n    shadingModelName: string;\n    /** Property values by full property name (e.g. \"DiffuseColor\", \"Maya|baseColor\", \"3dsMax|Parameters|roughness\") */\n    props: Map<string, { type: string; values: FBXPropertyValue[] }>;\n    /** Textures connected to the material by property name (OP connection property) */\n    texturesByProp: Map<string, TTexture>;\n    /** Connected shader implementation, when any */\n    shader?: {\n        renderApi: string;\n        /** shader semantic name -> material property names */\n        bindings: Map<string, string[]>;\n    };\n}\n\nconst enum Flag {\n    DefaultW1 = 1,\n    WidenToRgb = 2,\n    MultiplyValue = 4,\n}\nconst enum Transform {\n    None = 0,\n    InvertX = 1,\n    UnknownShininess = 2,\n}\nconst enum FeatureFlag {\n    Inverted = 1,\n    IfExists = 2,\n    IfTexture = 4,\n    IfAround1 = 8,\n}\n\ntype MapEntry = [FBXPbrMapName | FBXFbxMapName, number, number, string];\ntype FeatureEntry = [FBXMaterialFeatureName, number, string];\n\nconst BASE_FBX: MapEntry[] = [\n    [\"diffuseColor\", Flag.DefaultW1, 0, \"Diffuse\"],\n    [\"diffuseColor\", Flag.DefaultW1, 0, \"DiffuseColor\"],\n    [\"diffuseFactor\", 0, 0, \"DiffuseFactor\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"Specular\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"SpecularColor\"],\n    [\"specularFactor\", 0, 0, \"SpecularFactor\"],\n    [\"specularExponent\", 0, 0, \"Shininess\"],\n    [\"specularExponent\", 0, 0, \"ShininessExponent\"],\n    [\"reflectionColor\", Flag.DefaultW1, 0, \"Reflection\"],\n    [\"reflectionColor\", Flag.DefaultW1, 0, \"ReflectionColor\"],\n    [\"reflectionFactor\", 0, 0, \"ReflectionFactor\"],\n    [\"transparencyColor\", Flag.DefaultW1, 0, \"Transparent\"],\n    [\"transparencyColor\", Flag.DefaultW1, 0, \"TransparentColor\"],\n    [\"transparencyFactor\", 0, 0, \"TransparentFactor\"],\n    [\"transparencyFactor\", 0, 0, \"TransparencyFactor\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"Emissive\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"EmissiveColor\"],\n    [\"emissionFactor\", 0, 0, \"EmissiveFactor\"],\n    [\"ambientColor\", Flag.DefaultW1, 0, \"Ambient\"],\n    [\"ambientColor\", Flag.DefaultW1, 0, \"AmbientColor\"],\n    [\"ambientFactor\", 0, 0, \"AmbientFactor\"],\n    [\"normalMap\", 0, 0, \"NormalMap\"],\n    [\"bump\", 0, 0, \"Bump\"],\n    [\"bumpFactor\", 0, 0, \"BumpFactor\"],\n    [\"displacement\", 0, 0, \"Displacement\"],\n    [\"displacementFactor\", 0, 0, \"DisplacementFactor\"],\n    [\"vectorDisplacement\", 0, 0, \"VectorDisplacement\"],\n    [\"vectorDisplacementFactor\", 0, 0, \"VectorDisplacementFactor\"],\n];\n\nconst LAMBERT_PBR: MapEntry[] = [\n    [\"baseColor\", Flag.DefaultW1, 0, \"Diffuse\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"DiffuseColor\"],\n    [\"baseFactor\", 0, 0, \"DiffuseFactor\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"Transparent\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"TransparentColor\"],\n    [\"transmissionFactor\", 0, 0, \"TransparentFactor\"],\n    [\"transmissionFactor\", 0, 0, \"TransparencyFactor\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"Emissive\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"EmissiveColor\"],\n    [\"emissionFactor\", 0, 0, \"EmissiveFactor\"],\n    [\"normalMap\", 0, 0, \"NormalMap\"],\n];\n\nconst PHONG_PBR: MapEntry[] = [\n    [\"baseColor\", Flag.DefaultW1, 0, \"Diffuse\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"DiffuseColor\"],\n    [\"baseFactor\", 0, 0, \"DiffuseFactor\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"Specular\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"SpecularColor\"],\n    [\"specularFactor\", 0, 0, \"SpecularFactor\"],\n    [\"roughness\", 0, Transform.UnknownShininess, \"Shininess\"],\n    [\"roughness\", 0, Transform.UnknownShininess, \"ShininessExponent\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"Transparent\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"TransparentColor\"],\n    [\"transmissionFactor\", 0, 0, \"TransparentFactor\"],\n    [\"transmissionFactor\", 0, 0, \"TransparencyFactor\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"Emissive\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"EmissiveColor\"],\n    [\"emissionFactor\", 0, 0, \"EmissiveFactor\"],\n    [\"normalMap\", 0, 0, \"NormalMap\"],\n];\n\nconst OSL_PBR: MapEntry[] = [\n    [\"baseFactor\", 0, 0, \"base\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"base_color\"],\n    [\"roughness\", 0, 0, \"specular_roughness\"],\n    [\"diffuseRoughness\", 0, 0, \"diffuse_roughness\"],\n    [\"metalness\", 0, 0, \"metalness\"],\n    [\"specularFactor\", 0, 0, \"specular\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"specular_color\"],\n    [\"specularIor\", 0, 0, \"specular_IOR\"],\n    [\"specularAnisotropy\", 0, 0, \"specular_anisotropy\"],\n    [\"specularRotation\", 0, 0, \"specular_rotation\"],\n    [\"transmissionFactor\", 0, 0, \"transmission\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"transmission_color\"],\n    [\"transmissionDepth\", 0, 0, \"transmission_depth\"],\n    [\"transmissionScatter\", Flag.WidenToRgb, 0, \"transmission_scatter\"],\n    [\"transmissionScatterAnisotropy\", 0, 0, \"transmission_scatter_anisotropy\"],\n    [\"transmissionDispersion\", 0, 0, \"transmission_dispersion\"],\n    [\"transmissionExtraRoughness\", 0, 0, \"transmission_extra_roughness\"],\n    [\"subsurfaceFactor\", 0, 0, \"subsurface\"],\n    [\"subsurfaceColor\", Flag.DefaultW1, 0, \"subsurface_color\"],\n    [\"subsurfaceRadius\", Flag.WidenToRgb, 0, \"subsurface_radius\"],\n    [\"subsurfaceScale\", 0, 0, \"subsurface_scale\"],\n    [\"subsurfaceAnisotropy\", 0, 0, \"subsurface_anisotropy\"],\n    [\"sheenFactor\", 0, 0, \"sheen\"],\n    [\"sheenColor\", Flag.DefaultW1, 0, \"sheen_color\"],\n    [\"sheenRoughness\", 0, 0, \"sheen_roughness\"],\n    [\"coatFactor\", 0, 0, \"coat\"],\n    [\"coatColor\", Flag.DefaultW1, 0, \"coat_color\"],\n    [\"coatRoughness\", 0, 0, \"coat_roughness\"],\n    [\"coatIor\", 0, 0, \"coat_IOR\"],\n    [\"coatAnisotropy\", 0, 0, \"coat_anisotropy\"],\n    [\"coatRotation\", 0, 0, \"coat_rotation\"],\n    [\"coatNormal\", 0, 0, \"coat_normal\"],\n    [\"coatAffectBaseColor\", Flag.DefaultW1, 0, \"coat_affect_color\"],\n    [\"coatAffectBaseRoughness\", 0, 0, \"coat_affect_roughness\"],\n    [\"thinFilmThickness\", 0, 0, \"thin_film_thickness\"],\n    [\"thinFilmIor\", 0, 0, \"thin_film_IOR\"],\n    [\"emissionFactor\", 0, 0, \"emission\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emission_color\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"opacity\"],\n    [\"normalMap\", 0, 0, \"NormalMap\"],\n    [\"normalMap\", 0, 0, \"normalCamera\"],\n    [\"tangentMap\", 0, 0, \"tangent\"],\n];\nconst OSL_FEATURES: FeatureEntry[] = [[\"thinWalled\", 0, \"thin_walled\"]];\n\nconst ARNOLD_PBR: MapEntry[] = [\n    [\"baseFactor\", 0, 0, \"base\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"baseColor\"],\n    [\"roughness\", 0, 0, \"specularRoughness\"],\n    [\"diffuseRoughness\", 0, 0, \"diffuseRoughness\"],\n    [\"metalness\", 0, 0, \"metalness\"],\n    [\"specularFactor\", 0, 0, \"specular\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"specularColor\"],\n    [\"specularIor\", 0, 0, \"specularIOR\"],\n    [\"specularAnisotropy\", 0, 0, \"specularAnisotropy\"],\n    [\"specularRotation\", 0, 0, \"specularRotation\"],\n    [\"transmissionFactor\", 0, 0, \"transmission\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"transmissionColor\"],\n    [\"transmissionDepth\", 0, 0, \"transmissionDepth\"],\n    [\"transmissionScatter\", Flag.WidenToRgb, 0, \"transmissionScatter\"],\n    [\"transmissionScatterAnisotropy\", 0, 0, \"transmissionScatterAnisotropy\"],\n    [\"transmissionDispersion\", 0, 0, \"transmissionDispersion\"],\n    [\"transmissionExtraRoughness\", 0, 0, \"transmissionExtraRoughness\"],\n    [\"subsurfaceFactor\", 0, 0, \"subsurface\"],\n    [\"subsurfaceColor\", Flag.DefaultW1, 0, \"subsurfaceColor\"],\n    [\"subsurfaceRadius\", Flag.WidenToRgb, 0, \"subsurfaceRadius\"],\n    [\"subsurfaceScale\", 0, 0, \"subsurfaceScale\"],\n    [\"subsurfaceAnisotropy\", 0, 0, \"subsurfaceAnisotropy\"],\n    [\"sheenFactor\", 0, 0, \"sheen\"],\n    [\"sheenColor\", Flag.DefaultW1, 0, \"sheenColor\"],\n    [\"sheenRoughness\", 0, 0, \"sheenRoughness\"],\n    [\"coatFactor\", 0, 0, \"coat\"],\n    [\"coatColor\", Flag.DefaultW1, 0, \"coatColor\"],\n    [\"coatRoughness\", 0, 0, \"coatRoughness\"],\n    [\"coatIor\", 0, 0, \"coatIOR\"],\n    [\"coatAnisotropy\", 0, 0, \"coatAnisotropy\"],\n    [\"coatRotation\", 0, 0, \"coatRotation\"],\n    [\"coatNormal\", 0, 0, \"coatNormal\"],\n    [\"thinFilmThickness\", 0, 0, \"thinFilmThickness\"],\n    [\"thinFilmIor\", 0, 0, \"thinFilmIOR\"],\n    [\"emissionFactor\", 0, 0, \"emission\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emissionColor\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"opacity\"],\n    [\"indirectDiffuse\", 0, 0, \"indirectDiffuse\"],\n    [\"indirectSpecular\", 0, 0, \"indirectSpecular\"],\n    [\"normalMap\", 0, 0, \"NormalMap\"],\n    [\"normalMap\", 0, 0, \"normalCamera\"],\n    [\"tangentMap\", 0, 0, \"tangent\"],\n    [\"matteColor\", Flag.DefaultW1, 0, \"aiMatteColor\"],\n    [\"matteFactor\", 0, 0, \"aiMatteColorA\"],\n    [\"subsurfaceType\", 0, 0, \"subsurfaceType\"],\n    [\"transmissionPriority\", 0, 0, \"dielectricPriority\"],\n    [\"transmissionEnableInAov\", 0, 0, \"transmitAovs\"],\n];\nconst ARNOLD_FEATURES: FeatureEntry[] = [\n    [\"matte\", 0, \"aiEnableMatte\"],\n    [\"thinWalled\", 0, \"thinWalled\"],\n    [\"caustics\", 0, \"caustics\"],\n    [\"internalReflections\", 0, \"internalReflections\"],\n    [\"exitToBackground\", 0, \"exitToBackground\"],\n];\n\nconst MAX_PHYSICAL_PBR: MapEntry[] = [\n    [\"baseFactor\", 0, 0, \"base_weight\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"base_color\"],\n    [\"roughness\", 0, 0, \"roughness\"],\n    [\"diffuseRoughness\", 0, 0, \"diff_rough\"],\n    [\"diffuseRoughness\", 0, 0, \"diff_roughness\"],\n    [\"metalness\", 0, 0, \"metalness\"],\n    [\"specularFactor\", 0, 0, \"reflectivity\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"refl_color\"],\n    [\"specularAnisotropy\", 0, 0, \"anisotropy\"],\n    [\"specularRotation\", 0, 0, \"aniso_angle\"],\n    [\"specularRotation\", 0, 0, \"anisoangle\"],\n    [\"specularIor\", 0, 0, \"trans_ior\"],\n    [\"transmissionFactor\", 0, 0, \"transparency\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"trans_color\"],\n    [\"transmissionDepth\", 0, 0, \"trans_depth\"],\n    [\"transmissionRoughness\", 0, 0, \"trans_rough\"],\n    [\"transmissionRoughness\", 0, 0, \"trans_roughness\"],\n    [\"subsurfaceFactor\", 0, 0, \"scattering\"],\n    [\"subsurfaceTintColor\", Flag.DefaultW1, 0, \"sss_color\"],\n    [\"subsurfaceColor\", Flag.DefaultW1, 0, \"sss_scatter_color\"],\n    [\"subsurfaceRadius\", Flag.WidenToRgb, 0, \"sss_depth\"],\n    [\"subsurfaceScale\", 0, 0, \"sss_scale\"],\n    [\"coatFactor\", 0, 0, \"coat\"],\n    [\"coatFactor\", 0, 0, \"coating\"],\n    [\"coatColor\", Flag.DefaultW1, 0, \"coat_color\"],\n    [\"coatRoughness\", 0, 0, \"coat_rough\"],\n    [\"coatRoughness\", 0, 0, \"coat_roughness\"],\n    [\"coatIor\", 0, 0, \"coat_ior\"],\n    [\"coatNormal\", 0, 0, \"coat_bump\"],\n    [\"coatNormal\", 0, 0, \"clearcoat_bump_map_amt\"],\n    [\"coatAffectBaseColor\", Flag.DefaultW1, 0, \"coat_affect_color\"],\n    [\"coatAffectBaseRoughness\", 0, 0, \"coat_affect_roughness\"],\n    [\"emissionFactor\", 0, 0, \"emission\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emit_color\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"cutout\"],\n    [\"normalMap\", 0, 0, \"bump\"],\n    [\"normalMap\", 0, 0, \"bump_map_amt\"],\n    [\"displacementMap\", 0, 0, \"displacement\"],\n    [\"displacementMap\", 0, 0, \"displacement_map_amt\"],\n    [\"subsurfaceType\", 0, 0, \"subsurfaceType\"],\n];\nconst MAX_PHYSICAL_FEATURES: FeatureEntry[] = [\n    [\"thinWalled\", 0, \"thin_walled\"],\n    [\"specular\", 0, \"material_mode\"],\n    [\"diffuseRoughness\", 0, \"material_mode\"],\n    [\"transmissionRoughness\", FeatureFlag.Inverted, \"trans_roughness_lock\"],\n    [\"roughnessAsGlossiness\", 0, \"roughness_inv\"],\n    [\"transmissionRoughnessAsGlossiness\", 0, \"trans_roughness_inv\"],\n    [\"coatRoughnessAsGlossiness\", 0, \"coat_roughness_inv\"],\n];\n\nconst GLTF_PBR: MapEntry[] = [\n    [\"baseColor\", Flag.DefaultW1, 0, \"main|baseColor\"],\n    [\"roughness\", 0, 0, \"main|roughness\"],\n    [\"metalness\", 0, 0, \"main|metalness\"],\n    [\"normalMap\", 0, 0, \"main|normal\"],\n    [\"ambientOcclusion\", 0, 0, \"main|ambientOcclusion\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"main|emission\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"main|emissionColor\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"main|Alpha\"],\n    [\"coatFactor\", 0, 0, \"extension|clearcoat\"],\n    [\"coatRoughness\", 0, 0, \"extension|clearcoatRoughness\"],\n    [\"coatNormal\", 0, 0, \"extension|clearcoatNormal\"],\n    [\"sheenColor\", Flag.DefaultW1, 0, \"extension|sheenColor\"],\n    [\"sheenRoughness\", 0, 0, \"extension|sheenRoughness\"],\n    [\"specularFactor\", 0, 0, \"extension|specular\"],\n    [\"specularFactor\", 0, 0, \"extension|Specular\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"extension|specularcolor\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"extension|specularColor\"],\n    [\"transmissionFactor\", 0, 0, \"extension|transmission\"],\n    [\"specularIor\", 0, 0, \"extension|indexOfRefraction\"],\n];\nconst GLTF_FEATURES: FeatureEntry[] = [\n    [\"doubleSided\", 0, \"main|DoubleSided\"],\n    [\"sheen\", 0, \"extension|enableSheen\"],\n    [\"coat\", 0, \"extension|enableClearCoat\"],\n    [\"transmission\", 0, \"extension|enableTransmission\"],\n    [\"ior\", 0, \"extension|enableIndexOfRefraction\"],\n    [\"specular\", 0, \"extension|enableSpecular\"],\n    [\"unlit\", 0, \"extension|unlit\"],\n];\n\nconst OPENPBR_PBR: MapEntry[] = [\n    [\"baseFactor\", 0, 0, \"base_weight\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"base_color\"],\n    [\"roughness\", 0, 0, \"specular_roughness\"],\n    [\"diffuseRoughness\", 0, 0, \"base_diffuse_roughness\"],\n    [\"metalness\", 0, 0, \"base_metalness\"],\n    [\"specularFactor\", 0, 0, \"specular_weight\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"specular_color\"],\n    [\"specularAnisotropy\", 0, 0, \"specular_roughness_anisotropy\"],\n    [\"specularIor\", 0, 0, \"specular_ior\"],\n    [\"transmissionFactor\", 0, 0, \"transmission_weight\"],\n    [\"transmissionColor\", Flag.DefaultW1, 0, \"transmission_color\"],\n    [\"transmissionDepth\", 0, 0, \"transmission_depth\"],\n    [\"transmissionScatter\", Flag.WidenToRgb, 0, \"transmission_scatter\"],\n    [\"transmissionScatterAnisotropy\", 0, 0, \"transmission_scatter_anisotropy\"],\n    [\"transmissionDispersion\", 0, 0, \"transmission_dispersion_scale\"],\n    [\"subsurfaceFactor\", 0, 0, \"subsurface_weight\"],\n    [\"subsurfaceColor\", Flag.DefaultW1, 0, \"subsurface_color\"],\n    [\"subsurfaceRadius\", Flag.WidenToRgb, 0, \"subsurface_radius_scale\"],\n    [\"subsurfaceScale\", 0, 0, \"subsurface_radius\"],\n    [\"subsurfaceAnisotropy\", 0, 0, \"subsurface_scatter_anisotropy\"],\n    [\"coatFactor\", 0, 0, \"coat_weight\"],\n    [\"coatColor\", Flag.DefaultW1, 0, \"coat_color\"],\n    [\"coatRoughness\", 0, 0, \"coat_roughness\"],\n    [\"coatAnisotropy\", 0, 0, \"coat_roughness_anisotropy\"],\n    [\"coatIor\", 0, 0, \"coat_ior\"],\n    [\"coatNormal\", 0, 0, \"coat_normal_map\"],\n    [\"sheenFactor\", 0, 0, \"fuzz_weight\"],\n    [\"sheenColor\", Flag.DefaultW1, 0, \"fuzz_color\"],\n    [\"sheenRoughness\", 0, 0, \"fuzz_roughness\"],\n    [\"emissionFactor\", 0, 0, \"emission_weight\"],\n    [\"emissionFactor\", Flag.MultiplyValue, 0, \"emission_luminance\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emission_color\"],\n    [\"thinFilmFactor\", 0, 0, \"thin_film_weight\"],\n    [\"thinFilmThickness\", 0, 0, \"thin_film_thickness\"],\n    [\"thinFilmIor\", 0, 0, \"thin_film_ior\"],\n    [\"normalMap\", 0, 0, \"bump\"],\n    [\"normalMap\", 0, 0, \"bump_map_amt\"],\n    [\"displacementMap\", 0, 0, \"displacement\"],\n    [\"displacementMap\", 0, 0, \"displacement_map_amt\"],\n    [\"coatNormal\", 0, 0, \"coat_bump\"],\n    [\"coatNormal\", 0, 0, \"coat_bump_map_amt\"],\n    [\"tangentMap\", 0, 0, \"geometry_tangent_map\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"geometry_opacity\"],\n];\nconst OPENPBR_FEATURES: FeatureEntry[] = [[\"thinWalled\", 0, \"geometry_thin_walled\"]];\n\nconst MAX_METAL_ROUGH_PBR: MapEntry[] = [\n    [\"baseColor\", Flag.DefaultW1, 0, \"base_color\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"baseColor\"],\n    [\"roughness\", 0, 0, \"roughness\"],\n    [\"roughness\", 0, 0, \"Roughness_Map\"],\n    [\"metalness\", 0, 0, \"metalness\"],\n    [\"ambientOcclusion\", 0, 0, \"ao\"],\n    [\"normalMap\", 0, 0, \"norm\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emit_color\"],\n    [\"displacementMap\", 0, 0, \"displacement\"],\n    [\"displacementMap\", 0, 0, \"displacement_amt\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"opacity\"],\n];\nconst MAX_SPEC_GLOSS_PBR: MapEntry[] = [\n    [\"baseColor\", Flag.DefaultW1, 0, \"base_color\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"baseColor\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"Specular\"],\n    [\"specularColor\", Flag.DefaultW1, 0, \"specular\"],\n    [\"roughness\", 0, 0, \"glossiness\"],\n    [\"ambientOcclusion\", 0, 0, \"ao\"],\n    [\"normalMap\", 0, 0, \"norm\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emit_color\"],\n    [\"displacementMap\", 0, 0, \"displacement\"],\n    [\"displacementMap\", 0, 0, \"displacement_amt\"],\n    [\"opacity\", Flag.WidenToRgb, 0, \"opacity\"],\n];\nconst MAX_PBR_FEATURES: FeatureEntry[] = [[\"roughnessAsGlossiness\", FeatureFlag.IfAround1, \"useGlossiness\"]];\n\nconst SHADERFX_PBR: MapEntry[] = [\n    [\"baseColor\", Flag.DefaultW1, 0, \"color\"],\n    [\"baseColor\", Flag.DefaultW1, 0, \"base_color\"],\n    [\"roughness\", 0, 0, \"roughness\"],\n    [\"metalness\", 0, 0, \"metallic\"],\n    [\"normalMap\", 0, 0, \"normal\"],\n    [\"emissionFactor\", 0, 0, \"emissive_intensity\"],\n    [\"emissionColor\", Flag.DefaultW1, 0, \"emissive\"],\n    [\"ambientOcclusion\", 0, 0, \"ao\"],\n];\n\ninterface ShaderTable {\n    maps: MapEntry[];\n    features: FeatureEntry[];\n    defaultFeatures: FBXMaterialFeatureName[];\n    texturePrefix?: string;\n    textureSuffix?: string;\n    textureEnabledPrefix?: string;\n    textureEnabledSuffix?: string;\n}\n\nconst PBR_COMMON: FBXMaterialFeatureName[] = [\"pbr\", \"metalness\", \"diffuse\", \"specular\", \"coat\", \"sheen\", \"transmission\", \"opacity\", \"ior\", \"diffuseRoughness\"];\n\nconst SHADER_TABLES: Record<FBXShaderType, ShaderTable> = {\n    unknown: { maps: PHONG_PBR, features: [], defaultFeatures: [\"diffuse\", \"specular\", \"emission\", \"transmission\"] },\n    fbxLambert: { maps: LAMBERT_PBR, features: [], defaultFeatures: [\"diffuse\", \"emission\", \"transmission\"] },\n    fbxPhong: { maps: PHONG_PBR, features: [], defaultFeatures: [\"diffuse\", \"specular\", \"emission\", \"transmission\"] },\n    oslStandardSurface: { maps: OSL_PBR, features: OSL_FEATURES, defaultFeatures: PBR_COMMON },\n    arnoldStandardSurface: { maps: ARNOLD_PBR, features: ARNOLD_FEATURES, defaultFeatures: PBR_COMMON },\n    \"3dsMaxPhysicalMaterial\": {\n        maps: MAX_PHYSICAL_PBR,\n        features: MAX_PHYSICAL_FEATURES,\n        defaultFeatures: [\"pbr\", \"metalness\", \"diffuse\", \"coat\", \"sheen\", \"transmission\", \"opacity\", \"ior\"],\n        textureSuffix: \"_map\",\n        textureEnabledSuffix: \"_map_on\",\n    },\n    \"3dsMaxPbrMetalRough\": { maps: MAX_METAL_ROUGH_PBR, features: MAX_PBR_FEATURES, defaultFeatures: [\"pbr\", \"metalness\", \"diffuse\", \"opacity\"], textureSuffix: \"_map\" },\n    \"3dsMaxPbrSpecGloss\": { maps: MAX_SPEC_GLOSS_PBR, features: MAX_PBR_FEATURES, defaultFeatures: [\"pbr\", \"specular\", \"diffuse\", \"opacity\"], textureSuffix: \"_map\" },\n    gltfMaterial: {\n        maps: GLTF_PBR,\n        features: GLTF_FEATURES,\n        defaultFeatures: [\"pbr\", \"metalness\", \"diffuse\", \"emission\", \"opacity\", \"ambientOcclusion\"],\n        textureSuffix: \"Map\",\n    },\n    openPbrMaterial: { maps: OPENPBR_PBR, features: OPENPBR_FEATURES, defaultFeatures: PBR_COMMON, textureSuffix: \"_map\", textureEnabledSuffix: \"_map_on\" },\n    shaderFxGraph: {\n        maps: SHADERFX_PBR,\n        features: [],\n        defaultFeatures: [\"pbr\", \"metalness\", \"diffuse\", \"emission\", \"ambientOcclusion\"],\n        texturePrefix: \"TEX_\",\n        textureSuffix: \"_map\",\n        textureEnabledPrefix: \"use_\",\n        textureEnabledSuffix: \"_map\",\n    },\n};\n\n/** Shader types whose parameters are physically based; the loader emits PBR materials for them by default. */\nexport function isPbrShaderType(type: FBXShaderType): boolean {\n    return type !== \"unknown\" && type !== \"fbxLambert\" && type !== \"fbxPhong\";\n}\n\nfunction applyTransform(transform: number, v: number[]): void {\n    switch (transform) {\n        case Transform.InvertX:\n            v[0] = 1 - v[0];\n            break;\n        case Transform.UnknownShininess:\n            // Roughness from a Phong exponent, the same heuristic the FBX SDK / ufbx uses.\n            if (v[0] >= 0) {\n                v[0] = 1 - Math.sqrt(v[0]) * 0.1;\n                if (v[0] < 0) {\n                    v[0] = 0;\n                }\n            }\n            break;\n        default:\n            break;\n    }\n}\n\nfunction numericValues(values: FBXPropertyValue[]): number[] {\n    const out: number[] = [];\n    for (const v of values) {\n        if (typeof v === \"number\") {\n            out.push(v);\n        } else if (typeof v === \"boolean\") {\n            out.push(v ? 1 : 0);\n        } else {\n            break;\n        }\n    }\n    return out;\n}\n\n/** Detects the shader flavour of a material from its shading model name, connected shader and 3ds Max class ids. */\nexport function detectShaderType<T>(source: FBXMaterialSource<T>): { shaderType: FBXShaderType; shaderPropPrefix: string } {\n    let shaderType: FBXShaderType = \"unknown\";\n    const model = source.shadingModelName.toLowerCase();\n    if (model === \"lambert\") {\n        shaderType = \"fbxLambert\";\n    } else if (model === \"phong\") {\n        shaderType = \"fbxPhong\";\n    }\n    if (source.shader) {\n        switch (source.shader.renderApi) {\n            case \"ARNOLD_SHADER_ID\":\n                return { shaderType: \"arnoldStandardSurface\", shaderPropPrefix: \"\" };\n            case \"OSL\":\n                return { shaderType: \"oslStandardSurface\", shaderPropPrefix: \"\" };\n            case \"SFX_PBS_SHADER\":\n                return { shaderType: \"shaderFxGraph\", shaderPropPrefix: \"\" };\n            default:\n                return { shaderType: \"unknown\", shaderPropPrefix: \"\" };\n        }\n    }\n    if (shaderType === \"unknown\") {\n        const a = (numericValues(source.props.get(\"3dsMax|ClassIDa\")?.values ?? [])[0] ?? 0) >>> 0;\n        const b = (numericValues(source.props.get(\"3dsMax|ClassIDb\")?.values ?? [])[0] ?? 0) >>> 0;\n        if (a === 0x3d6b1cec && b === 0xdeadc001) {\n            return { shaderType: \"3dsMaxPhysicalMaterial\", shaderPropPrefix: \"3dsMax|Parameters|\" };\n        }\n        if (a === 0xf1551e33 && b === 0x37fb1337) {\n            return { shaderType: \"openPbrMaterial\", shaderPropPrefix: \"3dsMax|Parameters|\" };\n        }\n        if (a === 0x38420192 && b === 0x45fe4e1b) {\n            return { shaderType: \"gltfMaterial\", shaderPropPrefix: \"3dsMax|\" };\n        }\n        if (a === 0xd00f1e00 && b === 0xbe77e500) {\n            return { shaderType: \"3dsMaxPbrMetalRough\", shaderPropPrefix: \"3dsMax|main|\" };\n        }\n        if (a === 0xd00f1e00 && b === 0x01dbad33) {\n            return { shaderType: \"3dsMaxPbrSpecGloss\", shaderPropPrefix: \"3dsMax|main|\" };\n        }\n    }\n    return { shaderType, shaderPropPrefix: \"\" };\n}\n\n/**\n * Resolves the unified material model from raw material data.\n */\nexport function resolveMaterialModel<T>(source: FBXMaterialSource<T>): FBXMaterialModel<T> {\n    const { shaderType, shaderPropPrefix } = detectShaderType(source);\n    const table = SHADER_TABLES[shaderType];\n    const model: FBXMaterialModel<T> = { shaderType, shaderPropPrefix, fbx: {}, pbr: {}, features: {} };\n\n    for (const f of table.defaultFeatures) {\n        model.features[f] = { enabled: true, explicit: false };\n    }\n\n    const materialPropsFor = (semantic: string): string[] => {\n        const bound = source.shader?.bindings.get(semantic);\n        return bound && bound.length > 0 ? bound : [semantic];\n    };\n    const prefix = source.shader ? \"\" : shaderPropPrefix;\n\n    const fetch = (\n        entries: MapEntry[],\n        target: Partial<Record<string, FBXMaterialMap<T>>>,\n        prefix2: string,\n        suffix: string,\n        wantValue: boolean,\n        wantTexture: boolean,\n        wantEnabled: boolean\n    ) => {\n        for (const [mapName, flags, transform, prop] of entries) {\n            const semantic = prefix + prefix2 + prop + suffix;\n            for (const name of materialPropsFor(semantic)) {\n                const entry = source.props.get(name);\n                const map = (target[mapName] ??= { valueComponents: 0, textureEnabled: false });\n                if (wantValue && entry && entry.type !== \"Reference\") {\n                    const nums = numericValues(entry.values);\n                    if (nums.length > 0) {\n                        const v = nums.slice(0, 4);\n                        if (flags & Flag.MultiplyValue) {\n                            v[0] *= map.value?.[0] ?? 1;\n                            map.value = [v[0], ...(map.value?.slice(1) ?? [])];\n                        } else {\n                            map.value = v;\n                        }\n                        applyTransform(transform, map.value);\n                        const components = nums.length >= 4 ? 4 : nums.length === 3 ? 3 : nums.length === 2 ? 2 : 1;\n                        if (flags & Flag.DefaultW1 && components < 4) {\n                            map.value[3] = 1;\n                        }\n                        if (flags & Flag.WidenToRgb && components === 1) {\n                            map.value[1] = map.value[0];\n                            map.value[2] = map.value[0];\n                        }\n                        map.valueComponents = components;\n                    }\n                }\n                if (wantTexture) {\n                    const texture = source.texturesByProp.get(name);\n                    if (texture) {\n                        map.texture = texture;\n                        map.textureEnabled = true;\n                    }\n                }\n                if (wantEnabled && entry) {\n                    const nums = numericValues(entry.values);\n                    if (nums.length > 0) {\n                        map.textureEnabled = nums[0] !== 0;\n                    }\n                }\n            }\n        }\n    };\n\n    // Classic Lambert/Phong parameters are always read.\n    fetch(BASE_FBX, model.fbx, \"\", \"\", true, true, false);\n    // Shader specific parameters, textures with vendor prefix/suffix, and texture toggles.\n    if (table.texturePrefix || table.textureSuffix) {\n        fetch(table.maps, model.pbr, table.texturePrefix ?? \"\", table.textureSuffix ?? \"\", false, true, false);\n    }\n    fetch(table.maps, model.pbr, \"\", \"\", true, true, false);\n    if (table.textureEnabledPrefix || table.textureEnabledSuffix) {\n        fetch(table.maps, model.pbr, table.textureEnabledPrefix ?? \"\", table.textureEnabledSuffix ?? \"\", false, false, true);\n    }\n    // Feature toggles\n    for (const [feature, flags, prop] of table.features) {\n        const semantic = prefix + prop;\n        for (const name of materialPropsFor(semantic)) {\n            const entry = source.props.get(name);\n            const info = (model.features[feature] ??= { enabled: false, explicit: false });\n            if (entry && entry.type !== \"Reference\") {\n                const nums = numericValues(entry.values);\n                if (nums.length > 0) {\n                    info.enabled = nums[0] !== 0;\n                    info.explicit = true;\n                    if (flags & FeatureFlag.IfAround1) {\n                        info.enabled = nums[0] >= 0.5 && nums[0] <= 1.5;\n                    }\n                    if (flags & FeatureFlag.Inverted) {\n                        info.enabled = !info.enabled;\n                    }\n                    if (flags & FeatureFlag.IfExists) {\n                        info.enabled = true;\n                    }\n                }\n            }\n            if (flags & FeatureFlag.IfTexture && source.texturesByProp.has(name)) {\n                info.enabled = true;\n            }\n        }\n    }\n\n    // Factors default to 1 when the matching colour is set and non-zero, 0 otherwise.\n    const updateFactor = (target: Partial<Record<string, FBXMaterialMap<T>>>, factorName: string, colorName: string) => {\n        const factor = (target[factorName] ??= { valueComponents: 0, textureEnabled: false });\n        if (factor.value) {\n            return;\n        }\n        const color = target[colorName];\n        const nonZero = color?.value && color.value.some((c) => c !== 0);\n        factor.value = [nonZero ? 1 : 0];\n        factor.valueComponents = 1;\n    };\n    updateFactor(model.fbx, \"diffuseFactor\", \"diffuseColor\");\n    updateFactor(model.fbx, \"specularFactor\", \"specularColor\");\n    updateFactor(model.fbx, \"reflectionFactor\", \"reflectionColor\");\n    updateFactor(model.fbx, \"transparencyFactor\", \"transparencyColor\");\n    updateFactor(model.fbx, \"emissionFactor\", \"emissionColor\");\n    updateFactor(model.fbx, \"ambientFactor\", \"ambientColor\");\n    updateFactor(model.pbr, \"baseFactor\", \"baseColor\");\n    updateFactor(model.pbr, \"specularFactor\", \"specularColor\");\n    updateFactor(model.pbr, \"emissionFactor\", \"emissionColor\");\n    updateFactor(model.pbr, \"sheenFactor\", \"sheenColor\");\n    updateFactor(model.pbr, \"thinFilmFactor\", \"thinFilmThickness\");\n    updateFactor(model.pbr, \"transmissionFactor\", \"transmissionColor\");\n\n    if (!model.pbr.transmissionRoughness?.value && model.pbr.roughness?.value && model.pbr.transmissionExtraRoughness?.value) {\n        model.pbr.transmissionRoughness = {\n            value: [model.pbr.roughness.value[0] + model.pbr.transmissionExtraRoughness.value[0]],\n            valueComponents: 1,\n            textureEnabled: false,\n        };\n    }\n\n    // Roughness <-> glossiness\n    const remaps: [FBXMaterialFeatureName, FBXPbrMapName, FBXPbrMapName][] = [\n        [\"roughnessAsGlossiness\", \"roughness\", \"glossiness\"],\n        [\"coatRoughnessAsGlossiness\", \"coatRoughness\", \"coatGlossiness\"],\n        [\"transmissionRoughnessAsGlossiness\", \"transmissionRoughness\", \"transmissionGlossiness\"],\n    ];\n    for (const [feature, roughName, glossName] of remaps) {\n        const rough = model.pbr[roughName];\n        if (model.features[feature]?.enabled) {\n            if (rough) {\n                model.pbr[glossName] = rough;\n                model.pbr[roughName] = rough.value ? { value: [1 - rough.value[0]], valueComponents: 1, textureEnabled: false } : { valueComponents: 0, textureEnabled: false };\n            }\n        } else if (rough?.value) {\n            model.pbr[glossName] = { value: [1 - rough.value[0]], valueComponents: 1, textureEnabled: false };\n        }\n    }\n\n    return model;\n}\n\n/** Colour (first three components) of a map, or undefined. */\nexport function mapColor<T>(map: FBXMaterialMap<T> | undefined): [number, number, number] | undefined {\n    if (!map?.value) {\n        return undefined;\n    }\n    const v = map.value;\n    if (map.valueComponents === 1) {\n        return [v[0], v[0], v[0]];\n    }\n    return [v[0], v[1] ?? v[0], v[2] ?? v[0]];\n}\n\n/** Scalar (first component) of a map, or undefined. */\nexport function mapScalar<T>(map: FBXMaterialMap<T> | undefined): number | undefined {\n    return map?.value ? map.value[0] : undefined;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXNode, type FBXPropertyValue, findChildByName, getPropertyValue, cleanFBXName } from \"../types/fbxTypes\";\n\nimport { type FBXObjectMap, getChildren } from \"./connections\";\n\nimport {\n    extractUserProperties,\n    getPropertyEntries,\n    getPropertyTemplate,\n    resolvePropertyValue,\n    resolvePropertyValues,\n    type FBXPropertyTemplate,\n    type FBXPropertyTemplateMap,\n    type FBXUserPropertyValue,\n} from \"./propertyTemplates\";\nimport { resolveMaterialModel, type FBXMaterialModel, type FBXMaterialSource } from \"./materialModel\";\n\n/** Parsed material data */\nexport interface FBXMaterialData {\n    id: number;\n    name: string;\n    type: \"Lambert\" | \"Phong\";\n    properties: FBXMaterialProperties;\n    textures: FBXTextureRef[];\n    /** Unified classic + PBR parameter model resolved from whichever shader flavour the file uses */\n    model: FBXMaterialModel<FBXTextureRef>;\n    /** User-defined properties */\n    userProperties?: Record<string, FBXUserPropertyValue>;\n}\n\nexport interface FBXMaterialProperties {\n    diffuseColor?: [number, number, number];\n    diffuseFactor?: number;\n    ambientColor?: [number, number, number];\n    ambientFactor?: number;\n    specularColor?: [number, number, number];\n    specularFactor?: number;\n    shininess?: number;\n    emissiveColor?: [number, number, number];\n    emissiveFactor?: number;\n    opacity?: number;\n    transparencyFactor?: number;\n}\n\nexport interface FBXTextureRef {\n    /** Which material property this texture is connected to */\n    propertyName: string;\n    /** Absolute file path from the FBX */\n    fileName: string;\n    /** Relative file path from the FBX */\n    relativeFileName: string;\n    /** Texture node ID */\n    id: number;\n    /** Embedded texture data (from Video node Content), if available */\n    embeddedData: Uint8Array | null;\n    /** UV translation [u, v] */\n    uvTranslation?: [number, number];\n    /** UV scaling [u, v] */\n    uvScaling?: [number, number];\n    /** UV rotation in degrees */\n    uvRotation?: number;\n    /** Which UV set index this texture uses */\n    uvSetIndex?: number;\n    /** Which named UV set this texture uses */\n    uvSetName?: string;\n    /** WrapModeU: 0 = repeat, 1 = clamp */\n    wrapU?: number;\n    /** WrapModeV: 0 = repeat, 1 = clamp */\n    wrapV?: number;\n    /** Set when the texture came from a LayeredTexture (only the first layer is used) */\n    layeredTextureId?: number;\n}\n\n/**\n * Extract material data from an FBX Material node.\n */\nexport function extractMaterial(materialNode: FBXNode, materialId: number, objectMap: FBXObjectMap, templates?: FBXPropertyTemplateMap): FBXMaterialData {\n    const name = cleanFBXName(getPropertyValue<string>(materialNode, 1) ?? \"Material\");\n    const template = getMaterialTemplate(materialNode, templates);\n\n    // Determine Lambert vs Phong from ShadingModel property\n    const shadingModel = findChildByName(materialNode, \"ShadingModel\");\n    const shadingType = shadingModel\n        ? (getPropertyValue<string>(shadingModel, 0) ?? \"Lambert\")\n        : (resolvePropertyValue<string>(materialNode, template, \"ShadingModel\") ?? \"Lambert\");\n    const type: \"Lambert\" | \"Phong\" = shadingType.toLowerCase() === \"phong\" ? \"Phong\" : \"Lambert\";\n\n    // Extract properties from Properties70\n    const properties = extractMaterialProperties(materialNode, template);\n\n    // Find connected textures\n    const textureTemplate = templates ? (getPropertyTemplate(templates, \"Texture\", \"FbxFileTexture\") ?? getPropertyTemplate(templates, \"Texture\")) : undefined;\n    const textures = extractTextures(materialId, objectMap, textureTemplate);\n\n    // Resolve the unified material model (classic + PBR parameters) from all properties, textures and shader bindings.\n    const props = new Map<string, { type: string; values: FBXPropertyValue[] }>();\n    for (const tp of template?.properties.values() ?? []) {\n        props.set(tp.name, { type: tp.propertyType, values: tp.values });\n    }\n    for (const entry of getPropertyEntries(materialNode)) {\n        props.set(entry.name, { type: entry.type, values: entry.values });\n    }\n    const texturesByProp = new Map<string, FBXTextureRef>();\n    for (const tex of textures) {\n        if (!texturesByProp.has(tex.propertyName)) {\n            texturesByProp.set(tex.propertyName, tex);\n        }\n    }\n    const source: FBXMaterialSource<FBXTextureRef> = { shadingModelName: shadingType, props, texturesByProp, shader: extractShaderInfo(materialId, objectMap) };\n    const model = resolveMaterialModel(source);\n\n    return { id: materialId, name, type, properties, textures, model, userProperties: extractUserProperties(materialNode) };\n}\n\n/**\n * Shader implementation connected to a material (Arnold, OSL / Standard Surface, Stingray PBS): the RenderAPI names\n * the flavour and the binding table maps shader semantics to material property names.\n */\nfunction extractShaderInfo(materialId: number, objectMap: FBXObjectMap): { renderApi: string; bindings: Map<string, string[]> } | undefined {\n    // The material is connected as a child of its Implementation (Material -> Implementation), so look at parents.\n    const implementations = objectMap.connections\n        .filter((conn) => conn.type === \"OO\" && conn.childId === materialId && objectMap.objects.get(conn.parentId)?.name === \"Implementation\")\n        .map((conn) => ({ id: conn.parentId, node: objectMap.objects.get(conn.parentId)! }));\n    if (implementations.length === 0) {\n        return undefined;\n    }\n    const impl = implementations[0];\n    const renderApi = getPropertyEntries(impl.node).find((e) => e.name === \"RenderAPI\")?.values[0];\n    const bindings = new Map<string, string[]>();\n    const add = (shaderProp: string, materialProp: string) => {\n        const list = bindings.get(shaderProp);\n        if (list) {\n            list.push(materialProp);\n        } else {\n            bindings.set(shaderProp, [materialProp]);\n        }\n    };\n    for (const table of getChildren(objectMap, impl.id, \"BindingTable\")) {\n        for (const entry of table.node.children) {\n            if (entry.name !== \"Entry\") {\n                continue;\n            }\n            const src = getPropertyValue<string>(entry, 0);\n            const srcType = getPropertyValue<string>(entry, 1);\n            const dst = getPropertyValue<string>(entry, 2);\n            const dstType = getPropertyValue<string>(entry, 3);\n            if (typeof src !== \"string\" || typeof dst !== \"string\") {\n                continue;\n            }\n            if (srcType === \"FbxPropertyEntry\" && dstType === \"FbxSemanticEntry\") {\n                add(dst, src);\n            } else if (srcType === \"FbxSemanticEntry\" && dstType === \"FbxPropertyEntry\") {\n                add(src, dst);\n            }\n        }\n    }\n    return { renderApi: typeof renderApi === \"string\" ? renderApi : \"\", bindings };\n}\n\nfunction extractMaterialProperties(materialNode: FBXNode, template?: FBXPropertyTemplate): FBXMaterialProperties {\n    const props: FBXMaterialProperties = {};\n    props.diffuseColor = getColorProperty(materialNode, template, \"DiffuseColor\") ?? getColorProperty(materialNode, template, \"Diffuse\");\n    props.diffuseFactor = getNumberProperty(materialNode, template, \"DiffuseFactor\");\n    props.ambientColor = getColorProperty(materialNode, template, \"AmbientColor\") ?? getColorProperty(materialNode, template, \"Ambient\");\n    props.ambientFactor = getNumberProperty(materialNode, template, \"AmbientFactor\");\n    props.specularColor = getColorProperty(materialNode, template, \"SpecularColor\") ?? getColorProperty(materialNode, template, \"Specular\");\n    props.specularFactor = getNumberProperty(materialNode, template, \"SpecularFactor\");\n    props.shininess = getNumberProperty(materialNode, template, \"Shininess\") ?? getNumberProperty(materialNode, template, \"ShininessExponent\");\n    props.emissiveColor = getColorProperty(materialNode, template, \"EmissiveColor\") ?? getColorProperty(materialNode, template, \"Emissive\");\n    props.emissiveFactor = getNumberProperty(materialNode, template, \"EmissiveFactor\");\n    props.opacity = getNumberProperty(materialNode, template, \"Opacity\");\n    props.transparencyFactor = getNumberProperty(materialNode, template, \"TransparencyFactor\");\n\n    return props;\n}\n\nfunction extractTextures(materialId: number, objectMap: FBXObjectMap, template?: FBXPropertyTemplate): FBXTextureRef[] {\n    const textures: FBXTextureRef[] = [];\n    const textureChildren = getChildren(objectMap, materialId, \"Texture\");\n\n    for (const { id, node, propertyName } of textureChildren) {\n        textures.push(extractTextureRef(id, node, propertyName, objectMap, template));\n    }\n\n    // LayeredTexture: several textures blended into one slot. Babylon has no layer blending, so the first layer\n    // stands in for the stack; the layer count is recorded on the ref for diagnostics.\n    for (const { id: layeredId, propertyName } of getChildren(objectMap, materialId, \"LayeredTexture\")) {\n        const layers = getChildren(objectMap, layeredId, \"Texture\");\n        if (layers.length === 0) {\n            continue;\n        }\n        const ref = extractTextureRef(layers[0].id, layers[0].node, propertyName, objectMap, template);\n        ref.layeredTextureId = layeredId;\n        textures.push(ref);\n    }\n\n    return textures;\n}\n\nexport function extractTextureRef(id: number, node: FBXNode, propertyName: string | undefined, objectMap: FBXObjectMap, template?: FBXPropertyTemplate): FBXTextureRef {\n    {\n        const fileNameNode = findChildByName(node, \"FileName\");\n        const relFileNameNode = findChildByName(node, \"RelativeFilename\");\n\n        const fileName = fileNameNode ? (getPropertyValue<string>(fileNameNode, 0) ?? \"\") : \"\";\n        const relativeFileName = relFileNameNode ? (getPropertyValue<string>(relFileNameNode, 0) ?? \"\") : \"\";\n\n        // Extract UV transform properties\n        let uvTranslation: [number, number] | undefined;\n        let uvScaling: [number, number] | undefined;\n        const uvRotation = getNumberProperty(node, template, \"UVRotation\") ?? getNumberProperty(node, template, \"Rotation\");\n        let uvSetName: string | undefined;\n        uvTranslation = getTextureVector2(node, template, \"UVTranslation\") ?? getTextureVector2(node, template, \"Translation\");\n        uvScaling = getTextureVector2(node, template, \"UVScaling\") ?? getTextureVector2(node, template, \"Scaling\");\n        const uvSet = resolvePropertyValue<string>(node, template, \"UVSet\");\n        if (uvSet && uvSet.length > 0) {\n            uvSetName = uvSet;\n        }\n        uvTranslation ??= getNumberPairChild(node, \"ModelUVTranslation\");\n        uvScaling ??= getNumberPairChild(node, \"ModelUVScaling\");\n        const wrapU = getNumberProperty(node, template, \"WrapModeU\");\n        const wrapV = getNumberProperty(node, template, \"WrapModeV\");\n\n        // Check for embedded texture data in connected Video node\n        let embeddedData: Uint8Array | null = null;\n        const videoChildren = getChildren(objectMap, id, \"Video\");\n        for (const { node: videoNode } of videoChildren) {\n            const contentNode = findChildByName(videoNode, \"Content\");\n            if (contentNode && contentNode.properties.length > 0) {\n                const content = contentNode.properties[0].value;\n                if (content instanceof Uint8Array && content.length > 0) {\n                    embeddedData = content;\n                } else if (content instanceof ArrayBuffer && (content as ArrayBuffer).byteLength > 0) {\n                    embeddedData = new Uint8Array(content as ArrayBuffer);\n                }\n            }\n        }\n\n        return {\n            propertyName: propertyName ?? \"DiffuseColor\",\n            fileName,\n            relativeFileName,\n            id,\n            embeddedData,\n            uvTranslation,\n            uvScaling,\n            uvRotation,\n            uvSetName,\n            wrapU,\n            wrapV,\n        };\n    }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────────\n\nfunction getMaterialTemplate(materialNode: FBXNode, templates: FBXPropertyTemplateMap | undefined): FBXPropertyTemplate | undefined {\n    if (!templates) {\n        return undefined;\n    }\n\n    const shadingModel = findChildByName(materialNode, \"ShadingModel\");\n    const shadingType = shadingModel ? getPropertyValue<string>(shadingModel, 0) : undefined;\n    if (shadingType?.toLowerCase() === \"phong\") {\n        return getPropertyTemplate(templates, \"Material\", \"FbxSurfacePhong\") ?? getPropertyTemplate(templates, \"Material\");\n    }\n    if (shadingType?.toLowerCase() === \"lambert\") {\n        return getPropertyTemplate(templates, \"Material\", \"FbxSurfaceLambert\") ?? getPropertyTemplate(templates, \"Material\");\n    }\n\n    return getPropertyTemplate(templates, \"Material\");\n}\n\nfunction getColorProperty(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string): [number, number, number] | undefined {\n    const values = resolvePropertyValues(node, template, propertyName);\n    if (!values || values.length < 3) {\n        return undefined;\n    }\n    const r = toNumber(values[0]);\n    const g = toNumber(values[1]);\n    const b = toNumber(values[2]);\n    if (r === undefined || g === undefined || b === undefined) {\n        return undefined;\n    }\n    return [r, g, b];\n}\n\nfunction getNumberProperty(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string): number | undefined {\n    return toNumber(resolvePropertyValue(node, template, propertyName));\n}\n\nfunction getTextureVector2(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string): [number, number] | undefined {\n    const values = resolvePropertyValues(node, template, propertyName);\n    if (!values) {\n        return undefined;\n    }\n    const u = toNumber(values[0]);\n    const v = toNumber(values[1]);\n    return u !== undefined && v !== undefined ? [u, v] : undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n    if (typeof value === \"number\") {\n        return value;\n    }\n    return undefined;\n}\n\nfunction getNumberPairChild(node: FBXNode, childName: string): [number, number] | undefined {\n    const child = findChildByName(node, childName);\n    if (!child) {\n        return undefined;\n    }\n    const u = toNumber(child.properties[0]?.value);\n    const v = toNumber(child.properties[1]?.value);\n    return u !== undefined && v !== undefined ? [u, v] : undefined;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { extractNodeTransform, type FBXNodeTransformData } from \"./nodeTransform\";\nimport { getPropertyTemplate, type FBXPropertyTemplate, type FBXPropertyTemplateMap } from \"./propertyTemplates\";\nimport { type FBXNode, findChildByName, getPropertyValue, cleanFBXName, getNodeArray } from \"../types/fbxTypes\";\n\nimport { type FBXObjectMap, getChildren } from \"./connections\";\n\nconst MAX_BONE_INFLUENCES = 8;\n\nexport type FBXClusterMode = \"Normalize\" | \"Additive\" | \"TotalOne\" | \"Unknown\";\n\nexport interface FBXSkinDiagnostic {\n    type: \"cluster-mode-runtime-unsupported\" | \"missing-cluster-transform\" | \"missing-cluster-transform-link\" | \"missing-bind-pose-matrix\" | \"associate-model-present\";\n    message: string;\n    boneModelId?: number;\n    boneName?: string;\n    clusterMode?: FBXClusterMode;\n}\n\n/** Represents a single bone (cluster) in the FBX skeleton */\nexport interface FBXBoneData {\n    /** The Model node ID for this bone */\n    modelId: number;\n    /** Bone name (from the Model node) */\n    name: string;\n    /** Index of this bone in the skeleton */\n    index: number;\n    /** Index of the parent bone (-1 for root) */\n    parentIndex: number;\n    /** Whether this bone corresponds to an FBX Cluster with vertex weights */\n    isCluster: boolean;\n    /** Local translation from parent (Lcl Translation) */\n    translation: [number, number, number];\n    /** Local rotation in degrees (Lcl Rotation) */\n    rotation: [number, number, number];\n    /** Pre-rotation in degrees (applied before Lcl Rotation) */\n    preRotation: [number, number, number];\n    /** Post-rotation in degrees (applied after Lcl Rotation, inverted) */\n    postRotation: [number, number, number];\n    /** Rotation pivot point */\n    rotationPivot: [number, number, number];\n    /** Scaling pivot point */\n    scalingPivot: [number, number, number];\n    /** Rotation offset */\n    rotationOffset: [number, number, number];\n    /** Scaling offset */\n    scalingOffset: [number, number, number];\n    /** Local scale (Lcl Scaling) */\n    scale: [number, number, number];\n    /** Rotation order: 0=XYZ, 1=XZY, 2=YZX, 3=YXZ, 4=ZXY, 5=ZYX */\n    rotationOrder: number;\n    /** FBX transform inheritance mode. 0=RrSs, 1=RSrs, 2=Rrs */\n    inheritType: number;\n    /** Cluster skinning mode */\n    clusterMode: FBXClusterMode;\n    /** Bind pose transform matrix (cluster Transform, 4x4) */\n    bindPoseMatrix: Float64Array | null;\n    /** Bone's world transform at bind time (cluster TransformLink, 4x4) */\n    transformLinkMatrix: Float64Array | null;\n    /** Associate model world transform at bind time (cluster TransformAssociateModel, 4x4) */\n    transformAssociateModelMatrix: Float64Array | null;\n    /** Model's absolute matrix from the FBX BindPose, when present */\n    modelBindPoseMatrix: Float64Array | null;\n    /** Recoverable bind/skinning diagnostics for this bone */\n    diagnostics: FBXSkinDiagnostic[];\n}\n\n/** Represents a skin deformer with its clusters */\nexport interface FBXSkinData {\n    /** Skin deformer ID */\n    id: number;\n    /** Geometry ID this skin is attached to */\n    geometryId: number;\n    /** Mesh model world matrix from the FBX BindPose, when present */\n    meshBindPoseMatrix: Float64Array | null;\n    /** Bones in this skeleton */\n    bones: FBXBoneData[];\n    /** Per-vertex bone indices, sorted by descending weight and capped for Babylon skinning */\n    boneIndices: number[][];\n    /** Per-vertex bone weights, matching boneIndices */\n    boneWeights: number[][];\n    /** Recoverable skinning/bind diagnostics */\n    diagnostics: FBXSkinDiagnostic[];\n}\n\n/**\n * Extract all skin deformers from the FBX scene.\n * Returns skin data including bone hierarchy and vertex weights.\n */\n// Template used to resolve bone transform defaults while extractSkins runs (bones are Models).\nlet currentModelTemplate: FBXPropertyTemplate | undefined;\n\nexport function extractSkins(objectMap: FBXObjectMap, propertyTemplates?: FBXPropertyTemplateMap): FBXSkinData[] {\n    currentModelTemplate = propertyTemplates ? (getPropertyTemplate(propertyTemplates, \"Model\", \"FbxNode\") ?? getPropertyTemplate(propertyTemplates, \"Model\")) : undefined;\n    const skins: FBXSkinData[] = [];\n\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"Deformer\" && getPropertyValue<string>(node, 2) === \"Skin\") {\n            const skin = extractSkin(id, node, objectMap);\n            if (skin) {\n                skins.push(skin);\n            }\n        }\n    }\n\n    return skins;\n}\n\nfunction extractSkin(skinId: number, _skinNode: FBXNode, objectMap: FBXObjectMap): FBXSkinData | null {\n    // Find the geometry this skin is attached to\n    // Skin is a child of the geometry in FBX connection graph\n    const skinParent = objectMap.parentOf.get(skinId);\n    if (!skinParent) {\n        return null;\n    }\n\n    const geometryId = skinParent.id;\n    const geometryNode = objectMap.objects.get(geometryId);\n    if (!geometryNode || geometryNode.name !== \"Geometry\") {\n        return null;\n    }\n    const modelParent = objectMap.parentOf.get(geometryId);\n    const modelParentNode = modelParent ? objectMap.objects.get(modelParent.id) : undefined;\n    const meshModelId = modelParentNode?.name === \"Model\" ? modelParent!.id : undefined;\n\n    // Find all clusters (children of this skin)\n    const clusterEntries = getChildren(objectMap, skinId, \"Deformer\");\n    if (clusterEntries.length === 0) {\n        return null;\n    }\n\n    // For each cluster, find the connected bone Model\n    // Connection graph: BoneModel → Cluster (bone is child of cluster)\n    const boneModelMap = new Map<number, { clusterId: number; clusterNode: FBXNode }>();\n    for (const { id: clusterId, node: clusterNode } of clusterEntries) {\n        const subType = getPropertyValue<string>(clusterNode, 2);\n        if (subType !== \"Cluster\") {\n            continue;\n        }\n\n        // The bone Model is a child of the Cluster\n        const boneChildren = getChildren(objectMap, clusterId, \"Model\");\n        if (boneChildren.length > 0) {\n            boneModelMap.set(boneChildren[0].id, { clusterId, clusterNode });\n        }\n    }\n\n    // Build bone hierarchy from Model parent-child relationships. Include\n    // skeleton-like ancestors even when they are not weighted clusters; some\n    // rigs (for example 3ds Max Biped) animate a non-cluster root above the\n    // clustered bones.\n    const bindPoseMatrices = extractBindPoseMatrices(geometryId, objectMap);\n    const skinDiagnostics: FBXSkinDiagnostic[] = [];\n    const bones = buildBoneHierarchy(boneModelMap, bindPoseMatrices, objectMap, skinDiagnostics);\n    if (bones.length === 0) {\n        return null;\n    }\n\n    // Extract per-vertex weights from clusters\n    const { boneIndices, boneWeights } = extractVertexWeights(bones, boneModelMap, objectMap);\n\n    return {\n        id: skinId,\n        geometryId,\n        meshBindPoseMatrix: meshModelId !== undefined ? (bindPoseMatrices.get(meshModelId) ?? null) : null,\n        bones,\n        boneIndices,\n        boneWeights,\n        diagnostics: skinDiagnostics,\n    };\n}\n\n/**\n * Build a flat ordered bone list with parent indices from the FBX Model hierarchy.\n */\nfunction buildBoneHierarchy(\n    boneModelMap: Map<number, { clusterId: number; clusterNode: FBXNode }>,\n    bindPoseMatrices: Map<number, Float64Array>,\n    objectMap: FBXObjectMap,\n    skinDiagnostics: FBXSkinDiagnostic[]\n): FBXBoneData[] {\n    const bones: FBXBoneData[] = [];\n    const visited = new Set<number>();\n    const skeletonModelIds = collectSkeletonModelIds(boneModelMap, objectMap);\n    const parentByModelId = buildSkeletonParentMap(skeletonModelIds, objectMap);\n    const childrenByModelId = buildSkeletonChildrenMap(skeletonModelIds, parentByModelId);\n\n    const rootBoneIds = Array.from(skeletonModelIds).filter((modelId) => !parentByModelId.has(modelId));\n\n    // BFS to build ordered list\n    const queue: { modelId: number; parentIndex: number }[] = rootBoneIds.map((id) => ({\n        modelId: id,\n        parentIndex: -1,\n    }));\n\n    while (queue.length > 0) {\n        const { modelId, parentIndex } = queue.shift()!;\n        if (visited.has(modelId)) {\n            continue;\n        }\n        visited.add(modelId);\n\n        const modelNode = objectMap.objects.get(modelId);\n        if (!modelNode) {\n            continue;\n        }\n\n        const boneIndex = bones.length;\n\n        const clusterInfo = boneModelMap.get(modelId);\n        const transform = extractBoneTransform(modelNode);\n        const { bindPoseMatrix, transformLinkMatrix, transformAssociateModelMatrix, clusterMode } = clusterInfo\n            ? extractClusterMatrices(clusterInfo.clusterNode)\n            : { bindPoseMatrix: null, transformLinkMatrix: null, transformAssociateModelMatrix: null, clusterMode: \"Unknown\" as const };\n        const diagnostics = createBoneDiagnostics(\n            modelId,\n            cleanFBXName(getPropertyValue<string>(modelNode, 1) ?? `Bone${boneIndex}`),\n            clusterInfo !== undefined,\n            clusterMode,\n            bindPoseMatrix,\n            transformLinkMatrix,\n            transformAssociateModelMatrix,\n            bindPoseMatrices.get(modelId) ?? null\n        );\n        skinDiagnostics.push(...diagnostics);\n\n        bones.push({\n            modelId,\n            name: cleanFBXName(getPropertyValue<string>(modelNode, 1) ?? `Bone${boneIndex}`),\n            index: boneIndex,\n            parentIndex,\n            isCluster: clusterInfo !== undefined,\n            translation: transform.translation,\n            rotation: transform.rotation,\n            preRotation: transform.preRotation,\n            postRotation: transform.postRotation,\n            rotationPivot: transform.rotationPivot,\n            scalingPivot: transform.scalingPivot,\n            rotationOffset: transform.rotationOffset,\n            scalingOffset: transform.scalingOffset,\n            scale: transform.scale,\n            rotationOrder: transform.rotationOrder,\n            inheritType: transform.inheritType,\n            clusterMode,\n            bindPoseMatrix,\n            transformLinkMatrix,\n            transformAssociateModelMatrix,\n            modelBindPoseMatrix: bindPoseMatrices.get(modelId) ?? null,\n            diagnostics,\n        });\n\n        for (const childId of childrenByModelId.get(modelId) ?? []) {\n            if (!visited.has(childId)) {\n                queue.push({ modelId: childId, parentIndex: boneIndex });\n            }\n        }\n    }\n\n    return bones;\n}\n\nfunction extractBindPoseMatrices(geometryId: number, objectMap: FBXObjectMap): Map<number, Float64Array> {\n    const modelParent = objectMap.parentOf.get(geometryId);\n    const modelParentNode = modelParent ? objectMap.objects.get(modelParent.id) : undefined;\n    const modelId = modelParentNode?.name === \"Model\" ? modelParent!.id : undefined;\n    if (modelId === undefined) {\n        return new Map();\n    }\n\n    for (const [, poseNode] of Array.from(objectMap.objects)) {\n        if (poseNode.name !== \"Pose\" || getPropertyValue<string>(poseNode, 2) !== \"BindPose\") {\n            continue;\n        }\n\n        const matrices = new Map<number, Float64Array>();\n        for (const poseChild of poseNode.children) {\n            if (poseChild.name !== \"PoseNode\") {\n                continue;\n            }\n\n            const nodeChild = findChildByName(poseChild, \"Node\");\n            const matrixChild = findChildByName(poseChild, \"Matrix\");\n            const nodeId = nodeChild?.properties[0]?.value;\n            const matrixValue = getNodeArray(matrixChild);\n            if (typeof nodeId !== \"number\") {\n                continue;\n            }\n\n            const matrix = toFloat64Array(matrixValue);\n            if (matrix?.length === 16) {\n                matrices.set(nodeId, matrix);\n            }\n        }\n\n        if (matrices.has(modelId)) {\n            return matrices;\n        }\n    }\n\n    return new Map();\n}\n\nfunction buildSkeletonChildrenMap(skeletonModelIds: Set<number>, parentByModelId: Map<number, number>): Map<number, number[]> {\n    const childrenByModelId = new Map<number, number[]>();\n\n    for (const modelId of Array.from(skeletonModelIds)) {\n        const parentId = parentByModelId.get(modelId);\n        if (parentId === undefined) {\n            continue;\n        }\n\n        if (!childrenByModelId.has(parentId)) {\n            childrenByModelId.set(parentId, []);\n        }\n        childrenByModelId.get(parentId)!.push(modelId);\n    }\n\n    return childrenByModelId;\n}\n\nfunction collectSkeletonModelIds(boneModelMap: Map<number, { clusterId: number; clusterNode: FBXNode }>, objectMap: FBXObjectMap): Set<number> {\n    const skeletonModelIds = new Set<number>(Array.from(boneModelMap.keys()));\n\n    for (const modelId of Array.from(boneModelMap.keys())) {\n        let parentId = findModelParentId(modelId, objectMap);\n        while (parentId !== undefined) {\n            const parentNode = objectMap.objects.get(parentId);\n            if (!parentNode || parentNode.name !== \"Model\") {\n                break;\n            }\n\n            skeletonModelIds.add(parentId);\n            parentId = findModelParentId(parentId, objectMap);\n        }\n    }\n\n    return skeletonModelIds;\n}\n\nfunction buildSkeletonParentMap(skeletonModelIds: Set<number>, objectMap: FBXObjectMap): Map<number, number> {\n    const parentByModelId = new Map<number, number>();\n\n    for (const modelId of Array.from(skeletonModelIds)) {\n        let parentId = findModelParentId(modelId, objectMap);\n        while (parentId !== undefined) {\n            if (skeletonModelIds.has(parentId)) {\n                parentByModelId.set(modelId, parentId);\n                break;\n            }\n            parentId = findModelParentId(parentId, objectMap);\n        }\n    }\n\n    return parentByModelId;\n}\n\nfunction findModelParentId(modelId: number, objectMap: FBXObjectMap): number | undefined {\n    const parentConnection = objectMap.connections.find((conn) => conn.type === \"OO\" && conn.childId === modelId && objectMap.objects.get(conn.parentId)?.name === \"Model\");\n    return parentConnection?.parentId;\n}\n\nexport function isSkeletonModel(modelNode: FBXNode): boolean {\n    const subType = getPropertyValue<string>(modelNode, 2);\n    return subType === \"Root\" || subType === \"LimbNode\";\n}\n\nexport function extractBoneTransform(modelNode: FBXNode, template?: FBXPropertyTemplate): FBXNodeTransformData {\n    return extractNodeTransform(modelNode, template ?? currentModelTemplate);\n}\n\nfunction extractClusterMatrices(clusterNode: FBXNode): {\n    bindPoseMatrix: Float64Array | null;\n    transformLinkMatrix: Float64Array | null;\n    transformAssociateModelMatrix: Float64Array | null;\n    clusterMode: FBXClusterMode;\n} {\n    let bindPoseMatrix: Float64Array | null = null;\n    let transformLinkMatrix: Float64Array | null = null;\n    let transformAssociateModelMatrix: Float64Array | null = null;\n    let clusterMode: FBXClusterMode = \"Normalize\";\n\n    const transformNode = findChildByName(clusterNode, \"Transform\");\n    if (transformNode && transformNode.properties[0]) {\n        const val = getNodeArray(transformNode);\n        if (val instanceof Float64Array && val.length === 16) {\n            bindPoseMatrix = val;\n        } else if (val instanceof Float32Array && val.length === 16) {\n            bindPoseMatrix = new Float64Array(val);\n        }\n    }\n\n    const transformLinkNode = findChildByName(clusterNode, \"TransformLink\");\n    if (transformLinkNode && transformLinkNode.properties[0]) {\n        const val = getNodeArray(transformLinkNode);\n        if (val instanceof Float64Array && val.length === 16) {\n            transformLinkMatrix = val;\n        } else if (val instanceof Float32Array && val.length === 16) {\n            transformLinkMatrix = new Float64Array(val);\n        }\n    }\n\n    const transformAssociateModelNode = findChildByName(clusterNode, \"TransformAssociateModel\");\n    if (transformAssociateModelNode && transformAssociateModelNode.properties[0]) {\n        const val = getNodeArray(transformAssociateModelNode);\n        if (val instanceof Float64Array && val.length === 16) {\n            transformAssociateModelMatrix = val;\n        } else if (val instanceof Float32Array && val.length === 16) {\n            transformAssociateModelMatrix = new Float64Array(val);\n        }\n    }\n\n    const modeNode = findChildByName(clusterNode, \"Mode\");\n    const mode = modeNode ? getPropertyValue<string>(modeNode, 0) : undefined;\n    if (mode === \"Normalize\" || mode === \"Additive\" || mode === \"TotalOne\") {\n        clusterMode = mode;\n    } else if (mode) {\n        clusterMode = \"Unknown\";\n    }\n\n    return { bindPoseMatrix, transformLinkMatrix, transformAssociateModelMatrix, clusterMode };\n}\n\nfunction createBoneDiagnostics(\n    modelId: number,\n    boneName: string,\n    isCluster: boolean,\n    clusterMode: FBXClusterMode,\n    bindPoseMatrix: Float64Array | null,\n    transformLinkMatrix: Float64Array | null,\n    transformAssociateModelMatrix: Float64Array | null,\n    modelBindPoseMatrix: Float64Array | null\n): FBXSkinDiagnostic[] {\n    if (!isCluster) {\n        return [];\n    }\n\n    const diagnostics: FBXSkinDiagnostic[] = [];\n    if (clusterMode === \"Additive\" || clusterMode === \"TotalOne\") {\n        diagnostics.push({\n            type: \"cluster-mode-runtime-unsupported\",\n            message: `Cluster mode '${clusterMode}' is preserved but not applied by Babylon linear blend skinning.`,\n            boneModelId: modelId,\n            boneName,\n            clusterMode,\n        });\n    }\n    if (!bindPoseMatrix) {\n        diagnostics.push({\n            type: \"missing-cluster-transform\",\n            message: \"Cluster is missing Transform matrix; falling back to rest/bind-pose data.\",\n            boneModelId: modelId,\n            boneName,\n            clusterMode,\n        });\n    }\n    if (!transformLinkMatrix) {\n        diagnostics.push({\n            type: \"missing-cluster-transform-link\",\n            message: \"Cluster is missing TransformLink matrix; falling back to model bind pose or rest transform.\",\n            boneModelId: modelId,\n            boneName,\n            clusterMode,\n        });\n    }\n    if (!modelBindPoseMatrix) {\n        diagnostics.push({\n            type: \"missing-bind-pose-matrix\",\n            message: \"No BindPose matrix was found for this bone model.\",\n            boneModelId: modelId,\n            boneName,\n            clusterMode,\n        });\n    }\n    if (transformAssociateModelMatrix) {\n        diagnostics.push({\n            type: \"associate-model-present\",\n            message: \"TransformAssociateModel is preserved for future associate-model skinning semantics.\",\n            boneModelId: modelId,\n            boneName,\n            clusterMode,\n        });\n    }\n\n    return diagnostics;\n}\n\n/**\n * Extract per-vertex bone indices and weights from cluster data.\n * Returns arrays indexed by control point index.\n */\nfunction extractVertexWeights(\n    bones: FBXBoneData[],\n    boneModelMap: Map<number, { clusterId: number; clusterNode: FBXNode }>,\n    objectMap: FBXObjectMap\n): { boneIndices: number[][]; boneWeights: number[][] } {\n    // We need to find the max vertex index to size our arrays\n    let maxVertexIndex = 0;\n\n    // First pass: find max vertex index\n    for (const bone of bones) {\n        const clusterInfo = boneModelMap.get(bone.modelId);\n        if (!clusterInfo) {\n            continue;\n        }\n\n        const indexesNode = findChildByName(clusterInfo.clusterNode, \"Indexes\");\n        if (!indexesNode) {\n            continue;\n        }\n\n        const indexes = toInt32Array(getNodeArray(indexesNode));\n        if (!indexes) {\n            continue;\n        }\n\n        for (let i = 0; i < indexes.length; i++) {\n            if (indexes[i] > maxVertexIndex) {\n                maxVertexIndex = indexes[i];\n            }\n        }\n    }\n\n    // Initialize arrays\n    const vertexCount = maxVertexIndex + 1;\n    const boneIndices: number[][] = new Array(vertexCount);\n    const boneWeights: number[][] = new Array(vertexCount);\n    for (let i = 0; i < vertexCount; i++) {\n        boneIndices[i] = [];\n        boneWeights[i] = [];\n    }\n\n    // Second pass: collect influences\n    for (const bone of bones) {\n        const clusterInfo = boneModelMap.get(bone.modelId);\n        if (!clusterInfo) {\n            continue;\n        }\n\n        const indexesNode = findChildByName(clusterInfo.clusterNode, \"Indexes\");\n        const weightsNode = findChildByName(clusterInfo.clusterNode, \"Weights\");\n        if (!indexesNode || !weightsNode) {\n            continue;\n        }\n\n        const indexes = toInt32Array(getNodeArray(indexesNode));\n        const weights = toFloat64Array(getNodeArray(weightsNode));\n        if (!indexes || !weights) {\n            continue;\n        }\n\n        for (let i = 0; i < indexes.length; i++) {\n            const vertIdx = indexes[i];\n            boneIndices[vertIdx].push(bone.index);\n            boneWeights[vertIdx].push(weights[i]);\n        }\n    }\n\n    // Sort by weight descending and cap to Babylon's primary + extra influence buffers.\n    for (let i = 0; i < vertexCount; i++) {\n        if (boneIndices[i].length === 0) {\n            continue;\n        }\n\n        const pairs = boneIndices[i].map((bi, idx) => ({\n            index: bi,\n            weight: boneWeights[i][idx],\n        }));\n        pairs.sort((a, b) => b.weight - a.weight);\n        const cappedPairs = pairs.slice(0, MAX_BONE_INFLUENCES);\n        boneIndices[i] = cappedPairs.map((p) => p.index);\n        boneWeights[i] = cappedPairs.map((p) => p.weight);\n    }\n\n    // Normalize weights to sum to 1.0\n    for (let i = 0; i < vertexCount; i++) {\n        const sum = boneWeights[i].reduce((a, b) => a + b, 0);\n        if (sum > 0) {\n            for (let j = 0; j < boneWeights[i].length; j++) {\n                boneWeights[i][j] /= sum;\n            }\n        }\n    }\n\n    return { boneIndices, boneWeights };\n}\n\n// ── Utilities ──────────────────────────────────────────────────────────────────\n\nfunction toInt32Array(value: unknown): Int32Array | null {\n    if (value instanceof Int32Array) {\n        return value;\n    }\n    if (value instanceof Float64Array) {\n        const result = new Int32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = Math.round(value[i]);\n        }\n        return result;\n    }\n    return null;\n}\n\nfunction toFloat64Array(value: unknown): Float64Array | null {\n    if (value instanceof Float64Array) {\n        return value;\n    }\n    if (value instanceof Float32Array) {\n        return new Float64Array(value);\n    }\n    return null;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXObjectMap } from \"./connections\";\nimport { type FBXBoneData, type FBXSkinData, extractBoneTransform, isSkeletonModel } from \"./skeleton\";\n\nimport { cleanFBXName, getPropertyValue } from \"../types/fbxTypes\";\n\nexport type FBXRigBoneData = FBXBoneData;\n\nexport interface FBXSkinBindingData {\n    skinId: number;\n    geometryId: number;\n    rigId: string;\n    skinBoneIndexToRigBoneIndex: number[];\n    clusterModelIds: Set<number>;\n}\n\nexport interface FBXRigData {\n    id: string;\n    rootModelIds: number[];\n    bones: FBXRigBoneData[];\n    modelIdToBoneIndex: Map<number, number>;\n    clusterModelIds: Set<number>;\n    skinBindings: FBXSkinBindingData[];\n    warnings: string[];\n}\n\nexport function resolveRigs(objectMap: FBXObjectMap, skins: FBXSkinData[]): FBXRigData[] {\n    if (skins.length === 0) {\n        return [];\n    }\n\n    const groupByRoot = new Map<number, FBXSkinData[]>();\n\n    for (const skin of skins) {\n        const clusterModelIds = skin.bones.filter((bone) => bone.isCluster).map((bone) => bone.modelId);\n        if (clusterModelIds.length === 0) {\n            continue;\n        }\n\n        const rootModelId = findRigGroupingRoot(clusterModelIds, objectMap);\n        const group = groupByRoot.get(rootModelId);\n        if (group) {\n            group.push(skin);\n        } else {\n            groupByRoot.set(rootModelId, [skin]);\n        }\n    }\n\n    return Array.from(groupByRoot.entries())\n        .sort(([a], [b]) => compareNumber(a, b))\n        .map(([rootModelId, groupSkins]) => buildRig(rootModelId, groupSkins, objectMap));\n}\n\nfunction buildRig(rootModelId: number, skins: FBXSkinData[], objectMap: FBXObjectMap): FBXRigData {\n    const clusterModelIds = new Set<number>();\n    const rigModelIds = new Set<number>();\n    const sourceBonesByModelId = new Map<number, FBXBoneData[]>();\n    const sourceOrderByModelId = new Map<number, number>();\n\n    for (const skin of skins) {\n        for (const bone of skin.bones) {\n            if (!sourceOrderByModelId.has(bone.modelId)) {\n                sourceOrderByModelId.set(bone.modelId, sourceOrderByModelId.size);\n            }\n\n            let sources = sourceBonesByModelId.get(bone.modelId);\n            if (!sources) {\n                sources = [];\n                sourceBonesByModelId.set(bone.modelId, sources);\n            }\n            sources.push(bone);\n\n            if (!bone.isCluster) {\n                continue;\n            }\n\n            clusterModelIds.add(bone.modelId);\n            for (const ancestorId of getModelAncestorChain(bone.modelId, objectMap)) {\n                rigModelIds.add(ancestorId);\n            }\n        }\n    }\n\n    // Skeleton models below the clusters (leaf joints, \"_end\" effectors) are part of the same rig even without\n    // clusters of their own; keeping them as bones lets inherit-mode handling and animation stay uniform.\n    const pending = Array.from(rigModelIds);\n    while (pending.length > 0) {\n        const parentId = pending.pop()!;\n        for (const conn of objectMap.connections) {\n            if (conn.type !== \"OO\" || conn.parentId !== parentId || rigModelIds.has(conn.childId)) {\n                continue;\n            }\n            const child = objectMap.objects.get(conn.childId);\n            if (child && child.name === \"Model\" && isSkeletonModel(child)) {\n                rigModelIds.add(conn.childId);\n                pending.push(conn.childId);\n            }\n        }\n    }\n\n    const warnings = collectTransformLinkWarnings(sourceBonesByModelId);\n    const preferredBoneByModelId = new Map<number, FBXBoneData>();\n    for (const [modelId, sources] of Array.from(sourceBonesByModelId)) {\n        preferredBoneByModelId.set(modelId, choosePreferredBoneSource(sources));\n    }\n\n    const parentByModelId = buildParentMap(rigModelIds, objectMap);\n    const orderedModelIds = orderParentsBeforeChildren(rigModelIds, parentByModelId, sourceOrderByModelId);\n    const bones: FBXRigBoneData[] = [];\n    const modelIdToBoneIndex = new Map<number, number>();\n\n    for (const modelId of orderedModelIds) {\n        const sourceBone = preferredBoneByModelId.get(modelId) ?? createFallbackBone(modelId, objectMap);\n        if (!sourceBone) {\n            continue;\n        }\n\n        const parentModelId = parentByModelId.get(modelId);\n        const parentIndex = parentModelId === undefined ? -1 : (modelIdToBoneIndex.get(parentModelId) ?? -1);\n        const index = bones.length;\n        const bone: FBXRigBoneData = {\n            ...sourceBone,\n            index,\n            parentIndex,\n            isCluster: clusterModelIds.has(modelId),\n        };\n        bones.push(bone);\n        modelIdToBoneIndex.set(modelId, index);\n    }\n\n    const skinBindings = skins.map((skin) => buildSkinBinding(skin, `rig_${rootModelId.toString()}`, modelIdToBoneIndex));\n\n    return {\n        id: `rig_${rootModelId.toString()}`,\n        rootModelIds: bones.filter((bone) => bone.parentIndex < 0).map((bone) => bone.modelId),\n        bones,\n        modelIdToBoneIndex,\n        clusterModelIds,\n        skinBindings,\n        warnings,\n    };\n}\n\nfunction buildSkinBinding(skin: FBXSkinData, rigId: string, modelIdToBoneIndex: Map<number, number>): FBXSkinBindingData {\n    const skinBoneIndexToRigBoneIndex = skin.bones.map((bone) => {\n        const rigBoneIndex = modelIdToBoneIndex.get(bone.modelId);\n        if (rigBoneIndex === undefined && bone.isCluster) {\n            throw new Error(`FBX rig resolver: cluster bone ${bone.name} is missing from resolved rig ${rigId}`);\n        }\n        return rigBoneIndex ?? -1;\n    });\n\n    return {\n        skinId: skin.id,\n        geometryId: skin.geometryId,\n        rigId,\n        skinBoneIndexToRigBoneIndex,\n        clusterModelIds: new Set(skin.bones.filter((bone) => bone.isCluster).map((bone) => bone.modelId)),\n    };\n}\n\nfunction findRigGroupingRoot(clusterModelIds: number[], objectMap: FBXObjectMap): number {\n    const lca = findLowestCommonAncestor(clusterModelIds, objectMap) ?? clusterModelIds[0];\n    let root = lca;\n    let parentId = findModelParentId(root, objectMap);\n\n    while (parentId !== undefined) {\n        const parentNode = objectMap.objects.get(parentId);\n        if (!parentNode || parentNode.name !== \"Model\" || !isSkeletonModel(parentNode)) {\n            break;\n        }\n\n        root = parentId;\n        parentId = findModelParentId(parentId, objectMap);\n    }\n\n    return root;\n}\n\nfunction findLowestCommonAncestor(modelIds: number[], objectMap: FBXObjectMap): number | undefined {\n    if (modelIds.length === 0) {\n        return undefined;\n    }\n\n    const chains = modelIds.map((modelId) => getModelAncestorChain(modelId, objectMap));\n    const common = new Set(chains[0]);\n    for (const chain of chains.slice(1)) {\n        for (const modelId of Array.from(common)) {\n            if (!chain.includes(modelId)) {\n                common.delete(modelId);\n            }\n        }\n    }\n\n    return chains[0].find((modelId) => common.has(modelId));\n}\n\nfunction getModelAncestorChain(modelId: number, objectMap: FBXObjectMap): number[] {\n    const chain: number[] = [];\n    let currentId: number | undefined = modelId;\n\n    while (currentId !== undefined) {\n        const node = objectMap.objects.get(currentId);\n        if (!node || node.name !== \"Model\") {\n            break;\n        }\n\n        chain.push(currentId);\n        currentId = findModelParentId(currentId, objectMap);\n    }\n\n    return chain;\n}\n\nfunction buildParentMap(modelIds: Set<number>, objectMap: FBXObjectMap): Map<number, number> {\n    const parentByModelId = new Map<number, number>();\n\n    for (const modelId of Array.from(modelIds)) {\n        const parentId = findModelParentId(modelId, objectMap);\n        if (parentId !== undefined && modelIds.has(parentId)) {\n            parentByModelId.set(modelId, parentId);\n        }\n    }\n\n    return parentByModelId;\n}\n\nfunction orderParentsBeforeChildren(modelIds: Set<number>, parentByModelId: Map<number, number>, sourceOrderByModelId: Map<number, number>): number[] {\n    const childrenByModelId = new Map<number, number[]>();\n    for (const modelId of Array.from(modelIds)) {\n        const parentId = parentByModelId.get(modelId);\n        if (parentId === undefined) {\n            continue;\n        }\n\n        let children = childrenByModelId.get(parentId);\n        if (!children) {\n            children = [];\n            childrenByModelId.set(parentId, children);\n        }\n        children.push(modelId);\n    }\n\n    for (const children of Array.from(childrenByModelId.values())) {\n        children.sort((a, b) => compareSourceOrder(a, b, sourceOrderByModelId));\n    }\n\n    const roots = Array.from(modelIds)\n        .filter((modelId) => !parentByModelId.has(modelId))\n        .sort((a, b) => compareSourceOrder(a, b, sourceOrderByModelId));\n    const ordered: number[] = [];\n    const queue = [...roots];\n\n    while (queue.length > 0) {\n        const modelId = queue.shift()!;\n        ordered.push(modelId);\n        queue.push(...(childrenByModelId.get(modelId) ?? []));\n    }\n\n    return ordered;\n}\n\nfunction findModelParentId(modelId: number, objectMap: FBXObjectMap): number | undefined {\n    const parentConnection = objectMap.connections.find((conn) => conn.type === \"OO\" && conn.childId === modelId && objectMap.objects.get(conn.parentId)?.name === \"Model\");\n    return parentConnection?.parentId;\n}\n\nfunction choosePreferredBoneSource(sources: FBXBoneData[]): FBXBoneData {\n    return (\n        sources.find((bone) => bone.isCluster && bone.transformLinkMatrix) ??\n        sources.find((bone) => bone.isCluster) ??\n        sources.find((bone) => bone.modelBindPoseMatrix) ??\n        sources[0]\n    );\n}\n\nfunction collectTransformLinkWarnings(sourceBonesByModelId: Map<number, FBXBoneData[]>): string[] {\n    const warnings: string[] = [];\n\n    for (const [modelId, sources] of Array.from(sourceBonesByModelId)) {\n        const matrices = sources.filter((bone) => bone.isCluster && bone.transformLinkMatrix).map((bone) => bone.transformLinkMatrix!);\n        if (matrices.length < 2) {\n            continue;\n        }\n\n        const first = matrices[0];\n        if (matrices.some((matrix) => !areMatricesEquivalent(first, matrix, 1e-5))) {\n            warnings.push(`Model ${modelId.toString()} has differing Cluster.TransformLink matrices across skins`);\n        }\n    }\n\n    return warnings;\n}\n\nfunction areMatricesEquivalent(a: Float64Array, b: Float64Array, epsilon: number): boolean {\n    if (a.length !== b.length) {\n        return false;\n    }\n    for (let i = 0; i < a.length; i++) {\n        if (Math.abs(a[i] - b[i]) > epsilon) {\n            return false;\n        }\n    }\n    return true;\n}\n\nfunction createFallbackBone(modelId: number, objectMap: FBXObjectMap): FBXBoneData | null {\n    const modelNode = objectMap.objects.get(modelId);\n    if (!modelNode || modelNode.name !== \"Model\") {\n        return null;\n    }\n\n    const transform = extractBoneTransform(modelNode);\n    return {\n        modelId,\n        name: cleanFBXName(getPropertyValue<string>(modelNode, 1) ?? `Bone${modelId.toString()}`),\n        index: -1,\n        parentIndex: -1,\n        isCluster: false,\n        translation: transform.translation,\n        rotation: transform.rotation,\n        preRotation: transform.preRotation,\n        postRotation: transform.postRotation,\n        rotationPivot: transform.rotationPivot,\n        scalingPivot: transform.scalingPivot,\n        rotationOffset: transform.rotationOffset,\n        scalingOffset: transform.scalingOffset,\n        scale: transform.scale,\n        rotationOrder: transform.rotationOrder,\n        inheritType: transform.inheritType,\n        clusterMode: \"Unknown\",\n        bindPoseMatrix: null,\n        transformLinkMatrix: null,\n        transformAssociateModelMatrix: null,\n        modelBindPoseMatrix: null,\n        diagnostics: [],\n    };\n}\n\nfunction compareNumber(a: number, b: number): number {\n    return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction compareSourceOrder(a: number, b: number, sourceOrderByModelId: Map<number, number>): number {\n    const aOrder = sourceOrderByModelId.get(a) ?? Number.MAX_SAFE_INTEGER;\n    const bOrder = sourceOrderByModelId.get(b) ?? Number.MAX_SAFE_INTEGER;\n    return aOrder - bOrder || compareNumber(a, b);\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * FBX animation curve model and evaluator.\n *\n * Keys carry cubic Bezier tangents expressed the way the FBX SDK stores them: a left and right tangent with a time\n * extent (dx, as a fraction of the segment scaled by the tangent weight) and a value extent (dy). Linear and constant\n * segments are represented the same way so that a single evaluator handles every case, including the weighted\n * tangents Maya and MotionBuilder write, TCB keys, and the pre/post extrapolation modes.\n */\n\n/** FBX time units: 46186158000 ticks per second */\nexport const FBX_TIME_UNIT = 46186158000;\n\nexport type FBXInterpolationType = \"constant\" | \"linear\" | \"cubic\";\n\nexport type FBXExtrapolationMode = \"constant\" | \"repeat\" | \"mirror\" | \"slope\" | \"repeatRelative\";\n\nexport interface FBXExtrapolation {\n    mode: FBXExtrapolationMode;\n    /** Number of repetitions, or -1 for infinite */\n    repeatCount: number;\n}\n\n/** A single keyframe */\nexport interface FBXKeyframe {\n    /** Time in seconds */\n    time: number;\n    /** Value at this keyframe */\n    value: number;\n    /** Interpolation used from this key to the next key */\n    interpolation: FBXInterpolationType;\n    /** Constant interpolation variant */\n    constantMode?: \"standard\" | \"next\";\n    /** Left (incoming) tangent: time extent in seconds and value extent */\n    leftDx: number;\n    leftDy: number;\n    /** Right (outgoing) tangent: time extent in seconds and value extent */\n    rightDx: number;\n    rightDy: number;\n    /** Cubic outgoing slope in value units per second (derived, kept for consumers that export hermite keys) */\n    rightSlope?: number;\n    /** Cubic incoming slope for the next key, in value units per second (derived) */\n    nextLeftSlope?: number;\n}\n\n/** An animation curve (one axis of one property) */\nexport interface FBXCurveData {\n    /** Channel: \"d|X\", \"d|Y\", \"d|Z\" */\n    channel: string;\n    /** Keyframes */\n    keys: FBXKeyframe[];\n    /** True for baked sample curves that should be connected as linear samples */\n    isSampled?: boolean;\n    preExtrapolation?: FBXExtrapolation;\n    postExtrapolation?: FBXExtrapolation;\n}\n\n// Key attribute flags (KeyAttrFlags), as written by the FBX SDK.\nconst KEY_INTERPOLATION_CONSTANT = 0x2;\nconst KEY_INTERPOLATION_CUBIC = 0x8;\nconst KEY_TANGENT_TCB = 0x200;\nconst KEY_TANGENT_USER = 0x400;\nconst KEY_TANGENT_BROKEN = 0x800;\nconst KEY_CONSTANT_NEXT = 0x100;\nconst KEY_CLAMP = 0x1000;\nconst KEY_TIME_INDEPENDENT = 0x2000;\nconst KEY_CLAMP_PROGRESSIVE = 0x4000;\nconst KEY_WEIGHTED_RIGHT = 0x1000000;\nconst KEY_WEIGHTED_NEXT_LEFT = 0x2000000;\n\nconst DEFAULT_WEIGHT = 0.333333;\nconst KEY_CLAMP_THRESHOLD = 0.00001;\n\n/** Raw key attribute data for one key, after run-length decoding. */\nexport interface FBXKeyAttributes {\n    flags: number;\n    data: [number, number, number, number];\n}\n\n/**\n * Builds keyframes from parallel time/value arrays and their (run-length encoded) attributes, resolving every\n * tangent mode the FBX SDK writes: user, broken, auto (with clamp / progressive clamp / time-independent flags and\n * auto bias), TCB, weighted, linear and constant.\n */\nexport function buildKeyframes(times: ArrayLike<number>, values: ArrayLike<number>, attributes: (index: number) => FBXKeyAttributes): FBXKeyframe[] {\n    const numKeys = Math.min(times.length, values.length);\n    const keys: FBXKeyframe[] = [];\n    if (numKeys === 0) {\n        return keys;\n    }\n\n    let slopeLeft = 0;\n    let weightLeft = DEFAULT_WEIGHT;\n    let prevTime = 0;\n    let nextTime = Number(times[0]) / FBX_TIME_UNIT;\n\n    for (let i = 0; i < numKeys; i++) {\n        const time = nextTime;\n        const value = values[i];\n        if (i + 1 < numKeys) {\n            nextTime = Number(times[i + 1]) / FBX_TIME_UNIT;\n        }\n        const prevValue = i > 0 ? values[i - 1] : value;\n        const nextValue = i + 1 < numKeys ? values[i + 1] : value;\n\n        const attr = attributes(i);\n        const flags = attr.flags;\n        let slopeRight = attr.data[0];\n        let weightRight = DEFAULT_WEIGHT;\n        let nextSlopeLeft = attr.data[1];\n        let nextWeightLeft = DEFAULT_WEIGHT;\n\n        if ((flags & (KEY_WEIGHTED_RIGHT | KEY_WEIGHTED_NEXT_LEFT)) !== 0) {\n            // Two 0.4 decimal fixed point weights packed into the bit pattern of the third float.\n            const packed = floatToUint32Bits(attr.data[2]);\n            if (flags & KEY_WEIGHTED_RIGHT) {\n                weightRight = (packed & 0xffff) * 0.0001;\n            }\n            if (flags & KEY_WEIGHTED_NEXT_LEFT) {\n                nextWeightLeft = (packed >>> 16) * 0.0001;\n            }\n        }\n\n        let interpolation: FBXInterpolationType;\n        let constantMode: \"standard\" | \"next\" = \"standard\";\n\n        if (flags & KEY_INTERPOLATION_CONSTANT) {\n            interpolation = \"constant\";\n            constantMode = flags & KEY_CONSTANT_NEXT ? \"next\" : \"standard\";\n            weightRight = nextWeightLeft = DEFAULT_WEIGHT;\n            slopeRight = nextSlopeLeft = 0;\n        } else if (flags & KEY_INTERPOLATION_CUBIC) {\n            interpolation = \"cubic\";\n            if (flags & KEY_TANGENT_TCB) {\n                let tcbSlopeLeft = 0;\n                let tcbSlopeRight = 0;\n                let edge = false;\n                if (i > 0 && time > prevTime) {\n                    tcbSlopeLeft = (value - prevValue) / (time - prevTime);\n                } else {\n                    edge = true;\n                }\n                if (i + 1 < numKeys && nextTime > time) {\n                    tcbSlopeRight = (nextValue - value) / (nextTime - time);\n                } else {\n                    edge = true;\n                }\n                const tcb = solveTcb(attr.data[0], attr.data[1], attr.data[2], tcbSlopeLeft, tcbSlopeRight, edge);\n                slopeLeft = tcb.left;\n                slopeRight = tcb.right;\n                nextSlopeLeft = 0;\n                nextWeightLeft = DEFAULT_WEIGHT;\n            } else if (flags & KEY_TANGENT_USER) {\n                // User tangents: slopes are stored explicitly. Unified vs broken makes no difference to evaluation.\n                void KEY_TANGENT_BROKEN;\n            } else {\n                // Auto tangents\n                if (i > 0 && i + 1 < numKeys && time > prevTime && nextTime > time) {\n                    if (Math.abs(slopeLeft + slopeRight) <= 0.0001) {\n                        slopeLeft = slopeRight = solveAutoTangent(prevTime, time, nextTime, prevValue, value, nextValue, weightLeft, weightRight, slopeRight, flags);\n                    } else {\n                        slopeLeft = solveAutoTangent(prevTime, time, nextTime, prevValue, value, nextValue, weightLeft, weightRight, -slopeLeft, flags);\n                        slopeRight = solveAutoTangent(prevTime, time, nextTime, prevValue, value, nextValue, weightLeft, weightRight, slopeRight, flags);\n                    }\n                } else if (i > 0 && time > prevTime) {\n                    slopeLeft = slopeRight = solveAutoTangentOneSided(prevTime, time, prevValue, value, -slopeLeft, flags);\n                } else if (i + 1 < numKeys && nextTime > time) {\n                    slopeLeft = slopeRight = solveAutoTangentOneSided(time, nextTime, value, nextValue, slopeRight, flags);\n                } else {\n                    slopeLeft = slopeRight = 0;\n                }\n            }\n        } else {\n            // Linear or unknown interpolation: tangents match the linear segment with 1/3 weights.\n            interpolation = \"linear\";\n            weightRight = DEFAULT_WEIGHT;\n            nextWeightLeft = DEFAULT_WEIGHT;\n            const deltaTime = nextTime - time;\n            slopeRight = nextSlopeLeft = deltaTime > 0 ? (nextValue - value) / deltaTime : 0;\n        }\n\n        const key: FBXKeyframe = { time, value, interpolation, constantMode, leftDx: 0, leftDy: 0, rightDx: 0, rightDy: 0 };\n        if (time > prevTime) {\n            key.leftDx = weightLeft * (time - prevTime);\n            key.leftDy = key.leftDx * slopeLeft;\n        }\n        if (nextTime > time) {\n            key.rightDx = weightRight * (nextTime - time);\n            key.rightDy = key.rightDx * slopeRight;\n        }\n        key.rightSlope = slopeRight;\n        keys.push(key);\n\n        slopeLeft = nextSlopeLeft;\n        weightLeft = nextWeightLeft;\n        prevTime = time;\n    }\n\n    for (let i = 0; i + 1 < keys.length; i++) {\n        const next = keys[i + 1];\n        keys[i].nextLeftSlope = next.leftDx > 0 ? next.leftDy / next.leftDx : 0;\n    }\n    return keys;\n}\n\nconst f32 = new Float32Array(1);\nconst u32 = new Uint32Array(f32.buffer);\nfunction floatToUint32Bits(v: number): number {\n    f32[0] = v;\n    return u32[0];\n}\n\nfunction solveTcb(tension: number, continuity: number, bias: number, slopeLeft: number, slopeRight: number, edge: boolean): { left: number; right: number } {\n    const factor = edge ? 1 : 0.5;\n    const d00 = factor * (1 - tension) * (1 + bias) * (1 - continuity);\n    const d01 = factor * (1 - tension) * (1 - bias) * (1 + continuity);\n    const d10 = factor * (1 - tension) * (1 + bias) * (1 + continuity);\n    const d11 = factor * (1 - tension) * (1 - bias) * (1 - continuity);\n    return { left: d00 * slopeLeft + d01 * slopeRight, right: d10 * slopeLeft + d11 * slopeRight };\n}\n\n/** Auto tangent as the FBX SDK computes it, including clamping and auto bias. */\nexport function solveAutoTangent(\n    prevTime: number,\n    time: number,\n    nextTime: number,\n    prevValue: number,\n    value: number,\n    nextValue: number,\n    weightLeft: number,\n    weightRight: number,\n    autoBias: number,\n    flags: number\n): number {\n    if (flags & KEY_CLAMP) {\n        if (Math.min(Math.abs(prevValue - value), Math.abs(nextValue - value)) <= KEY_CLAMP_THRESHOLD) {\n            return 0;\n        }\n    }\n\n    let slope = (nextValue - prevValue) / (nextTime - prevTime);\n\n    if ((flags & KEY_TIME_INDEPENDENT) === 0) {\n        const slopeLeft = (value - prevValue) / (time - prevTime);\n        const slopeRight = (nextValue - value) / (nextTime - time);\n        const delta = (time - prevTime) / (nextTime - prevTime);\n        slope = slope * 0.5 + (slopeLeft * (1 - delta) + slopeRight * delta) * 0.5;\n\n        const biasWeight = Math.abs(autoBias) / 100;\n        if (biasWeight > 0.0001) {\n            const biasTarget = autoBias > 0 ? slopeRight : slopeLeft;\n            const biasDelta = biasTarget - slope;\n            slope = slope * (1 - biasWeight) + biasTarget * biasWeight;\n            const absBiasWeight = biasWeight - 5;\n            if (absBiasWeight > 0) {\n                let biasSign = Math.abs(biasDelta) > 0.00001 ? biasDelta : autoBias;\n                biasSign = biasSign > 0 ? 1 : -1;\n                slope += absBiasWeight * absBiasWeight * biasSign * 40;\n            }\n        }\n    }\n\n    if (flags & KEY_CLAMP_PROGRESSIVE) {\n        const slopeSign = slope >= 0 ? 1 : -1;\n        let absSlope = slopeSign * slope;\n        const rangeLeft = weightLeft * (time - prevTime);\n        const rangeRight = weightRight * (nextTime - time);\n        let maxLeft = rangeLeft > 0 ? (slopeSign * (value - prevValue)) / rangeLeft : 0;\n        let maxRight = rangeRight > 0 ? (slopeSign * (nextValue - value)) / rangeRight : 0;\n        if (!(maxLeft > 0)) {\n            maxLeft = 0;\n        }\n        if (!(maxRight > 0)) {\n            maxRight = 0;\n        }\n        absSlope = Math.min(absSlope, maxLeft, maxRight);\n        slope = slopeSign * absSlope;\n    }\n\n    return slope;\n}\n\nfunction solveAutoTangentOneSided(t0: number, t1: number, v0: number, v1: number, autoBias: number, flags: number): number {\n    if (flags & KEY_CLAMP_PROGRESSIVE) {\n        return 0;\n    }\n    if (flags & KEY_CLAMP) {\n        if (Math.abs(v1 - v0) <= KEY_CLAMP_THRESHOLD) {\n            return 0;\n        }\n    }\n    let slope = (v1 - v0) / (t1 - t0);\n    if ((flags & KEY_TIME_INDEPENDENT) === 0) {\n        const absBiasWeight = Math.abs(autoBias) / 100 - 5;\n        if (absBiasWeight > 0) {\n            slope += absBiasWeight * absBiasWeight * (autoBias > 0 ? 1 : -1) * 40;\n        }\n    }\n    return slope;\n}\n\n/** Builds a keyframe list from explicit per-key slopes (legacy Takes and synthetic curves). */\nexport function keyframesFromSlopes(\n    times: number[],\n    values: number[],\n    interpolation: FBXInterpolationType[],\n    constantNext: boolean[],\n    leftSlope: number[],\n    rightSlope: number[],\n    leftWeight?: number[],\n    rightWeight?: number[]\n): FBXKeyframe[] {\n    const keys: FBXKeyframe[] = [];\n    for (let i = 0; i < times.length; i++) {\n        const key: FBXKeyframe = {\n            time: times[i],\n            value: values[i],\n            interpolation: interpolation[i],\n            constantMode: constantNext[i] ? \"next\" : \"standard\",\n            leftDx: 0,\n            leftDy: 0,\n            rightDx: 0,\n            rightDy: 0,\n            rightSlope: rightSlope[i],\n            nextLeftSlope: i + 1 < times.length ? leftSlope[i + 1] : undefined,\n        };\n        if (i > 0 && times[i] > times[i - 1]) {\n            key.leftDx = (leftWeight?.[i] ?? DEFAULT_WEIGHT) * (times[i] - times[i - 1]);\n            key.leftDy = key.leftDx * leftSlope[i];\n        }\n        if (i + 1 < times.length && times[i + 1] > times[i]) {\n            key.rightDx = (rightWeight?.[i] ?? DEFAULT_WEIGHT) * (times[i + 1] - times[i]);\n            key.rightDy = key.rightDx * rightSlope[i];\n        }\n        keys.push(key);\n    }\n    return keys;\n}\n\n/** Reads a `Pre-Extrapolation` / `Post-Extrapolation` block: `Type` is a character code, `Repetition` a count. */\nexport function parseExtrapolation(typeValue: unknown, repetitionValue: unknown): FBXExtrapolation {\n    const code = typeof typeValue === \"string\" ? typeValue.charCodeAt(0) : typeof typeValue === \"number\" ? typeValue : 0;\n    let mode: FBXExtrapolationMode;\n    switch (String.fromCharCode(code)) {\n        case \"A\":\n            mode = \"repeatRelative\";\n            break;\n        case \"K\":\n            mode = \"slope\";\n            break;\n        case \"M\":\n            mode = \"mirror\";\n            break;\n        case \"R\":\n            mode = \"repeat\";\n            break;\n        default:\n            mode = \"constant\";\n    }\n    let repeatCount = typeof repetitionValue === \"number\" ? repetitionValue : -1;\n    if (repeatCount < 0) {\n        repeatCount = -1;\n    }\n    return { mode, repeatCount };\n}\n\nfunction findCubicBezierT(p1: number, p2: number, x0: number): number {\n    const p1_3 = p1 * 3;\n    const p2_3 = p2 * 3;\n    const a = p1_3 - p2_3 + 1;\n    const b = p2_3 - p1_3 - p1_3;\n    const c = p1_3;\n    const a_3 = 3 * a;\n    const b_2 = 2 * b;\n    let t = x0;\n    let x1: number;\n    const eps = 8.881784197001252e-16;\n    for (let i = 0; i < 11; i++) {\n        const t2 = t * t;\n        const t3 = t2 * t;\n        x1 = a * t3 + b * t2 + c * t - x0;\n        const d = a_3 * t2 + b_2 * t + c;\n        if (d === 0) {\n            break;\n        }\n        t -= x1 / d;\n        if (i >= 2 && Math.abs(x1) <= eps) {\n            break;\n        }\n    }\n    return t;\n}\n\n/**\n * Evaluates a curve at a time in seconds, following the FBX SDK: constant/linear/cubic Bezier segments inside the\n * key range and the curve's pre/post extrapolation outside it.\n */\n/**\n * Tangent handles of the segment between two keys. Keys built by the parsers carry explicit handles; keys that\n * only carry slopes (`rightSlope` / `nextLeftSlope`) get the SDK's default one-third weighting.\n */\nfunction segmentTangents(prev: FBXKeyframe, next: FBXKeyframe): { rightDx: number; rightDy: number; leftDx: number; leftDy: number } {\n    const dt = next.time - prev.time;\n    const hasHandles =\n        Number.isFinite(prev.rightDx) && Number.isFinite(prev.rightDy) && Number.isFinite(next.leftDx) && Number.isFinite(next.leftDy) && (prev.rightDx > 0 || next.leftDx > 0);\n    if (hasHandles) {\n        return { rightDx: prev.rightDx, rightDy: prev.rightDy, leftDx: next.leftDx, leftDy: next.leftDy };\n    }\n    const rightSlope = prev.rightSlope ?? 0;\n    const leftSlope = prev.nextLeftSlope ?? (next.leftDx > 0 ? next.leftDy / next.leftDx : rightSlope);\n    return { rightDx: dt / 3, rightDy: (dt / 3) * rightSlope, leftDx: dt / 3, leftDy: (dt / 3) * leftSlope };\n}\n\nexport function evaluateCurve(curve: FBXCurveData | undefined, time: number, defaultValue: number, noExtrapolation = false): number {\n    if (!curve || curve.keys.length === 0) {\n        return defaultValue;\n    }\n    const keys = curve.keys;\n    if (keys.length === 1) {\n        return keys[0].value;\n    }\n\n    const minTime = keys[0].time;\n    const maxTime = keys[keys.length - 1].time;\n    if (!noExtrapolation && (time < minTime || time > maxTime)) {\n        return extrapolateCurve(curve, time);\n    }\n\n    // Binary search for the first key with time > `time`.\n    let begin = 0;\n    let end = keys.length;\n    while (end - begin >= 8) {\n        const mid = (begin + end) >> 1;\n        if (keys[mid].time <= time) {\n            begin = mid + 1;\n        } else {\n            end = mid;\n        }\n    }\n    end = keys.length;\n    for (; begin < end; begin++) {\n        const next = keys[begin];\n        if (next.time <= time) {\n            continue;\n        }\n        if (begin === 0) {\n            return next.value;\n        }\n        const prev = keys[begin - 1];\n        if (prev.time === time) {\n            return prev.value;\n        }\n        const rcpDelta = 1 / (next.time - prev.time);\n        let t = (time - prev.time) * rcpDelta;\n        switch (prev.interpolation) {\n            case \"constant\":\n                return prev.constantMode === \"next\" ? next.value : prev.value;\n            case \"linear\":\n                return prev.value * (1 - t) + next.value * t;\n            default: {\n                const tangents = segmentTangents(prev, next);\n                const x1 = tangents.rightDx * rcpDelta;\n                const x2 = 1 - tangents.leftDx * rcpDelta;\n                t = findCubicBezierT(x1, x2, t);\n                const t2 = t * t;\n                const t3 = t2 * t;\n                const u = 1 - t;\n                const u2 = u * u;\n                const u3 = u2 * u;\n                const y0 = prev.value;\n                const y3 = next.value;\n                const y1 = y0 + tangents.rightDy;\n                const y2 = y3 - tangents.leftDy;\n                return u3 * y0 + 3 * (u2 * t * y1 + u * t2 * y2) + t3 * y3;\n            }\n        }\n    }\n    return keys[keys.length - 1].value;\n}\n\nfunction extrapolateCurve(curve: FBXCurveData, realTime: number): number {\n    const keys = curve.keys;\n    const minTime = keys[0].time;\n    const maxTime = keys[keys.length - 1].time;\n    const pre = realTime < minTime;\n    const key = pre ? keys[0] : keys[keys.length - 1];\n    const ext = (pre ? curve.preExtrapolation : curve.postExtrapolation) ?? { mode: \"constant\", repeatCount: -1 };\n\n    if (ext.mode === \"constant\") {\n        return key.value;\n    }\n    if (ext.mode === \"slope\") {\n        const dx = pre ? key.rightDx : key.leftDx;\n        const dy = pre ? key.rightDy : key.leftDy;\n        return dx !== 0 ? key.value + dy * ((realTime - key.time) / dx) : key.value;\n    }\n    if (ext.repeatCount === 0) {\n        return key.value;\n    }\n\n    // Work in KTime ticks to stay frame exact.\n    const scale = FBX_TIME_UNIT;\n    const min = Math.round(minTime * scale);\n    const max = Math.round(maxTime * scale);\n    const time = realTime * scale;\n    const delta = pre ? min - time : time - max;\n    const duration = max - min;\n    if (!(duration >= 1)) {\n        return key.value;\n    }\n\n    const rep = delta / duration;\n    let repN = Math.floor(rep);\n    let repD = delta - repN * duration;\n    if (ext.repeatCount > 0 && repN >= ext.repeatCount) {\n        repN = ext.repeatCount - 1;\n        repD = duration;\n    }\n    if (ext.mode === \"mirror\") {\n        const parity = repN * 0.5 - Math.floor(repN * 0.5);\n        if (parity <= 0.25) {\n            repD = duration - repD;\n        }\n    }\n    if (pre) {\n        repD = duration - repD;\n    }\n    const newTime = (min + repD) / scale;\n    let value = evaluateCurve(curve, newTime, key.value, true);\n    if (ext.mode === \"repeatRelative\") {\n        let valueDelta = keys[keys.length - 1].value - keys[0].value;\n        if (pre) {\n            valueDelta = -valueDelta;\n        }\n        value += valueDelta * (repN + 1);\n    }\n    return value;\n}\n\n// ── Euler / quaternion helpers for layer blending ─────────────────────────────\n\nexport type Vec3 = [number, number, number];\nexport type Quat = [number, number, number, number];\n\nconst DEG2RAD = Math.PI / 180;\nconst RAD2DEG = 180 / Math.PI;\n\n/** Euler angles in degrees with an FBX rotation order (0=XYZ ... 5=ZYX; spheric falls back to XYZ) to a quaternion. */\nexport function eulerToQuat(v: Vec3, order: number): Quat {\n    const vx = v[0] * (DEG2RAD * 0.5);\n    const vy = v[1] * (DEG2RAD * 0.5);\n    const vz = v[2] * (DEG2RAD * 0.5);\n    const cx = Math.cos(vx),\n        sx = Math.sin(vx);\n    const cy = Math.cos(vy),\n        sy = Math.sin(vy);\n    const cz = Math.cos(vz),\n        sz = Math.sin(vz);\n    switch (order) {\n        case 1: // XZY\n            return [cx * sy * sz + cy * cz * sx, cx * cz * sy + cy * sx * sz, cx * cy * sz - cz * sx * sy, cx * cy * cz - sx * sy * sz];\n        case 2: // YZX\n            return [-cx * sy * sz + cy * cz * sx, cx * cz * sy - cy * sx * sz, cx * cy * sz + cz * sx * sy, cx * cy * cz + sx * sy * sz];\n        case 3: // YXZ\n            return [-cx * sy * sz + cy * cz * sx, cx * cz * sy + cy * sx * sz, cx * cy * sz + cz * sx * sy, cx * cy * cz - sx * sy * sz];\n        case 4: // ZXY\n            return [cx * sy * sz + cy * cz * sx, cx * cz * sy - cy * sx * sz, cx * cy * sz - cz * sx * sy, cx * cy * cz + sx * sy * sz];\n        case 5: // ZYX\n            return [cx * sy * sz + cy * cz * sx, cx * cz * sy - cy * sx * sz, cx * cy * sz + cz * sx * sy, cx * cy * cz - sx * sy * sz];\n        default: // XYZ\n            return [-cx * sy * sz + cy * cz * sx, cx * cz * sy + cy * sx * sz, cx * cy * sz - cz * sx * sy, cx * cy * cz + sx * sy * sz];\n    }\n}\n\n/** Quaternion to Euler angles in degrees for an FBX rotation order (inverse of eulerToQuat). */\nexport function quatToEuler(q: Quat, order: number): Vec3 {\n    const eps = 0.999999999;\n    const [qx, qy, qz, qw] = q;\n    let vx = 0,\n        vy = 0,\n        vz = 0;\n    let t: number;\n    const halfPi = Math.PI * 0.5;\n    switch (order) {\n        case 1: // XZY\n            t = 2 * (qw * qz + qx * qy);\n            if (Math.abs(t) < eps) {\n                vz = Math.asin(t);\n                vy = Math.atan2(2 * (qw * qy - qx * qz), 2 * (qw * qw + qx * qx) - 1);\n                vx = -Math.atan2(-2 * (qw * qx - qy * qz), 2 * (qw * qw + qy * qy) - 1);\n            } else {\n                vz = Math.sign(t) * halfPi;\n                vy = Math.atan2(2 * t * (qw * qx + qy * qz), -t * (2 * qx * qy - 2 * qw * qz));\n            }\n            break;\n        case 2: // YZX\n            t = 2 * (qw * qz - qx * qy);\n            if (Math.abs(t) < eps) {\n                vz = Math.asin(t);\n                vx = Math.atan2(2 * (qw * qx + qy * qz), 2 * (qw * qw + qy * qy) - 1);\n                vy = -Math.atan2(-2 * (qw * qy + qx * qz), 2 * (qw * qw + qx * qx) - 1);\n            } else {\n                vz = Math.sign(t) * halfPi;\n                vx = Math.atan2(-2 * t * (qw * qy - qx * qz), t * (2 * qw * qz + 2 * qx * qy));\n            }\n            break;\n        case 3: // YXZ\n            t = 2 * (qw * qx + qy * qz);\n            if (Math.abs(t) < eps) {\n                vx = Math.asin(t);\n                vz = Math.atan2(2 * (qw * qz - qx * qy), 2 * (qw * qw + qy * qy) - 1);\n                vy = -Math.atan2(-2 * (qw * qy - qx * qz), 2 * (qw * qw + qz * qz) - 1);\n            } else {\n                vx = Math.sign(t) * halfPi;\n                vz = Math.atan2(2 * t * (qw * qy + qx * qz), -t * (2 * qy * qz - 2 * qw * qx));\n            }\n            break;\n        case 4: // ZXY\n            t = 2 * (qw * qx - qy * qz);\n            if (Math.abs(t) < eps) {\n                vx = Math.asin(t);\n                vy = Math.atan2(2 * (qw * qy + qx * qz), 2 * (qw * qw + qz * qz) - 1);\n                vz = -Math.atan2(-2 * (qw * qz + qx * qy), 2 * (qw * qw + qy * qy) - 1);\n            } else {\n                vx = Math.sign(t) * halfPi;\n                vy = Math.atan2(-2 * t * (qw * qz - qx * qy), t * (2 * qw * qx + 2 * qy * qz));\n            }\n            break;\n        case 5: // ZYX\n            t = 2 * (qw * qy + qx * qz);\n            if (Math.abs(t) < eps) {\n                vy = Math.asin(t);\n                vx = Math.atan2(2 * (qw * qx - qy * qz), 2 * (qw * qw + qz * qz) - 1);\n                vz = -Math.atan2(-2 * (qw * qz - qx * qy), 2 * (qw * qw + qx * qx) - 1);\n            } else {\n                vy = Math.sign(t) * halfPi;\n                vx = Math.atan2(2 * t * (qw * qz + qx * qy), -t * (2 * qx * qz - 2 * qw * qy));\n            }\n            break;\n        default: // XYZ\n            t = 2 * (qw * qy - qx * qz);\n            if (Math.abs(t) < eps) {\n                vy = Math.asin(t);\n                vz = Math.atan2(2 * (qw * qz + qx * qy), 2 * (qw * qw + qx * qx) - 1);\n                vx = -Math.atan2(-2 * (qw * qx + qy * qz), 2 * (qw * qw + qz * qz) - 1);\n            } else {\n                vy = Math.sign(t) * halfPi;\n                vz = Math.atan2(-2 * t * (qw * qx - qy * qz), t * (2 * qw * qy + 2 * qx * qz));\n            }\n            break;\n    }\n    return [vx * RAD2DEG, vy * RAD2DEG, vz * RAD2DEG];\n}\n\nfunction quatMul(a: Quat, b: Quat): Quat {\n    return [\n        a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],\n        a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0],\n        a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3],\n        a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2],\n    ];\n}\n\nfunction quatSlerp(a: Quat, b: Quat, t: number): Quat {\n    let dot = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n    let bx = b[0],\n        by = b[1],\n        bz = b[2],\n        bw = b[3];\n    if (dot < 0) {\n        dot = -dot;\n        bx = -bx;\n        by = -by;\n        bz = -bz;\n        bw = -bw;\n    }\n    let wa: number;\n    let wb: number;\n    if (dot > 0.9995) {\n        wa = 1 - t;\n        wb = t;\n    } else {\n        const omega = Math.acos(Math.min(1, dot));\n        const rcpSin = 1 / Math.sin(omega);\n        wa = Math.sin((1 - t) * omega) * rcpSin;\n        wb = Math.sin(t * omega) * rcpSin;\n    }\n    const x = a[0] * wa + bx * wb;\n    const y = a[1] * wa + by * wb;\n    const z = a[2] * wa + bz * wb;\n    const w = a[3] * wa + bw * wb;\n    const len = Math.hypot(x, y, z, w) || 1;\n    return [x / len, y / len, z / len, w / len];\n}\n\nfunction powAbs(v: number, e: number): number {\n    return v >= 0 ? Math.pow(v, e) : -Math.pow(-v, e);\n}\n\n/** Blend semantics of an animation layer, derived from its BlendMode and accumulation modes. */\nexport interface FBXLayerBlend {\n    /** Layer participates in blending (BlendMode Additive or Override Passthrough) */\n    blended: boolean;\n    /** Layer adds onto the result instead of replacing it (BlendMode Additive) */\n    additive: boolean;\n    /** Rotations compose as quaternions (RotationAccumulationMode ByLayer) */\n    composeRotation: boolean;\n    /** Scales compose multiplicatively (ScaleAccumulationMode Multiply) */\n    composeScale: boolean;\n    /** Layer weight in [0, 1] */\n    weight: number;\n}\n\n/**\n * Combines one animation layer's value into the running result, exactly as the FBX SDK evaluator does.\n * `kind` selects the accumulation rule: \"R\" rotations (degrees, rotation order given), \"S\" scales, anything else linear.\n */\nexport function combineLayerValue(result: Vec3, value: Vec3, layer: FBXLayerBlend, kind: \"T\" | \"R\" | \"S\" | \"other\", rotationOrder: number): Vec3 {\n    const w = layer.weight;\n    if (layer.additive) {\n        if (layer.composeScale && kind === \"S\") {\n            return [result[0] * powAbs(value[0], w), result[1] * powAbs(value[1], w), result[2] * powAbs(value[2], w)];\n        }\n        if (layer.composeRotation && kind === \"R\") {\n            const a = eulerToQuat(result, rotationOrder);\n            const b = quatSlerp([0, 0, 0, 1], eulerToQuat(value, rotationOrder), w);\n            return quatToEuler(quatMul(a, b), rotationOrder);\n        }\n        return [result[0] + value[0] * w, result[1] + value[1] * w, result[2] + value[2] * w];\n    }\n    if (layer.blended) {\n        const rw = 1 - w;\n        if (layer.composeScale && kind === \"S\") {\n            return [powAbs(result[0], rw) * powAbs(value[0], w), powAbs(result[1], rw) * powAbs(value[1], w), powAbs(result[2], rw) * powAbs(value[2], w)];\n        }\n        if (layer.composeRotation && kind === \"R\") {\n            return quatToEuler(quatSlerp(eulerToQuat(result, rotationOrder), eulerToQuat(value, rotationOrder), w), rotationOrder);\n        }\n        return [result[0] * rw + value[0] * w, result[1] * rw + value[1] * w, result[2] * rw + value[2] * w];\n    }\n    return [value[0], value[1], value[2]];\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, findChildByName, findDocumentNode, getNodeArray, getPropertyValue, cleanFBXName } from \"../types/fbxTypes\";\n\nimport { type FBXObjectMap, getChildren } from \"./connections\";\nimport { getPropertyEntries } from \"./propertyTemplates\";\nimport {\n    FBX_TIME_UNIT,\n    buildKeyframes,\n    evaluateCurve,\n    keyframesFromSlopes,\n    parseExtrapolation,\n    combineLayerValue,\n    type FBXCurveData,\n    type FBXInterpolationType,\n    type FBXKeyframe,\n    type FBXLayerBlend,\n} from \"./animationCurve\";\n\nexport { FBX_TIME_UNIT } from \"./animationCurve\";\nexport type { FBXCurveData, FBXExtrapolation, FBXExtrapolationMode, FBXInterpolationType, FBXKeyframe, FBXLayerBlend } from \"./animationCurve\";\nexport { combineLayerValue, evaluateCurve, eulerToQuat, quatToEuler } from \"./animationCurve\";\n\nconst KEY_ATTR_DATA_STRIDE = 4;\n\n/** An animation curve node (T/R/S for one bone) */\nexport interface FBXCurveNodeData {\n    /** Property type: \"T\" (translation), \"R\" (rotation), \"S\" (scale) */\n    type: string;\n    /** Target model (bone) ID */\n    targetModelId: number;\n    /** Curves for each axis */\n    curves: FBXCurveData[];\n    /** Index of the owning layer within the stack's layer list */\n    layerIndex: number;\n    /** Default channel values (`d|X`, `d|Y`, `d|Z`) used for channels without a curve */\n    defaultValues?: [number, number, number];\n}\n\n/** Non-transform animation curve node (property animation), evaluated by the loader when a Babylon mapping exists. */\nexport interface FBXUnsupportedCurveNodeData {\n    /** Raw AnimationCurveNode property type/name */\n    type: string;\n    /** CurveNode object ID */\n    id: number;\n    /** Index of the owning layer within the stack's layer list */\n    layerIndex: number;\n    /** Target object ID if the curve node is connected to an object/property */\n    targetId: number | null;\n    /** OP connection property name on the target, e.g. Visibility */\n    propertyName?: string;\n    /** Number of connected animation curves that were ignored */\n    curveCount: number;\n    /** Connected curves preserved for diagnostics and future runtime support */\n    curves: FBXCurveData[];\n    /** Local default values stored on the unsupported curve node */\n    defaultValues: Record<string, number>;\n}\n\n/** Recoverable animation import issue. */\nexport interface FBXAnimationDiagnostic {\n    /** Diagnostic category. */\n    type: \"multiple-animation-layers\" | \"unsupported-layer-blend-mode\" | \"partial-layer-weight\" | \"unsupported-curve-node\";\n    /** Human-readable diagnostic message. */\n    message: string;\n    /** Animation layer name associated with the diagnostic, if applicable. */\n    layerName?: string;\n    /** AnimationCurveNode object ID associated with the diagnostic, if applicable. */\n    curveNodeId?: number;\n    /** AnimationCurveNode type/name associated with the diagnostic, if applicable. */\n    curveNodeType?: string;\n    /** Target object ID associated with the diagnostic, if applicable. */\n    targetId?: number | null;\n    /** Target property name associated with the diagnostic, if applicable. */\n    propertyName?: string;\n}\n\n/** Animation layer with blend mode info */\nexport interface FBXAnimationLayerData {\n    /** Layer name */\n    name: string;\n    /** Layer weight (0-100, default 100) */\n    weight: number;\n    /** Layer weight normalized to 0-1 */\n    normalizedWeight: number;\n    /** Blend mode: 0=Additive, 1=Override, 2=OverridePassthrough */\n    blendMode: number;\n    /** Resolved blend semantics used by the evaluator */\n    blend: FBXLayerBlend;\n    /** Animated layer weight (0-100), when the Weight property carries a curve */\n    weightCurve?: FBXCurveData;\n    /** Curve nodes in this layer */\n    curveNodes: FBXCurveNodeData[];\n    /** Unsupported/non-TRS curve nodes preserved for diagnostics */\n    unsupportedCurveNodes: FBXUnsupportedCurveNodeData[];\n    /** Recoverable layer diagnostics */\n    diagnostics: FBXAnimationDiagnostic[];\n}\n\n/** Options for animation extraction. */\nexport interface FBXAnimationExtractOptions {\n    /**\n     * Shift each clip so its first key sits at time 0 (default true). False keeps the times authored in the file, so\n     * clips of one file stay aligned with each other and with the declared stack range.\n     */\n    rebaseKeyframes?: boolean;\n}\n\n/** One animation clip (AnimationStack) */\nexport interface FBXAnimationStackData {\n    /** Animation name */\n    name: string;\n    /** Clip start in seconds after any keyframe rebasing */\n    startTime: number;\n    /** Clip stop in seconds after any keyframe rebasing */\n    stopTime: number;\n    /** Duration in seconds */\n    duration: number;\n    /** Per-bone curve nodes (flattened from all layers for backward compat) */\n    curveNodes: FBXCurveNodeData[];\n    /** Animation layers (preserves blend mode info) */\n    layers: FBXAnimationLayerData[];\n    /** Unsupported/non-TRS curve nodes preserved for diagnostics */\n    unsupportedCurveNodes: FBXUnsupportedCurveNodeData[];\n    /** Recoverable animation diagnostics */\n    diagnostics: FBXAnimationDiagnostic[];\n}\n\n/**\n * Extract all animation stacks from the FBX scene.\n */\nexport function extractAnimations(objectMap: FBXObjectMap, doc?: FBXDocument, options: FBXAnimationExtractOptions = {}): FBXAnimationStackData[] {\n    const stacks: FBXAnimationStackData[] = [];\n    const rebaseKeyframes = options.rebaseKeyframes ?? true;\n\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"AnimationStack\") {\n            const stack = extractAnimStack(id, node, objectMap, rebaseKeyframes);\n            if (stack) {\n                stacks.push(stack);\n            }\n        }\n    }\n\n    // Pre-7000 files have no AnimationStack objects; their animation lives in the top-level Takes block.\n    if (stacks.length === 0 && doc) {\n        stacks.push(...extractLegacyTakes(doc, objectMap, rebaseKeyframes));\n    }\n\n    return stacks;\n}\n\nfunction extractAnimStack(stackId: number, stackNode: FBXNode, objectMap: FBXObjectMap, rebaseKeyframes: boolean): FBXAnimationStackData | null {\n    const name = cleanFBXName(getPropertyValue<string>(stackNode, 1) ?? \"Animation\");\n    const declaredTimeSpan = extractAnimationStackTimeSpan(stackNode);\n\n    // Find AnimationLayer children of this stack\n    const layerEntries = getChildren(objectMap, stackId, \"AnimationLayer\");\n    if (layerEntries.length === 0) {\n        return null;\n    }\n\n    // Collect all CurveNodes from all layers\n    const allCurveNodes: FBXCurveNodeData[] = [];\n    const allUnsupportedCurveNodes: FBXUnsupportedCurveNodeData[] = [];\n    const layers: FBXAnimationLayerData[] = [];\n    const diagnostics: FBXAnimationDiagnostic[] = [];\n    let minTime = Infinity;\n    let maxTime = -Infinity;\n\n    for (const { id: layerId, node: layerNode } of layerEntries) {\n        // Extract layer properties\n        const layerName = cleanFBXName(getPropertyValue<string>(layerNode, 1) ?? \"Layer\");\n        let weight = 100;\n        let blendMode = 0;\n        let rotationAccumulationMode = 0;\n        let scaleAccumulationMode = 0;\n\n        for (const entry of getPropertyEntries(layerNode)) {\n            const v = entry.values[0];\n            if (typeof v !== \"number\") {\n                continue;\n            }\n            if (entry.name === \"Weight\") {\n                weight = v;\n            } else if (entry.name === \"BlendMode\") {\n                blendMode = v;\n            } else if (entry.name === \"RotationAccumulationMode\") {\n                rotationAccumulationMode = v;\n            } else if (entry.name === \"ScaleAccumulationMode\") {\n                scaleAccumulationMode = v;\n            }\n        }\n        const layerIndex = layers.length;\n\n        // AnimationCurveNodes are children of the layer\n        const curveNodeEntries = getChildren(objectMap, layerId, \"AnimationCurveNode\");\n        const layerCurveNodes: FBXCurveNodeData[] = [];\n        const layerUnsupportedCurveNodes: FBXUnsupportedCurveNodeData[] = [];\n        const layerDiagnostics: FBXAnimationDiagnostic[] = [];\n        let layerWeightCurve: FBXCurveData | undefined;\n\n        for (const { id: curveNodeId, node: curveNodeNode } of curveNodeEntries) {\n            const curveNodeData = extractCurveNode(curveNodeId, curveNodeNode, objectMap, layerIndex);\n            if (!curveNodeData) {\n                const unsupported = extractUnsupportedCurveNode(curveNodeId, curveNodeNode, objectMap, layerIndex);\n                if (unsupported) {\n                    // The layer's own Weight property can be animated; it drives blending rather than a target.\n                    if (unsupported.targetId === layerId && unsupported.propertyName === \"Weight\" && unsupported.curves.length > 0) {\n                        layerWeightCurve = unsupported.curves[0];\n                        continue;\n                    }\n                    scanCurveTimes(unsupported.curves, (time) => {\n                        if (time < minTime) {\n                            minTime = time;\n                        }\n                        if (time > maxTime) {\n                            maxTime = time;\n                        }\n                    });\n                    layerUnsupportedCurveNodes.push(unsupported);\n                    allUnsupportedCurveNodes.push(unsupported);\n                    const diagnostic: FBXAnimationDiagnostic = {\n                        type: \"unsupported-curve-node\",\n                        message: `AnimationCurveNode '${unsupported.type}' is preserved as diagnostic data but not evaluated at runtime.`,\n                        layerName,\n                        curveNodeId,\n                        curveNodeType: unsupported.type,\n                        targetId: unsupported.targetId,\n                        propertyName: unsupported.propertyName,\n                    };\n                    layerDiagnostics.push(diagnostic);\n                    diagnostics.push(diagnostic);\n                }\n                continue;\n            }\n\n            for (const curve of curveNodeData.curves) {\n                for (const key of curve.keys) {\n                    if (key.time < minTime) {\n                        minTime = key.time;\n                    }\n                    if (key.time > maxTime) {\n                        maxTime = key.time;\n                    }\n                }\n            }\n\n            layerCurveNodes.push(curveNodeData);\n            allCurveNodes.push(curveNodeData);\n        }\n\n        layers.push({\n            name: layerName,\n            weight,\n            normalizedWeight: weight / 100,\n            blendMode,\n            blend: makeLayerBlend(blendMode, weight, rotationAccumulationMode, scaleAccumulationMode),\n            weightCurve: layerWeightCurve,\n            curveNodes: layerCurveNodes,\n            unsupportedCurveNodes: layerUnsupportedCurveNodes,\n            diagnostics: layerDiagnostics,\n        });\n    }\n\n    if (allCurveNodes.length === 0 && allUnsupportedCurveNodes.length === 0) {\n        return null;\n    }\n\n    return finalizeAnimStack(name, layers, allCurveNodes, allUnsupportedCurveNodes, diagnostics, minTime, maxTime, declaredTimeSpan, rebaseKeyframes);\n}\n\n/**\n * Resolves the clip span from the declared time span or the key range and, when requested, rebases key times so\n * the first key sits at zero.\n */\nfunction finalizeAnimStack(\n    name: string,\n    layers: FBXAnimationLayerData[],\n    allCurveNodes: FBXCurveNodeData[],\n    allUnsupportedCurveNodes: FBXUnsupportedCurveNodeData[],\n    diagnostics: FBXAnimationDiagnostic[],\n    minTime: number,\n    maxTime: number,\n    declaredTimeSpan: { start: number; stop: number } | null,\n    rebaseKeyframes: boolean\n): FBXAnimationStackData {\n    const hasKeys = isFinite(minTime) && isFinite(maxTime);\n    const timeOffset = rebaseKeyframes && hasKeys && minTime > 0 ? minTime : 0;\n\n    // Rebase all keyframe times so the animation starts at 0\n    if (timeOffset > 0) {\n        for (const cn of allCurveNodes) {\n            for (const curve of cn.curves) {\n                for (const key of curve.keys) {\n                    key.time -= timeOffset;\n                }\n            }\n        }\n        for (const cn of allUnsupportedCurveNodes) {\n            for (const curve of cn.curves) {\n                for (const key of curve.keys) {\n                    key.time -= timeOffset;\n                }\n            }\n        }\n        maxTime -= timeOffset;\n    }\n\n    const declaredStart = declaredTimeSpan ? (rebaseKeyframes ? Math.max(declaredTimeSpan.start - timeOffset, 0) : declaredTimeSpan.start) : 0;\n    const declaredStop = declaredTimeSpan ? Math.max(declaredTimeSpan.stop - timeOffset, declaredStart) : 0;\n    const hasDeclaredDuration = declaredStop > declaredStart;\n    // Without a declared span the clip covers its keys (a clip whose keys are all negative ends before zero).\n    const keyStart = hasKeys ? minTime - timeOffset : 0;\n    const keyStop = hasKeys ? maxTime : 0;\n    const startTime = hasDeclaredDuration ? declaredStart : rebaseKeyframes ? Math.min(0, keyStart) : keyStart;\n    const stopTime = hasDeclaredDuration ? declaredStop : Math.max(keyStop, startTime);\n\n    return {\n        name,\n        startTime,\n        stopTime,\n        duration: Math.max(stopTime - startTime, 0),\n        curveNodes: allCurveNodes,\n        layers,\n        unsupportedCurveNodes: allUnsupportedCurveNodes,\n        diagnostics,\n    };\n}\n\nfunction extractAnimationStackTimeSpan(stackNode: FBXNode): { start: number; stop: number } | null {\n    const props70 = findChildByName(stackNode, \"Properties70\");\n    if (!props70) {\n        return null;\n    }\n\n    let start = 0;\n    let stop: number | null = null;\n\n    for (const p of props70.children) {\n        if (p.name !== \"P\") {\n            continue;\n        }\n        const pName = getPropertyValue<string>(p, 0);\n        if (pName === \"LocalStart\" || pName === \"ReferenceStart\") {\n            start = fbxTimeToSeconds(p.properties[4]?.value) ?? start;\n        } else if (pName === \"LocalStop\" || pName === \"ReferenceStop\") {\n            stop = fbxTimeToSeconds(p.properties[4]?.value) ?? stop;\n        }\n    }\n\n    return stop !== null ? { start, stop } : null;\n}\n\nfunction extractCurveNode(curveNodeId: number, curveNodeNode: FBXNode, objectMap: FBXObjectMap, layerIndex: number): FBXCurveNodeData | null {\n    const typeName = cleanFBXName(getPropertyValue<string>(curveNodeNode, 1) ?? \"\");\n    const rawDefaults = extractCurveNodeDefaultValues(curveNodeNode);\n    const defaultValues: [number, number, number] | undefined =\n        \"d|X\" in rawDefaults || \"d|Y\" in rawDefaults || \"d|Z\" in rawDefaults ? [rawDefaults[\"d|X\"] ?? 0, rawDefaults[\"d|Y\"] ?? 0, rawDefaults[\"d|Z\"] ?? 0] : undefined;\n\n    // Handle T (translation), R (rotation), S (scale) targeting Models\n    if (typeName === \"T\" || typeName === \"R\" || typeName === \"S\") {\n        const targetModelId = findCurveNodeTarget(curveNodeId, objectMap);\n        if (targetModelId === null) {\n            return null;\n        }\n\n        // A curve node without curves still contributes its default values to layer blending (Maya writes such\n        // nodes on the base layer when only additive layers animate a property).\n        const curves = extractCurves(curveNodeId, objectMap);\n        if (curves.length === 0 && !defaultValues) {\n            return null;\n        }\n\n        return {\n            type: typeName,\n            targetModelId,\n            curves,\n            layerIndex,\n            defaultValues,\n        };\n    }\n\n    // FBX 7.1 writes blend shape weight curves against the geometry, named after the shape channel\n    const geometryChannelId = findCurveNodeGeometryShapeChannel(curveNodeId, objectMap);\n    if (geometryChannelId !== null) {\n        const curves = extractCurves(curveNodeId, objectMap);\n        if (curves.length === 0) {\n            return null;\n        }\n        return { type: \"DeformPercent\", targetModelId: geometryChannelId, curves, layerIndex, defaultValues };\n    }\n\n    // Handle DeformPercent targeting BlendShapeChannels\n    if (typeName === \"DeformPercent\") {\n        const targetId = findCurveNodeBlendShapeTarget(curveNodeId, objectMap);\n        if (targetId === null) {\n            return null;\n        }\n\n        const curves = extractCurves(curveNodeId, objectMap);\n        if (curves.length === 0) {\n            return null;\n        }\n\n        return {\n            type: \"DeformPercent\",\n            targetModelId: targetId,\n            curves,\n            layerIndex,\n            defaultValues,\n        };\n    }\n\n    return null;\n}\n\nfunction extractUnsupportedCurveNode(curveNodeId: number, curveNodeNode: FBXNode, objectMap: FBXObjectMap, layerIndex: number): FBXUnsupportedCurveNodeData | null {\n    const typeName = cleanFBXName(getPropertyValue<string>(curveNodeNode, 1) ?? \"\");\n    const curves = extractCurves(curveNodeId, objectMap);\n    const defaultValues = extractCurveNodeDefaultValues(curveNodeNode);\n    if (curves.length === 0 && Object.keys(defaultValues).length === 0) {\n        return null;\n    }\n\n    let targetId: number | null = null;\n    let propertyName: string | undefined;\n    for (const conn of objectMap.connections) {\n        if (conn.childId === curveNodeId && conn.type === \"OP\") {\n            targetId = conn.parentId;\n            propertyName = conn.propertyName;\n            break;\n        }\n    }\n\n    return {\n        type: typeName,\n        id: curveNodeId,\n        layerIndex,\n        targetId,\n        propertyName,\n        curveCount: curves.length,\n        curves,\n        defaultValues,\n    };\n}\n\nfunction scanCurveTimes(curves: FBXCurveData[], visit: (time: number) => void): void {\n    for (const curve of curves) {\n        for (const key of curve.keys) {\n            visit(key.time);\n        }\n    }\n}\n\n/**\n * Find the Model that an AnimationCurveNode targets.\n * The CurveNode connects to the Model via OP connection with a property name.\n */\nfunction findCurveNodeTarget(curveNodeId: number, objectMap: FBXObjectMap): number | null {\n    // Look for connections where this curveNode is a child (going up to parent)\n    // The OP connection from curveNode → Model has the property name (e.g. \"Lcl Translation\")\n    for (const conn of objectMap.connections) {\n        if (conn.childId === curveNodeId && conn.type === \"OP\") {\n            const parentNode = objectMap.objects.get(conn.parentId);\n            if (parentNode && parentNode.name === \"Model\") {\n                return conn.parentId;\n            }\n        }\n    }\n    return null;\n}\n\n/** When a curve node is connected to a Geometry through a property named like one of its blend shape channels. */\nfunction findCurveNodeGeometryShapeChannel(curveNodeId: number, objectMap: FBXObjectMap): number | null {\n    for (const conn of objectMap.connections) {\n        if (conn.childId !== curveNodeId || conn.type !== \"OP\" || !conn.propertyName) {\n            continue;\n        }\n        const parentNode = objectMap.objects.get(conn.parentId);\n        if (!parentNode || parentNode.name !== \"Geometry\") {\n            continue;\n        }\n        for (const deformer of getChildren(objectMap, conn.parentId, \"Deformer\")) {\n            if (getPropertyValue<string>(deformer.node, 2) !== \"BlendShape\") {\n                continue;\n            }\n            for (const channel of getChildren(objectMap, deformer.id, \"Deformer\")) {\n                if (getPropertyValue<string>(channel.node, 2) === \"BlendShapeChannel\" && cleanFBXName(getPropertyValue<string>(channel.node, 1) ?? \"\") === conn.propertyName) {\n                    return channel.id;\n                }\n            }\n        }\n    }\n    return null;\n}\n\n/**\n * Find the BlendShapeChannel that a DeformPercent AnimationCurveNode targets.\n */\nfunction findCurveNodeBlendShapeTarget(curveNodeId: number, objectMap: FBXObjectMap): number | null {\n    for (const conn of objectMap.connections) {\n        if (conn.childId === curveNodeId && conn.type === \"OP\") {\n            const parentNode = objectMap.objects.get(conn.parentId);\n            if (parentNode && parentNode.name === \"Deformer\") {\n                const subType = getPropertyValue<string>(parentNode, 2);\n                if (subType === \"BlendShapeChannel\") {\n                    return conn.parentId;\n                }\n            }\n        }\n    }\n    // Also check OO connections\n    for (const conn of objectMap.connections) {\n        if (conn.childId === curveNodeId && conn.type === \"OO\") {\n            const parentNode = objectMap.objects.get(conn.parentId);\n            if (parentNode && parentNode.name === \"Deformer\") {\n                const subType = getPropertyValue<string>(parentNode, 2);\n                if (subType === \"BlendShapeChannel\") {\n                    return conn.parentId;\n                }\n            }\n        }\n    }\n    return null;\n}\n\n/**\n * Extract AnimationCurves connected to a CurveNode.\n * Each curve connects via OP with channel \"d|X\", \"d|Y\", or \"d|Z\".\n */\nfunction extractCurves(curveNodeId: number, objectMap: FBXObjectMap): FBXCurveData[] {\n    const curves: FBXCurveData[] = [];\n\n    // Find AnimationCurve children of this CurveNode\n    for (const conn of objectMap.connections) {\n        if (conn.parentId === curveNodeId && conn.type === \"OP\") {\n            const curveNode = objectMap.objects.get(conn.childId);\n            if (!curveNode || curveNode.name !== \"AnimationCurve\") {\n                continue;\n            }\n\n            const channel = conn.propertyName ?? \"d|X\";\n            const keys = extractKeyframes(curveNode);\n            if (keys.length > 0) {\n                curves.push({ channel, keys, ...extractCurveExtrapolation(curveNode) });\n            }\n        }\n    }\n\n    // Also check OO connections (some exporters use OO for curve→curveNode)\n    if (curves.length === 0) {\n        const ooChildren = getChildren(objectMap, curveNodeId, \"AnimationCurve\");\n        // For OO connections, infer channel from order (X, Y, Z)\n        const channelNames = [\"d|X\", \"d|Y\", \"d|Z\"];\n        for (let i = 0; i < ooChildren.length && i < 3; i++) {\n            const keys = extractKeyframes(ooChildren[i].node);\n            if (keys.length > 0) {\n                curves.push({ channel: channelNames[i], keys, ...extractCurveExtrapolation(ooChildren[i].node) });\n            }\n        }\n    }\n\n    return curves;\n}\n\nfunction extractCurveNodeDefaultValues(curveNodeNode: FBXNode): Record<string, number> {\n    const defaults: Record<string, number> = {};\n    const props70 = findChildByName(curveNodeNode, \"Properties70\");\n    for (const p of props70?.children ?? []) {\n        if (p.name !== \"P\") {\n            continue;\n        }\n        const propName = getPropertyValue<string>(p, 0);\n        if (!propName?.startsWith(\"d|\")) {\n            continue;\n        }\n        const value = toNumber(p.properties[4]?.value);\n        if (value !== null) {\n            defaults[propName] = value;\n        }\n    }\n    return defaults;\n}\n\n/**\n * Extract keyframes from an AnimationCurve node.\n */\nfunction extractKeyframes(curveNode: FBXNode): FBXKeyframe[] {\n    const keyTimeNode = findChildByName(curveNode, \"KeyTime\");\n    const keyValueNode = findChildByName(curveNode, \"KeyValueFloat\");\n\n    if (!keyTimeNode || !keyValueNode) {\n        return [];\n    }\n\n    const keyTimes = toInt64Array(getNodeArray(keyTimeNode));\n    const keyValues = toFloat32Array(getNodeArray(keyValueNode));\n    const keyAttrFlags = toInt32Array(getNodeArray(findChildByName(curveNode, \"KeyAttrFlags\")));\n    const keyAttrData = toFloat32Array(getNodeArray(findChildByName(curveNode, \"KeyAttrDataFloat\")));\n    const keyAttrRefCount = toInt32Array(getNodeArray(findChildByName(curveNode, \"KeyAttrRefCount\")));\n\n    if (!keyTimes || !keyValues) {\n        return [];\n    }\n    if (keyTimes.length !== keyValues.length) {\n        return [];\n    }\n\n    const keyAttributeIndices = buildKeyAttributeIndices(keyTimes.length, keyAttrFlags, keyAttrRefCount);\n    return buildKeyframes(keyTimes, keyValues, (i) => {\n        const attrIndex = keyAttributeIndices[i];\n        const flag = attrIndex >= 0 ? (keyAttrFlags?.[attrIndex] ?? 0) : 0;\n        const dataOffset = attrIndex * KEY_ATTR_DATA_STRIDE;\n        return {\n            flags: flag,\n            data: [\n                getFiniteKeyAttrData(keyAttrData, dataOffset) ?? 0,\n                getFiniteKeyAttrData(keyAttrData, dataOffset + 1) ?? 0,\n                getFiniteKeyAttrData(keyAttrData, dataOffset + 2) ?? 0,\n                getFiniteKeyAttrData(keyAttrData, dataOffset + 3) ?? 0,\n            ],\n        };\n    });\n}\n\nfunction extractCurveExtrapolation(curveNode: FBXNode): { preExtrapolation: FBXExtrapolationLike; postExtrapolation: FBXExtrapolationLike } {\n    const read = (name: string) => {\n        const node = findChildByName(curveNode, name);\n        return parseExtrapolation(findChildByName(node ?? curveNode, \"Type\")?.properties[0]?.value, findChildByName(node ?? curveNode, \"Repetition\")?.properties[0]?.value);\n    };\n    return { preExtrapolation: read(\"Pre-Extrapolation\"), postExtrapolation: read(\"Post-Extrapolation\") };\n}\ntype FBXExtrapolationLike = ReturnType<typeof parseExtrapolation>;\n\nfunction makeLayerBlend(blendMode: number, weight: number, rotationAccumulationMode: number, scaleAccumulationMode: number): FBXLayerBlend {\n    let blended = false;\n    let additive = false;\n    switch (blendMode) {\n        case 0:\n            blended = true;\n            additive = true;\n            break;\n        case 2:\n            blended = true;\n            break;\n        default:\n            break;\n    }\n    let w = weight / 100;\n    if (w < 0) {\n        w = 0;\n    }\n    if (w > 0.99999) {\n        w = 1;\n    }\n    return { blended, additive, composeRotation: rotationAccumulationMode === 0, composeScale: scaleAccumulationMode === 0, weight: w };\n}\n\n/**\n * Samples an FBX animation curve at a specific time.\n * @param curveData - Curve data to sample\n * @param time - Time in seconds\n * @returns The sampled value, or null when the curve has no keys\n */\nexport function sampleFBXCurveAtTime(curveData: FBXCurveData | undefined, time: number): number | null {\n    if (!curveData || curveData.keys.length === 0) {\n        return null;\n    }\n    return evaluateCurve(curveData, time, curveData.keys[0].value);\n}\n\n// ── Utilities ──────────────────────────────────────────────────────────────────\n\nfunction toInt64Array(value: unknown): Float64Array | null {\n    if (value instanceof Float64Array) {\n        return value;\n    }\n    return null;\n}\n\nfunction toInt32Array(value: unknown): Int32Array | null {\n    if (value instanceof Int32Array) {\n        return value;\n    }\n    if (value instanceof Float32Array || value instanceof Float64Array) {\n        const result = new Int32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = value[i];\n        }\n        return result;\n    }\n    return null;\n}\n\nfunction fbxTimeToSeconds(value: unknown): number | null {\n    if (typeof value === \"number\") {\n        return value / FBX_TIME_UNIT;\n    }\n    return null;\n}\n\nfunction toNumber(value: unknown): number | null {\n    if (typeof value === \"number\") {\n        return value;\n    }\n    return null;\n}\n\nfunction toFloat32Array(value: unknown): Float32Array | null {\n    if (value instanceof Float32Array) {\n        return value;\n    }\n    if (value instanceof Float64Array) {\n        const result = new Float32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = value[i];\n        }\n        return result;\n    }\n    return null;\n}\n\nfunction buildKeyAttributeIndices(keyCount: number, keyAttrFlags: Int32Array | null, keyAttrRefCount: Int32Array | null): number[] {\n    if (!keyAttrFlags || keyAttrFlags.length === 0) {\n        return new Array(keyCount).fill(-1);\n    }\n\n    if (keyAttrRefCount && keyAttrRefCount.length > 0) {\n        let total = 0;\n        for (const count of keyAttrRefCount) {\n            total += count;\n        }\n\n        if (total === keyCount) {\n            const indices: number[] = [];\n            for (let attrIndex = 0; attrIndex < keyAttrRefCount.length; attrIndex++) {\n                const count = keyAttrRefCount[attrIndex];\n                for (let i = 0; i < count; i++) {\n                    indices.push(attrIndex);\n                }\n            }\n            return indices;\n        }\n    }\n\n    if (keyAttrFlags.length === keyCount) {\n        return Array.from({ length: keyCount }, (_, i) => i);\n    }\n\n    if (keyAttrFlags.length === 1) {\n        return new Array(keyCount).fill(0);\n    }\n\n    return Array.from({ length: keyCount }, (_, i) => Math.min(i, keyAttrFlags.length - 1));\n}\n\nfunction getFiniteKeyAttrData(keyAttrData: Float32Array | null, index: number): number | undefined {\n    if (!keyAttrData || index < 0 || index >= keyAttrData.length) {\n        return undefined;\n    }\n    const value = keyAttrData[index];\n    return Number.isFinite(value) ? value : undefined;\n}\n\n// ── Legacy Takes (FBX 5.x / 6.x) ───────────────────────────────────────────────\n\n/**\n * Pre-7000 files store animation in a top-level `Takes` block instead of AnimationStack/Layer/CurveNode objects:\n *\n *   Takes: { Take: \"name\" { LocalTime: start, stop\n *     Model: \"Model::joint1\" { Channel: \"Transform\" { Channel: \"T\" { Channel: \"X\" { Default, KeyVer, KeyCount, Key } } } } } }\n *\n * Each take becomes one animation stack with a single layer. Models are matched through the same legacy string ids\n * that the connection resolver synthesizes for 6.x objects.\n */\nexport function extractLegacyTakes(doc: FBXDocument, objectMap: FBXObjectMap, rebaseKeyframes = true): FBXAnimationStackData[] {\n    const takesNode = findDocumentNode(doc, \"Takes\");\n    if (!takesNode) {\n        return [];\n    }\n\n    // Take entries name models by their full \"Class::Name\" string; older writers may use the bare name.\n    const legacyIds = new Map<string, number>();\n    const legacyIdsByCleanName = new Map<string, number>();\n    for (const entry of objectMap.objectEntries) {\n        if (entry.legacyName !== undefined && !entry.synthetic && !legacyIds.has(entry.legacyName)) {\n            legacyIds.set(entry.legacyName, entry.id);\n            const clean = cleanFBXName(entry.legacyName);\n            if (!legacyIdsByCleanName.has(clean)) {\n                legacyIdsByCleanName.set(clean, entry.id);\n            }\n        }\n    }\n\n    const stacks: FBXAnimationStackData[] = [];\n    let syntheticId = -1000000;\n\n    for (const take of takesNode.children) {\n        if (take.name !== \"Take\") {\n            continue;\n        }\n        const name = cleanFBXName(getPropertyValue<string>(take, 0) ?? \"Take\");\n        const timeSpan = readLegacyTimeSpan(findChildByName(take, \"LocalTime\")) ?? readLegacyTimeSpan(findChildByName(take, \"ReferenceTime\"));\n\n        const curveNodes: FBXCurveNodeData[] = [];\n        const unsupportedCurveNodes: FBXUnsupportedCurveNodeData[] = [];\n        let minTime = Infinity;\n        let maxTime = -Infinity;\n        const track = (curves: FBXCurveData[]) => {\n            for (const curve of curves) {\n                for (const key of curve.keys) {\n                    if (key.time < minTime) {\n                        minTime = key.time;\n                    }\n                    if (key.time > maxTime) {\n                        maxTime = key.time;\n                    }\n                }\n            }\n        };\n\n        for (const model of take.children) {\n            if (model.name !== \"Model\") {\n                continue;\n            }\n            const rawModelName = getPropertyValue<string>(model, 0) ?? \"\";\n            const targetModelId = legacyIds.get(rawModelName) ?? legacyIdsByCleanName.get(cleanFBXName(rawModelName));\n            if (targetModelId === undefined) {\n                continue;\n            }\n\n            for (const channel of model.children) {\n                if (channel.name !== \"Channel\") {\n                    continue;\n                }\n                const channelName = getPropertyValue<string>(channel, 0) ?? \"\";\n                if (channelName === \"Transform\") {\n                    for (const sub of channel.children) {\n                        if (sub.name !== \"Channel\") {\n                            continue;\n                        }\n                        const subName = getPropertyValue<string>(sub, 0);\n                        if (subName !== \"T\" && subName !== \"R\" && subName !== \"S\") {\n                            continue;\n                        }\n                        const curves = readLegacyCompoundChannel(sub, doc.version);\n                        if (curves.length > 0) {\n                            track(curves);\n                            curveNodes.push({ type: subName, targetModelId, curves, layerIndex: 0 });\n                        }\n                    }\n                } else {\n                    const curves = readLegacyCompoundChannel(channel, doc.version);\n                    if (curves.length > 0) {\n                        track(curves);\n                        // Blend shape weights are channels named after the shape (\"name (Shape)\" before 6.0).\n                        const shapeChannelId = findLegacyShapeChannel(objectMap, targetModelId, channelName);\n                        if (shapeChannelId !== undefined) {\n                            curveNodes.push({ type: \"DeformPercent\", targetModelId: shapeChannelId, curves, layerIndex: 0 });\n                            continue;\n                        }\n                        // Light and camera properties live on the synthesized node attribute.\n                        const attributeId = LEGACY_ATTRIBUTE_CHANNELS.has(channelName) ? getChildren(objectMap, targetModelId, \"NodeAttribute\")[0]?.id : undefined;\n                        unsupportedCurveNodes.push({\n                            type: channelName,\n                            id: syntheticId--,\n                            layerIndex: 0,\n                            targetId: attributeId ?? targetModelId,\n                            propertyName: channelName,\n                            curveCount: curves.length,\n                            curves,\n                            defaultValues: {},\n                        });\n                    }\n                }\n            }\n        }\n\n        if (curveNodes.length === 0 && unsupportedCurveNodes.length === 0) {\n            continue;\n        }\n\n        const layer: FBXAnimationLayerData = {\n            name: \"BaseLayer\",\n            weight: 100,\n            normalizedWeight: 1,\n            blendMode: 0,\n            blend: makeLayerBlend(0, 100, 0, 0),\n            curveNodes,\n            unsupportedCurveNodes,\n            diagnostics: [],\n        };\n        stacks.push(finalizeAnimStack(name, [layer], curveNodes, unsupportedCurveNodes, [], minTime, maxTime, timeSpan, rebaseKeyframes));\n    }\n\n    return stacks;\n}\n\n/** Take channel names that animate light or camera attribute properties rather than the model itself. */\nconst LEGACY_ATTRIBUTE_CHANNELS = new Set([\n    \"Color\",\n    \"Intensity\",\n    \"OuterAngle\",\n    \"InnerAngle\",\n    \"ConeAngle\",\n    \"HotSpot\",\n    \"FieldOfView\",\n    \"FieldOfViewX\",\n    \"FieldOfViewY\",\n    \"FocalLength\",\n    \"NearPlane\",\n    \"FarPlane\",\n    \"OrthoZoom\",\n    \"Roll\",\n    \"FilmWidth\",\n    \"FilmHeight\",\n]);\n\n/** Finds the synthesized BlendShapeChannel of a legacy model whose shape is named like the take channel. */\nfunction findLegacyShapeChannel(objectMap: FBXObjectMap, modelId: number, channelName: string): number | undefined {\n    const suffix = \" (Shape)\";\n    const name = channelName.endsWith(suffix) ? channelName.slice(0, -suffix.length) : channelName;\n    for (const geometry of getChildren(objectMap, modelId, \"Geometry\")) {\n        for (const deformer of getChildren(objectMap, geometry.id, \"Deformer\")) {\n            if (getPropertyValue<string>(deformer.node, 2) !== \"BlendShape\") {\n                continue;\n            }\n            for (const channel of getChildren(objectMap, deformer.id, \"Deformer\")) {\n                if (getPropertyValue<string>(channel.node, 2) === \"BlendShapeChannel\" && cleanFBXName(getPropertyValue<string>(channel.node, 1) ?? \"\") === name) {\n                    return channel.id;\n                }\n            }\n        }\n    }\n    return undefined;\n}\n\nfunction readLegacyTimeSpan(node: FBXNode | undefined): { start: number; stop: number } | null {\n    if (!node) {\n        return null;\n    }\n    const start = fbxTimeToSeconds(node.properties[0]?.value);\n    const stop = fbxTimeToSeconds(node.properties[1]?.value);\n    return start !== null && stop !== null ? { start, stop } : null;\n}\n\n/** A channel either holds keys directly (scalar property) or has X/Y/Z child channels (vector property). */\nfunction readLegacyCompoundChannel(node: FBXNode, version: number): FBXCurveData[] {\n    const hasKeys = (n: FBXNode) => n.children.some((c) => c.name === \"Key\" || c.name === \"Default\");\n    if (hasKeys(node)) {\n        const keys = decodeLegacyKeys(node, version);\n        return keys.length > 0 ? [{ channel: \"d|X\", keys, ...extractCurveExtrapolation(node) }] : [];\n    }\n    const curves: FBXCurveData[] = [];\n    for (const child of node.children) {\n        if (child.name !== \"Channel\" || !hasKeys(child)) {\n            continue;\n        }\n        const axis = getPropertyValue<string>(child, 0) ?? \"X\";\n        const keys = decodeLegacyKeys(child, version);\n        if (keys.length > 0) {\n            curves.push({ channel: `d|${axis}`, keys, ...extractCurveExtrapolation(child) });\n        }\n        if (curves.length === 3) {\n            break;\n        }\n    }\n    return curves;\n}\n\n/**\n * Decodes the heterogeneous legacy `Key:` list (int64 times, double values and bare mode characters).\n * The layout per key is `time, value, mode[, params...]`, mirroring the FBX SDK's pre-7000 key encoding.\n */\nfunction decodeLegacyKeys(channel: FBXNode, version: number): FBXKeyframe[] {\n    const keyNode = findChildByName(channel, \"Key\");\n    if (!keyNode) {\n        return [];\n    }\n    const vals = keyNode.properties.map((p) => p.value);\n    const num = (v: unknown): number => (typeof v === \"number\" ? v : typeof v === \"boolean\" ? (v ? 1 : 0) : NaN);\n    const chr = (v: unknown): string => (typeof v === \"string\" ? v : typeof v === \"number\" ? String.fromCharCode(v) : typeof v === \"boolean\" ? (v ? \"\\x01\" : \"\\0\") : \"?\");\n\n    let keyVer = toNumber(findChildByName(channel, \"KeyVer\")?.properties[0]?.value) ?? 0;\n    if (keyVer <= 0) {\n        keyVer = version < 5000 ? 4003 : version < 6000 ? 4004 : 4005;\n    }\n    const keyCount = toNumber(findChildByName(channel, \"KeyCount\")?.properties[0]?.value) ?? 0;\n\n    const times: number[] = [];\n    const values: number[] = [];\n    const interp: FBXInterpolationType[] = [];\n    const constNext: boolean[] = [];\n    const leftSlope: number[] = [];\n    const rightSlope: number[] = [];\n    const leftWeight: number[] = [];\n    const rightWeight: number[] = [];\n    const autoFlag: boolean[] = [];\n    let pendingLeft = 0;\n    let pendingLeftWeight = 1 / 3;\n    let p = 0;\n\n    for (let i = 0; i < keyCount; i++) {\n        if (p + 3 > vals.length) {\n            break;\n        }\n        const time = num(vals[p]) / FBX_TIME_UNIT;\n        const value = num(vals[p + 1]);\n        const mode = chr(vals[p + 2]);\n        p += 3;\n\n        let right = 0;\n        let nextLeft = 0;\n        let weightRight = 1 / 3;\n        let nextWeightLeft = 1 / 3;\n        let auto = false;\n        let kind: FBXInterpolationType = \"cubic\";\n        let isNext = false;\n\n        if (mode === \"U\") {\n            const slopeMode = chr(vals[p]);\n            p += 1;\n            let numWeights = 1;\n            if (slopeMode === \"s\" || slopeMode === \"b\") {\n                right = num(vals[p]);\n                nextLeft = num(vals[p + 1]);\n                p += 2;\n                if (keyVer === 4003) {\n                    numWeights = 0;\n                }\n            } else if (slopeMode === \"a\") {\n                auto = true;\n                if (keyVer <= 4004) {\n                    numWeights = 0;\n                }\n            } else if (slopeMode === \"p\" || slopeMode === \"q\") {\n                auto = true;\n                p += 2;\n                numWeights = keyVer <= 4004 ? 1 : 2;\n            } else if (slopeMode === \"t\") {\n                auto = true;\n                p += 3;\n                numWeights = 0;\n            } else if (slopeMode === \"d\") {\n                auto = true;\n                p += 1;\n            } else {\n                break;\n            }\n            for (; numWeights > 0; numWeights--) {\n                const weightMode = chr(vals[p]);\n                p += 1;\n                if (weightMode === \"n\" || weightMode === \"c\") {\n                    // automatic weights\n                } else if (weightMode === \"a\") {\n                    weightRight = num(vals[p]);\n                    nextWeightLeft = num(vals[p + 1]);\n                    p += 2;\n                } else if (weightMode === \"l\") {\n                    nextWeightLeft = num(vals[p]);\n                    p += 1;\n                } else if (weightMode === \"r\") {\n                    weightRight = num(vals[p]);\n                    p += 1;\n                } else {\n                    p = vals.length;\n                    break;\n                }\n            }\n        } else if (mode === \"L\") {\n            kind = \"linear\";\n        } else if (mode === \"C\") {\n            kind = \"constant\";\n            if (keyVer >= 4004) {\n                isNext = chr(vals[p]) === \"n\";\n                p += 1;\n            }\n        } else {\n            break;\n        }\n\n        times.push(time);\n        values.push(value);\n        interp.push(kind);\n        constNext.push(isNext);\n        leftSlope.push(pendingLeft);\n        rightSlope.push(right);\n        leftWeight.push(pendingLeftWeight);\n        rightWeight.push(weightRight);\n        autoFlag.push(auto);\n        pendingLeft = nextLeft;\n        pendingLeftWeight = nextWeightLeft;\n    }\n\n    // Resolve automatic and linear tangents now that neighbouring keys are known.\n    for (let i = 0; i < times.length; i++) {\n        if (autoFlag[i]) {\n            const s =\n                i > 0 && i + 1 < times.length\n                    ? solveLegacyAutoTangent(times[i - 1], times[i], times[i + 1], values[i - 1], values[i], values[i + 1], leftWeight[i], rightWeight[i])\n                    : 0;\n            leftSlope[i] = s;\n            rightSlope[i] = s;\n        }\n        if (interp[i] === \"linear\" && i + 1 < times.length) {\n            const dt = times[i + 1] - times[i];\n            const s = dt > 0 ? (values[i + 1] - values[i]) / dt : 0;\n            rightSlope[i] = s;\n            if (!autoFlag[i + 1]) {\n                leftSlope[i + 1] = s;\n            }\n        }\n    }\n\n    return keyframesFromSlopes(times, values, interp, constNext, leftSlope, rightSlope, leftWeight, rightWeight);\n}\n\n/** Time-independent auto tangent with progressive clamping and 1/3 weights, as the SDK computes legacy 'a' keys. */\nfunction solveLegacyAutoTangent(t0: number, t1: number, t2: number, v0: number, v1: number, v2: number, weightLeft: number, weightRight: number): number {\n    if (!(t2 > t0)) {\n        return 0;\n    }\n    const slope = (v2 - v0) / (t2 - t0);\n    const sign = slope >= 0 ? 1 : -1;\n    let abs = sign * slope;\n    const rangeLeft = weightLeft * (t1 - t0);\n    const rangeRight = weightRight * (t2 - t1);\n    let maxLeft = rangeLeft > 0 ? (sign * (v1 - v0)) / rangeLeft : 0;\n    let maxRight = rangeRight > 0 ? (sign * (v2 - v1)) / rangeRight : 0;\n    if (!(maxLeft > 0)) {\n        maxLeft = 0;\n    }\n    if (!(maxRight > 0)) {\n        maxRight = 0;\n    }\n    abs = Math.min(abs, maxLeft, maxRight);\n    return sign * abs;\n}\n\n// ── Layered evaluation ─────────────────────────────────────────────────────────\n\n/**\n * Evaluates one transform channel (T, R or S) of a target at `time`, blending every animation layer of the stack the\n * way the FBX SDK does: the first layer animating the channel replaces the static value, later layers are combined\n * according to their blend mode, weight and accumulation modes.\n * @param curveNodes - Curve nodes targeting this model (any layers, any types)\n * @param layers - Stack layers, in order\n * @param type - Channel to evaluate\n * @param staticValue - Value when nothing animates the channel\n * @param rotationOrder - Rotation order of the target (for rotation composition)\n * @param time - Time in seconds\n */\nexport function evaluateLayeredChannel(\n    curveNodes: readonly FBXCurveNodeData[],\n    layers: readonly FBXAnimationLayerData[],\n    type: \"T\" | \"R\" | \"S\",\n    staticValue: readonly [number, number, number],\n    rotationOrder: number,\n    time: number\n): [number, number, number] {\n    let result: [number, number, number] = [staticValue[0], staticValue[1], staticValue[2]];\n    for (let layerIndex = 0; layerIndex < Math.max(layers.length, 1); layerIndex++) {\n        const node = curveNodes.find((cn) => cn.type === type && cn.layerIndex === layerIndex);\n        if (!node) {\n            continue;\n        }\n        const defaults = node.defaultValues ?? result;\n        const value: [number, number, number] = [\n            evaluateCurve(\n                node.curves.find((c) => c.channel === \"d|X\"),\n                time,\n                defaults[0]\n            ),\n            evaluateCurve(\n                node.curves.find((c) => c.channel === \"d|Y\"),\n                time,\n                defaults[1]\n            ),\n            evaluateCurve(\n                node.curves.find((c) => c.channel === \"d|Z\"),\n                time,\n                defaults[2]\n            ),\n        ];\n        const layer = layers[layerIndex];\n        // The base layer replaces the static value; every other layer blends onto the running result, even when the\n        // base layer does not animate this channel (then it blends with the static value), as in the SDK.\n        if (layerIndex === 0 || !layer) {\n            result = value;\n        } else {\n            let blend = layer.blend;\n            if (layer.weightCurve && blend.blended) {\n                let w = evaluateCurve(layer.weightCurve, time, layer.weight) / 100;\n                w = w < 0 ? 0 : w > 0.99999 ? 1 : w;\n                blend = { ...blend, weight: w };\n            }\n            result = combineLayerValue(result, value, blend, type, rotationOrder);\n        }\n    }\n    return result;\n}\n\n/** Curves of one animated property (or blend shape weight) contributed by one animation layer. */\nexport interface FBXLayeredPropertySource {\n    /** Index of the owning layer within the stack's layer list */\n    layerIndex: number;\n    /** Curves of the property, keyed by channel name (`d|X`, `d|DeformPercent`, ...) */\n    curves: readonly FBXCurveData[];\n    /** Default channel values stored on the curve node */\n    defaultValues?: Record<string, number>;\n}\n\n/**\n * Evaluates an animated property through the animation layers: the base layer replaces the static value, every\n * further layer blends onto the running result according to its blend mode and (possibly animated) weight, like\n * `evaluateLayeredChannel` does for transforms.\n * @param sources - Per-layer curves of the property\n * @param layers - Stack layers, in order\n * @param channels - Channel names to evaluate, in output order\n * @param staticValue - Value per channel when nothing animates it\n * @param time - Time in seconds\n * @returns One value per channel\n */\nexport function evaluateLayeredProperty(\n    sources: readonly FBXLayeredPropertySource[],\n    layers: readonly FBXAnimationLayerData[],\n    channels: readonly string[],\n    staticValue: readonly number[],\n    time: number\n): number[] {\n    const result = channels.map((_, i) => staticValue[i] ?? 0);\n    for (let layerIndex = 0; layerIndex < Math.max(layers.length, 1); layerIndex++) {\n        const source = sources.find((s) => s.layerIndex === layerIndex);\n        if (!source) {\n            continue;\n        }\n        const value = channels.map((channel, i) =>\n            evaluateCurve(\n                source.curves.find((c) => c.channel === channel),\n                time,\n                source.defaultValues?.[channel] ?? result[i]\n            )\n        );\n        const layer = layers[layerIndex];\n        if (layerIndex === 0 || !layer) {\n            for (let i = 0; i < result.length; i++) {\n                result[i] = value[i];\n            }\n            continue;\n        }\n        let blend = layer.blend;\n        if (layer.weightCurve && blend.blended) {\n            let w = evaluateCurve(layer.weightCurve, time, layer.weight) / 100;\n            w = w < 0 ? 0 : w > 0.99999 ? 1 : w;\n            blend = { ...blend, weight: w };\n        }\n        for (let i = 0; i < result.length; i++) {\n            result[i] = combineLayerValue([result[i], 0, 0], [value[i], 0, 0], blend, \"other\", 0)[0];\n        }\n    }\n    return result;\n}\n\n/**\n * True when every curve of the given channel is inside a constant (stepped) segment at `time`, so a baked key at\n * that time should hold its value instead of interpolating towards the next sample.\n */\nexport function isChannelSteppedAt(curveNodes: readonly FBXCurveNodeData[], type: \"T\" | \"R\" | \"S\", time: number): boolean {\n    let sawCurve = false;\n    for (const node of curveNodes) {\n        if (node.type !== type) {\n            continue;\n        }\n        for (const curve of node.curves) {\n            const keys = curve.keys;\n            if (keys.length < 2) {\n                continue;\n            }\n            sawCurve = true;\n            // Outside the key range the curve extrapolates continuously; only interior constant segments step.\n            if (time < keys[0].time || time >= keys[keys.length - 1].time) {\n                return false;\n            }\n            let i = 0;\n            while (i + 1 < keys.length && keys[i + 1].time <= time) {\n                i++;\n            }\n            if (keys[i].interpolation !== \"constant\") {\n                return false;\n            }\n        }\n    }\n    return sawCurve;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { getPropertyEntries } from \"./propertyTemplates\";\nimport { type FBXNode, findChildByName, getPropertyValue, cleanFBXName, getNodeArray } from \"../types/fbxTypes\";\n\nimport { type FBXObjectMap, getChildren } from \"./connections\";\n\n/** A single morph target (shape) within a blend shape channel */\nexport interface FBXShapeData {\n    /** Sparse vertex indices affected by this shape */\n    indices: Uint32Array;\n    /** Absolute vertex positions for affected vertices [x,y,z,...] */\n    vertices: Float64Array;\n    /** Normals for affected vertices [x,y,z,...] (optional) */\n    normals: Float64Array | null;\n}\n\nexport interface FBXBlendShapeDiagnostic {\n    type: \"full-weights-mismatch\" | \"missing-full-weights\";\n    message: string;\n    channelId: number;\n    channelName: string;\n}\n\n/** A blend shape channel (one animatable morph target) */\nexport interface FBXBlendShapeChannelData {\n    /** Channel name */\n    name: string;\n    /** Channel node ID */\n    id: number;\n    /** Default weight (0-100 in FBX) */\n    deformPercent: number;\n    /** Shape geometry (typically one per channel, but FBX supports in-between shapes) */\n    shapes: FBXShapeData[];\n    /** In-between full weights in FBX DeformPercent units (0-100), one per shape when present */\n    fullWeights: number[] | null;\n    /** Recoverable blend-shape diagnostics */\n    diagnostics: FBXBlendShapeDiagnostic[];\n}\n\n/** A blend shape deformer attached to a geometry */\nexport interface FBXBlendShapeData {\n    /** Deformer ID */\n    id: number;\n    /** Geometry ID this blend shape is attached to */\n    geometryId: number;\n    /** Channels (each is an animatable morph target) */\n    channels: FBXBlendShapeChannelData[];\n}\n\n/**\n * Extract all blend shape deformers from the FBX scene.\n */\nexport function extractBlendShapes(objectMap: FBXObjectMap): FBXBlendShapeData[] {\n    const blendShapes: FBXBlendShapeData[] = [];\n\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"Deformer\" && getPropertyValue<string>(node, 2) === \"BlendShape\") {\n            const bs = extractBlendShape(id, node, objectMap);\n            if (bs) {\n                blendShapes.push(bs);\n            }\n        }\n    }\n\n    return blendShapes;\n}\n\nfunction extractBlendShape(deformerId: number, _deformerNode: FBXNode, objectMap: FBXObjectMap): FBXBlendShapeData | null {\n    // Find the geometry this blend shape is attached to\n    const parent = objectMap.parentOf.get(deformerId);\n    if (!parent) {\n        return null;\n    }\n\n    const parentNode = objectMap.objects.get(parent.id);\n    if (!parentNode || parentNode.name !== \"Geometry\") {\n        return null;\n    }\n\n    const geometryId = parent.id;\n\n    // Find BlendShapeChannel children\n    const channels: FBXBlendShapeChannelData[] = [];\n    const channelChildren = getChildren(objectMap, deformerId, \"Deformer\");\n\n    for (const { id: channelId, node: channelNode } of channelChildren) {\n        const subType = getPropertyValue<string>(channelNode, 2);\n        if (subType !== \"BlendShapeChannel\") {\n            continue;\n        }\n\n        const channelName = cleanFBXName(getPropertyValue<string>(channelNode, 1) ?? \"MorphTarget\");\n\n        // Read DeformPercent from Properties70\n        let deformPercent = 0;\n        for (const entry of getPropertyEntries(channelNode)) {\n            if (entry.name === \"DeformPercent\" && typeof entry.values[0] === \"number\") {\n                deformPercent = entry.values[0];\n            }\n        }\n\n        const rawFullWeights = extractFullWeights(channelNode);\n\n        // Find connected Shape geometries\n        const shapes: FBXShapeData[] = [];\n        const shapeChildren = getChildren(objectMap, channelId, \"Geometry\");\n\n        for (const { node: shapeNode } of shapeChildren) {\n            const shapeSubType = getPropertyValue<string>(shapeNode, 2);\n            if (shapeSubType !== \"Shape\") {\n                continue;\n            }\n\n            const shape = extractShape(shapeNode);\n            if (shape) {\n                shapes.push(shape);\n            }\n        }\n\n        if (shapes.length > 0) {\n            const diagnostics: FBXBlendShapeDiagnostic[] = [];\n            const fullWeights = normalizeFullWeights(rawFullWeights, shapes, channelId, channelName, diagnostics);\n            channels.push({\n                name: channelName,\n                id: channelId,\n                deformPercent,\n                shapes: sortShapesByFullWeight(shapes, fullWeights),\n                fullWeights: fullWeights ? [...fullWeights].sort((a, b) => a - b) : null,\n                diagnostics,\n            });\n        }\n    }\n\n    if (channels.length === 0) {\n        return null;\n    }\n\n    return {\n        id: deformerId,\n        geometryId,\n        channels,\n    };\n}\n\nfunction extractFullWeights(channelNode: FBXNode): number[] | null {\n    const fullWeightsNode = findChildByName(channelNode, \"FullWeights\");\n    const rawFullWeights = getNodeArray(fullWeightsNode);\n    if (!rawFullWeights) {\n        return null;\n    }\n\n    if (rawFullWeights instanceof Float64Array || rawFullWeights instanceof Float32Array || rawFullWeights instanceof Int32Array) {\n        return Array.from(rawFullWeights, (value) => Number(value));\n    }\n    return null;\n}\n\nfunction normalizeFullWeights(\n    fullWeights: number[] | null,\n    shapes: FBXShapeData[],\n    channelId: number,\n    channelName: string,\n    diagnostics: FBXBlendShapeDiagnostic[]\n): number[] | null {\n    if (!fullWeights) {\n        if (shapes.length > 1) {\n            diagnostics.push({\n                type: \"missing-full-weights\",\n                message: \"Blend shape channel has multiple shapes but no FullWeights; using the first shape for compatibility.\",\n                channelId,\n                channelName,\n            });\n        }\n        return null;\n    }\n\n    if (fullWeights.length !== shapes.length) {\n        if (shapes.length === 1) {\n            return null;\n        }\n\n        diagnostics.push({\n            type: \"full-weights-mismatch\",\n            message: `FullWeights length ${fullWeights.length} does not match shape count ${shapes.length}; using the first shape for compatibility.`,\n            channelId,\n            channelName,\n        });\n        return null;\n    }\n\n    return fullWeights;\n}\n\nfunction sortShapesByFullWeight(shapes: FBXShapeData[], fullWeights: number[] | null): FBXShapeData[] {\n    if (!fullWeights || fullWeights.length !== shapes.length) {\n        return shapes.length > 1 ? [shapes[0]] : shapes;\n    }\n\n    return shapes\n        .map((shape, index) => ({ shape, weight: fullWeights[index] }))\n        .sort((a, b) => a.weight - b.weight)\n        .map((entry) => entry.shape);\n}\n\nfunction extractShape(shapeNode: FBXNode): FBXShapeData | null {\n    // Shape has: Indexes (sparse vertex indices), Vertices (delta offsets from base), Normals (optional delta)\n    const indexesNode = findChildByName(shapeNode, \"Indexes\");\n    const verticesNode = findChildByName(shapeNode, \"Vertices\");\n\n    if (!indexesNode || !verticesNode) {\n        return null;\n    }\n\n    const rawIndices = getNodeArray(indexesNode);\n    const rawVertices = getNodeArray(verticesNode);\n\n    if (!rawIndices || !rawVertices) {\n        return null;\n    }\n\n    const indices = toUint32Array(rawIndices);\n    if (!indices) {\n        return null;\n    }\n\n    // Convert vertices\n    let vertices: Float64Array;\n    if (rawVertices instanceof Float64Array) {\n        vertices = rawVertices;\n    } else if (rawVertices instanceof Float32Array) {\n        vertices = new Float64Array(rawVertices);\n    } else {\n        return null;\n    }\n\n    // Optional normals\n    let normals: Float64Array | null = null;\n    const normalsNode = findChildByName(shapeNode, \"Normals\");\n    if (normalsNode) {\n        const rawNormals = getNodeArray(normalsNode);\n        if (rawNormals instanceof Float64Array) {\n            normals = rawNormals;\n        } else if (rawNormals instanceof Float32Array) {\n            normals = new Float64Array(rawNormals);\n        }\n    }\n\n    return { indices, vertices, normals };\n}\n\nfunction toUint32Array(value: unknown): Uint32Array | null {\n    if (value instanceof Uint32Array) {\n        return value;\n    }\n    if (value instanceof Int32Array || value instanceof Float32Array || value instanceof Float64Array) {\n        const result = new Uint32Array(value.length);\n        for (let i = 0; i < value.length; i++) {\n            result[i] = value[i];\n        }\n        return result;\n    }\n    return null;\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXNode, cleanFBXName, getPropertyValue } from \"../types/fbxTypes\";\n\nimport { type FBXObjectMap } from \"./connections\";\n\nexport type FBXSceneDiagnosticType =\n    | \"unsupported-constraint\"\n    | \"unsupported-helper\"\n    | \"unsupported-deformer\"\n    | \"unsupported-node-attribute\"\n    | \"unsupported-pose\"\n    | \"unsupported-layered-texture\"\n    | \"connection-graph\";\n\nexport interface FBXSceneDiagnostic {\n    type: FBXSceneDiagnosticType;\n    message: string;\n    objectId?: number;\n    objectName?: string;\n    nodeName?: string;\n    subType?: string;\n    /** Number of accepted parent graph edges for objectId, when objectId is known. */\n    parentCount?: number;\n    childCount?: number;\n}\n\nconst HELPER_NODE_NAMES = new Set([\"Character\", \"CharacterPose\", \"ControlSet\", \"ControlSetPlug\"]);\n\n/** Node attribute subtypes that are converted (or intentionally represented as plain transform nodes). */\nconst HANDLED_NODE_ATTRIBUTES = new Set([\n    \"Camera\",\n    \"Light\",\n    \"Null\",\n    \"LodGroup\",\n    \"LimbNode\",\n    \"Limb\",\n    \"Root\",\n    \"Skeleton\",\n    \"Marker\",\n    \"CameraSwitcher\",\n    \"Mesh\",\n    \"NurbsCurve\",\n    \"NurbsSurface\",\n    \"TrimNurbsSurface\",\n    \"Line\",\n    \"Boundary\",\n]);\n\nexport function extractSceneDiagnostics(objectMap: FBXObjectMap): FBXSceneDiagnostic[] {\n    const diagnostics: FBXSceneDiagnostic[] = objectMap.diagnostics.map((diagnostic) => ({\n        type: \"connection-graph\",\n        message: diagnostic.message,\n        objectId: diagnostic.childId,\n        subType: diagnostic.reason,\n        parentCount: diagnostic.childId === undefined ? undefined : objectMap.connections.filter((connection) => connection.childId === diagnostic.childId).length,\n    }));\n\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        const subType = getPropertyValue<string>(node, 2) ?? \"\";\n        if (node.name === \"Constraint\") {\n            // Aim, parent, position, rotation and scale constraints are evaluated at runtime; IK chains are not.\n            const typeChild = node.children.find((c) => c.name === \"Type\");\n            const constraintType = (typeChild ? getPropertyValue<string>(typeChild, 0) : undefined) ?? subType;\n            const evaluated = new Set([\"Aim\", \"Parent-Child\", \"Position From Positions\", \"Rotation From Rotations\", \"Scale From Scales\"]);\n            if (!evaluated.has(constraintType)) {\n                diagnostics.push(\n                    createObjectDiagnostic(\n                        objectMap,\n                        id,\n                        node,\n                        \"unsupported-constraint\",\n                        `Constraint '${constraintType || cleanFBXName(getPropertyValue<string>(node, 1) ?? \"\")}' is preserved as metadata but not evaluated at runtime.`\n                    )\n                );\n            }\n            continue;\n        }\n\n        if (HELPER_NODE_NAMES.has(node.name)) {\n            diagnostics.push(\n                createObjectDiagnostic(objectMap, id, node, \"unsupported-helper\", `${node.name} helper data is preserved as diagnostic data but not evaluated at runtime.`)\n            );\n            continue;\n        }\n\n        if (node.name === \"LayeredTexture\") {\n            diagnostics.push(\n                createObjectDiagnostic(\n                    objectMap,\n                    id,\n                    node,\n                    \"unsupported-layered-texture\",\n                    \"LayeredTexture is preserved as diagnostic data; runtime texture layer blending is not implemented.\"\n                )\n            );\n            continue;\n        }\n\n        if (node.name === \"Pose\" && subType !== \"BindPose\") {\n            diagnostics.push(\n                createObjectDiagnostic(objectMap, id, node, \"unsupported-pose\", `Pose subtype '${subType}' is preserved as diagnostic data but not evaluated at runtime.`)\n            );\n            continue;\n        }\n\n        if (node.name === \"Deformer\" && !isSupportedDeformer(subType)) {\n            diagnostics.push(\n                createObjectDiagnostic(objectMap, id, node, \"unsupported-deformer\", `Deformer subtype '${subType}' is preserved as diagnostic data but not evaluated at runtime.`)\n            );\n            continue;\n        }\n\n        if (node.name === \"NodeAttribute\" && subType && !HANDLED_NODE_ATTRIBUTES.has(subType)) {\n            diagnostics.push(\n                createObjectDiagnostic(\n                    objectMap,\n                    id,\n                    node,\n                    \"unsupported-node-attribute\",\n                    `NodeAttribute subtype '${subType}' is preserved as diagnostic data but not converted to a Babylon object.`\n                )\n            );\n        }\n    }\n\n    return diagnostics;\n}\n\nfunction isSupportedDeformer(subType: string): boolean {\n    return subType === \"Skin\" || subType === \"Cluster\" || subType === \"BlendShape\" || subType === \"BlendShapeChannel\";\n}\n\nfunction createObjectDiagnostic(objectMap: FBXObjectMap, id: number, node: FBXNode, type: FBXSceneDiagnosticType, message: string): FBXSceneDiagnostic {\n    return {\n        type,\n        message,\n        objectId: id,\n        objectName: cleanFBXName(getPropertyValue<string>(node, 1) ?? node.name),\n        nodeName: node.name,\n        subType: getPropertyValue<string>(node, 2) ?? \"\",\n        parentCount: objectMap.connections.filter((connection) => connection.childId === id).length,\n        childCount: objectMap.childrenOf.get(id)?.length ?? 0,\n    };\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { extractNodeTransform } from \"./nodeTransform\";\nimport {\n    extractUserProperties,\n    getPropertyEntries,\n    type FBXUserPropertyValue,\n    extractPropertyTemplates,\n    getPropertyTemplate,\n    resolveNumberProperty,\n    resolvePropertyValue,\n    resolveVector3Property,\n    type FBXPropertyTemplate,\n    type FBXPropertyTemplateMap,\n} from \"./propertyTemplates\";\nimport { type FBXDocument, type FBXNode, findDocumentNode, findChildByName, getPropertyValue, cleanFBXName, getNodeArray } from \"../types/fbxTypes\";\n\nimport { resolveConnections, getChildren, type FBXObjectMap } from \"./connections\";\nimport { extractGeometry, type FBXGeometryData } from \"./geometry\";\nimport { extractLineGeometry, extractNurbsCurveGeometry, nurbsSurfaceToGeometry, type FBXCurveGeometryData } from \"./nurbs\";\nimport { isLegacyDocument, upgradeLegacyDocument } from \"./legacyDocument\";\nimport { extractConstraints, type FBXConstraintData } from \"./constraints\";\nimport { extractMaterial, extractTextureRef, type FBXMaterialData } from \"./materials\";\nimport { extractSkins, type FBXSkinData } from \"./skeleton\";\nimport { resolveRigs, type FBXRigData } from \"./rig\";\nimport { extractAnimations, type FBXAnimationStackData } from \"./animation\";\nimport { extractBlendShapes, type FBXBlendShapeData } from \"./blendShapes\";\nimport { extractSceneDiagnostics, type FBXSceneDiagnostic } from \"./sceneDiagnostics\";\n\n/** Represents a model (transform node) in the FBX scene */\nexport interface FBXModelData {\n    id: number;\n    name: string;\n    subType: string;\n    /** Geometry attached to this model (meshes and tessellated NURBS surfaces) */\n    geometry?: FBXGeometryData;\n    /** Curve geometry attached to this model (Line and NurbsCurve) */\n    curve?: FBXCurveGeometryData;\n    /** Materials assigned to this model */\n    materials: FBXMaterialData[];\n    /** Child models */\n    children: FBXModelData[];\n    /** Transform properties */\n    translation: [number, number, number];\n    rotation: [number, number, number];\n    scale: [number, number, number];\n    /** PreRotation (applied before Lcl Rotation, in degrees) */\n    preRotation: [number, number, number];\n    /** PostRotation (applied after Lcl Rotation, inverted, in degrees) */\n    postRotation: [number, number, number];\n    /** RotationPivot — point around which rotation occurs */\n    rotationPivot: [number, number, number];\n    /** ScalingPivot — point around which scaling occurs */\n    scalingPivot: [number, number, number];\n    /** RotationOffset — translation after rotation pivot */\n    rotationOffset: [number, number, number];\n    /** ScalingOffset — translation after scaling pivot */\n    scalingOffset: [number, number, number];\n    /** Geometric transforms — applied to geometry only, do not affect children */\n    geometricTranslation: [number, number, number];\n    geometricRotation: [number, number, number];\n    geometricScaling: [number, number, number];\n    /** Rotation order: 0=XYZ, 1=XZY, 2=YZX, 3=YXZ, 4=ZXY, 5=ZYX */\n    rotationOrder: number;\n    /** FBX transform inheritance mode. 0=RrSs, 1=RSrs, 2=Rrs */\n    inheritType: number;\n    /** Whether backface culling is disabled (\"CullingOff\") */\n    cullingOff: boolean;\n    /** User-defined custom properties from Properties70 */\n    customProperties?: Record<string, FBXUserPropertyValue>;\n    /** LOD group settings when this model is a LodGroup; children are the levels in order */\n    lodGroup?: FBXLodGroupData;\n    /** Display layer (CollectionExclusive) the model belongs to */\n    displayLayer?: FBXDisplayLayerData;\n    /** Recoverable model import diagnostics */\n    diagnostics: string[];\n}\n\n/** LOD group settings (NodeAttribute \"LodGroup\") */\nexport interface FBXLodGroupData {\n    /** Switch distance for level i+1 (level 0 has none). In scene units, or percent of screen when `relative`. */\n    thresholds: number[];\n    /** ThresholdsUsedAsPercentage */\n    relative: boolean;\n    /** DisplayLevels|LevelN: 0 use LOD, 1 show, 2 hide */\n    displayLevels: number[];\n}\n\n/** Display layer (CollectionExclusive \"DisplayLayer\") */\nexport interface FBXDisplayLayerData {\n    id: number;\n    name: string;\n    show: boolean;\n    freeze: boolean;\n    color: [number, number, number];\n    modelIds: number[];\n}\n\n/** One member of a selection set: a model, optionally with a component selection on its mesh */\nexport interface FBXSelectionNodeData {\n    modelId: number;\n    /** IsTheNodeInSet: the whole node is selected (as opposed to only components) */\n    includeNode: boolean;\n    /** Selected control point indices (VertexIndexArray) */\n    vertices?: number[];\n    /** Selected edge indices (EdgeIndexArray) */\n    edges?: number[];\n    /** Selected polygon indices (PolygonIndexArray) */\n    faces?: number[];\n}\n\n/** Selection set (Collection \"SelectionSet\") */\nexport interface FBXSelectionSetData {\n    id: number;\n    name: string;\n    members: FBXSelectionNodeData[];\n}\n\n/** Camera data extracted from FBX */\nexport interface FBXCameraData {\n    /** Model ID this camera is attached to */\n    modelId: number;\n    /** NodeAttribute object ID (animation curves target this) */\n    attributeId: number;\n    /** Camera name */\n    name: string;\n    /** Vertical field of view in degrees */\n    fieldOfView: number;\n    /** Horizontal field of view in degrees */\n    fieldOfViewX: number;\n    /** ApertureMode: 0 horizontal and vertical, 1 horizontal, 2 vertical, 3 focal length */\n    apertureMode: number;\n    /** Aperture (film gate after gate fit) size in inches */\n    apertureSizeInch: [number, number];\n    /** Orthographic view size (width, height) in scene units */\n    orthographicSize: [number, number];\n    /** Near clip plane */\n    nearPlane: number;\n    /** Far clip plane */\n    farPlane: number;\n    /** Aspect ratio (width/height), 0 = use viewport */\n    aspectRatio: number;\n    /** Projection type */\n    projectionType: \"perspective\" | \"orthographic\";\n    /** Focal length in millimeters when present */\n    focalLength?: number;\n    /** Filmback width in inches when present */\n    filmWidth?: number;\n    /** Filmback height in inches when present */\n    filmHeight?: number;\n    /** Orthographic zoom/height when present */\n    orthoZoom?: number;\n    /** Camera roll in degrees when present */\n    roll?: number;\n    /** User-defined properties on the camera attribute */\n    userProperties?: Record<string, FBXUserPropertyValue>;\n    /** Known unsupported or unrecognized camera properties */\n    unknownProperties: string[];\n    /** Recoverable camera import diagnostics */\n    diagnostics: string[];\n}\n\n/** Light data extracted from FBX */\nexport interface FBXLightData {\n    /** Model ID this light is attached to */\n    modelId: number;\n    /** NodeAttribute object ID (animation curves target this) */\n    attributeId: number;\n    /** Light name */\n    name: string;\n    /** Light type: 0=Point, 1=Directional, 2=Spot */\n    lightType: number;\n    /** Color [r,g,b] 0-1 */\n    color: [number, number, number];\n    /** Intensity multiplier */\n    intensity: number;\n    /** Cone angle in degrees (for spot lights) */\n    coneAngle: number;\n    /** Decay type: 0=None, 1=Linear, 2=Quadratic */\n    decayType: number;\n    /** Inner cone angle in degrees for spot lights */\n    innerAngle?: number;\n    /** Outer cone angle in degrees for spot lights */\n    outerAngle?: number;\n    /** Distance at which FBX attenuation starts; preserved as metadata */\n    decayStart?: number;\n    /** Whether FBX near attenuation is enabled */\n    enableNearAttenuation?: boolean;\n    /** Whether FBX far attenuation is enabled */\n    enableFarAttenuation?: boolean;\n    /** Whether the source light requested shadow casting */\n    castShadows?: boolean;\n    /** Near/far attenuation ranges in scene units (when enabled) */\n    nearAttenuationStart?: number;\n    nearAttenuationEnd?: number;\n    farAttenuationStart?: number;\n    farAttenuationEnd?: number;\n    /** Area light shape: 0 rectangle, 1 sphere */\n    areaLightShape?: number;\n    /** User-defined properties on the light attribute */\n    userProperties?: Record<string, FBXUserPropertyValue>;\n    /** Known unsupported or unrecognized light properties */\n    unknownProperties: string[];\n    /** Recoverable light import diagnostics */\n    diagnostics: string[];\n}\n\n/** Result of interpreting an FBX document */\nexport interface FBXSceneData {\n    /** All root-level models */\n    rootModels: FBXModelData[];\n    /** All geometries in the scene */\n    geometries: FBXGeometryData[];\n    /** All curve geometries (lines and tessellated NURBS curves) */\n    curves: FBXCurveGeometryData[];\n    /** All materials in the scene */\n    materials: FBXMaterialData[];\n    /** Skin deformers (skeletons + vertex weights) */\n    skins: FBXSkinData[];\n    /** Resolved deformation rigs shared by one or more skins */\n    rigs: FBXRigData[];\n    /** Blend shape deformers (morph targets) */\n    blendShapes: FBXBlendShapeData[];\n    /** Animation stacks (clips) */\n    animations: FBXAnimationStackData[];\n    /** Cameras */\n    cameras: FBXCameraData[];\n    /** Lights */\n    lights: FBXLightData[];\n    /** Scene-level unsupported feature diagnostics */\n    diagnostics: FBXSceneDiagnostic[];\n    /** Constraints (aim, parent, position, rotation, scale, IK) */\n    constraints: FBXConstraintData[];\n    /** Display layers */\n    displayLayers: FBXDisplayLayerData[];\n    /** Selection sets */\n    selectionSets: FBXSelectionSetData[];\n    /** Global settings */\n    upAxis: number;\n    upAxisSign: number;\n    frontAxis: number;\n    frontAxisSign: number;\n    coordAxis: number;\n    coordAxisSign: number;\n    unitScaleFactor: number;\n    /** Scene frame rate derived from GlobalSettings TimeMode / CustomFrameRate */\n    frameRate: number;\n}\n\n/**\n * Interpret a parsed FBX document into scene data.\n */\n/** Options controlling how the document is interpreted. */\nexport interface FBXInterpretOptions {\n    /** Segments per knot span when tessellating NURBS surfaces; defaults to the Step stored in the file */\n    nurbsSubdivision?: number;\n    /** Shift every clip so its first key sits at time 0 (default true); false keeps the authored times */\n    rebaseKeyframes?: boolean;\n}\n\n/**\n * Tessellated NURBS vertices carry no control point mapping, so skin clusters and blend shapes bound to the surface\n * cannot be applied; they are reported and the surface is imported undeformed.\n */\nfunction flagNurbsDeformers(objectMap: FBXObjectMap, geometryId: number, geometry: FBXGeometryData): void {\n    const kinds = getChildren(objectMap, geometryId, \"Deformer\")\n        .map((d) => getPropertyValue<string>(d.node, 2) ?? \"\")\n        .filter((kind) => kind === \"Skin\" || kind === \"BlendShape\");\n    if (kinds.length === 0) {\n        return;\n    }\n    geometry.diagnostics.push({\n        type: \"nurbs-deformer-ignored\",\n        message: `${Array.from(new Set(kinds)).join(\" and \")} deformer on NURBS surface '${geometry.name}' is ignored: the tessellated mesh has no control point mapping.`,\n    });\n}\n\nexport function interpretFBX(doc: FBXDocument, options: FBXInterpretOptions = {}): FBXSceneData {\n    if (isLegacyDocument(doc)) {\n        doc = upgradeLegacyDocument(doc);\n    }\n    const objectMap = resolveConnections(doc);\n    const propertyTemplates = extractPropertyTemplates(doc);\n\n    // Extract global settings\n    const globalSettings = extractGlobalSettings(doc);\n\n    // Extract all materials\n    const materials: FBXMaterialData[] = [];\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"Material\") {\n            materials.push(extractMaterial(node, id, objectMap, propertyTemplates));\n        }\n    }\n\n    attachLegacyLayerTextures(objectMap, materials, propertyTemplates);\n\n    // Extract all geometries\n    const geometries: FBXGeometryData[] = [];\n    const curves: FBXCurveGeometryData[] = [];\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"Geometry\") {\n            const subType = getPropertyValue<string>(node, 2);\n            if (subType === \"Mesh\") {\n                const geometry = extractGeometry(node, id);\n                // Edge-only or empty meshes have nothing to render; keep the node but drop the mesh.\n                if (geometry.positions.length > 0 && geometry.indices.length > 0) {\n                    geometries.push(geometry);\n                }\n            } else if (subType === \"NurbsSurface\") {\n                const geometry = nurbsSurfaceToGeometry(node, id, options.nurbsSubdivision);\n                if (geometry) {\n                    flagNurbsDeformers(objectMap, id, geometry);\n                    geometries.push(geometry);\n                }\n            } else if (subType === \"TrimNurbsSurface\") {\n                // The trimmed surface is rendered untrimmed: the underlying NurbsSurface is a child of the trim.\n                const surfaceChild = getChildren(objectMap, id, \"Geometry\").find((child) => getPropertyValue<string>(child.node, 2) === \"NurbsSurface\");\n                const geometry = surfaceChild ? nurbsSurfaceToGeometry(surfaceChild.node, id, options.nurbsSubdivision) : null;\n                if (geometry) {\n                    flagNurbsDeformers(objectMap, id, geometry);\n                    geometry.diagnostics.push({\n                        type: \"nurbs-trim-ignored\",\n                        message: `Trim curves of NURBS surface '${geometry.name}' are ignored; the surface is rendered untrimmed.`,\n                    });\n                    geometries.push(geometry);\n                }\n            } else if (subType === \"NurbsCurve\") {\n                curves.push(extractNurbsCurveGeometry(node, id));\n            } else if (subType === \"Line\") {\n                curves.push(extractLineGeometry(node, id));\n            }\n        }\n    }\n\n    // Extract skeleton/skinning data\n    const skins = extractSkins(objectMap, propertyTemplates);\n    const rigs = resolveRigs(objectMap, skins);\n\n    // Extract blend shape data\n    const blendShapes = extractBlendShapes(objectMap);\n\n    // Extract animation data\n    const animations = extractAnimations(objectMap, doc, { rebaseKeyframes: options.rebaseKeyframes ?? true });\n\n    // Extract cameras and lights from NodeAttribute objects\n    const cameras = extractCameras(objectMap, propertyTemplates);\n    const lights = extractLights(objectMap, propertyTemplates);\n    const diagnostics = extractSceneDiagnostics(objectMap);\n    const constraints = extractConstraints(objectMap);\n\n    // Build model hierarchy\n    const rootModels = buildModelHierarchy(objectMap, geometries, curves, materials, propertyTemplates);\n    const { displayLayers, selectionSets } = extractCollections(objectMap, rootModels);\n\n    return {\n        rootModels,\n        displayLayers,\n        selectionSets,\n        constraints,\n        geometries,\n        curves,\n        materials,\n        skins,\n        rigs,\n        blendShapes,\n        animations,\n        cameras,\n        lights,\n        diagnostics,\n        ...globalSettings,\n    };\n}\n\n// ── Legacy textures ────────────────────────────────────────────────────────────\n\n/**\n * Pre-7000 files connect textures to the Model and select them per polygon through the mesh's LayerElementTexture\n * (TextureId indexes the model's textures), instead of connecting textures to material properties. Assign those\n * textures to the diffuse slot of the material used by the same polygons.\n */\nfunction attachLegacyLayerTextures(objectMap: FBXObjectMap, materials: FBXMaterialData[], templates: FBXPropertyTemplateMap): void {\n    const materialById = new Map(materials.map((m) => [m.id, m] as const));\n    const textureTemplate = getPropertyTemplate(templates, \"Texture\", \"FbxFileTexture\") ?? getPropertyTemplate(templates, \"Texture\");\n    for (const [modelId, modelNode] of Array.from(objectMap.objects)) {\n        if (modelNode.name !== \"Model\") {\n            continue;\n        }\n        const textureChildren = getChildren(objectMap, modelId, \"Texture\");\n        if (textureChildren.length === 0) {\n            continue;\n        }\n        const modelMaterials = getChildren(objectMap, modelId, \"Material\")\n            .filter((c) => !c.propertyName)\n            .map((c) => materialById.get(c.id))\n            .filter((m): m is FBXMaterialData => m !== undefined);\n        if (modelMaterials.length === 0) {\n            continue;\n        }\n        const geometryNode = getChildren(objectMap, modelId, \"Geometry\")[0]?.node ?? modelNode;\n        const materialLayer = findChildByName(geometryNode, \"LayerElementMaterial\");\n        const materialIds = materialLayer ? getNodeArray(findChildByName(materialLayer, \"Materials\")) : null;\n\n        // Each texture kind has its own layer element: LayerElementTexture (diffuse), LayerElementEmissiveTextures,\n        // LayerElementSpecularTextures, LayerElementBumpTextures, ...\n        const slotForElement = (elementName: string): { prop: string; fbx: keyof FBXMaterialData[\"model\"][\"fbx\"]; pbr: keyof FBXMaterialData[\"model\"][\"pbr\"] } | null => {\n            const kind = elementName.replace(/^LayerElement/, \"\").replace(/Textures?$/, \"\");\n            switch (kind) {\n                case \"\":\n                case \"Diffuse\":\n                    return { prop: \"DiffuseColor\", fbx: \"diffuseColor\", pbr: \"baseColor\" };\n                case \"Emissive\":\n                    return { prop: \"EmissiveColor\", fbx: \"emissionColor\", pbr: \"emissionColor\" };\n                case \"Specular\":\n                    return { prop: \"SpecularColor\", fbx: \"specularColor\", pbr: \"specularColor\" };\n                case \"Ambient\":\n                    return { prop: \"AmbientColor\", fbx: \"ambientColor\", pbr: \"ambientOcclusion\" };\n                case \"Bump\":\n                case \"NormalMap\":\n                    return { prop: \"NormalMap\", fbx: \"normalMap\", pbr: \"normalMap\" };\n                case \"Transparent\":\n                    return { prop: \"TransparentColor\", fbx: \"transparencyColor\", pbr: \"opacity\" };\n                case \"Reflection\":\n                    return { prop: \"ReflectionColor\", fbx: \"reflectionColor\", pbr: \"specularColor\" };\n                case \"Shininess\":\n                    return { prop: \"ShininessExponent\", fbx: \"specularExponent\", pbr: \"roughness\" };\n                case \"Displacement\":\n                    return { prop: \"DisplacementColor\", fbx: \"displacement\", pbr: \"displacementMap\" };\n                default:\n                    return null;\n            }\n        };\n\n        const layerElements = geometryNode.children.filter((c) => /^LayerElement\\w*Textures?$/.test(c.name));\n        const textureRefs = textureChildren.map(({ id, node }) => extractTextureRef(id, node, undefined, objectMap, textureTemplate));\n        const assign = (materialIndex: number, textureIndex: number, slot: NonNullable<ReturnType<typeof slotForElement>>) => {\n            const material = modelMaterials[materialIndex];\n            const source = textureRefs[textureIndex];\n            if (!material || !source || material.textures.some((t) => t.propertyName === slot.prop)) {\n                return;\n            }\n            const ref = { ...source, propertyName: slot.prop };\n            material.textures.push(ref);\n            const fbxMap = (material.model.fbx[slot.fbx] ??= { valueComponents: 0, textureEnabled: false });\n            fbxMap.texture = ref;\n            fbxMap.textureEnabled = true;\n            const pbrMap = (material.model.pbr[slot.pbr] ??= { valueComponents: 0, textureEnabled: false });\n            pbrMap.texture = ref;\n            pbrMap.textureEnabled = true;\n        };\n\n        if (layerElements.length === 0) {\n            // No layer element: a single texture on a single-material model is the diffuse map.\n            if (modelMaterials.length === 1 && textureRefs.length === 1) {\n                assign(0, 0, slotForElement(\"LayerElementTexture\")!);\n            }\n            continue;\n        }\n        for (const element of layerElements) {\n            const slot = slotForElement(element.name);\n            const textureIds = getNodeArray(findChildByName(element, \"TextureId\"));\n            if (!slot || !textureIds || textureIds.length === 0) {\n                continue;\n            }\n            const polygonCount = Math.max(textureIds.length, materialIds?.length ?? 0);\n            for (let poly = 0; poly < polygonCount; poly++) {\n                const texIndex = textureIds[Math.min(poly, textureIds.length - 1)];\n                const matIndex = materialIds && materialIds.length > 0 ? materialIds[Math.min(poly, materialIds.length - 1)] : 0;\n                if (texIndex >= 0) {\n                    assign(matIndex, texIndex, slot);\n                }\n            }\n        }\n    }\n}\n\n// ── Model Hierarchy ────────────────────────────────────────────────────────────\n\nconst MAX_MODEL_DEPTH = 512;\n\nfunction buildModelHierarchy(\n    objectMap: FBXObjectMap,\n    geometries: FBXGeometryData[],\n    curves: FBXCurveGeometryData[],\n    materials: FBXMaterialData[],\n    propertyTemplates: FBXPropertyTemplateMap\n): FBXModelData[] {\n    const geometryMap = new Map<number, FBXGeometryData>();\n    for (const g of geometries) {\n        geometryMap.set(g.id, g);\n    }\n    const curveMap = new Map<number, FBXCurveGeometryData>();\n    for (const c of curves) {\n        curveMap.set(c.id, c);\n    }\n\n    const materialMap = new Map<number, FBXMaterialData>();\n    for (const m of materials) {\n        materialMap.set(m.id, m);\n    }\n\n    // Find root models (those connected to ID 0, which is the scene root)\n    const rootChildren = objectMap.childrenOf.get(0) ?? [];\n    const rootModels: FBXModelData[] = [];\n    const rootIds = new Set<number>();\n    const buildStack = new Set<number>();\n\n    for (const { id } of rootChildren) {\n        const node = objectMap.objects.get(id);\n        if (node && node.name === \"Model\" && !rootIds.has(id)) {\n            rootIds.add(id);\n            rootModels.push(buildModel(id, node, objectMap, geometryMap, curveMap, materialMap, propertyTemplates, buildStack));\n        }\n    }\n\n    // Models without any Model (or scene root) parent connection also live at the root, as in the FBX SDK.\n    // Typical examples are the default \"Producer\" cameras and the camera switcher written by Maya, MotionBuilder\n    // and Blender in 6.x files, which are never connected.\n    const hasModelParent = new Set<number>();\n    for (const conn of objectMap.connections) {\n        if (conn.type !== \"OO\") {\n            continue;\n        }\n        const parentNode = objectMap.objects.get(conn.parentId);\n        if (conn.parentId === 0 || parentNode?.name === \"Model\") {\n            hasModelParent.add(conn.childId);\n        }\n    }\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"Model\" && !hasModelParent.has(id) && !rootIds.has(id)) {\n            rootIds.add(id);\n            rootModels.push(buildModel(id, node, objectMap, geometryMap, curveMap, materialMap, propertyTemplates, buildStack));\n        }\n    }\n\n    return rootModels;\n}\n\nfunction buildModel(\n    modelId: number,\n    modelNode: FBXNode,\n    objectMap: FBXObjectMap,\n    geometryMap: Map<number, FBXGeometryData>,\n    curveMap: Map<number, FBXCurveGeometryData>,\n    materialMap: Map<number, FBXMaterialData>,\n    propertyTemplates: FBXPropertyTemplateMap,\n    buildStack: Set<number>\n): FBXModelData {\n    const name = cleanFBXName(getPropertyValue<string>(modelNode, 1) ?? \"Model\");\n    buildStack.add(modelId);\n    const subType = getPropertyValue<string>(modelNode, 2) ?? \"Null\";\n\n    // Find attached geometry\n    const geomChildren = getChildren(objectMap, modelId, \"Geometry\");\n    const geometry = geomChildren.map((child) => geometryMap.get(child.id)).find((g) => g !== undefined);\n    const curve = geomChildren.map((child) => curveMap.get(child.id)).find((c) => c !== undefined);\n\n    // Find attached materials\n    const matChildren = getChildren(objectMap, modelId, \"Material\");\n    const modelMaterials: FBXMaterialData[] = [];\n    for (const { id } of matChildren) {\n        const mat = materialMap.get(id);\n        if (mat) {\n            modelMaterials.push(mat);\n        }\n    }\n\n    // Extract transform\n    const transform = extractTransform(modelNode, getPropertyTemplate(propertyTemplates, \"Model\", \"FbxNode\") ?? getPropertyTemplate(propertyTemplates, \"Model\"));\n\n    // Recursively build child models\n    // Only object-object connections express parenting; OP connections (look-at targets, constraint sources) do not.\n    const childModelNodes = getChildren(objectMap, modelId, \"Model\").filter((child) => !child.propertyName);\n    const children: FBXModelData[] = [];\n    const cycleDiagnostics: string[] = [];\n    for (const { id, node } of childModelNodes) {\n        if (buildStack.size > MAX_MODEL_DEPTH) {\n            cycleDiagnostics.push(`Model hierarchy deeper than ${MAX_MODEL_DEPTH} levels; deeper children were skipped.`);\n            break;\n        }\n        if (buildStack.has(id)) {\n            // Malformed files (duplicate ids, recursive connections) can make a model its own ancestor.\n            cycleDiagnostics.push(`Model connection cycle detected at '${cleanFBXName(getPropertyValue<string>(node, 1) ?? \"\")}'; the recursive child was skipped.`);\n            continue;\n        }\n        children.push(buildModel(id, node, objectMap, geometryMap, curveMap, materialMap, propertyTemplates, buildStack));\n    }\n    buildStack.delete(modelId);\n\n    // Extract culling\n    const cullingNode = modelNode.children.find((c) => c.name === \"Culling\");\n    const cullingOff = cullingNode ? getPropertyValue<string>(cullingNode, 0) === \"CullingOff\" : false;\n\n    // Extract user-defined custom properties\n    const customProperties = extractCustomProperties(modelNode);\n\n    // LOD groups carry their thresholds on the LodGroup node attribute\n    let lodGroup: FBXLodGroupData | undefined;\n    if (subType === \"LodGroup\") {\n        const attribute = getChildren(objectMap, modelId, \"NodeAttribute\").find((a) => getPropertyValue<string>(a.node, 2) === \"LodGroup\");\n        const entries = attribute ? getPropertyEntries(attribute.node) : [];\n        const thresholds: number[] = [];\n        const displayLevels: number[] = [];\n        for (let i = 0; ; i++) {\n            const entry = entries.find((e) => e.name === `Thresholds|Level${i}`);\n            if (!entry) {\n                break;\n            }\n            thresholds.push(typeof entry.values[0] === \"number\" ? entry.values[0] : 0);\n        }\n        for (let i = 0; ; i++) {\n            const entry = entries.find((e) => e.name === `DisplayLevels|Level${i}`);\n            if (!entry) {\n                break;\n            }\n            displayLevels.push(typeof entry.values[0] === \"number\" ? entry.values[0] : 0);\n        }\n        const relativeEntry = entries.find((e) => e.name === \"ThresholdsUsedAsPercentage\");\n        lodGroup = { thresholds, relative: !!relativeEntry && relativeEntry.values[0] !== 0 && relativeEntry.values[0] !== false, displayLevels };\n    }\n\n    return {\n        id: modelId,\n        name,\n        subType,\n        geometry,\n        materials: modelMaterials,\n        children,\n        cullingOff,\n        customProperties,\n        lodGroup,\n        curve,\n        ...transform,\n        diagnostics: [...transform.diagnostics, ...cycleDiagnostics],\n    };\n}\n\n/** Display layers and selection sets: which models belong to which collection. */\nfunction extractCollections(objectMap: FBXObjectMap, rootModels: FBXModelData[]): { displayLayers: FBXDisplayLayerData[]; selectionSets: FBXSelectionSetData[] } {\n    const modelById = new Map<number, FBXModelData>();\n    const walk = (models: FBXModelData[]) => {\n        for (const m of models) {\n            modelById.set(m.id, m);\n            walk(m.children);\n        }\n    };\n    walk(rootModels);\n\n    const displayLayers: FBXDisplayLayerData[] = [];\n    const selectionSets: FBXSelectionSetData[] = [];\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name === \"CollectionExclusive\") {\n            const entries = getPropertyEntries(node);\n            const num = (name: string, fallback: number) => {\n                const v = entries.find((e) => e.name === name)?.values[0];\n                return typeof v === \"number\" ? v : typeof v === \"boolean\" ? (v ? 1 : 0) : fallback;\n            };\n            const colorValues = entries.find((e) => e.name === \"Color\")?.values;\n            const color: [number, number, number] =\n                colorValues && typeof colorValues[0] === \"number\" && typeof colorValues[1] === \"number\" && typeof colorValues[2] === \"number\"\n                    ? [colorValues[0], colorValues[1], colorValues[2]]\n                    : [0.8, 0.8, 0.8];\n            const layer: FBXDisplayLayerData = {\n                id,\n                name: cleanFBXName(getPropertyValue<string>(node, 1) ?? \"DisplayLayer\"),\n                show: num(\"Show\", 1) !== 0,\n                freeze: num(\"Freeze\", 0) !== 0,\n                color,\n                modelIds: getChildren(objectMap, id, \"Model\").map((c) => c.id),\n            };\n            displayLayers.push(layer);\n            for (const modelId of layer.modelIds) {\n                const model = modelById.get(modelId);\n                if (model) {\n                    model.displayLayer = layer;\n                }\n            }\n        } else if (node.name === \"SelectionSet\" || (node.name === \"Collection\" && getPropertyValue<string>(node, 2) === \"SelectionSet\")) {\n            const members: FBXSelectionNodeData[] = [];\n            for (const child of getChildren(objectMap, id)) {\n                if (child.node.name === \"Model\") {\n                    members.push({ modelId: child.id, includeNode: true });\n                } else if (child.node.name === \"SelectionNode\") {\n                    const indices = (name: string): number[] | undefined => {\n                        const arrayNode = findChildByName(child.node, name);\n                        if (!arrayNode) {\n                            return undefined;\n                        }\n                        return Array.from(getNodeArray(arrayNode) as ArrayLike<number>);\n                    };\n                    const inSet = findChildByName(child.node, \"IsTheNodeInSet\")?.properties[0]?.value;\n                    for (const target of getChildren(objectMap, child.id, \"Model\")) {\n                        members.push({\n                            modelId: target.id,\n                            includeNode: inSet === undefined || inSet === 1 || inSet === true,\n                            vertices: indices(\"VertexIndexArray\"),\n                            edges: indices(\"EdgeIndexArray\"),\n                            faces: indices(\"PolygonIndexArray\"),\n                        });\n                    }\n                }\n            }\n            selectionSets.push({ id, name: cleanFBXName(getPropertyValue<string>(node, 1) ?? \"SelectionSet\"), members });\n        }\n    }\n    return { displayLayers, selectionSets };\n}\n\nfunction extractTransform(\n    modelNode: FBXNode,\n    template?: FBXPropertyTemplate\n): {\n    translation: [number, number, number];\n    rotation: [number, number, number];\n    scale: [number, number, number];\n    preRotation: [number, number, number];\n    postRotation: [number, number, number];\n    rotationPivot: [number, number, number];\n    scalingPivot: [number, number, number];\n    rotationOffset: [number, number, number];\n    scalingOffset: [number, number, number];\n    geometricTranslation: [number, number, number];\n    geometricRotation: [number, number, number];\n    geometricScaling: [number, number, number];\n    rotationOrder: number;\n    inheritType: number;\n    diagnostics: string[];\n} {\n    return extractNodeTransform(modelNode, template);\n}\n\n// ── Global Settings ────────────────────────────────────────────────────────────\n\ninterface GlobalSettings {\n    upAxis: number;\n    upAxisSign: number;\n    frontAxis: number;\n    frontAxisSign: number;\n    coordAxis: number;\n    coordAxisSign: number;\n    unitScaleFactor: number;\n    frameRate: number;\n}\n\n// Frame rates per FBX TimeMode enum value (eDefaultMode, eFrames120, ... eFrames59dot94).\nconst TIME_MODE_FPS = [30, 120, 100, 60, 50, 48, 30, 30, 29.97, 29.97, 25, 24, 1000, 23.976, 24, 96, 72, 59.94];\n\nfunction extractGlobalSettings(doc: FBXDocument): GlobalSettings {\n    const defaults: GlobalSettings = {\n        upAxis: 1,\n        upAxisSign: 1,\n        frontAxis: 2,\n        frontAxisSign: 1,\n        coordAxis: 0,\n        coordAxisSign: 1,\n        unitScaleFactor: 1,\n        frameRate: 30,\n    };\n\n    const gsNode = findDocumentNode(doc, \"GlobalSettings\");\n    if (!gsNode) {\n        return defaults;\n    }\n\n    let timeMode = 0;\n    let customFrameRate = 24;\n\n    for (const { name: propName, values } of getPropertyEntries(gsNode)) {\n        const value = toNumber(values[0]);\n        if (propName && value !== undefined) {\n            switch (propName) {\n                case \"UpAxis\":\n                    defaults.upAxis = value;\n                    break;\n                case \"UpAxisSign\":\n                    defaults.upAxisSign = value;\n                    break;\n                case \"FrontAxis\":\n                    defaults.frontAxis = value;\n                    break;\n                case \"FrontAxisSign\":\n                    defaults.frontAxisSign = value;\n                    break;\n                case \"CoordAxis\":\n                    defaults.coordAxis = value;\n                    break;\n                case \"CoordAxisSign\":\n                    defaults.coordAxisSign = value;\n                    break;\n                case \"UnitScaleFactor\":\n                    defaults.unitScaleFactor = value;\n                    break;\n                case \"TimeMode\":\n                    timeMode = value;\n                    break;\n                case \"CustomFrameRate\":\n                    customFrameRate = value;\n                    break;\n            }\n        }\n    }\n\n    if (timeMode === 14) {\n        defaults.frameRate = customFrameRate > 0 ? customFrameRate : 24;\n    } else {\n        defaults.frameRate = TIME_MODE_FPS[timeMode] ?? 30;\n    }\n\n    return defaults;\n}\n\n// ── Cameras & Lights ──────────────────────────────────────────────────────────\n\nconst SYSTEM_PROPERTIES = new Set([\n    \"Lcl Translation\",\n    \"Lcl Rotation\",\n    \"Lcl Scaling\",\n    \"PreRotation\",\n    \"PostRotation\",\n    \"RotationPivot\",\n    \"ScalingPivot\",\n    \"RotationOffset\",\n    \"ScalingOffset\",\n    \"RotationOrder\",\n    \"GeometricTranslation\",\n    \"GeometricRotation\",\n    \"GeometricScaling\",\n    \"Visibility\",\n    \"InheritType\",\n    \"ScalingMax\",\n    \"DefaultAttributeIndex\",\n    \"currentUVSet\",\n    \"lockInfluenceWeights\",\n]);\n\nfunction extractCustomProperties(modelNode: FBXNode): Record<string, FBXUserPropertyValue> | undefined {\n    // Properties flagged \"U\" are user-defined. Some writers (MotionBuilder) flag their own template properties\n    // as user properties too, so the well-known node properties are filtered out again.\n    const flagged = extractUserProperties(modelNode);\n    if (!flagged) {\n        return undefined;\n    }\n    let hasAny = false;\n    const custom: Record<string, FBXUserPropertyValue> = {};\n    for (const name of Object.keys(flagged)) {\n        if (!SYSTEM_PROPERTIES.has(name)) {\n            custom[name] = flagged[name];\n            hasAny = true;\n        }\n    }\n    return hasAny ? custom : undefined;\n}\n\nconst CAMERA_PROPERTIES = new Set([\n    \"FieldOfView\",\n    \"FieldOfViewX\",\n    \"FieldOfViewY\",\n    \"NearPlane\",\n    \"FarPlane\",\n    \"AspectWidth\",\n    \"AspectHeight\",\n    \"FilmAspectRatio\",\n    \"FocalLength\",\n    \"FilmWidth\",\n    \"FilmHeight\",\n    \"ApertureWidth\",\n    \"ApertureHeight\",\n    \"CameraProjectionType\",\n    \"ProjectionType\",\n    \"OrthoZoom\",\n    \"Roll\",\n    \"ApertureMode\",\n]);\n\nconst LIGHT_PROPERTIES = new Set([\n    \"LightType\",\n    \"Color\",\n    \"Intensity\",\n    \"InnerAngle\",\n    \"OuterAngle\",\n    \"ConeAngle\",\n    \"DecayType\",\n    \"DecayStart\",\n    \"EnableNearAttenuation\",\n    \"EnableFarAttenuation\",\n    \"CastShadow\",\n    \"Shadow\",\n]);\n\nfunction extractCameras(objectMap: FBXObjectMap, templates: FBXPropertyTemplateMap): FBXCameraData[] {\n    const cameras: FBXCameraData[] = [];\n    const cameraTemplate = getPropertyTemplate(templates, \"NodeAttribute\", \"FbxCamera\") ?? getPropertyTemplate(templates, \"NodeAttribute\");\n\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name !== \"NodeAttribute\") {\n            continue;\n        }\n        const subType = getPropertyValue<string>(node, 2);\n        if (subType !== \"Camera\") {\n            continue;\n        }\n\n        // Find the model this camera is attached to (parent)\n        const parent = objectMap.parentOf.get(id);\n        if (!parent) {\n            continue;\n        }\n        const parentNode = objectMap.objects.get(parent.id);\n        if (!parentNode || parentNode.name !== \"Model\") {\n            continue;\n        }\n\n        const name = cleanFBXName(getPropertyValue<string>(parentNode, 1) ?? \"Camera\");\n\n        const nearPlane = resolveNumberProperty(node, cameraTemplate, \"NearPlane\", 0.1);\n        const farPlane = resolveNumberProperty(node, cameraTemplate, \"FarPlane\", 10000);\n        const projectionType =\n            resolveNumberProperty(node, cameraTemplate, \"CameraProjectionType\", 0) === 1 || resolveNumberProperty(node, cameraTemplate, \"ProjectionType\", 0) === 1\n                ? \"orthographic\"\n                : \"perspective\";\n        const focalLength = toNumber(resolvePropertyValue(node, cameraTemplate, \"FocalLength\"));\n        const filmWidth = toNumber(resolvePropertyValue(node, cameraTemplate, \"FilmWidth\")) ?? toNumber(resolvePropertyValue(node, cameraTemplate, \"ApertureWidth\"));\n        const filmHeight = toNumber(resolvePropertyValue(node, cameraTemplate, \"FilmHeight\")) ?? toNumber(resolvePropertyValue(node, cameraTemplate, \"ApertureHeight\"));\n        const orthoZoom = toNumber(resolvePropertyValue(node, cameraTemplate, \"OrthoZoom\"));\n        const roll = toNumber(resolvePropertyValue(node, cameraTemplate, \"Roll\"));\n        const resolved = resolveCameraParameters(node, cameraTemplate);\n        const aspectRatio = resolved.aspectRatio;\n        const fieldOfView = resolved.fovDegY;\n        const diagnostics: string[] = [];\n        if (projectionType === \"orthographic\" && orthoZoom === undefined) {\n            diagnostics.push(\"Orthographic camera has no OrthoZoom; runtime orthographic bounds use a fallback.\");\n        }\n        if (focalLength !== undefined && filmHeight === undefined && resolvePropertyValue(node, cameraTemplate, \"FieldOfView\") === undefined) {\n            diagnostics.push(\"FocalLength is present without FilmHeight; default field of view fallback may be used.\");\n        }\n\n        cameras.push({\n            modelId: parent.id,\n            attributeId: id,\n            userProperties: extractUserProperties(node),\n            name,\n            fieldOfView,\n            fieldOfViewX: resolved.fovDegX,\n            apertureMode: resolved.apertureMode,\n            apertureSizeInch: resolved.apertureSizeInch,\n            orthographicSize: resolved.orthographicSize,\n            nearPlane,\n            farPlane,\n            aspectRatio,\n            projectionType,\n            focalLength,\n            filmWidth,\n            filmHeight,\n            orthoZoom,\n            roll,\n            unknownProperties: collectUnknownLocalProperties(node, CAMERA_PROPERTIES),\n            diagnostics,\n        });\n    }\n\n    return cameras;\n}\n\nfunction extractLights(objectMap: FBXObjectMap, templates: FBXPropertyTemplateMap): FBXLightData[] {\n    const lights: FBXLightData[] = [];\n    const lightTemplate = getPropertyTemplate(templates, \"NodeAttribute\", \"FbxLight\") ?? getPropertyTemplate(templates, \"NodeAttribute\");\n\n    for (const [id, node] of Array.from(objectMap.objects)) {\n        if (node.name !== \"NodeAttribute\") {\n            continue;\n        }\n        const subType = getPropertyValue<string>(node, 2);\n        if (subType !== \"Light\") {\n            continue;\n        }\n\n        // Find the model this light is attached to\n        const parent = objectMap.parentOf.get(id);\n        if (!parent) {\n            continue;\n        }\n        const parentNode = objectMap.objects.get(parent.id);\n        if (!parentNode || parentNode.name !== \"Model\") {\n            continue;\n        }\n\n        const name = cleanFBXName(getPropertyValue<string>(parentNode, 1) ?? \"Light\");\n\n        const lightType = resolveNumberProperty(node, lightTemplate, \"LightType\", 0);\n        const color = resolveVector3Property(node, lightTemplate, \"Color\", [1, 1, 1]);\n        const intensity = resolveNumberProperty(node, lightTemplate, \"Intensity\", 100) / 100;\n        const outerAngle = toNumber(resolvePropertyValue(node, lightTemplate, \"OuterAngle\")) ?? toNumber(resolvePropertyValue(node, lightTemplate, \"ConeAngle\"));\n        const innerAngle = toNumber(resolvePropertyValue(node, lightTemplate, \"InnerAngle\"));\n        const coneAngle = outerAngle ?? 45;\n        const decayType = resolveNumberProperty(node, lightTemplate, \"DecayType\", 2);\n        const decayStart = toNumber(resolvePropertyValue(node, lightTemplate, \"DecayStart\"));\n        const enableNearAttenuation = toBoolean(resolvePropertyValue(node, lightTemplate, \"EnableNearAttenuation\"));\n        const enableFarAttenuation = toBoolean(resolvePropertyValue(node, lightTemplate, \"EnableFarAttenuation\"));\n        const castShadows =\n            toBoolean(resolvePropertyValue(node, lightTemplate, \"CastShadow\")) ??\n            toBoolean(resolvePropertyValue(parentNode, undefined, \"CastShadow\")) ??\n            toBoolean(resolvePropertyValue(parentNode, undefined, \"Shadow\"));\n        const diagnostics: string[] = [];\n        if (decayType !== 2) {\n            diagnostics.push(`DecayType ${decayType} is preserved as metadata; Babylon falloff is not remapped in this pass.`);\n        }\n        if (decayStart !== undefined) {\n            diagnostics.push(\"DecayStart is preserved as metadata and is not mapped to Babylon light range.\");\n        }\n\n        lights.push({\n            modelId: parent.id,\n            attributeId: id,\n            userProperties: extractUserProperties(node),\n            nearAttenuationStart: toNumber(resolvePropertyValue(node, lightTemplate, \"NearAttenuationStart\")),\n            nearAttenuationEnd: toNumber(resolvePropertyValue(node, lightTemplate, \"NearAttenuationEnd\")),\n            farAttenuationStart: toNumber(resolvePropertyValue(node, lightTemplate, \"FarAttenuationStart\")),\n            farAttenuationEnd: toNumber(resolvePropertyValue(node, lightTemplate, \"FarAttenuationEnd\")),\n            areaLightShape: toNumber(resolvePropertyValue(node, lightTemplate, \"AreaLightShape\")),\n            name,\n            lightType,\n            color,\n            intensity,\n            coneAngle,\n            decayType,\n            innerAngle,\n            outerAngle,\n            decayStart,\n            enableNearAttenuation,\n            enableFarAttenuation,\n            castShadows,\n            unknownProperties: collectUnknownLocalProperties(node, LIGHT_PROPERTIES),\n            diagnostics,\n        });\n    }\n\n    return lights;\n}\n\n// ── Utilities ──────────────────────────────────────────────────────────────────\n\nfunction toNumber(value: unknown): number | undefined {\n    if (typeof value === \"number\") {\n        return value;\n    }\n    return undefined;\n}\n\nfunction toBoolean(value: unknown): boolean | undefined {\n    if (typeof value === \"boolean\") {\n        return value;\n    }\n    if (typeof value === \"number\") {\n        return value !== 0;\n    }\n    return undefined;\n}\n\n/** Film back sizes in thousandths of an inch per FBX ApertureFormat enum value. */\nconst APERTURE_FORMATS: [number, number][] = [\n    [1000, 1000],\n    [404, 295],\n    [493, 292],\n    [864, 630],\n    [816, 612],\n    [980, 735],\n    [825, 446],\n    [864, 732],\n    [2066, 906],\n    [1485, 991],\n    [2080, 1480],\n    [2772, 2072],\n];\n\n/**\n * Resolves the camera's projection parameters the way the FBX SDK does: aspect ratio from AspectWidth/Height and\n * the aspect mode, aperture (film gate) from the film size, squeeze ratio and gate fit, and the horizontal and\n * vertical field of view from the aperture mode (horizontal, vertical, both, or focal length).\n */\nfunction resolveCameraParameters(\n    node: FBXNode,\n    template?: FBXPropertyTemplate\n): { fovDegX: number; fovDegY: number; aspectRatio: number; apertureMode: number; apertureSizeInch: [number, number]; orthographicSize: [number, number] } {\n    const num = (name: string, fallback: number) => toNumber(resolvePropertyValue(node, template, name)) ?? fallback;\n    const aspectMode = num(\"AspectRatioMode\", 0);\n    const apertureMode = num(\"ApertureMode\", 2);\n    const apertureFormat = Math.max(0, Math.min(APERTURE_FORMATS.length - 1, Math.round(num(\"ApertureFormat\", 0))));\n    const gateFit = num(\"GateFit\", 0);\n    let aspectX = num(\"AspectW\", 0);\n    let aspectY = num(\"AspectH\", 0);\n    aspectX = num(\"AspectWidth\", aspectX);\n    aspectY = num(\"AspectHeight\", aspectY);\n    const fov = num(\"FieldOfView\", 0);\n    const fovX = num(\"FieldOfViewX\", 0);\n    const fovY = num(\"FieldOfViewY\", 0);\n    const focalLength = num(\"FocalLength\", 0);\n    const orthoExtent = 30 * num(\"OrthoZoom\", 1);\n    const format = APERTURE_FORMATS[apertureFormat];\n    let filmX = num(\"FilmWidth\", format[0] * 0.001);\n    let filmY = num(\"FilmHeight\", format[1] * 0.001);\n    const squeeze = num(\"FilmSqueezeRatio\", apertureFormat === 7 ? 2 : 1);\n\n    if (aspectX <= 0 && aspectY <= 0) {\n        aspectX = filmX > 0 ? filmX : 1;\n        aspectY = filmY > 0 ? filmY : 1;\n    } else if (aspectX <= 0) {\n        aspectX = filmX > 0 && filmY > 0 ? (aspectY / filmY) * filmX : aspectY;\n    } else if (aspectY <= 0) {\n        aspectY = filmX > 0 && filmY > 0 ? (aspectX / filmX) * filmY : aspectX;\n    }\n    filmY *= squeeze;\n\n    let resX = aspectX;\n    let resY = aspectY;\n    switch (aspectMode) {\n        case 3: // fixed width\n            resX = aspectX;\n            resY = aspectX * aspectY;\n            break;\n        case 4: // fixed height\n            resX = aspectY * aspectX;\n            resY = aspectY;\n            break;\n        default:\n            break;\n    }\n    const aspectRatio = resY !== 0 ? resX / resY : 1;\n    const filmRatio = filmY !== 0 ? filmX / filmY : 1;\n\n    let effectiveFit = gateFit;\n    if (effectiveFit === 3) {\n        effectiveFit = aspectRatio > filmRatio ? 2 : 1;\n    } else if (effectiveFit === 4) {\n        effectiveFit = aspectRatio < filmRatio ? 2 : 1;\n    }\n    let apertureX = filmX;\n    let apertureY = filmY;\n    let orthoX = orthoExtent;\n    let orthoY = orthoExtent;\n    switch (effectiveFit) {\n        case 1: // vertical\n            apertureX = filmY * aspectRatio;\n            apertureY = filmY;\n            orthoX = orthoExtent * aspectRatio;\n            break;\n        case 2: // horizontal\n            apertureX = filmX;\n            apertureY = filmX / aspectRatio;\n            orthoY = orthoExtent / aspectRatio;\n            break;\n        default:\n            break;\n    }\n    filmX = apertureX;\n    void filmX;\n\n    const d2r = Math.PI / 180;\n    const r2d = 180 / Math.PI;\n    let tanX: number;\n    let tanY: number;\n    switch (apertureMode) {\n        case 0:\n            tanX = Math.tan(fovX * d2r * 0.5);\n            tanY = Math.tan(fovY * d2r * 0.5);\n            break;\n        case 1:\n            tanX = Math.tan(fov * d2r * 0.5);\n            tanY = tanX / aspectRatio;\n            break;\n        case 3: {\n            const focalInch = focalLength / 25.4;\n            tanX = focalInch > 0 ? (apertureX / focalInch) * 0.5 : Math.tan(fov * d2r * 0.5) * aspectRatio;\n            tanY = focalInch > 0 ? (apertureY / focalInch) * 0.5 : Math.tan(fov * d2r * 0.5);\n            break;\n        }\n        default:\n            tanY = Math.tan(fov * d2r * 0.5);\n            tanX = tanY * aspectRatio;\n            break;\n    }\n    return {\n        fovDegX: Math.atan(tanX) * r2d * 2,\n        fovDegY: Math.atan(tanY) * r2d * 2,\n        aspectRatio,\n        apertureMode,\n        apertureSizeInch: [apertureX, apertureY],\n        orthographicSize: [orthoX, orthoY],\n    };\n}\n\nfunction collectUnknownLocalProperties(node: FBXNode, known: Set<string>): string[] {\n    const unknown = new Set<string>();\n    for (const containerName of [\"Properties70\", \"Properties60\"]) {\n        const container = findChildByName(node, containerName);\n        for (const propertyNode of container?.children ?? []) {\n            if (propertyNode.name !== \"P\" && propertyNode.name !== \"Property\") {\n                continue;\n            }\n            const propertyName = getPropertyValue<string>(propertyNode, 0);\n            if (propertyName && !known.has(propertyName)) {\n                unknown.add(propertyName);\n            }\n        }\n    }\n    return Array.from(unknown).sort();\n}\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nimport { Matrix } from \"core/Maths/math.vector\";\r\n\r\nexport type FBXVector3 = [number, number, number];\r\n\r\nexport interface FBXTransformComponents {\r\n    translation: FBXVector3;\r\n    rotation: FBXVector3;\r\n    scale: FBXVector3;\r\n    preRotation: FBXVector3;\r\n    postRotation: FBXVector3;\r\n    rotationPivot: FBXVector3;\r\n    scalingPivot: FBXVector3;\r\n    rotationOffset: FBXVector3;\r\n    scalingOffset: FBXVector3;\r\n    rotationOrder: number;\r\n    inheritType?: number;\r\n}\r\n\r\nexport function eulerToMatrixXYZ(rx: number, ry: number, rz: number): Matrix {\r\n    const mx = Matrix.RotationX(rx);\r\n    const my = Matrix.RotationY(ry);\r\n    const mz = Matrix.RotationZ(rz);\r\n    return mx.multiply(my).multiply(mz);\r\n}\r\n\r\nexport function eulerToMatrix(rx: number, ry: number, rz: number, order: number): Matrix {\r\n    const mx = Matrix.RotationX(rx);\r\n    const my = Matrix.RotationY(ry);\r\n    const mz = Matrix.RotationZ(rz);\r\n\r\n    switch (order) {\r\n        case 0:\r\n            return mx.multiply(my).multiply(mz); // XYZ\r\n        case 1:\r\n            return mx.multiply(mz).multiply(my); // XZY\r\n        case 2:\r\n            return my.multiply(mz).multiply(mx); // YZX\r\n        case 3:\r\n            return my.multiply(mx).multiply(mz); // YXZ\r\n        case 4:\r\n            return mz.multiply(mx).multiply(my); // ZXY\r\n        case 5:\r\n            return mz.multiply(my).multiply(mx); // ZYX\r\n        default:\r\n            return mx.multiply(my).multiply(mz); // fallback to XYZ\r\n    }\r\n}\r\n\r\nexport function computeFBXGeometricMatrix(translation: FBXVector3, rotation: FBXVector3, scale: FBXVector3): Matrix {\r\n    const translationM = Matrix.Translation(translation[0], translation[1], translation[2]);\r\n    return computeFBXGeometricDeltaMatrix(rotation, scale).multiply(translationM);\r\n}\r\n\r\nexport function computeFBXGeometricDeltaMatrix(rotation: FBXVector3, scale: FBXVector3): Matrix {\r\n    const d2r = Math.PI / 180;\r\n    const scaleM = Matrix.Scaling(scale[0], scale[1], scale[2]);\r\n    const rotationM = eulerToMatrixXYZ(rotation[0] * d2r, rotation[1] * d2r, rotation[2] * d2r);\r\n    return scaleM.multiply(rotationM);\r\n}\r\n\r\nexport function computeFBXGeometricNormalMatrix(rotation: FBXVector3, scale: FBXVector3): Matrix {\r\n    const d2r = Math.PI / 180;\r\n    const inverseScaleM = Matrix.Scaling(scale[0] === 0 ? 0 : 1 / scale[0], scale[1] === 0 ? 0 : 1 / scale[1], scale[2] === 0 ? 0 : 1 / scale[2]);\r\n    const rotationM = eulerToMatrixXYZ(rotation[0] * d2r, rotation[1] * d2r, rotation[2] * d2r);\r\n    return inverseScaleM.multiply(rotationM);\r\n}\r\n\r\nexport function computeFBXLocalMatrix(components: FBXTransformComponents): Matrix {\r\n    const { translation, rotation, scale, preRotation, postRotation, rotationPivot, scalingPivot, rotationOffset, scalingOffset, rotationOrder } = components;\r\n    const d2r = Math.PI / 180;\r\n\r\n    const hasPivots = rotationPivot[0] !== 0 || rotationPivot[1] !== 0 || rotationPivot[2] !== 0 || scalingPivot[0] !== 0 || scalingPivot[1] !== 0 || scalingPivot[2] !== 0;\r\n    const hasOffsets = rotationOffset[0] !== 0 || rotationOffset[1] !== 0 || rotationOffset[2] !== 0 || scalingOffset[0] !== 0 || scalingOffset[1] !== 0 || scalingOffset[2] !== 0;\r\n    const hasPostRot = postRotation[0] !== 0 || postRotation[1] !== 0 || postRotation[2] !== 0;\r\n\r\n    if (!hasPivots && !hasOffsets && !hasPostRot) {\r\n        const preRotM = eulerToMatrixXYZ(preRotation[0] * d2r, preRotation[1] * d2r, preRotation[2] * d2r);\r\n        const lclRotM = eulerToMatrix(rotation[0] * d2r, rotation[1] * d2r, rotation[2] * d2r, rotationOrder);\r\n        const translationM = Matrix.Translation(translation[0], translation[1], translation[2]);\r\n        const rotationM = lclRotM.multiply(preRotM);\r\n        const scaleM = Matrix.Scaling(scale[0], scale[1], scale[2]);\r\n        return scaleM.multiply(rotationM).multiply(translationM);\r\n    }\r\n\r\n    const T = Matrix.Translation(translation[0], translation[1], translation[2]);\r\n    const Roff = Matrix.Translation(rotationOffset[0], rotationOffset[1], rotationOffset[2]);\r\n    const Rp = Matrix.Translation(rotationPivot[0], rotationPivot[1], rotationPivot[2]);\r\n    const RpInv = Matrix.Translation(-rotationPivot[0], -rotationPivot[1], -rotationPivot[2]);\r\n    const Soff = Matrix.Translation(scalingOffset[0], scalingOffset[1], scalingOffset[2]);\r\n    const Sp = Matrix.Translation(scalingPivot[0], scalingPivot[1], scalingPivot[2]);\r\n    const SpInv = Matrix.Translation(-scalingPivot[0], -scalingPivot[1], -scalingPivot[2]);\r\n\r\n    const Rpre = eulerToMatrixXYZ(preRotation[0] * d2r, preRotation[1] * d2r, preRotation[2] * d2r);\r\n    const R = eulerToMatrix(rotation[0] * d2r, rotation[1] * d2r, rotation[2] * d2r, rotationOrder);\r\n    const S = Matrix.Scaling(scale[0], scale[1], scale[2]);\r\n\r\n    let RpostInv: Matrix;\r\n    if (hasPostRot) {\r\n        const Rpost = eulerToMatrixXYZ(postRotation[0] * d2r, postRotation[1] * d2r, postRotation[2] * d2r);\r\n        RpostInv = new Matrix();\r\n        Rpost.invertToRef(RpostInv);\r\n    } else {\r\n        RpostInv = Matrix.Identity();\r\n    }\r\n\r\n    let result = SpInv;\r\n    result = result.multiply(S);\r\n    result = result.multiply(Sp);\r\n    result = result.multiply(Soff);\r\n    result = result.multiply(RpInv);\r\n    result = result.multiply(RpostInv);\r\n    result = result.multiply(R);\r\n    result = result.multiply(Rpre);\r\n    result = result.multiply(Rp);\r\n    result = result.multiply(Roff);\r\n    result = result.multiply(T);\r\n    return result;\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\n/**\n * Runtime evaluation of FBX constraints. An `FBXConstraintBehavior` is attached to each constrained node; all\n * behaviors of a scene register with one `FBXConstraintSolver`, which solves them in dependency order (a constraint\n * whose target or parent is driven by another constraint is solved after it) and reuses scratch objects, so solving\n * allocates nothing per frame.\n *\n * The solver brackets the scene's animation phase: before animations run it writes each node's unconstrained\n * transform back, after they ran it captures the result as the new unconstrained transform and solves. A partial\n * weight therefore always blends from what animation (or nothing) produced this frame, never from the previous\n * solve's output, so a 50% weight stays a 50% blend instead of converging on the target.\n *\n * All maths happen in FBX space, i.e. relative to the loader's root node, so the handedness conversion applied\n * at the root never enters the solve.\n */\nimport { type Behavior } from \"core/Behaviors/behavior\";\nimport { type Nullable } from \"core/types\";\nimport { type Node } from \"core/node\";\nimport { type Observer } from \"core/Misc/observable\";\nimport { type Scene } from \"core/scene\";\nimport { Matrix, Quaternion, Vector3 } from \"core/Maths/math.vector.pure\";\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\nimport { type FBXConstraintData } from \"./interpreter/constraints\";\nimport { eulerToMatrixXYZ } from \"./interpreter/transform\";\n\nconst DEG2RAD = Math.PI / 180;\n\n/** Resolved target of a constraint. */\nexport interface FBXConstraintBehaviorTarget {\n    /** Target node */\n    node: TransformNode;\n    /** Normalized target weight (0..1) */\n    weight: number;\n    /** Offset matrix for parent constraints (in the target's space) */\n    offset: Matrix;\n}\n\n/** Options resolved by the loader when creating the behavior. */\nexport interface FBXConstraintBehaviorOptions {\n    /** Root of the loaded asset; world matrices are made relative to it */\n    root: TransformNode;\n    /** Resolved targets of the constraint, in file order */\n    targets: FBXConstraintBehaviorTarget[];\n    /** World up object of an aim constraint, when it has one */\n    upNode: Nullable<TransformNode>;\n    /** Scene up axis in FBX space */\n    sceneUp: Vector3;\n}\n\n/** Scratch objects shared by every solve; the solver runs on one thread, one constraint at a time. */\nconst Scratch = {\n    invRoot: new Matrix(),\n    parent: new Matrix(),\n    invParent: new Matrix(),\n    world: new Matrix(),\n    local: new Matrix(),\n    mA: new Matrix(),\n    mB: new Matrix(),\n    mC: new Matrix(),\n    mD: new Matrix(),\n    position: new Vector3(),\n    scale: new Vector3(),\n    translation: new Vector3(),\n    decomposedScale: new Vector3(),\n    localValue: new Vector3(),\n    up: new Vector3(),\n    forward: new Vector3(),\n    origin: new Vector3(),\n    axisA: new Vector3(),\n    axisB: new Vector3(),\n    axisC: new Vector3(),\n    eulerA: new Vector3(),\n    eulerB: new Vector3(),\n    rotation: new Quaternion(),\n    decomposedRotation: new Quaternion(),\n    result: new Quaternion(),\n};\n\nconst Solvers = new WeakMap<Scene, FBXConstraintSolver>();\n\n/**\n * Solves every FBX constraint of a scene once per frame, in dependency order, from the scene's animation phase\n * observers (`beginFrame` before animations, `solve` after them). Created on demand by the first\n * `FBXConstraintBehavior` attached in the scene and removed with the last one.\n */\nexport class FBXConstraintSolver {\n    private readonly _scene: Scene;\n    private readonly _behaviors: FBXConstraintBehavior[] = [];\n    private _ordered: FBXConstraintBehavior[] = [];\n    private _cyclic: FBXConstraintBehavior[] = [];\n    private _dirty = false;\n    private _beforeAnimations: Nullable<Observer<Scene>> = null;\n    private _afterAnimations: Nullable<Observer<Scene>> = null;\n\n    private constructor(scene: Scene) {\n        this._scene = scene;\n    }\n\n    /**\n     * Solver of a scene, if any constraint behavior is attached in it.\n     * @param scene - Scene to look up\n     * @returns The solver, or undefined\n     */\n    public static Get(scene: Scene): FBXConstraintSolver | undefined {\n        return Solvers.get(scene);\n    }\n\n    /**\n     * Solver of a scene, created when missing.\n     * @param scene - Scene to look up\n     * @returns The solver\n     */\n    public static GetOrCreate(scene: Scene): FBXConstraintSolver {\n        let solver = Solvers.get(scene);\n        if (!solver) {\n            solver = new FBXConstraintSolver(scene);\n            Solvers.set(scene, solver);\n        }\n        return solver;\n    }\n\n    /** Registered behaviors in solve order (a target's constraint before the constraints that read it). */\n    public get constraints(): readonly FBXConstraintBehavior[] {\n        this._ensureOrder();\n        return this._ordered;\n    }\n\n    /**\n     * Behaviors that take part in a dependency cycle (A targets B while B targets A). They are solved after all\n     * acyclic constraints, in registration order, so each sees the other's result from the previous solve.\n     */\n    public get cyclicConstraints(): readonly FBXConstraintBehavior[] {\n        this._ensureOrder();\n        return this._cyclic;\n    }\n\n    /**\n     * Adds a behavior to the solve set.\n     * @param behavior - Behavior to add\n     */\n    public register(behavior: FBXConstraintBehavior): void {\n        if (this._behaviors.indexOf(behavior) >= 0) {\n            return;\n        }\n        this._behaviors.push(behavior);\n        this._dirty = true;\n        if (!this._beforeAnimations) {\n            this._beforeAnimations = this._scene.onBeforeAnimationsObservable.add(() => this.beginFrame());\n            this._afterAnimations = this._scene.onAfterAnimationsObservable.add(() => this.solve());\n        }\n    }\n\n    /**\n     * Removes a behavior from the solve set; the solver disposes itself with the last one.\n     * @param behavior - Behavior to remove\n     */\n    public unregister(behavior: FBXConstraintBehavior): void {\n        const index = this._behaviors.indexOf(behavior);\n        if (index < 0) {\n            return;\n        }\n        this._behaviors.splice(index, 1);\n        this._dirty = true;\n        if (this._behaviors.length === 0) {\n            this._scene.onBeforeAnimationsObservable.remove(this._beforeAnimations);\n            this._scene.onAfterAnimationsObservable.remove(this._afterAnimations);\n            this._beforeAnimations = null;\n            this._afterAnimations = null;\n            Solvers.delete(this._scene);\n        }\n    }\n\n    /** Marks the solve order stale, e.g. after re-parenting a constrained node. */\n    public invalidateOrder(): void {\n        this._dirty = true;\n    }\n\n    /**\n     * Start of a frame, before animations run: every constrained node gets its unconstrained transform back, so\n     * that animation either overwrites it or leaves it untouched.\n     */\n    public beginFrame(): void {\n        for (const behavior of this._behaviors) {\n            behavior.restoreBase();\n        }\n    }\n\n    /**\n     * End of the animation phase: takes every constrained node's current transform as its unconstrained value,\n     * then solves every registered constraint once, in dependency order.\n     */\n    public solve(): void {\n        this._ensureOrder();\n        for (const behavior of this._behaviors) {\n            behavior.captureBase();\n        }\n        for (const behavior of this._ordered) {\n            behavior.evaluate();\n        }\n    }\n\n    private _ensureOrder(): void {\n        if (!this._dirty) {\n            return;\n        }\n        this._dirty = false;\n        const behaviors = this._behaviors;\n        const count = behaviors.length;\n        // dependencies[i] lists the behaviors that must be solved before behaviors[i]\n        const dependencies: number[][] = behaviors.map(() => []);\n        for (let i = 0; i < count; i++) {\n            const reads = behaviors[i].dependencyNodes();\n            for (let j = 0; j < count; j++) {\n                if (i === j) {\n                    continue;\n                }\n                const driven = behaviors[j].attachedNode;\n                if (driven && reads.some((node) => FBXConstraintSolver._IsAncestorOrSelf(driven, node))) {\n                    dependencies[i].push(j);\n                }\n            }\n        }\n        // Kahn's algorithm; whatever is left when no free behavior remains sits on a cycle.\n        const remaining = dependencies.map((deps) => deps.length);\n        const done = behaviors.map(() => false);\n        const ordered: FBXConstraintBehavior[] = [];\n        let progressed = true;\n        while (progressed) {\n            progressed = false;\n            for (let i = 0; i < count; i++) {\n                if (done[i] || remaining[i] > 0) {\n                    continue;\n                }\n                done[i] = true;\n                ordered.push(behaviors[i]);\n                progressed = true;\n                for (let k = 0; k < count; k++) {\n                    if (!done[k] && dependencies[k].indexOf(i) >= 0) {\n                        remaining[k]--;\n                    }\n                }\n            }\n        }\n        const cyclic: FBXConstraintBehavior[] = [];\n        for (let i = 0; i < count; i++) {\n            if (!done[i]) {\n                cyclic.push(behaviors[i]);\n                ordered.push(behaviors[i]);\n            }\n        }\n        this._ordered = ordered;\n        this._cyclic = cyclic;\n    }\n\n    private static _IsAncestorOrSelf(ancestor: TransformNode, node: Nullable<Node>): boolean {\n        let current: Nullable<Node> = node;\n        while (current) {\n            if (current === ancestor) {\n                return true;\n            }\n            current = current.parent;\n        }\n        return false;\n    }\n}\n\n/** Babylon behavior evaluating an FBX aim, parent, position, rotation or scale constraint. */\nexport class FBXConstraintBehavior implements Behavior<TransformNode> {\n    /** Behavior name (`fbxConstraint:` followed by the constraint name) */\n    public readonly name: string;\n    /** Node the behavior is attached to */\n    public attachedNode: Nullable<TransformNode> = null;\n    /** Set to false to pause the constraint without detaching it */\n    public enabled = true;\n\n    private readonly _offsetTranslation: Vector3;\n    private readonly _offsetRotation: Matrix;\n    private readonly _offsetScale: Vector3;\n    private readonly _localBasisTransposed: Nullable<Matrix>;\n    /** Unconstrained transform of the current frame (what animation produced), blended towards the constraint's result. */\n    private readonly _base = { position: new Vector3(), rotation: new Quaternion(), scaling: new Vector3() };\n    private _hasBase = false;\n\n    /**\n     * Creates the behavior.\n     * @param constraint - Constraint data extracted from the file\n     * @param _options - Resolved targets and scene information\n     */\n    public constructor(\n        /** Constraint data extracted from the file */\n        public readonly constraint: FBXConstraintData,\n        private readonly _options: FBXConstraintBehaviorOptions\n    ) {\n        this.name = `fbxConstraint:${constraint.name}`;\n        this._offsetTranslation = new Vector3(constraint.offsetTranslation[0], constraint.offsetTranslation[1], constraint.offsetTranslation[2]);\n        this._offsetRotation = eulerToMatrixXYZ(constraint.offsetRotation[0] * DEG2RAD, constraint.offsetRotation[1] * DEG2RAD, constraint.offsetRotation[2] * DEG2RAD);\n        this._offsetScale = new Vector3(constraint.offsetScale[0], constraint.offsetScale[1], constraint.offsetScale[2]);\n        const localBasis = new Matrix();\n        this._localBasisTransposed = FBXConstraintBehavior._OrthonormalBasisToRef(\n            new Vector3(constraint.aimVector[0], constraint.aimVector[1], constraint.aimVector[2]),\n            new Vector3(constraint.upVector[0], constraint.upVector[1], constraint.upVector[2]),\n            localBasis\n        )\n            ? localBasis.transpose()\n            : null;\n    }\n\n    /** Nothing to initialize */\n    public init(): void {}\n\n    /**\n     * Registers the behavior with the scene's solver, takes the node's current transform as the unconstrained\n     * value and solves the constraint once.\n     * @param target - Node to constrain\n     */\n    public attach(target: TransformNode): void {\n        this.attachedNode = target;\n        FBXConstraintSolver.GetOrCreate(target.getScene()).register(this);\n        this.captureBase();\n        this.evaluate();\n    }\n\n    /** Unregisters the behavior; the node keeps its last solved transform. */\n    public detach(): void {\n        if (this.attachedNode) {\n            FBXConstraintSolver.Get(this.attachedNode.getScene())?.unregister(this);\n        }\n        this.attachedNode = null;\n        this._hasBase = false;\n    }\n\n    /**\n     * Takes the node's current transform as the unconstrained value the next solve blends from. The solver calls\n     * this after the scene's animations ran; call it yourself after writing a transform by hand.\n     */\n    public captureBase(): void {\n        const node = this.attachedNode;\n        if (!node) {\n            return;\n        }\n        if (!node.rotationQuaternion) {\n            node.rotationQuaternion = Quaternion.FromEulerVector(node.rotation);\n        }\n        this._base.position.copyFrom(node.position);\n        this._base.rotation.copyFrom(node.rotationQuaternion);\n        this._base.scaling.copyFrom(node.scaling);\n        this._hasBase = true;\n    }\n\n    /**\n     * Writes the unconstrained transform back to the node. The solver calls this before the scene's animations\n     * run, so a node nothing animates keeps its unconstrained value between frames instead of the solved one.\n     */\n    public restoreBase(): void {\n        const node = this.attachedNode;\n        if (!node || !this._hasBase) {\n            return;\n        }\n        node.position.copyFrom(this._base.position);\n        node.rotationQuaternion!.copyFrom(this._base.rotation);\n        node.scaling.copyFrom(this._base.scaling);\n    }\n\n    /**\n     * Nodes whose world transform the solve reads: the targets, the up node and the constrained node's parent.\n     * @returns The nodes, used by the solver to order constraints\n     */\n    public dependencyNodes(): Nullable<Node>[] {\n        const nodes: Nullable<Node>[] = this._options.targets.map((t) => t.node);\n        nodes.push(this._options.upNode);\n        nodes.push(this.attachedNode ? this.attachedNode.parent : null);\n        return nodes;\n    }\n\n    /**\n     * Solves the constraint from the captured unconstrained transform and writes the node's local transform.\n     * Blends are relative to the value captured by `captureBase`, not to whatever the node holds now.\n     */\n    public evaluate(): void {\n        const node = this.attachedNode;\n        const c = this.constraint;\n        if (!node || !this.enabled || !c.active || c.weight <= 0 || this._options.targets.length === 0) {\n            return;\n        }\n        if (!this._hasBase) {\n            this.captureBase();\n        }\n        this._options.root.computeWorldMatrix(true).invertToRef(Scratch.invRoot);\n        const parent = node.parent as Nullable<TransformNode>;\n        if (parent && typeof parent.computeWorldMatrix === \"function\") {\n            this._fbxWorld(parent, Scratch.parent);\n        } else {\n            Matrix.IdentityToRef(Scratch.parent);\n        }\n        Scratch.parent.invertToRef(Scratch.invParent);\n\n        switch (c.type) {\n            case \"position\":\n                this._solvePosition(node);\n                break;\n            case \"rotation\":\n                this._solveRotation(node);\n                break;\n            case \"scale\":\n                this._solveScale(node);\n                break;\n            case \"parent\":\n                this._solveParent(node);\n                break;\n            case \"aim\":\n                this._solveAim(node);\n                break;\n            default:\n                break;\n        }\n    }\n\n    /**\n     * World matrix of a node relative to the asset root (FBX space).\n     * @param node - node to evaluate\n     * @param out - matrix receiving the result\n     * @returns `out`\n     */\n    private _fbxWorld(node: TransformNode, out: Matrix): Matrix {\n        node.computeWorldMatrix(true).multiplyToRef(Scratch.invRoot, out);\n        return out;\n    }\n\n    /**\n     * Weighted blend of the targets' world transforms (relative to the root).\n     * @param position - Receives the blended translation\n     * @param rotation - Receives the blended rotation\n     * @param scale - Receives the blended scale\n     * @returns The total target weight, 0 when no target contributes\n     */\n    private _blendTargets(position: Vector3, rotation: Quaternion, scale: Vector3): number {\n        position.set(0, 0, 0);\n        scale.set(0, 0, 0);\n        rotation.set(0, 0, 0, 1);\n        let total = 0;\n        for (const target of this._options.targets) {\n            if (target.weight <= 0) {\n                continue;\n            }\n            target.offset.multiplyToRef(this._fbxWorld(target.node, Scratch.world), Scratch.local);\n            Scratch.local.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n            const next = total + target.weight;\n            position.addInPlace(Scratch.translation.scaleInPlace(target.weight));\n            scale.addInPlace(Scratch.decomposedScale.scaleInPlace(target.weight));\n            if (total === 0) {\n                rotation.copyFrom(Scratch.decomposedRotation);\n            } else {\n                Quaternion.SlerpToRef(rotation, Scratch.decomposedRotation, target.weight / next, rotation);\n            }\n            total = next;\n        }\n        if (total > 0) {\n            position.scaleInPlace(1 / total);\n            scale.scaleInPlace(1 / total);\n        }\n        return total;\n    }\n\n    private _applyWeighted(base: Vector3, desired: Vector3, mask: readonly boolean[], out: Vector3): void {\n        const w = this.constraint.weight;\n        out.set(mask[0] ? base.x + (desired.x - base.x) * w : base.x, mask[1] ? base.y + (desired.y - base.y) * w : base.y, mask[2] ? base.z + (desired.z - base.z) * w : base.z);\n    }\n\n    private _applyRotation(node: TransformNode, desiredLocal: Quaternion, mask: readonly boolean[]): void {\n        const base = this._base.rotation;\n        const result = Scratch.result;\n        result.copyFrom(desiredLocal);\n        if (!(mask[0] && mask[1] && mask[2])) {\n            base.toEulerAnglesToRef(Scratch.eulerA);\n            desiredLocal.toEulerAnglesToRef(Scratch.eulerB);\n            Quaternion.FromEulerAnglesToRef(\n                mask[0] ? Scratch.eulerB.x : Scratch.eulerA.x,\n                mask[1] ? Scratch.eulerB.y : Scratch.eulerA.y,\n                mask[2] ? Scratch.eulerB.z : Scratch.eulerA.z,\n                result\n            );\n        }\n        if (this.constraint.weight < 1) {\n            Quaternion.SlerpToRef(base, result, this.constraint.weight, result);\n        }\n        node.rotationQuaternion!.copyFrom(result);\n    }\n\n    private _writePosition(node: TransformNode, desiredLocal: Vector3): void {\n        this._applyWeighted(this._base.position, desiredLocal, this.constraint.affectTranslation, node.position);\n    }\n\n    private _writeScaling(node: TransformNode, desiredLocal: Vector3): void {\n        this._applyWeighted(this._base.scaling, desiredLocal, this.constraint.affectScale, node.scaling);\n    }\n\n    private _solvePosition(node: TransformNode): void {\n        if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n            return;\n        }\n        Vector3.TransformCoordinatesToRef(Scratch.position, Scratch.invParent, Scratch.localValue);\n        Scratch.localValue.addInPlace(this._offsetTranslation);\n        this._writePosition(node, Scratch.localValue);\n    }\n\n    private _solveRotation(node: TransformNode): void {\n        if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n            return;\n        }\n        Matrix.FromQuaternionToRef(Scratch.rotation, Scratch.mA);\n        this._offsetRotation.multiplyToRef(Scratch.mA, Scratch.mB);\n        Scratch.mB.multiplyToRef(Scratch.invParent, Scratch.mC);\n        Scratch.mC.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n        this._applyRotation(node, Scratch.decomposedRotation, this.constraint.affectRotation);\n    }\n\n    private _solveScale(node: TransformNode): void {\n        if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n            return;\n        }\n        Scratch.parent.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n        const parentScale = Scratch.decomposedScale;\n        const scale = Scratch.scale;\n        Scratch.localValue.set(\n            (parentScale.x !== 0 ? scale.x / parentScale.x : scale.x) * this._offsetScale.x,\n            (parentScale.y !== 0 ? scale.y / parentScale.y : scale.y) * this._offsetScale.y,\n            (parentScale.z !== 0 ? scale.z / parentScale.z : scale.z) * this._offsetScale.z\n        );\n        this._writeScaling(node, Scratch.localValue);\n    }\n\n    private _solveParent(node: TransformNode): void {\n        if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n            return;\n        }\n        Matrix.ComposeToRef(Scratch.scale, Scratch.rotation, Scratch.position, Scratch.mA);\n        Scratch.mA.multiplyToRef(Scratch.invParent, Scratch.mB);\n        Scratch.mB.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n        this._writePosition(node, Scratch.translation);\n        this._applyRotation(node, Scratch.decomposedRotation, this.constraint.affectRotation);\n        this._writeScaling(node, Scratch.decomposedScale);\n    }\n\n    private _solveAim(node: TransformNode): void {\n        const c = this.constraint;\n        if (!this._localBasisTransposed || this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n            return;\n        }\n        // The node's own world position (after animation) is the origin of the aim.\n        const nodeWorld = this._fbxWorld(node, Scratch.world);\n        nodeWorld.getTranslationToRef(Scratch.origin);\n        Scratch.position.subtractToRef(Scratch.origin, Scratch.forward);\n        if (Scratch.forward.lengthSquared() < 1e-20) {\n            return;\n        }\n        Scratch.forward.normalize();\n\n        // Up direction in world space\n        const up = Scratch.up;\n        switch (c.worldUpType) {\n            case 1: // aim the up vector at the up node\n                if (this._options.upNode) {\n                    this._fbxWorld(this._options.upNode, Scratch.local).getTranslationToRef(up);\n                    up.subtractInPlace(Scratch.origin);\n                } else {\n                    up.copyFrom(this._options.sceneUp);\n                }\n                break;\n            case 2: // copy the up vector from the up node's orientation\n                if (this._options.upNode) {\n                    this._fbxWorld(this._options.upNode, Scratch.local).decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n                    up.set(c.worldUpVector[0], c.worldUpVector[1], c.worldUpVector[2]);\n                    up.rotateByQuaternionToRef(Scratch.decomposedRotation, up);\n                } else {\n                    up.copyFrom(this._options.sceneUp);\n                }\n                break;\n            case 3: // explicit world vector\n                up.set(c.worldUpVector[0], c.worldUpVector[1], c.worldUpVector[2]);\n                break;\n            case 4: // none: keep the current roll by using the node's current up\n                Scratch.localValue.set(c.upVector[0], c.upVector[1], c.upVector[2]);\n                Vector3.TransformNormalToRef(Scratch.localValue, nodeWorld, up);\n                break;\n            default: // scene up\n                up.copyFrom(this._options.sceneUp);\n                break;\n        }\n        if (up.lengthSquared() < 1e-20 || Math.abs(Vector3.Dot(up.normalizeToRef(Scratch.localValue), Scratch.forward)) > 0.9999) {\n            // Degenerate up: pick any perpendicular vector\n            if (Math.abs(Scratch.forward.y) < 0.9) {\n                up.set(0, 1, 0);\n            } else {\n                up.set(1, 0, 0);\n            }\n        }\n\n        // World basis (forward, up, side); the local basis (aimVector, upVector, side) is fixed per constraint.\n        if (!FBXConstraintBehavior._OrthonormalBasisToRef(Scratch.forward, up, Scratch.mA)) {\n            return;\n        }\n        // rotation R with R(localBasis) = worldBasis: R = localBasis^T * worldBasis (row-vector convention)\n        this._localBasisTransposed.multiplyToRef(Scratch.mA, Scratch.mB);\n        this._offsetRotation.multiplyToRef(Scratch.mB, Scratch.mC);\n        Scratch.mC.multiplyToRef(Scratch.invParent, Scratch.mD);\n        Scratch.mD.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n        this._applyRotation(node, Scratch.decomposedRotation, c.affectRotation);\n    }\n\n    /**\n     * Builds a rotation matrix whose rows are `first`, `second` made orthogonal to it, and their cross product.\n     * @param first - primary axis\n     * @param second - secondary axis\n     * @param out - matrix receiving the basis\n     * @returns false when the axes are parallel or degenerate (`out` is then unchanged)\n     */\n    private static _OrthonormalBasisToRef(first: Vector3, second: Vector3, out: Matrix): boolean {\n        const a = Scratch.axisA;\n        const b = Scratch.axisB;\n        const cr = Scratch.axisC;\n        first.normalizeToRef(a);\n        second.subtractToRef(a.scaleToRef(Vector3.Dot(a, second), b), b);\n        if (a.lengthSquared() < 1e-20 || b.lengthSquared() < 1e-20) {\n            return false;\n        }\n        b.normalize();\n        Vector3.CrossToRef(a, b, cr);\n        Matrix.FromValuesToRef(a.x, a.y, a.z, 0, b.x, b.y, b.z, 0, cr.x, cr.y, cr.z, 0, 0, 0, 0, 1, out);\n        return true;\n    }\n}\n","import { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\n/**\r\n * Defines the FBX loader plugin metadata.\r\n */\r\nexport const FBXFileLoaderMetadata = {\r\n    name: \"fbx\",\r\n\r\n    extensions: {\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".fbx\": { isBinary: true },\r\n    } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n","/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport {\n    type ISceneLoaderPluginAsync,\n    type ISceneLoaderPluginFactory,\n    type ISceneLoaderAsyncResult,\n    type ISceneLoaderProgressEvent,\n    type SceneLoaderPluginOptions,\n    RegisterSceneLoaderPlugin,\n} from \"core/Loading/sceneLoader\";\nimport { type Scene } from \"core/scene\";\nimport { type FloatArray, type Nullable } from \"core/types\";\nimport { Mesh } from \"core/Meshes/mesh.pure\";\nimport { LinesMesh } from \"core/Meshes/linesMesh.pure\";\nimport { SubMesh } from \"core/Meshes/subMesh\";\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\nimport { StandardMaterial } from \"core/Materials/standardMaterial.pure\";\nimport { PBRMaterial } from \"core/Materials/PBR/pbrMaterial.pure\";\nimport { Material } from \"core/Materials/material\";\nimport { MultiMaterial } from \"core/Materials/multiMaterial.pure\";\nimport { type ITextureCreationOptions, Texture } from \"core/Materials/Textures/texture.pure\";\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\nimport { Color3 } from \"core/Maths/math.color.pure\";\nimport { Vector3, Quaternion, Matrix } from \"core/Maths/math.vector.pure\";\nimport { TransformNode } from \"core/Meshes/transformNode.pure\";\nimport { Skeleton } from \"core/Bones/skeleton\";\nimport { Bone } from \"core/Bones/bone\";\nimport { Animation } from \"core/Animations/animation.pure\";\nimport { AnimationGroup } from \"core/Animations/animationGroup.pure\";\nimport { AnimationKeyInterpolation, type IAnimationKey } from \"core/Animations/animationKey\";\nimport { MorphTarget } from \"core/Morph/morphTarget\";\nimport { MorphTargetManager } from \"core/Morph/morphTargetManager\";\nimport { Camera } from \"core/Cameras/camera.pure\";\nimport { FreeCamera } from \"core/Cameras/freeCamera.pure\";\nimport { PointLight } from \"core/Lights/pointLight.pure\";\nimport { DirectionalLight } from \"core/Lights/directionalLight.pure\";\nimport { SpotLight } from \"core/Lights/spotLight.pure\";\nimport { type Light } from \"core/Lights/light\";\nimport { AssetContainer } from \"core/assetContainer\";\nimport { GetMimeType } from \"core/Misc/fileTools.pure\";\n\nimport { parseBinaryFBX } from \"./parsers/fbxBinaryParser\";\nimport { parseAsciiFBX } from \"./parsers/fbxAsciiParser\";\nimport { interpretFBX, type FBXModelData, type FBXSceneData, type FBXCameraData, type FBXLightData } from \"./interpreter/fbxInterpreter\";\nimport { type FBXDocument } from \"./types/fbxTypes\";\nimport { type FBXGeometryData } from \"./interpreter/geometry\";\nimport { type FBXCurveGeometryData } from \"./interpreter/nurbs\";\nimport { FBXConstraintBehavior, type FBXConstraintBehaviorTarget } from \"./fbxConstraintBehavior\";\nimport { type FBXMaterialData, type FBXTextureRef } from \"./interpreter/materials\";\nimport { isPbrShaderType, mapColor, mapScalar } from \"./interpreter/materialModel\";\nimport { type FBXSkinData, type FBXBoneData } from \"./interpreter/skeleton\";\nimport { type FBXRigData, type FBXSkinBindingData } from \"./interpreter/rig\";\nimport { type FBXBlendShapeData, type FBXShapeData } from \"./interpreter/blendShapes\";\nimport {\n    evaluateLayeredChannel,\n    evaluateLayeredProperty,\n    isChannelSteppedAt,\n    sampleFBXCurveAtTime,\n    type FBXAnimationLayerData,\n    type FBXAnimationStackData,\n    type FBXCurveData,\n    type FBXCurveNodeData,\n    type FBXLayeredPropertySource,\n    type FBXUnsupportedCurveNodeData,\n} from \"./interpreter/animation\";\nimport {\n    computeFBXGeometricDeltaMatrix,\n    computeFBXGeometricMatrix,\n    computeFBXGeometricNormalMatrix,\n    computeFBXLocalMatrix,\n    eulerToMatrix,\n    eulerToMatrixXYZ,\n} from \"./interpreter/transform\";\nimport { FBXFileLoaderMetadata } from \"./fbxFileLoader.metadata\";\n\nconst FBX_ASCII_MAGIC = \"; FBX\";\nconst FBX_BINARY_MAGIC = \"Kaydara FBX Binary\";\nconst BIND_REST_SCALE_RATIO_THRESHOLD = 10;\n\n/**\n * Source convention for tangent-space normal maps loaded from FBX normal-map slots.\n */\nexport type FBXNormalMapCoordinateSystem = \"y-up\" | \"y-down\";\n\n/**\n * Defines options for the FBX loader.\n */\nexport interface FBXFileLoaderOptions {\n    /**\n     * Bundle of defaults for the options that change what the loaded scene looks like.\n     * - \"compatible\" (default): the behaviour of the loader as first shipped: StandardMaterial for every material,\n     *   one Babylon geometry per model, curve geometry skipped, constraints recorded as metadata only, clips rebased\n     *   to start at frame 0, cameras and lights placed in world space.\n     * - \"full\": everything the loader can do: PBRMaterial for physically based shaders, geometry shared between\n     *   instances, curves as lines meshes, constraints solved at runtime, authored clip times, cameras and lights\n     *   parented to their nodes so they animate.\n     * An option set explicitly always wins over the preset.\n     */\n    preset?: \"compatible\" | \"full\";\n    /**\n     * Source convention for tangent-space normal maps connected through FBX normal-map slots.\n     * FBX does not standardize this convention, so the loader defaults to the glTF/USD-style Y-up convention.\n     * Set to \"y-down\" for assets authored with inverted green/Y normal maps.\n     */\n    normalMapCoordinateSystem?: FBXNormalMapCoordinateSystem;\n    /**\n     * Which Babylon material to build.\n     * - \"standard\" (default, \"full\" preset: \"auto\"): always StandardMaterial (PBR parameters are approximated).\n     * - \"auto\": PBRMaterial for physically based FBX materials (Standard Surface, Arnold, 3ds Max Physical,\n     *   3ds Max PBR, glTF, OpenPBR, Stingray PBS) and StandardMaterial for classic Lambert/Phong materials.\n     * - \"pbr\": always PBRMaterial (Lambert/Phong parameters are converted).\n     */\n    materials?: \"auto\" | \"standard\" | \"pbr\";\n    /**\n     * Unit conversion applied at the root of the loaded hierarchy.\n     * - \"preserve\" (default): keep the file's units (1 Babylon unit = 1 FBX unit).\n     * - \"meters\": scale so that 1 Babylon unit is 1 meter, using the file's UnitScaleFactor.\n     * - a number: centimeters per Babylon unit (100 = meters, 1 = centimeters, 2.54 = inches).\n     */\n    unitScale?: \"preserve\" | \"meters\" | number;\n    /**\n     * Share vertex data between models that reference the same FBX geometry (default false, \"full\" preset: true).\n     * Skinned meshes are never shared.\n     */\n    shareGeometry?: boolean;\n    /**\n     * Called for every recoverable issue found while loading (unsupported features, malformed data that was\n     * skipped, approximations). The same list is stored on the root node's metadata as `fbxDiagnostics`.\n     */\n    onWarning?: (warning: FBXLoaderWarning) => void;\n    /**\n     * Segments per knot span when tessellating NURBS surfaces. Zero or undefined uses the subdivision stored in\n     * the file (usually 4), capped at 16.\n     */\n    nurbsSubdivision?: number;\n    /** How curve geometry (Line, NurbsCurve) is imported: skipped (default) or as lines meshes (\"full\" preset). */\n    curves?: \"lines\" | \"skip\";\n    /**\n     * Constraints (aim, parent, position, rotation, scale): \"metadata\" (default) only records them on the nodes,\n     * \"apply\" (\"full\" preset) attaches an `FBXConstraintBehavior` to each constrained node so it is solved before\n     * every render. IK chains are always metadata only.\n     */\n    constraints?: \"apply\" | \"metadata\";\n    /**\n     * Shift every clip so its first keyframe sits at frame 0 (default true). With false (\"full\" preset) keys keep\n     * the times authored in the file, so clips of one file stay aligned with each other and with their declared\n     * ranges.\n     */\n    rebaseAnimations?: boolean;\n    /**\n     * Parent cameras and lights to their FBX node so they follow its animation (default false, \"full\" preset:\n     * true). Otherwise they are created at the node's world position and orientation, unparented.\n     */\n    attachCamerasAndLights?: boolean;\n}\n\n/** A recoverable issue reported while loading an FBX file. */\nexport interface FBXLoaderWarning {\n    /** Which part of the loader reported the issue */\n    source: \"scene\" | \"model\" | \"geometry\" | \"skin\" | \"rig\" | \"animation\" | \"blendShape\" | \"camera\" | \"light\";\n    /** Human readable description */\n    message: string;\n    /** Name of the affected object, when known */\n    objectName?: string;\n    /** Structured details from the interpreter, when any */\n    details?: unknown;\n}\n\ninterface IFBXSceneLoaderAsyncResult extends ISceneLoaderAsyncResult {\n    materials: Material[];\n    textures: BaseTexture[];\n    cameras: Camera[];\n}\n\n/**\n * FBX file loader plugin for Babylon.js.\n * Pure TypeScript implementation — no Autodesk FBX SDK dependency.\n */\nexport class FBXFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\n    /**\n     * Defines the name of the plugin.\n     */\n    public readonly name = FBXFileLoaderMetadata.name;\n\n    /**\n     * Defines the extension the plugin is able to load.\n     */\n    public readonly extensions = FBXFileLoaderMetadata.extensions;\n\n    private readonly _options: Required<FBXFileLoaderOptions>;\n    private readonly _bindRestBones = new WeakSet<Bone>();\n    private readonly _sourceBonesBySkeleton = new WeakMap<Skeleton, Bone[]>();\n    private readonly _scaleCompensationHelpersBySkeleton = new WeakMap<Skeleton, Map<number, Bone>>();\n    /** Frame rate of the file being loaded (GlobalSettings TimeMode); animation is baked at this rate. */\n    private _frameRate = 30;\n    /** Layers of the animation stack currently being converted; used by the transform samplers. */\n    private _activeLayers: readonly FBXAnimationLayerData[] = [];\n    /** Parent model per model id, for inherit-mode aware sampling. */\n    private _parentModelById = new Map<number, FBXModelData>();\n    /** Curve nodes per model id for the stack currently being converted. */\n    private _curveNodesByModelId = new Map<number, FBXCurveNodeData[]>();\n    /** Helper nodes inserted above models whose InheritType is not RSrs. */\n    private _inheritScaleHelpers = new Map<number, TransformNode>();\n    /** First mesh built per (geometry, geometric transform), for geometry sharing between instances. */\n    private _meshByGeometryKey = new Map<string, Mesh>();\n    /** Instance mesh -> source mesh whose geometry it shares. */\n    private _instanceSource = new Map<Mesh, Mesh>();\n    /** Property curve nodes that were mapped onto Babylon animations; their \"not evaluated\" diagnostics are dropped. */\n    private _evaluatedCurveNodeIds = new Set<number>();\n\n    /**\n     * Creates a new FBX loader.\n     * @param options - Options controlling FBX loading behavior\n     */\n    public constructor(options: FBXFileLoaderOptions = {}) {\n        const full = options.preset === \"full\";\n        this._options = {\n            preset: full ? \"full\" : \"compatible\",\n            normalMapCoordinateSystem: options.normalMapCoordinateSystem ?? \"y-up\",\n            materials: options.materials ?? (full ? \"auto\" : \"standard\"),\n            unitScale: options.unitScale ?? \"preserve\",\n            shareGeometry: options.shareGeometry ?? full,\n            onWarning: options.onWarning ?? (() => {}),\n            nurbsSubdivision: options.nurbsSubdivision ?? 0,\n            curves: options.curves ?? (full ? \"lines\" : \"skip\"),\n            constraints: options.constraints ?? (full ? \"apply\" : \"metadata\"),\n            rebaseAnimations: options.rebaseAnimations ?? !full,\n            attachCamerasAndLights: options.attachCamerasAndLights ?? full,\n        };\n    }\n\n    /**\n     * Creates an FBX loader plugin instance with options from SceneLoader.\n     * @param options - Scene loader plugin options\n     * @returns The configured FBX loader\n     */\n    public createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\n        return new FBXFileLoader(options[FBXFileLoaderMetadata.name]);\n    }\n\n    /**\n     * Imports meshes from an FBX file and adds them to the scene.\n     * @param meshesNames - A string or array of mesh names to import, or null/undefined to import all meshes\n     * @param scene - The scene to add imported meshes to\n     * @param data - The FBX data to load\n     * @param rootUrl - Root URL used to resolve external resources\n     * @param _onProgress - Callback called while the file is loading\n     * @param _fileName - Name of the file being loaded\n     * @returns A promise containing the loaded meshes, particle systems, skeletons, animation groups, transform nodes, geometries, and lights\n     */\n    public async importMeshAsync(\n        meshesNames: string | readonly string[] | null | undefined,\n        scene: Scene,\n        data: unknown,\n        rootUrl: string,\n        _onProgress?: (event: ISceneLoaderProgressEvent) => void,\n        _fileName?: string\n    ): Promise<ISceneLoaderAsyncResult> {\n        const fbxScene = this._parseAndInterpret(data);\n        const result = this._buildScene(fbxScene, scene, rootUrl, meshesNames);\n        return result;\n    }\n\n    /**\n     * Loads all FBX content into the scene.\n     * @param scene - The scene to load the FBX content into\n     * @param data - The FBX data to load\n     * @param rootUrl - Root URL used to resolve external resources\n     * @param _onProgress - Callback called while the file is loading\n     * @param _fileName - Name of the file being loaded\n     * @returns A promise that resolves when loading is complete\n     */\n    public async loadAsync(scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise<void> {\n        const fbxScene = this._parseAndInterpret(data);\n        this._buildScene(fbxScene, scene, rootUrl, null);\n    }\n\n    /**\n     * Loads all FBX content into an asset container.\n     * @param scene - The scene used to create the asset container\n     * @param data - The FBX data to load\n     * @param rootUrl - Root URL used to resolve external resources\n     * @param _onProgress - Callback called while the file is loading\n     * @param _fileName - Name of the file being loaded\n     * @returns A promise containing the loaded asset container\n     */\n    public async loadAssetContainerAsync(\n        scene: Scene,\n        data: unknown,\n        rootUrl: string,\n        _onProgress?: (event: ISceneLoaderProgressEvent) => void,\n        _fileName?: string\n    ): Promise<AssetContainer> {\n        const fbxScene = this._parseAndInterpret(data);\n\n        const container = new AssetContainer(scene);\n\n        // Build the scene into a temporary holder, then move results to container\n        const result = this._buildScene(fbxScene, scene, rootUrl, null);\n\n        for (const mesh of result.meshes) {\n            container.meshes.push(mesh);\n        }\n        for (const skeleton of result.skeletons) {\n            container.skeletons.push(skeleton);\n        }\n        for (const ag of result.animationGroups) {\n            container.animationGroups.push(ag);\n        }\n        for (const tn of result.transformNodes) {\n            container.transformNodes.push(tn);\n        }\n        for (const light of result.lights) {\n            container.lights.push(light);\n        }\n        for (const camera of result.cameras) {\n            container.cameras.push(camera);\n        }\n        for (const material of result.materials) {\n            this._addMaterialToContainer(material, container);\n        }\n        for (const texture of result.textures) {\n            this._addTextureToContainer(texture, container);\n        }\n        for (const mesh of result.meshes) {\n            // Lines meshes own an internal colour shader; it is not an asset of the file.\n            if (mesh instanceof LinesMesh) {\n                continue;\n            }\n            this._addMaterialToContainer(mesh.material, container);\n        }\n\n        // Remove all added objects from the scene (container owns them)\n        this._setAssetContainer(container);\n        container.removeAllFromScene();\n\n        return container;\n    }\n\n    // ── Parsing ────────────────────────────────────────────────────────────\n\n    /**\n     * Parses and interprets the file. Parsing is synchronous, so no progress events are emitted: the scene loader's\n     * progress callback reports download bytes and must not be fed synthetic counts.\n     */\n    private _parseAndInterpret(data: unknown): FBXSceneData {\n        const doc = this._parse(data);\n        return interpretFBX(doc, {\n            nurbsSubdivision: this._options.nurbsSubdivision > 0 ? this._options.nurbsSubdivision : undefined,\n            rebaseKeyframes: this._options.rebaseAnimations,\n        });\n    }\n\n    private _parse(data: unknown): FBXDocument {\n        if (data instanceof ArrayBuffer) {\n            return this._parseFromArrayBuffer(data);\n        }\n        if (ArrayBuffer.isView(data)) {\n            const view = data as ArrayBufferView;\n            const buffer = view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength) as ArrayBuffer;\n            return this._parseFromArrayBuffer(buffer);\n        }\n        if (typeof data === \"string\") {\n            return parseAsciiFBX(data);\n        }\n        throw new Error(\"FBXFileLoader: unsupported data type\");\n    }\n\n    private _parseFromArrayBuffer(buffer: ArrayBuffer): FBXDocument {\n        // Check magic bytes to determine binary vs ASCII\n        const headerBytes = new Uint8Array(buffer, 0, Math.min(21, buffer.byteLength));\n        const header = String.fromCharCode(...headerBytes);\n\n        if (header.startsWith(FBX_BINARY_MAGIC)) {\n            return parseBinaryFBX(buffer);\n        }\n\n        // Try ASCII. Most files start with \"; FBX x.y.z project file\", but the header comment is optional:\n        // some exporters start straight at FBXHeaderExtension or even at Objects.\n        const text = new TextDecoder(\"utf-8\").decode(buffer);\n        const head = text.substring(0, 4096);\n        if (head.trimStart().startsWith(FBX_ASCII_MAGIC) || /^\\s*(?:;[^\\n]*\\n\\s*)*(?:FBXHeaderExtension|Definitions|Objects|Connections)\\s*:/.test(head)) {\n            return parseAsciiFBX(text);\n        }\n\n        throw new Error(\"FBXFileLoader: unrecognized FBX format\");\n    }\n\n    // ── Scene Building ─────────────────────────────────────────────────────\n\n    private _buildScene(fbxScene: FBXSceneData, scene: Scene, rootUrl: string, meshesNames: string | readonly string[] | null | undefined): IFBXSceneLoaderAsyncResult {\n        const nameFilter = this._buildNameFilter(meshesNames);\n        this._frameRate = fbxScene.frameRate > 0 ? fbxScene.frameRate : 30;\n        this._inheritScaleHelpers = new Map();\n\n        // Create materials\n        const materialCache = new Map<number, Material>();\n        for (const matData of fbxScene.materials) {\n            const material = this._createMaterial(matData, scene, rootUrl);\n            materialCache.set(matData.id, material);\n        }\n\n        // Create one Babylon skeleton per resolved deformation rig.\n        const skeletons: Skeleton[] = [];\n        const skeletonByRigId = new Map<string, Skeleton>();\n        const skeletonByGeometryId = new Map<number, Skeleton>();\n        const skinByGeometryId = new Map<number, FBXSkinData>();\n        const skinBindingByGeometryId = new Map<number, FBXSkinBindingData>();\n        const skinById = new Map<number, FBXSkinData>();\n\n        for (const skin of fbxScene.skins) {\n            skinById.set(skin.id, skin);\n        }\n\n        this._rigBoneModelIds = new Set();\n        for (const rig of fbxScene.rigs) {\n            for (const bone of rig.bones) {\n                this._rigBoneModelIds.add(bone.modelId);\n            }\n        }\n        for (const rig of fbxScene.rigs) {\n            const skeleton = this._createSkeleton(rig.id, rig.bones, scene);\n            skeletons.push(skeleton);\n            skeletonByRigId.set(rig.id, skeleton);\n\n            for (const binding of rig.skinBindings) {\n                const skin = skinById.get(binding.skinId);\n                if (!skin) {\n                    continue;\n                }\n\n                skeletonByGeometryId.set(binding.geometryId, skeleton);\n                skinByGeometryId.set(binding.geometryId, skin);\n                skinBindingByGeometryId.set(binding.geometryId, binding);\n            }\n        }\n\n        // Collect model data for animation sampling.\n        const modelIdToData = new Map<number, FBXModelData>();\n        this._parentModelById = new Map();\n        const collectModelData = (models: FBXModelData[], parent: FBXModelData | null) => {\n            for (const m of models) {\n                modelIdToData.set(m.id, m);\n                if (parent) {\n                    this._parentModelById.set(m.id, parent);\n                }\n                collectModelData(m.children, m);\n            }\n        };\n        collectModelData(fbxScene.rootModels, null);\n        const cullingConflictMaterialIds = FBXFileLoader._collectCullingConflictMaterialIds(fbxScene.rootModels);\n        const cullingMaterialCloneCache = new Map<Material, Material>();\n\n        // Build the FBX hierarchy under the same handedness conversion root that\n        // Babylon's glTF loader uses when loading right-handed assets into a\n        // left-handed scene. If the FBX file declares a non-Y-up scene basis,\n        // add a child axis-conversion root so model/bind math stays in FBX space.\n        const rootNode = new TransformNode(\"__fbx_root__\", scene);\n        if (!scene.useRightHandedSystem) {\n            rootNode.rotation.y = Math.PI;\n            rootNode.scaling.z = -1;\n        }\n        // FBX units: one file unit is UnitScaleFactor centimeters.\n        const unitScale = this._options.unitScale;\n        const cmPerTargetUnit = unitScale === \"preserve\" ? 0 : unitScale === \"meters\" ? 100 : unitScale;\n        if (cmPerTargetUnit > 0 && fbxScene.unitScaleFactor > 0) {\n            const factor = fbxScene.unitScaleFactor / cmPerTargetUnit;\n            rootNode.scaling.scaleInPlace(factor);\n        }\n        rootNode.metadata = { ...((rootNode.metadata as object) ?? {}), fbxUnitScaleFactor: fbxScene.unitScaleFactor, fbxFrameRate: fbxScene.frameRate };\n        this._meshByGeometryKey = new Map();\n        this._instanceSource = new Map();\n        this._evaluatedCurveNodeIds = new Set();\n\n        const meshes: Mesh[] = [];\n        const transformNodes: TransformNode[] = [rootNode];\n        let assetRoot = rootNode;\n        const axisConversion = FBXFileLoader._computeFBXAxisConversionMatrix(fbxScene);\n        if (!axisConversion.equals(Matrix.Identity())) {\n            assetRoot = new TransformNode(\"__fbx_axis_conversion__\", scene);\n            assetRoot.parent = rootNode;\n            FBXFileLoader._applyMatrixToTransform(assetRoot, axisConversion);\n            transformNodes.push(assetRoot);\n        }\n        const modelIdToNode = new Map<number, TransformNode>();\n        const fbxWorldIdentity = Matrix.Identity();\n\n        for (const model of fbxScene.rootModels) {\n            this._buildModel(\n                model,\n                scene,\n                assetRoot,\n                assetRoot,\n                fbxWorldIdentity,\n                materialCache,\n                nameFilter,\n                meshes,\n                transformNodes,\n                skeletonByGeometryId,\n                skinByGeometryId,\n                skinBindingByGeometryId,\n                modelIdToNode,\n                cullingConflictMaterialIds,\n                cullingMaterialCloneCache\n            );\n        }\n        this._linkSkeletonsToTransformNodes(fbxScene.rigs, skeletonByRigId, modelIdToNode, transformNodes, scene);\n\n        // Link non-skinned child meshes/nodes to their parent bones so they\n        // follow skeletal animation. Preserve their current world matrix when\n        // switching from the FBX model hierarchy to Babylon's bone parent.\n        for (const rig of fbxScene.rigs) {\n            const skeleton = skeletonByRigId.get(rig.id);\n            if (!skeleton) {\n                continue;\n            }\n\n            const skinnedMesh = meshes.find((m) => m.skeleton === skeleton) ?? null;\n            const boneReferenceNode = skinnedMesh ?? rootNode;\n            const boneTransformNodes = new Set<TransformNode>();\n            for (const skeletonBone of skeleton.bones) {\n                const transformNode = skeletonBone.getTransformNode();\n                if (transformNode) {\n                    boneTransformNodes.add(transformNode);\n                }\n            }\n\n            // Children of joints (props, end effectors, meshes) stay parented to the joint's TransformNode. Bones are\n            // linked to those nodes, so the hierarchy already follows the animation; attaching to the bone's skinning\n            // matrix would move them into the skinned mesh's space instead of the node's.\n            void boneTransformNodes;\n            void boneReferenceNode;\n        }\n\n        // Apply blend shapes (morph targets) to meshes\n        if (fbxScene.blendShapes.length > 0) {\n            this._applyBlendShapes(fbxScene.blendShapes, meshes, scene);\n            for (const [instance, source] of Array.from(this._instanceSource)) {\n                if (source.morphTargetManager && !instance.morphTargetManager) {\n                    instance.morphTargetManager = source.morphTargetManager;\n                }\n            }\n        }\n\n        // Create cameras\n        const cameras: FreeCamera[] = [];\n        const cameraByAttributeId = new Map<number, FreeCamera>();\n        for (const camData of fbxScene.cameras) {\n            const cam = this._createCamera(camData, modelIdToNode, scene);\n            if (cam) {\n                cameras.push(cam);\n                cameraByAttributeId.set(camData.attributeId, cam);\n            }\n        }\n\n        // Create lights\n        const sceneLights: (PointLight | DirectionalLight | SpotLight)[] = [];\n        const lightByAttributeId = new Map<number, Light>();\n        for (const lightData of fbxScene.lights) {\n            const light = this._createLight(lightData, modelIdToNode, scene);\n            if (light) {\n                sceneLights.push(light);\n                lightByAttributeId.set(lightData.attributeId, light);\n            }\n        }\n\n        this._applyConstraints(fbxScene, modelIdToNode, rootNode, scene);\n\n        // Create animation groups\n        const animationGroups: AnimationGroup[] = [];\n        for (const animStack of fbxScene.animations) {\n            const group = this._createAnimationGroup(animStack, fbxScene.rigs, skeletonByRigId, scene, modelIdToNode, modelIdToData, meshes, {\n                cameraByAttributeId,\n                lightByAttributeId,\n                materialCache,\n            });\n            if (group) {\n                animationGroups.push(group);\n            }\n        }\n\n        // Reported last so that property curves the animation groups picked up are not flagged as unevaluated.\n        this._reportDiagnostics(fbxScene, rootNode, modelIdToNode);\n\n        return {\n            meshes,\n            particleSystems: [],\n            skeletons,\n            animationGroups,\n            transformNodes,\n            geometries: [],\n            lights: sceneLights,\n            spriteManagers: [],\n            materials: Array.from(materialCache.values()),\n            textures: Array.from(new Set(Array.from(materialCache.values()).flatMap((material) => material.getActiveTextures()))),\n            cameras,\n        };\n    }\n\n    private _addMaterialToContainer(material: Nullable<Material>, container: AssetContainer): void {\n        if (!material) {\n            return;\n        }\n\n        if (material instanceof MultiMaterial) {\n            if (!container.multiMaterials.includes(material)) {\n                container.multiMaterials.push(material);\n            }\n            for (const subMaterial of material.subMaterials) {\n                this._addMaterialToContainer(subMaterial, container);\n            }\n        } else if (!container.materials.includes(material)) {\n            container.materials.push(material);\n        }\n\n        for (const texture of material.getActiveTextures()) {\n            this._addTextureToContainer(texture, container);\n        }\n    }\n\n    private _addTextureToContainer(texture: BaseTexture, container: AssetContainer): void {\n        if (!container.textures.includes(texture)) {\n            container.textures.push(texture);\n        }\n    }\n\n    private _setAssetContainer(container: AssetContainer): void {\n        for (const asset of container.meshes) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.transformNodes) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.skeletons) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.animationGroups) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.lights) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.cameras) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.materials) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.multiMaterials) {\n            asset._parentContainer = container;\n        }\n        for (const asset of container.textures) {\n            asset._parentContainer = container;\n        }\n    }\n\n    private static _computeFBXAxisConversionMatrix(fbxScene: FBXSceneData): Matrix {\n        const basisRows: [number, number, number][] = [\n            [0, 0, 0],\n            [0, 0, 0],\n            [0, 0, 0],\n        ];\n\n        const assignAxis = (sourceAxis: number, sourceSign: number, targetAxis: number): void => {\n            if (sourceAxis < 0 || sourceAxis > 2) {\n                return;\n            }\n            const row: [number, number, number] = [0, 0, 0];\n            row[targetAxis] = sourceSign >= 0 ? 1 : -1;\n            basisRows[sourceAxis] = row;\n        };\n\n        assignAxis(fbxScene.coordAxis, fbxScene.coordAxisSign, 0);\n        assignAxis(fbxScene.upAxis, fbxScene.upAxisSign, 1);\n        assignAxis(fbxScene.frontAxis, fbxScene.frontAxisSign, 2);\n\n        if (basisRows.some((row) => row.every((value) => value === 0))) {\n            return Matrix.Identity();\n        }\n\n        return Matrix.FromValues(\n            basisRows[0][0],\n            basisRows[0][1],\n            basisRows[0][2],\n            0,\n            basisRows[1][0],\n            basisRows[1][1],\n            basisRows[1][2],\n            0,\n            basisRows[2][0],\n            basisRows[2][1],\n            basisRows[2][2],\n            0,\n            0,\n            0,\n            0,\n            1\n        );\n    }\n\n    private _buildModel(\n        model: FBXModelData,\n        scene: Scene,\n        parentNode: Nullable<TransformNode>,\n        assetRoot: TransformNode,\n        parentFBXWorldMatrix: Matrix,\n        materialCache: Map<number, Material>,\n        nameFilter: ((name: string) => boolean) | null,\n        meshes: Mesh[],\n        transformNodes: TransformNode[],\n        skeletonByGeometryId: Map<number, Skeleton>,\n        skinByGeometryId: Map<number, FBXSkinData>,\n        skinBindingByGeometryId: Map<number, FBXSkinBindingData>,\n        modelIdToNode: Map<number, TransformNode>,\n        cullingConflictMaterialIds: Set<number>,\n        cullingMaterialCloneCache: Map<Material, Material>\n    ): void {\n        let parent = parentNode;\n        const localMatrix = FBXFileLoader._computeFBXModelLocalMatrix(model);\n        const fbxWorldMatrix = localMatrix.multiply(parentFBXWorldMatrix);\n\n        // Nodes with RrSs / Rrs inheritance do not inherit their parent's scale the normal way. Insert a helper that\n        // cancels the parent scale and re-express the local transform in that unscaled frame (see ufbx's\n        // inherit-mode evaluation). Skeleton bones with Rrs are handled by the rig code instead.\n        const parentModel = this._parentModelById.get(model.id);\n        const parentModelNode = parentModel ? modelIdToNode.get(parentModel.id) : undefined;\n        if (\n            parent &&\n            parentModel &&\n            parentModelNode &&\n            parent === parentModelNode &&\n            model.inheritType !== 1 &&\n            !this._isRigBone(model.id) &&\n            !this._isRigBone(parentModel.id) &&\n            !(parentModel.geometry && skinByGeometryId.has(parentModel.geometry.id))\n        ) {\n            // The helper sits beside the parent and carries the parent's rotation and translation with unit scale,\n            // i.e. the parent's \"unscaled\" frame. This avoids inverting the parent scale (which may be zero).\n            const helper = new TransformNode(`${model.name}__fbx_inheritScale`, scene);\n            helper.parent = parentModelNode.parent;\n            helper.position.copyFrom(parentModelNode.position);\n            helper.rotationQuaternion = parentModelNode.rotationQuaternion ? parentModelNode.rotationQuaternion.clone() : Quaternion.FromEulerVector(parentModelNode.rotation);\n            helper.scaling.set(1, 1, 1);\n            transformNodes.push(helper);\n            this._inheritScaleHelpers.set(model.id, helper);\n            parent = helper;\n        }\n\n        if (model.geometry && model.geometry.indices.length > 0 && (!nameFilter || nameFilter(model.name))) {\n            // Create mesh. Tessellated NURBS carry no control point mapping, so their deformers are not applied\n            // (the interpreter reports them).\n            const deformable = model.geometry.controlPointIndices !== null;\n            const skeleton = deformable ? skeletonByGeometryId.get(model.geometry.id) : undefined;\n            const skin = deformable ? skinByGeometryId.get(model.geometry.id) : undefined;\n            const skinBinding = deformable ? skinBindingByGeometryId.get(model.geometry.id) : undefined;\n\n            if (skeleton && skin) {\n                skeleton.needInitialSkinMatrix = true;\n            }\n\n            // Models referencing the same geometry (with the same geometric transform) share one Babylon geometry.\n            const geometryKey = `${model.geometry.id}|${model.geometricTranslation.join(\",\")}|${model.geometricRotation.join(\",\")}|${model.geometricScaling.join(\",\")}`;\n            const source = !skeleton && this._options.shareGeometry ? this._meshByGeometryKey.get(geometryKey) : undefined;\n            let mesh: Mesh;\n            if (source) {\n                mesh = source.clone(model.name, null, true);\n                mesh.sideOrientation = source.sideOrientation;\n                mesh.metadata = { ...((source.metadata as object) ?? {}), fbxInstanceOf: source.name };\n                this._instanceSource.set(mesh, source);\n            } else {\n                mesh = this._createMesh(model, model.geometry, scene, skeleton, skin, skinBinding);\n                if (!skeleton) {\n                    this._meshByGeometryKey.set(geometryKey, mesh);\n                }\n            }\n\n            // For skinned meshes: keep bind/pose math in FBX space, but parent\n            // the rendered mesh under the same conversion root as non-skinned\n            // meshes. The pose matrix cancels the real FBX mesh transform only;\n            // the root handedness conversion remains applied once at render time.\n            if (skeleton && skin) {\n                const meshBindMatrix = skin.meshBindPoseMatrix ? Matrix.FromArray(skin.meshBindPoseMatrix) : fbxWorldMatrix;\n                mesh.parent = assetRoot;\n                FBXFileLoader._applyMatrixToTransform(mesh, meshBindMatrix);\n                mesh.computeWorldMatrix(true);\n                mesh.updatePoseMatrix(Matrix.Invert(meshBindMatrix));\n                mesh.alwaysSelectAsActiveMesh = true;\n            } else {\n                if (parent) {\n                    mesh.parent = parent;\n                }\n                this._applyRestTRS(mesh, model);\n            }\n\n            // Apply material(s)\n            if (model.materials.length > 1 && model.geometry?.materialIndices) {\n                // Multi-material: create sub-meshes for each material\n                this._applyMultiMaterial(mesh, model, materialCache, scene, cullingConflictMaterialIds, cullingMaterialCloneCache);\n            } else if (model.materials.length > 0) {\n                const mat = materialCache.get(model.materials[0].id);\n                if (mat) {\n                    mesh.material = FBXFileLoader._getModelMaterial(mat, model, cullingMaterialCloneCache, cullingConflictMaterialIds.has(model.materials[0].id));\n                }\n            }\n\n            if (model.geometry?.colors) {\n                this._useUnmodulatedVertexColorMaterials(mesh, scene);\n            }\n            this._applyMaterialUVSetCoordinates(mesh.material, model.geometry);\n\n            meshes.push(mesh);\n            modelIdToNode.set(model.id, mesh);\n\n            FBXFileLoader._applyModelMetadata(mesh, model);\n\n            // Recurse children\n            for (const child of model.children) {\n                this._buildModel(\n                    child,\n                    scene,\n                    mesh,\n                    assetRoot,\n                    fbxWorldMatrix,\n                    materialCache,\n                    nameFilter,\n                    meshes,\n                    transformNodes,\n                    skeletonByGeometryId,\n                    skinByGeometryId,\n                    skinBindingByGeometryId,\n                    modelIdToNode,\n                    cullingConflictMaterialIds,\n                    cullingMaterialCloneCache\n                );\n            }\n        } else if (model.curve && this._options.curves !== \"skip\" && model.curve.polylines.length > 0 && (!nameFilter || nameFilter(model.name))) {\n            const lines = this._createLinesMesh(model, model.curve, scene);\n            if (parent) {\n                lines.parent = parent;\n            }\n            this._applyRestTRS(lines, model);\n            meshes.push(lines);\n            modelIdToNode.set(model.id, lines);\n            FBXFileLoader._applyModelMetadata(lines, model);\n\n            for (const child of model.children) {\n                this._buildModel(\n                    child,\n                    scene,\n                    lines,\n                    assetRoot,\n                    fbxWorldMatrix,\n                    materialCache,\n                    nameFilter,\n                    meshes,\n                    transformNodes,\n                    skeletonByGeometryId,\n                    skinByGeometryId,\n                    skinBindingByGeometryId,\n                    modelIdToNode,\n                    cullingConflictMaterialIds,\n                    cullingMaterialCloneCache\n                );\n            }\n        } else {\n            if ((model.geometry || model.curve) && nameFilter && !FBXFileLoader._modelSubtreeMatchesNameFilter(model, nameFilter)) {\n                return;\n            }\n\n            // Transform node (Null type or no geometry)\n            const transformNode = new TransformNode(model.name, scene);\n            if (parent) {\n                transformNode.parent = parent;\n            }\n\n            // Apply full FBX transform chain\n            this._applyRestTRS(transformNode, model);\n\n            transformNodes.push(transformNode);\n            modelIdToNode.set(model.id, transformNode);\n\n            FBXFileLoader._applyModelMetadata(transformNode, model);\n\n            // Recurse children\n            for (const child of model.children) {\n                this._buildModel(\n                    child,\n                    scene,\n                    transformNode,\n                    assetRoot,\n                    fbxWorldMatrix,\n                    materialCache,\n                    nameFilter,\n                    meshes,\n                    transformNodes,\n                    skeletonByGeometryId,\n                    skinByGeometryId,\n                    skinBindingByGeometryId,\n                    modelIdToNode,\n                    cullingConflictMaterialIds,\n                    cullingMaterialCloneCache\n                );\n            }\n            FBXFileLoader._applyLodGroup(model, modelIdToNode);\n        }\n    }\n\n    private _linkSkeletonsToTransformNodes(\n        rigs: FBXRigData[],\n        skeletonByRigId: Map<string, Skeleton>,\n        modelIdToNode: Map<number, TransformNode>,\n        transformNodes: TransformNode[],\n        scene: Scene\n    ): void {\n        for (const rig of rigs) {\n            const skeleton = skeletonByRigId.get(rig.id);\n            if (!skeleton) {\n                continue;\n            }\n\n            for (const boneData of rig.bones) {\n                const bone = this._getSourceBone(skeleton, boneData.index);\n                const boneNode = modelIdToNode.get(boneData.modelId);\n                if (!bone || !boneNode) {\n                    continue;\n                }\n\n                const scaleCompensationHelper = this._getScaleCompensationHelper(skeleton, boneData.index);\n                if (scaleCompensationHelper) {\n                    const helperNode = new TransformNode(scaleCompensationHelper.name, scene);\n                    helperNode.parent = boneNode.parent;\n                    boneNode.parent = helperNode;\n                    FBXFileLoader._applyMatrixToTransform(helperNode, scaleCompensationHelper.getLocalMatrix());\n                    FBXFileLoader._applyMatrixToTransform(boneNode, bone.getLocalMatrix());\n                    scaleCompensationHelper.linkTransformNode(helperNode);\n                    transformNodes.push(helperNode);\n                } else {\n                    FBXFileLoader._applyMatrixToTransform(boneNode, bone.getLocalMatrix());\n                }\n\n                bone.linkTransformNode(boneNode);\n            }\n        }\n    }\n\n    private static _modelSubtreeMatchesNameFilter(model: FBXModelData, nameFilter: (name: string) => boolean): boolean {\n        for (const child of model.children) {\n            if (child.geometry && child.subType === \"Mesh\" && nameFilter(child.name)) {\n                return true;\n            }\n            if (FBXFileLoader._modelSubtreeMatchesNameFilter(child, nameFilter)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private static _applyModelMetadata(node: TransformNode | Mesh, model: FBXModelData): void {\n        if (!model.customProperties && model.diagnostics.length === 0 && !model.displayLayer && !model.lodGroup) {\n            return;\n        }\n\n        node.metadata = {\n            ...((node.metadata as object) ?? {}),\n            ...(model.customProperties ? { fbxCustomProperties: model.customProperties, fbxUserProperties: model.customProperties } : {}),\n            ...(model.diagnostics.length > 0 ? { fbxDiagnostics: model.diagnostics } : {}),\n            ...(model.displayLayer\n                ? { fbxDisplayLayer: { name: model.displayLayer.name, show: model.displayLayer.show, freeze: model.displayLayer.freeze, color: model.displayLayer.color } }\n                : {}),\n            ...(model.lodGroup ? { fbxLodGroup: model.lodGroup } : {}),\n        };\n        // Hidden display layers hide their members, as in the authoring application.\n        if (model.displayLayer && !model.displayLayer.show) {\n            node.setEnabled(false);\n        }\n    }\n\n    /**\n     * Wires a LodGroup's children as Babylon LOD levels: the first child holds the highest detail; every further\n     * child replaces it beyond the group's threshold distance (or screen coverage when thresholds are percentages).\n     * Each child's display mode is honoured first: level 1 (show) stays visible outside the LOD chain, level 2\n     * (hide) is disabled, and only level 0 (use LOD) children take part in the distance switching.\n     */\n    private static _applyLodGroup(model: FBXModelData, modelIdToNode: Map<number, TransformNode>): void {\n        const lod = model.lodGroup;\n        if (!lod) {\n            return;\n        }\n        const lodChildren: { child: FBXModelData; level: number }[] = [];\n        for (let level = 0; level < model.children.length; level++) {\n            const child = model.children[level];\n            const display = lod.displayLevels[level] ?? 0;\n            if (display === 2) {\n                modelIdToNode.get(child.id)?.setEnabled(false);\n            } else if (display === 0) {\n                lodChildren.push({ child, level });\n            }\n        }\n        if (lodChildren.length < 2) {\n            return;\n        }\n        const meshesOf = (child: FBXModelData): Mesh[] => {\n            const node = modelIdToNode.get(child.id);\n            if (!node) {\n                return [];\n            }\n            const meshes: Mesh[] = node instanceof Mesh ? [node] : [];\n            for (const m of node.getChildMeshes(false)) {\n                if (m instanceof Mesh) {\n                    meshes.push(m);\n                }\n            }\n            return meshes;\n        };\n        const base = meshesOf(lodChildren[0].child);\n        for (let i = 1; i < lodChildren.length; i++) {\n            const level = lodChildren[i].level;\n            const levelMeshes = meshesOf(lodChildren[i].child);\n            const threshold = lod.thresholds[level - 1] ?? lod.thresholds[lod.thresholds.length - 1] ?? 0;\n            for (let i = 0; i < base.length; i++) {\n                const target = levelMeshes[i] ?? null;\n                if (lod.relative) {\n                    base[i].useLODScreenCoverage = true;\n                    base[i].addLODLevel(threshold / 100, target);\n                } else {\n                    base[i].addLODLevel(threshold, target);\n                }\n                if (target) {\n                    target.metadata = { ...((target.metadata as object) ?? {}), fbxLodLevel: level };\n                }\n            }\n        }\n    }\n\n    /** Builds a lines mesh from Line or tessellated NurbsCurve geometry, applying the model's geometric transform. */\n    private _createLinesMesh(model: FBXModelData, curve: FBXCurveGeometryData, scene: Scene): LinesMesh {\n        const lines = new LinesMesh(model.name, scene);\n        const positions: number[] = [];\n        const indices: number[] = [];\n        for (const polyline of curve.polylines) {\n            const count = polyline.length / 3;\n            if (count < 2) {\n                continue;\n            }\n            const base = positions.length / 3;\n            for (let i = 0; i < polyline.length; i++) {\n                positions.push(polyline[i]);\n            }\n            for (let i = 0; i < count - 1; i++) {\n                indices.push(base + i, base + i + 1);\n            }\n        }\n        const geometricMatrix = FBXFileLoader._computeFBXGeometricMatrix(model.geometricTranslation, model.geometricRotation, model.geometricScaling);\n        if (!geometricMatrix.equals(Matrix.Identity())) {\n            for (let i = 0; i < positions.length; i += 3) {\n                const v = Vector3.TransformCoordinates(new Vector3(positions[i], positions[i + 1], positions[i + 2]), geometricMatrix);\n                positions[i] = v.x;\n                positions[i + 1] = v.y;\n                positions[i + 2] = v.z;\n            }\n        }\n        const vertexData = new VertexData();\n        vertexData.positions = positions;\n        vertexData.indices = indices;\n        vertexData.applyToMesh(lines);\n        if (curve.color) {\n            lines.color = new Color3(curve.color[0], curve.color[1], curve.color[2]);\n        }\n        lines.metadata = { ...((lines.metadata as object) ?? {}), fbxCurveType: curve.kind, fbxCurveSegments: curve.polylines.length };\n        return lines;\n    }\n\n    private _createMesh(model: FBXModelData, geomData: FBXGeometryData, scene: Scene, skeleton?: Skeleton, skin?: FBXSkinData, skinBinding?: FBXSkinBindingData): Mesh {\n        const mesh = new Mesh(model.name, scene);\n        mesh.sideOrientation = scene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;\n        const vertexData = new VertexData();\n\n        // Convert Float64Array to Float32Array for Babylon\n        const positions = float64To32(geomData.positions);\n\n        const gt = model.geometricTranslation;\n        const gr = model.geometricRotation;\n        const gs = model.geometricScaling;\n\n        // Geometric transforms affect only this mesh's geometry, not children.\n        // Blender composes them as T * R * S; Babylon's row-vector equivalent is S * R * T.\n        const geometricPositionMatrix = FBXFileLoader._computeFBXGeometricMatrix(gt, gr, gs);\n        const geometricDeltaMatrix = FBXFileLoader._computeFBXGeometricDeltaMatrix(gr, gs);\n        const geometricNormalMatrix = FBXFileLoader._computeFBXGeometricNormalMatrix(gr, gs);\n        const hasGeometricPositionTransform = !geometricPositionMatrix.equals(Matrix.Identity());\n        const hasGeometricDeltaTransform = !geometricDeltaMatrix.equals(Matrix.Identity());\n        const hasGeometricNormalTransform = !geometricNormalMatrix.equals(Matrix.Identity());\n\n        if (hasGeometricPositionTransform) {\n            for (let i = 0; i < positions.length; i += 3) {\n                const v = Vector3.TransformCoordinates(new Vector3(positions[i], positions[i + 1], positions[i + 2]), geometricPositionMatrix);\n                positions[i] = v.x;\n                positions[i + 1] = v.y;\n                positions[i + 2] = v.z;\n            }\n        }\n\n        // For skinned meshes: do NOT bake mesh local transform into vertices.\n        // Vertices remain in their original mesh-local space, keeping the mesh data\n        // clean for retargeting. The mesh node carries its FBX transform as an\n        // initial pose, while TransformLink bind matrices handle skinning.\n\n        vertexData.positions = positions;\n        vertexData.indices = Array.from(geomData.indices);\n\n        let normals: Float32Array | undefined;\n        if (geomData.normals) {\n            normals = float64To32(geomData.normals);\n            if (hasGeometricNormalTransform) {\n                for (let i = 0; i < normals.length; i += 3) {\n                    const n = Vector3.TransformNormal(new Vector3(normals[i], normals[i + 1], normals[i + 2]), geometricNormalMatrix);\n                    if (n.lengthSquared() > 0) {\n                        n.normalize();\n                    }\n                    normals[i] = n.x;\n                    normals[i + 1] = n.y;\n                    normals[i + 2] = n.z;\n                }\n            }\n            vertexData.normals = normals;\n        }\n\n        if (geomData.uvs) {\n            vertexData.uvs = float64To32(geomData.uvs);\n        }\n        if (geomData.uvSets.length > 1) {\n            vertexData.uvs2 = float64To32(geomData.uvSets[1].data);\n        }\n        if (geomData.uvSets.length > 2) {\n            vertexData.uvs3 = float64To32(geomData.uvSets[2].data);\n        }\n        if (geomData.uvSets.length > 3) {\n            vertexData.uvs4 = float64To32(geomData.uvSets[3].data);\n        }\n        if (geomData.uvSets.length > 4) {\n            vertexData.uvs5 = float64To32(geomData.uvSets[4].data);\n        }\n        if (geomData.uvSets.length > 5) {\n            vertexData.uvs6 = float64To32(geomData.uvSets[5].data);\n        }\n\n        if (geomData.tangents) {\n            const tangents = float64To32(geomData.tangents);\n            if (hasGeometricNormalTransform) {\n                for (let i = 0; i < tangents.length; i += 4) {\n                    const t = Vector3.TransformNormal(new Vector3(tangents[i], tangents[i + 1], tangents[i + 2]), geometricNormalMatrix);\n                    if (t.lengthSquared() > 0) {\n                        t.normalize();\n                    }\n                    tangents[i] = t.x;\n                    tangents[i + 1] = t.y;\n                    tangents[i + 2] = t.z;\n                }\n            }\n            applyTangentHandednessScale(tangents, this._getNormalMapTangentHandednessScale());\n            vertexData.tangents = tangents;\n        } else if (normals && vertexData.uvs) {\n            vertexData.tangents = generateTangents(\n                positions,\n                normals,\n                vertexData.uvs,\n                geomData.indices,\n                this._getNormalMapTangentHandednessScale(),\n                geomData.controlPointIndices,\n                geomData.materialIndices\n            );\n        }\n\n        if (geomData.colors) {\n            // Force alpha to 1.0 — FBX vertex color alpha is often unreliable\n            // (e.g. zeroed out by exporters) and would cause transparency sorting issues.\n            const colors = new Float32Array(geomData.colors.length);\n            for (let i = 0; i < colors.length; i += 4) {\n                colors[i] = geomData.colors[i];\n                colors[i + 1] = geomData.colors[i + 1];\n                colors[i + 2] = geomData.colors[i + 2];\n                colors[i + 3] = 1.0;\n            }\n            vertexData.colors = colors;\n            mesh.hasVertexAlpha = false;\n        }\n\n        // Apply bone weights if we have a skin\n        if (skeleton && skin) {\n            const { matricesIndices, matricesWeights, matricesIndicesExtra, matricesWeightsExtra, numBoneInfluencers } = this._buildSkinningData(geomData, skin, skinBinding);\n            vertexData.matricesIndices = matricesIndices;\n            vertexData.matricesWeights = matricesWeights;\n            if (matricesIndicesExtra && matricesWeightsExtra) {\n                vertexData.matricesIndicesExtra = matricesIndicesExtra;\n                vertexData.matricesWeightsExtra = matricesWeightsExtra;\n            }\n            mesh.numBoneInfluencers = numBoneInfluencers;\n        }\n\n        vertexData.applyToMesh(mesh);\n\n        // Store geometry metadata for blend shape matching\n        mesh.metadata = {\n            ...((mesh.metadata as object) ?? {}),\n            fbxGeometryId: geomData.id,\n            fbxControlPointIndices: geomData.controlPointIndices,\n            fbxGeometryDeltaMatrix: hasGeometricDeltaTransform ? geometricDeltaMatrix : null,\n            fbxGeometryNormalMatrix: hasGeometricNormalTransform ? geometricNormalMatrix : null,\n            // Back-compat for existing morph delta handling metadata.\n            fbxPreRotMatrix: hasGeometricDeltaTransform ? geometricDeltaMatrix : null,\n        };\n\n        if (skeleton) {\n            mesh.skeleton = skeleton;\n        }\n\n        return mesh;\n    }\n\n    /**\n     * Apply multi-material to a mesh by creating sub-meshes grouped by material index.\n     * Reorders the index buffer so that triangles sharing the same material are contiguous.\n     */\n    private _applyMultiMaterial(\n        mesh: Mesh,\n        model: FBXModelData,\n        materialCache: Map<number, Material>,\n        scene: Scene,\n        cullingConflictMaterialIds: Set<number>,\n        cullingMaterialCloneCache: Map<Material, Material>\n    ): void {\n        const matIndices = model.geometry!.materialIndices!;\n        const recorded = (mesh.metadata as { fbxSubMeshMaterialIndices?: number[] } | undefined)?.fbxSubMeshMaterialIndices;\n        if (recorded) {\n            // Instance of an already split mesh: the index buffer and sub-meshes are shared; only the materials differ.\n            const multiMat = new MultiMaterial(model.name + \"_multi\", scene);\n            for (const matIdx of recorded) {\n                const fbxMat = model.materials[matIdx];\n                const mat = fbxMat ? materialCache.get(fbxMat.id) : undefined;\n                multiMat.subMaterials.push(mat ? FBXFileLoader._getModelMaterial(mat, model, cullingMaterialCloneCache, cullingConflictMaterialIds.has(fbxMat!.id)) : null);\n            }\n            mesh.material = multiMat;\n            return;\n        }\n        const indices = mesh.getIndices();\n        if (!indices) {\n            return;\n        }\n\n        const triCount = indices.length / 3;\n\n        // Group triangles by material index\n        const groups = new Map<number, number[]>(); // matIdx -> triangle indices\n        for (let ti = 0; ti < triCount; ti++) {\n            const matIdx = ti < matIndices.length ? matIndices[ti] : 0;\n            let group = groups.get(matIdx);\n            if (!group) {\n                group = [];\n                groups.set(matIdx, group);\n            }\n            group.push(ti);\n        }\n\n        // Sort group keys to ensure consistent ordering\n        const sortedMatIndices = Array.from(groups.keys()).sort((a, b) => a - b);\n\n        // Reorder index buffer so triangles are grouped by material\n        const newIndices: number[] = [];\n        const subMeshRanges: { start: number; count: number; matIdx: number }[] = [];\n\n        for (const matIdx of sortedMatIndices) {\n            const tris = groups.get(matIdx)!;\n            const start = newIndices.length;\n            for (const ti of tris) {\n                newIndices.push(indices[ti * 3], indices[ti * 3 + 1], indices[ti * 3 + 2]);\n            }\n            subMeshRanges.push({ start, count: tris.length * 3, matIdx });\n        }\n\n        // Update the mesh's index buffer\n        mesh.setIndices(newIndices);\n\n        // Create MultiMaterial\n        const multiMat = new MultiMaterial(model.name + \"_multi\", scene);\n        for (const range of subMeshRanges) {\n            const fbxMat = model.materials[range.matIdx];\n            if (fbxMat) {\n                const mat = materialCache.get(fbxMat.id);\n                if (mat) {\n                    multiMat.subMaterials.push(FBXFileLoader._getModelMaterial(mat, model, cullingMaterialCloneCache, cullingConflictMaterialIds.has(fbxMat.id)));\n                } else {\n                    multiMat.subMaterials.push(null);\n                }\n            } else {\n                multiMat.subMaterials.push(null);\n            }\n        }\n\n        mesh.material = multiMat;\n\n        // Clear existing sub-meshes and create new ones\n        mesh.subMeshes = [];\n        const vertexCount = mesh.getTotalVertices();\n        for (let i = 0; i < subMeshRanges.length; i++) {\n            const range = subMeshRanges[i];\n            new SubMesh(i, 0, vertexCount, range.start, range.count, mesh);\n        }\n        mesh.metadata = { ...((mesh.metadata as object) ?? {}), fbxSubMeshMaterialIndices: sortedMatIndices };\n    }\n\n    private static _collectCullingConflictMaterialIds(models: FBXModelData[]): Set<number> {\n        // Deliberately scan the full scene, not just name-filtered models. This\n        // can over-clone for filtered imports, but avoids shared culling state.\n        const usage = new Map<number, { cullingOff: boolean; cullingOn: boolean }>();\n        const collect = (model: FBXModelData): void => {\n            for (const material of model.materials) {\n                const state = usage.get(material.id) ?? { cullingOff: false, cullingOn: false };\n                if (model.cullingOff) {\n                    state.cullingOff = true;\n                } else {\n                    state.cullingOn = true;\n                }\n                usage.set(material.id, state);\n            }\n            for (const child of model.children) {\n                collect(child);\n            }\n        };\n        for (const model of models) {\n            collect(model);\n        }\n\n        const conflicts = new Set<number>();\n        for (const [materialId, state] of Array.from(usage)) {\n            if (state.cullingOff && state.cullingOn) {\n                conflicts.add(materialId);\n            }\n        }\n        return conflicts;\n    }\n\n    private static _getModelMaterial(material: Material, model: FBXModelData, cullingCloneCache?: Map<Material, Material>, cloneCullingOffMaterial = true): Material {\n        if (!model.cullingOff || !material.backFaceCulling) {\n            return material;\n        }\n        if (!cloneCullingOffMaterial) {\n            material.backFaceCulling = false;\n            return material;\n        }\n\n        const cached = cullingCloneCache?.get(material);\n        if (cached) {\n            return cached;\n        }\n\n        const clone = material.clone(`${material.name}_CullingOff`) ?? material;\n        clone.backFaceCulling = false;\n        cullingCloneCache?.set(material, clone);\n        return clone;\n    }\n\n    private _applyMaterialUVSetCoordinates(material: unknown, geometry: FBXGeometryData): void {\n        if (!material) {\n            return;\n        }\n        if (material instanceof MultiMaterial) {\n            for (const subMaterial of material.subMaterials) {\n                if (subMaterial instanceof StandardMaterial || subMaterial instanceof PBRMaterial) {\n                    this._applyStandardMaterialUVSetCoordinates(subMaterial, geometry);\n                }\n            }\n            return;\n        }\n        if (material instanceof StandardMaterial || material instanceof PBRMaterial) {\n            this._applyStandardMaterialUVSetCoordinates(material, geometry);\n        }\n    }\n\n    private _applyStandardMaterialUVSetCoordinates(material: StandardMaterial | PBRMaterial, geometry: FBXGeometryData): void {\n        for (const texture of material instanceof PBRMaterial\n            ? [\n                  material.albedoTexture,\n                  material.bumpTexture,\n                  material.emissiveTexture,\n                  material.ambientTexture,\n                  material.metallicTexture,\n                  material.reflectivityTexture,\n                  material.microSurfaceTexture,\n                  material.opacityTexture,\n                  material.clearCoat.texture,\n                  material.clearCoat.bumpTexture,\n                  material.sheen.texture,\n              ]\n            : [\n                  material.diffuseTexture,\n                  material.bumpTexture,\n                  material.emissiveTexture,\n                  material.ambientTexture,\n                  material.specularTexture,\n                  material.opacityTexture,\n                  material.reflectionTexture,\n              ]) {\n            if (!texture) {\n                continue;\n            }\n\n            const uvSetName = (texture.metadata as { fbxUVSetName?: string } | null | undefined)?.fbxUVSetName;\n            if (!uvSetName) {\n                continue;\n            }\n\n            const uvSetIndex = geometry.uvSets.findIndex((uvSet) => uvSet.name === uvSetName);\n            if (uvSetIndex >= 0) {\n                texture.coordinatesIndex = uvSetIndex;\n            }\n        }\n    }\n\n    /**\n     * Babylon multiplies vertex colors by material diffuse color. Use per-mesh\n     * material clones so vertex-colored geometry can render unmodulated without\n     * changing shared materials used by non-vertex-colored meshes.\n     */\n    private _useUnmodulatedVertexColorMaterials(mesh: Mesh, scene: Scene): void {\n        const assignedMat = mesh.material;\n        if (!assignedMat) {\n            return;\n        }\n\n        const unmodulated = (mat: Material): Material => {\n            if (mat instanceof StandardMaterial && !mat.diffuseTexture) {\n                const clone = mat.clone(`${mat.name}_VertexColor`);\n                clone.diffuseColor = new Color3(1, 1, 1);\n                return clone;\n            }\n            if (mat instanceof PBRMaterial && !mat.albedoTexture) {\n                const clone = mat.clone(`${mat.name}_VertexColor`);\n                clone.albedoColor = new Color3(1, 1, 1);\n                return clone;\n            }\n            return mat;\n        };\n\n        if (assignedMat instanceof MultiMaterial) {\n            const multiMat = new MultiMaterial(`${assignedMat.name}_VertexColor`, scene);\n            multiMat.subMaterials = assignedMat.subMaterials.map((sub) => (sub ? unmodulated(sub) : sub));\n            mesh.material = multiMat;\n            return;\n        }\n        mesh.material = unmodulated(assignedMat);\n    }\n\n    /**\n     * Build per-polygon-vertex bone indices and weights from the control-point-based skin data.\n     * The geometry expands control points to per-polygon-vertex, so we need to look up\n     * each polygon-vertex's control point index.\n     */\n    private _buildSkinningData(\n        geomData: FBXGeometryData,\n        skin: FBXSkinData,\n        skinBinding?: FBXSkinBindingData\n    ): {\n        matricesIndices: Float32Array;\n        matricesWeights: Float32Array;\n        matricesIndicesExtra: Float32Array | null;\n        matricesWeightsExtra: Float32Array | null;\n        numBoneInfluencers: number;\n    } {\n        // The positions array is per-polygon-vertex (already expanded).\n        // We need to figure out the control point index for each polygon vertex.\n        // The geometry stores positions per polygon-vertex, so geomData.positions.length/3\n        // = number of polygon vertices. We stored control point indices during expansion,\n        // but they aren't exported. Instead, we can use the fact that skin data is indexed\n        // by control point, and the geometry's _controlPointIndices stores this mapping.\n        //\n        // Since we don't have direct access to the control point mapping from FBXGeometryData,\n        // we'll use the vertex positions to build the skinning buffer. But actually,\n        // we should extend geometry to export control point indices per polygon-vertex.\n        //\n        // For now, use the approach of matching positions to control points.\n        // Actually, let's look at this differently - the indices/weights in the skin\n        // are per control point. The geometry already expanded to per polygon-vertex\n        // with positions copied from control points. We need to know which control point\n        // each polygon-vertex came from.\n        //\n        // We'll use geomData.controlPointIndices if available.\n        const vertexCount = geomData.positions.length / 3;\n        const matricesIndices = new Float32Array(vertexCount * 4);\n        const matricesWeights = new Float32Array(vertexCount * 4);\n        let matricesIndicesExtra: Float32Array | null = null;\n        let matricesWeightsExtra: Float32Array | null = null;\n        let numBoneInfluencers = 0;\n\n        if (geomData.controlPointIndices) {\n            for (let i = 0; i < vertexCount; i++) {\n                const cpIdx = geomData.controlPointIndices[i];\n                const boneIdx = skin.boneIndices[cpIdx] ?? [];\n                numBoneInfluencers = Math.max(numBoneInfluencers, Math.min(boneIdx.length, 8));\n            }\n\n            if (numBoneInfluencers > 4) {\n                matricesIndicesExtra = new Float32Array(vertexCount * 4);\n                matricesWeightsExtra = new Float32Array(vertexCount * 4);\n            }\n\n            for (let i = 0; i < vertexCount; i++) {\n                const cpIdx = geomData.controlPointIndices[i];\n                const boneIdx = skin.boneIndices[cpIdx] ?? [];\n                const boneWts = skin.boneWeights[cpIdx] ?? [];\n\n                for (let j = 0; j < 8; j++) {\n                    const indicesBuffer = j < 4 ? matricesIndices : matricesIndicesExtra;\n                    const weightsBuffer = j < 4 ? matricesWeights : matricesWeightsExtra;\n                    if (!indicesBuffer || !weightsBuffer) {\n                        continue;\n                    }\n\n                    const bufferIndex = i * 4 + (j % 4);\n                    if (j < boneIdx.length) {\n                        const skinBoneIndex = boneIdx[j];\n                        const rigBoneIndex = skinBinding ? skinBinding.skinBoneIndexToRigBoneIndex[skinBoneIndex] : skinBoneIndex;\n                        if (rigBoneIndex === undefined || rigBoneIndex < 0) {\n                            throw new Error(`FBXFileLoader: missing rig bone mapping for skin bone index ${skinBoneIndex}`);\n                        }\n                        indicesBuffer[bufferIndex] = rigBoneIndex;\n                    } else {\n                        indicesBuffer[bufferIndex] = 0;\n                    }\n                    weightsBuffer[bufferIndex] = j < boneWts.length ? boneWts[j] : 0;\n                }\n            }\n        }\n\n        return {\n            matricesIndices,\n            matricesWeights,\n            matricesIndicesExtra,\n            matricesWeightsExtra,\n            numBoneInfluencers: Math.max(numBoneInfluencers, 1),\n        };\n    }\n\n    private _createMaterial(matData: FBXMaterialData, scene: Scene, rootUrl: string): Material {\n        const mode = this._options.materials;\n        const usePbr = mode === \"pbr\" || (mode === \"auto\" && isPbrShaderType(matData.model.shaderType));\n        const material = usePbr ? this._createPbrMaterial(matData, scene, rootUrl) : this._createStandardMaterial(matData, scene, rootUrl);\n        material.metadata = {\n            ...((material.metadata as object) ?? {}),\n            ...(matData.userProperties ? { fbxUserProperties: matData.userProperties } : {}),\n            fbxShaderType: matData.model.shaderType,\n            fbxFeatures: Object.fromEntries(Object.entries(matData.model.features).map(([k, v]) => [k, v?.enabled ?? false])),\n        };\n        return material;\n    }\n\n    private _createPbrMaterial(matData: FBXMaterialData, scene: Scene, rootUrl: string): PBRMaterial {\n        const material = new PBRMaterial(matData.name, scene);\n        const pbr = matData.model.pbr;\n        const features = matData.model.features;\n        const enabled = (name: keyof typeof features) => features[name]?.enabled ?? false;\n        const specGloss = matData.model.shaderType === \"3dsMaxPbrSpecGloss\";\n\n        const scaleColor = (c: [number, number, number] | undefined, f: number | undefined): Color3 | undefined =>\n            c ? new Color3(c[0] * (f ?? 1), c[1] * (f ?? 1), c[2] * (f ?? 1)) : undefined;\n\n        // Base colour\n        const baseColor = mapColor(pbr.baseColor);\n        material.albedoColor = scaleColor(baseColor, pbr.baseColor?.texture ? 1 : mapScalar(pbr.baseFactor)) ?? Color3.White();\n\n        // Metal / rough or spec / gloss workflow\n        if (specGloss) {\n            material.metallic = null;\n            material.roughness = null;\n            material.reflectivityColor = scaleColor(mapColor(pbr.specularColor), 1) ?? Color3.White();\n            material.microSurface = mapScalar(pbr.glossiness) ?? 1 - (mapScalar(pbr.roughness) ?? 0.5);\n        } else {\n            material.metallic = enabled(\"metalness\") ? (mapScalar(pbr.metalness) ?? 0) : 0;\n            material.roughness = mapScalar(pbr.roughness) ?? (pbr.glossiness?.value ? 1 - pbr.glossiness.value[0] : 0.5);\n            if (enabled(\"specular\") && pbr.specularFactor?.value) {\n                material.metallicF0Factor = mapScalar(pbr.specularFactor) ?? 1;\n            }\n            if (enabled(\"specular\")) {\n                const specularColor = mapColor(pbr.specularColor);\n                if (specularColor) {\n                    material.metallicReflectanceColor = new Color3(specularColor[0], specularColor[1], specularColor[2]);\n                }\n            }\n        }\n\n        // Emission\n        const emission = scaleColor(mapColor(pbr.emissionColor), pbr.emissionColor?.texture ? 1 : mapScalar(pbr.emissionFactor));\n        if (emission && enabled(\"emission\")) {\n            material.emissiveColor = emission;\n        } else if (emission && (emission.r > 0 || emission.g > 0 || emission.b > 0)) {\n            material.emissiveColor = emission;\n        }\n\n        // Opacity / transparency\n        const opacity = mapColor(pbr.opacity);\n        if (opacity && enabled(\"opacity\")) {\n            material.alpha = (opacity[0] + opacity[1] + opacity[2]) / 3;\n        } else if (!isPbrShaderType(matData.model.shaderType)) {\n            material.alpha = FBXFileLoader._alphaFromClassicTransparency(matData);\n        }\n        if (material.alpha < 1) {\n            material.transparencyMode = Material.MATERIAL_ALPHABLEND;\n        }\n\n        // Transmission (refraction)\n        const transmission = mapScalar(pbr.transmissionFactor) ?? 0;\n        if (enabled(\"transmission\") && isPbrShaderType(matData.model.shaderType) && transmission > 0) {\n            material.subSurface.isRefractionEnabled = true;\n            material.subSurface.refractionIntensity = transmission;\n            const tint = mapColor(pbr.transmissionColor);\n            if (tint) {\n                material.subSurface.tintColor = new Color3(tint[0], tint[1], tint[2]);\n            }\n            const ior = mapScalar(pbr.specularIor);\n            if (ior && enabled(\"ior\")) {\n                material.subSurface.indexOfRefraction = ior;\n            }\n        } else {\n            const ior = mapScalar(pbr.specularIor);\n            if (ior && enabled(\"ior\") && ior > 1) {\n                material.indexOfRefraction = ior;\n            }\n        }\n\n        // Clear coat\n        const coat = mapScalar(pbr.coatFactor) ?? 0;\n        if ((enabled(\"coat\") && coat > 0) || pbr.coatFactor?.texture) {\n            material.clearCoat.isEnabled = true;\n            material.clearCoat.intensity = coat;\n            const coatRough = mapScalar(pbr.coatRoughness);\n            if (coatRough !== undefined) {\n                material.clearCoat.roughness = coatRough;\n            }\n            const coatIor = mapScalar(pbr.coatIor);\n            if (coatIor !== undefined && coatIor > 1) {\n                material.clearCoat.indexOfRefraction = coatIor;\n            }\n            const coatColor = mapColor(pbr.coatColor);\n            if (coatColor && (coatColor[0] !== 1 || coatColor[1] !== 1 || coatColor[2] !== 1)) {\n                material.clearCoat.isTintEnabled = true;\n                material.clearCoat.tintColor = new Color3(coatColor[0], coatColor[1], coatColor[2]);\n            }\n        }\n\n        // Sheen\n        const sheen = mapScalar(pbr.sheenFactor) ?? 0;\n        if ((enabled(\"sheen\") && sheen > 0) || pbr.sheenColor?.texture) {\n            material.sheen.isEnabled = true;\n            material.sheen.intensity = sheen;\n            const sheenColor = mapColor(pbr.sheenColor);\n            if (sheenColor) {\n                material.sheen.color = new Color3(sheenColor[0], sheenColor[1], sheenColor[2]);\n            }\n            const sheenRough = mapScalar(pbr.sheenRoughness);\n            if (sheenRough !== undefined) {\n                material.sheen.roughness = sheenRough;\n            }\n        }\n\n        if (enabled(\"unlit\")) {\n            material.unlit = true;\n        }\n        if (enabled(\"doubleSided\")) {\n            material.backFaceCulling = false;\n        }\n\n        // Textures\n        const textureFor = (map: { texture?: FBXTextureRef; textureEnabled: boolean } | undefined, isNormal = false): Nullable<Texture> => {\n            if (!map?.texture || !map.textureEnabled) {\n                return null;\n            }\n            const texture = FBXFileLoader._createTexture(map.texture, scene, rootUrl, isNormal);\n            if (texture) {\n                FBXFileLoader._applyTextureSettings(texture, map.texture);\n            }\n            return texture;\n        };\n\n        const albedo = textureFor(pbr.baseColor);\n        if (albedo) {\n            material.albedoTexture = albedo;\n        }\n        const normal = textureFor(pbr.normalMap, true);\n        if (normal) {\n            material.bumpTexture = normal;\n            this._configureNormalTexture(normal, material);\n        }\n        const emissiveTex = textureFor(pbr.emissionColor);\n        if (emissiveTex) {\n            material.emissiveTexture = emissiveTex;\n            if (!emission || (emission.r === 0 && emission.g === 0 && emission.b === 0)) {\n                material.emissiveColor = Color3.White();\n            }\n        }\n        const ao = textureFor(pbr.ambientOcclusion);\n        if (ao) {\n            material.ambientTexture = ao;\n            material.useAmbientInGrayScale = true;\n        }\n        if (specGloss) {\n            const spec = textureFor(pbr.specularColor);\n            if (spec) {\n                material.reflectivityTexture = spec;\n            }\n            const gloss = textureFor(pbr.glossiness) ?? textureFor(pbr.roughness);\n            if (gloss) {\n                material.microSurfaceTexture = gloss;\n            }\n        } else {\n            // Babylon reads metalness and roughness from one texture (B = metal, G = rough). Grayscale maps have\n            // identical channels, so either map works alone; two different maps cannot both be honoured. The choice\n            // is made on the references so that only the texture actually used is created.\n            const metalRef = pbr.metalness?.textureEnabled ? pbr.metalness.texture : undefined;\n            const roughSource =\n                pbr.roughness?.textureEnabled && pbr.roughness.texture ? pbr.roughness : pbr.glossiness?.textureEnabled && pbr.glossiness.texture ? pbr.glossiness : undefined;\n            const roughRef = roughSource?.texture;\n            const sameTexture = !!metalRef && !!roughRef && metalRef.id === roughRef.id;\n            let usesMetalTexture = false;\n            if (metalRef && (sameTexture || !roughRef)) {\n                const metalTex = textureFor(pbr.metalness);\n                if (metalTex) {\n                    usesMetalTexture = true;\n                    material.metallicTexture = metalTex;\n                    material.useMetallnessFromMetallicTextureBlue = true;\n                    material.useRoughnessFromMetallicTextureGreen = sameTexture;\n                    material.useRoughnessFromMetallicTextureAlpha = false;\n                }\n            } else if (roughRef) {\n                const roughTex = textureFor(roughSource);\n                if (roughTex) {\n                    material.metallicTexture = roughTex;\n                    material.useMetallnessFromMetallicTextureBlue = false;\n                    material.useRoughnessFromMetallicTextureGreen = true;\n                    material.useRoughnessFromMetallicTextureAlpha = false;\n                    if (metalRef) {\n                        material.metadata = { ...((material.metadata as object) ?? {}), fbxDroppedMetalnessTexture: metalRef.relativeFileName };\n                    }\n                }\n            }\n            // A roughness-only texture keeps the scalar metalness; a metalness texture needs metallic = 1 to show.\n            if (usesMetalTexture && material.metallic === 0) {\n                material.metallic = 1;\n            }\n        }\n        if (pbr.opacity?.texture && pbr.opacity.textureEnabled) {\n            if (albedo && pbr.opacity.texture.id === pbr.baseColor?.texture?.id) {\n                material.useAlphaFromAlbedoTexture = true;\n                material.transparencyMode = Material.MATERIAL_ALPHATESTANDBLEND;\n            } else {\n                const opacityTex = textureFor(pbr.opacity);\n                if (opacityTex) {\n                    material.opacityTexture = opacityTex;\n                    material.transparencyMode = Material.MATERIAL_ALPHATESTANDBLEND;\n                }\n            }\n        }\n        if (material.clearCoat.isEnabled) {\n            const coatTex = textureFor(pbr.coatFactor);\n            if (coatTex) {\n                material.clearCoat.texture = coatTex;\n            }\n            const coatNormal = textureFor(pbr.coatNormal, true);\n            if (coatNormal) {\n                material.clearCoat.bumpTexture = coatNormal;\n            }\n        }\n        if (material.sheen.isEnabled) {\n            const sheenTex = textureFor(pbr.sheenColor);\n            if (sheenTex) {\n                material.sheen.texture = sheenTex;\n            }\n        }\n\n        return material;\n    }\n\n    /** Alpha of a classic Lambert/Phong material: Opacity when present, otherwise 1 - TransparentColor * TransparencyFactor. */\n    private static _alphaFromClassicTransparency(matData: FBXMaterialData): number {\n        const props = matData.properties;\n        if (props.opacity !== undefined) {\n            return props.opacity;\n        }\n        const factor = mapScalar(matData.model.fbx.transparencyFactor);\n        if (factor === undefined) {\n            return 1;\n        }\n        const color = mapColor(matData.model.fbx.transparencyColor);\n        const amount = color ? (color[0] + color[1] + color[2]) / 3 : 1;\n        return Math.min(1, Math.max(0, 1 - amount * factor));\n    }\n\n    private static _applyTextureSettings(texture: Texture, tex: FBXTextureRef): void {\n        if (tex.uvTranslation) {\n            texture.uOffset = tex.uvTranslation[0];\n            texture.vOffset = tex.uvTranslation[1];\n        }\n        if (tex.uvScaling) {\n            texture.uScale = tex.uvScaling[0];\n            texture.vScale = tex.uvScaling[1];\n        }\n        if (tex.uvRotation !== undefined) {\n            texture.wAng = tex.uvRotation * (Math.PI / 180);\n        }\n        if (tex.uvSetIndex !== undefined) {\n            texture.coordinatesIndex = tex.uvSetIndex;\n        }\n        if (tex.wrapU !== undefined) {\n            texture.wrapU = tex.wrapU === 1 ? Texture.CLAMP_ADDRESSMODE : Texture.WRAP_ADDRESSMODE;\n        }\n        if (tex.wrapV !== undefined) {\n            texture.wrapV = tex.wrapV === 1 ? Texture.CLAMP_ADDRESSMODE : Texture.WRAP_ADDRESSMODE;\n        }\n        if (tex.uvSetName || tex.layeredTextureId !== undefined) {\n            texture.metadata = {\n                ...((texture.metadata as object) ?? {}),\n                ...(tex.uvSetName ? { fbxUVSetName: tex.uvSetName } : {}),\n                ...(tex.layeredTextureId !== undefined ? { fbxLayeredTextureId: tex.layeredTextureId } : {}),\n            };\n        }\n    }\n\n    private _createStandardMaterial(matData: FBXMaterialData, scene: Scene, rootUrl: string): StandardMaterial {\n        const material = new StandardMaterial(matData.name, scene);\n\n        const props = matData.properties;\n        const hasTexture = (...slots: string[]): boolean => matData.textures.some((texture) => slots.includes(texture.propertyName));\n\n        if (matData.type === \"Lambert\") {\n            material.specularColor = Color3.Black();\n        }\n\n        if (props.diffuseColor) {\n            const diffuseFactor = hasTexture(\"DiffuseColor\", \"Diffuse\") ? 1 : (props.diffuseFactor ?? 1);\n            material.diffuseColor = new Color3(props.diffuseColor[0] * diffuseFactor, props.diffuseColor[1] * diffuseFactor, props.diffuseColor[2] * diffuseFactor);\n        }\n\n        if (props.ambientColor) {\n            const ambientFactor = hasTexture(\"AmbientColor\", \"Ambient\") ? 1 : (props.ambientFactor ?? 1);\n            material.ambientColor = new Color3(props.ambientColor[0] * ambientFactor, props.ambientColor[1] * ambientFactor, props.ambientColor[2] * ambientFactor);\n        }\n\n        if (matData.type === \"Phong\" && props.specularColor) {\n            const specularFactor = hasTexture(\"SpecularColor\", \"Specular\", \"Shininess\", \"ShininessExponent\") ? 1 : (props.specularFactor ?? 1);\n            material.specularColor = new Color3(props.specularColor[0] * specularFactor, props.specularColor[1] * specularFactor, props.specularColor[2] * specularFactor);\n        }\n\n        if (props.emissiveColor) {\n            const emissiveFactor = hasTexture(\"EmissiveColor\", \"Emissive\") ? 1 : (props.emissiveFactor ?? 1);\n            material.emissiveColor = new Color3(props.emissiveColor[0] * emissiveFactor, props.emissiveColor[1] * emissiveFactor, props.emissiveColor[2] * emissiveFactor);\n        }\n\n        material.alpha = FBXFileLoader._alphaFromClassicTransparency(matData);\n\n        if (material.alpha < 1) {\n            material.transparencyMode = Material.MATERIAL_ALPHABLEND;\n        }\n\n        if (props.shininess !== undefined) {\n            material.specularPower = props.shininess;\n        }\n\n        // Apply textures\n        for (const tex of matData.textures) {\n            if (!FBXFileLoader._isSupportedMaterialTextureSlot(tex.propertyName)) {\n                continue;\n            }\n\n            const texture = FBXFileLoader._createTexture(tex, scene, rootUrl, FBXFileLoader._isNormalMapTextureSlot(tex.propertyName));\n            if (!texture) {\n                continue;\n            }\n\n            switch (tex.propertyName) {\n                case \"DiffuseColor\":\n                    material.diffuseTexture = texture;\n                    // In FBX, a connected diffuse texture provides the color.\n                    // Set diffuseColor to white so the texture isn't darkened by\n                    // the material's base color (many FBX exports set it near-black).\n                    material.diffuseColor = new Color3(1, 1, 1);\n                    break;\n                case \"NormalMap\":\n                case \"NormalMapTexture\":\n                case \"normalCamera\":\n                    material.bumpTexture = texture;\n                    this._configureNormalTexture(texture, material);\n                    break;\n                case \"Bump\":\n                case \"BumpFactor\":\n                    material.bumpTexture = texture;\n                    this._configureNormalTexture(texture, material);\n                    break;\n                case \"EmissiveColor\":\n                    material.emissiveTexture = texture;\n                    break;\n                case \"AmbientColor\":\n                    material.ambientTexture = texture;\n                    break;\n                case \"SpecularColor\":\n                    material.specularTexture = texture;\n                    break;\n                case \"TransparencyFactor\":\n                case \"TransparentColor\":\n                    material.opacityTexture = texture;\n                    material.transparencyMode = Material.MATERIAL_ALPHATESTANDBLEND;\n                    break;\n                case \"ReflectionColor\":\n                case \"ReflectionFactor\":\n                    material.reflectionTexture = texture;\n                    break;\n                case \"DisplacementColor\":\n                case \"Displacement\":\n                case \"DisplacementFactor\":\n                    // StandardMaterial doesn't have a displacement slot natively;\n                    // store for potential PBR conversion use\n                    break;\n                case \"ShininessExponent\":\n                case \"Shininess\":\n                    // Shininess map — no direct StandardMaterial slot\n                    break;\n            }\n\n            FBXFileLoader._applyTextureSettings(texture, tex);\n        }\n\n        return material;\n    }\n\n    private _configureNormalTexture(texture: Texture, material: StandardMaterial | PBRMaterial): void {\n        texture.gammaSpace = false;\n        material.invertNormalMapX = false;\n        material.invertNormalMapY = this._options.normalMapCoordinateSystem === \"y-down\";\n    }\n\n    private _getNormalMapTangentHandednessScale(): 1 | -1 {\n        return this._options.normalMapCoordinateSystem === \"y-down\" ? -1 : 1;\n    }\n\n    private static _isSupportedMaterialTextureSlot(propertyName: string): boolean {\n        switch (propertyName) {\n            case \"DiffuseColor\":\n            case \"NormalMap\":\n            case \"NormalMapTexture\":\n            case \"normalCamera\":\n            case \"Bump\":\n            case \"BumpFactor\":\n            case \"EmissiveColor\":\n            case \"AmbientColor\":\n            case \"SpecularColor\":\n            case \"TransparencyFactor\":\n            case \"TransparentColor\":\n            case \"ReflectionColor\":\n            case \"ReflectionFactor\":\n            case \"DisplacementColor\":\n            case \"Displacement\":\n            case \"DisplacementFactor\":\n            case \"ShininessExponent\":\n            case \"Shininess\":\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    private static _isNormalMapTextureSlot(propertyName: string): boolean {\n        switch (propertyName) {\n            case \"NormalMap\":\n            case \"NormalMapTexture\":\n            case \"normalCamera\":\n            case \"Bump\":\n            case \"BumpFactor\":\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    private static _createTexture(tex: FBXTextureRef, scene: Scene, rootUrl: string, isDataTexture: boolean): Nullable<Texture> {\n        const sourceName = FBXFileLoader._getTextureSourceName(tex);\n        const creationOptions = FBXFileLoader._getTextureCreationOptions(sourceName, isDataTexture, tex.embeddedData);\n\n        if (tex.embeddedData) {\n            const texture = new Texture(null, scene, creationOptions);\n            const embeddedTextureName = sourceName ?? `embeddedTexture_${tex.id.toString()}`;\n            texture.updateURL(`data:fbx-embedded-texture/${encodeURIComponent(embeddedTextureName)}`, new Uint8Array(tex.embeddedData), undefined, creationOptions.forcedExtension);\n            texture.name = embeddedTextureName;\n            return texture;\n        }\n\n        const textureUrls = FBXFileLoader._getExternalTextureUrls(tex, rootUrl);\n        const textureUrl = textureUrls.shift();\n        if (!textureUrl) {\n            return null;\n        }\n\n        return FBXFileLoader._createExternalTexture(textureUrl, textureUrls, scene, creationOptions);\n    }\n\n    private static _createExternalTexture(texturePath: string, fallbackUrls: string[], scene: Scene, creationOptions: ITextureCreationOptions): Texture {\n        fallbackUrls.push(...FBXFileLoader._buildTextureFallbackUrls(texturePath));\n        let fallbackIndex = 0;\n        const texture = new Texture(texturePath, scene, {\n            ...creationOptions,\n            onError: () => {\n                const fallbackUrl = fallbackUrls[fallbackIndex++];\n                if (fallbackUrl && texture.getScene()) {\n                    texture.updateURL(fallbackUrl, null, undefined, FBXFileLoader._getForcedExtension(fallbackUrl));\n                }\n            },\n        });\n        return texture;\n    }\n\n    private static _buildTextureFallbackUrls(texturePath: string): string[] {\n        const slashIndex = Math.max(texturePath.lastIndexOf(\"/\"), texturePath.lastIndexOf(\"\\\\\"));\n        const dotIndex = texturePath.lastIndexOf(\".\");\n        if (dotIndex <= slashIndex) {\n            return [];\n        }\n\n        const basePath = texturePath.slice(0, dotIndex);\n        const currentExtension = texturePath.slice(dotIndex + 1).toLowerCase();\n        const extensionFallbacks = [\"png\", \"jpg\", \"jpeg\", \"webp\", \"bmp\", \"tga\"];\n        return extensionFallbacks.filter((extension) => extension !== currentExtension).map((extension) => `${basePath}.${extension}`);\n    }\n\n    private static _getTextureCreationOptions(sourceName: Nullable<string>, isDataTexture: boolean, embeddedData: Nullable<Uint8Array>): ITextureCreationOptions {\n        const mimeType = embeddedData ? (sourceName ? FBXFileLoader._getMimeType(sourceName) : \"image/png\") : undefined;\n        return {\n            buffer: embeddedData ? new Uint8Array(embeddedData) : undefined,\n            forcedExtension: sourceName ? FBXFileLoader._getForcedExtension(sourceName, mimeType) : embeddedData ? \".png\" : undefined,\n            gammaSpace: !isDataTexture,\n            mimeType,\n        };\n    }\n\n    private static _getExternalTextureUrls(tex: FBXTextureRef, rootUrl: string): string[] {\n        const textureNames = [tex.relativeFileName, tex.fileName].filter((name): name is string => !!name);\n        const urls: string[] = [];\n\n        for (const textureName of textureNames) {\n            const normalized = textureName.replace(/\\\\/g, \"/\");\n            if (FBXFileLoader._isSafeRelativeTexturePath(normalized)) {\n                urls.push(rootUrl + normalized);\n            }\n\n            const basename = FBXFileLoader._getTextureSourceNameFromPath(normalized);\n            if (basename) {\n                urls.push(rootUrl + basename);\n            }\n        }\n\n        return Array.from(new Set(urls));\n    }\n\n    private static _getTextureSourceName(tex: FBXTextureRef): Nullable<string> {\n        const textureName = tex.relativeFileName || tex.fileName;\n        if (!textureName) {\n            return null;\n        }\n        const normalized = textureName.replace(/\\\\/g, \"/\");\n        return FBXFileLoader._getTextureSourceNameFromPath(normalized);\n    }\n\n    private static _getTextureSourceNameFromPath(texturePath: string): Nullable<string> {\n        return texturePath.split(\"/\").pop() ?? texturePath;\n    }\n\n    private static _isSafeRelativeTexturePath(texturePath: string): boolean {\n        if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(texturePath) || texturePath.startsWith(\"/\") || texturePath.startsWith(\"//\")) {\n            return false;\n        }\n\n        return !texturePath.split(\"/\").some((part) => part === \"..\");\n    }\n\n    private static _getForcedExtension(fileName: string, mimeType?: string): string | undefined {\n        const slashIndex = Math.max(fileName.lastIndexOf(\"/\"), fileName.lastIndexOf(\"\\\\\"));\n        const dotIndex = fileName.lastIndexOf(\".\");\n        if (dotIndex > slashIndex) {\n            return fileName.slice(dotIndex).toLowerCase();\n        }\n\n        switch (mimeType) {\n            case \"image/png\":\n                return \".png\";\n            case \"image/jpeg\":\n                return \".jpg\";\n            case \"image/webp\":\n                return \".webp\";\n            case \"image/bmp\":\n                return \".bmp\";\n            case \"image/gif\":\n                return \".gif\";\n            case \"image/x-tga\":\n                return \".tga\";\n            default:\n                return undefined;\n        }\n    }\n\n    private static _getMimeType(fileName: string): string {\n        const mimeType = GetMimeType(fileName);\n        if (mimeType) {\n            return mimeType;\n        }\n\n        const extension = FBXFileLoader._getForcedExtension(fileName);\n        switch (extension) {\n            case \".tga\":\n                return \"image/x-tga\";\n            case \".bmp\":\n                return \"image/bmp\";\n            case \".gif\":\n                return \"image/gif\";\n            default:\n                return \"image/png\";\n        }\n    }\n\n    /**\n     * Apply blend shape (morph target) deformers to meshes.\n     * FBX Shape vertices are stored as absolute positions for sparse control points.\n     * We compute deltas relative to the base mesh positions.\n     */\n    private _applyBlendShapes(blendShapes: FBXBlendShapeData[], meshes: Mesh[], scene: Scene): void {\n        // Build a map from geometry ID to mesh (using the mesh metadata we'll need to store)\n        // The mesh's geometry ID is tracked through the model hierarchy during _buildModel.\n        // We need to match blendShape.geometryId to the correct mesh.\n        // Strategy: match by examining which meshes have positions matching the geometry.\n\n        for (const bs of blendShapes) {\n            // Find the mesh that uses this geometry\n            const mesh = meshes.find((m) => {\n                const geomId = (m.metadata as { fbxGeometryId?: number } | undefined)?.fbxGeometryId;\n                return geomId === bs.geometryId;\n            });\n            if (!mesh) {\n                continue;\n            }\n\n            const morphTargetManager = new MorphTargetManager(scene);\n            morphTargetManager.optimizeInfluencers = false;\n            // Get preRotation matrix if the mesh had its positions baked\n            const deltaMatrix =\n                (mesh.metadata as { fbxGeometryDeltaMatrix?: Matrix | null; fbxPreRotMatrix?: Matrix | null } | undefined)?.fbxGeometryDeltaMatrix ??\n                (mesh.metadata as { fbxPreRotMatrix?: Matrix | null } | undefined)?.fbxPreRotMatrix ??\n                null;\n            const normalMatrix = (mesh.metadata as { fbxGeometryNormalMatrix?: Matrix | null } | undefined)?.fbxGeometryNormalMatrix ?? deltaMatrix;\n\n            for (const channel of bs.channels) {\n                // Get the control point indices for this mesh (stored as metadata)\n                const cpIndices = (mesh.metadata as { fbxControlPointIndices?: Uint32Array } | undefined)?.fbxControlPointIndices;\n                if (!cpIndices) {\n                    continue;\n                }\n\n                const basePositions = mesh.getVerticesData(\"position\");\n                const baseNormals = mesh.getVerticesData(\"normal\");\n                if (!basePositions) {\n                    continue;\n                }\n\n                const initialInfluences = calculateBlendShapeInfluences(channel.deformPercent, channel.fullWeights, channel.shapes.length);\n                const targetIndices: number[] = [];\n                for (let shapeIndex = 0; shapeIndex < channel.shapes.length; shapeIndex++) {\n                    const shape = channel.shapes[shapeIndex];\n                    if (!shape) {\n                        continue;\n                    }\n                    const targetData = buildMorphTargetData(shape, cpIndices, basePositions, baseNormals, deltaMatrix, normalMatrix);\n                    if (!targetData) {\n                        continue;\n                    }\n\n                    const targetName = channel.fullWeights && channel.shapes.length > 1 ? `${channel.name}_${channel.fullWeights[shapeIndex]}` : channel.name;\n                    const morphTarget = new MorphTarget(targetName, initialInfluences[shapeIndex] ?? 0, scene);\n                    morphTarget.setPositions(targetData.positions);\n                    if (targetData.normals) {\n                        morphTarget.setNormals(targetData.normals);\n                    }\n\n                    targetIndices.push(morphTargetManager.numTargets);\n                    morphTargetManager.addTarget(morphTarget);\n                }\n\n                if (targetIndices.length === 0) {\n                    continue;\n                }\n\n                // Store channel ID mapping on the mesh for animation targeting.\n                // Keep the legacy single-target map for existing consumers and add\n                // richer in-between metadata for FullWeights-aware animation baking.\n                if (!mesh.metadata) {\n                    mesh.metadata = {};\n                }\n                if (!(mesh.metadata as Record<string, unknown>).fbxBlendShapeChannelIds) {\n                    (mesh.metadata as Record<string, unknown>).fbxBlendShapeChannelIds = new Map<number, number>();\n                }\n                ((mesh.metadata as Record<string, unknown>).fbxBlendShapeChannelIds as Map<number, number>).set(channel.id, targetIndices[0]);\n                if (!(mesh.metadata as Record<string, unknown>).fbxBlendShapeChannelTargets) {\n                    (mesh.metadata as Record<string, unknown>).fbxBlendShapeChannelTargets = new Map<number, { targetIndices: number[]; fullWeights: number[] | null }>();\n                }\n                ((mesh.metadata as Record<string, unknown>).fbxBlendShapeChannelTargets as Map<number, { targetIndices: number[]; fullWeights: number[] | null }>).set(channel.id, {\n                    targetIndices,\n                    fullWeights: channel.fullWeights,\n                });\n            }\n\n            if (morphTargetManager.numTargets > 0) {\n                morphTargetManager.numMaxInfluencers = morphTargetManager.numTargets;\n                mesh.morphTargetManager = morphTargetManager;\n            }\n        }\n    }\n\n    private _createCamera(camData: FBXCameraData, modelIdToNode: Map<number, TransformNode>, scene: Scene): FreeCamera | null {\n        const parentNode = modelIdToNode.get(camData.modelId);\n        const worldMatrix = parentNode ? parentNode.computeWorldMatrix(true) : Matrix.Identity();\n        const position = Vector3.TransformCoordinates(Vector3.Zero(), worldMatrix);\n\n        const camera = new FreeCamera(camData.name, position, scene);\n        camera.fov = camData.fieldOfView * (Math.PI / 180);\n        camera.fovMode = Camera.FOVMODE_VERTICAL_FIXED;\n        void position;\n        camera.minZ = camData.nearPlane;\n        camera.maxZ = camData.farPlane;\n        camera.metadata = {\n            ...((camera.metadata as object) ?? {}),\n            fbxCamera: {\n                projectionType: camData.projectionType,\n                focalLength: camData.focalLength,\n                filmWidth: camData.filmWidth,\n                filmHeight: camData.filmHeight,\n                orthoZoom: camData.orthoZoom,\n                roll: camData.roll,\n                aspectRatio: camData.aspectRatio,\n                fieldOfViewX: camData.fieldOfViewX,\n                apertureMode: camData.apertureMode,\n                apertureSizeInch: camData.apertureSizeInch,\n                userProperties: camData.userProperties,\n                unknownProperties: camData.unknownProperties,\n                diagnostics: camData.diagnostics,\n            },\n        };\n\n        if (camData.projectionType === \"orthographic\") {\n            camera.mode = Camera.ORTHOGRAPHIC_CAMERA;\n            camera.orthoTop = camData.orthographicSize[1] / 2;\n            camera.orthoBottom = -camData.orthographicSize[1] / 2;\n            camera.orthoRight = camData.orthographicSize[0] / 2;\n            camera.orthoLeft = -camData.orthographicSize[0] / 2;\n        }\n\n        // FBX cameras look down their local +X axis. When attached, the camera is parented to its node so it follows\n        // the node's animation, and oriented with a fixed local rotation (camera forward +Z -> node +X), with the FBX\n        // Roll applied around the view axis first. Otherwise it is placed in world space, unparented.\n        if (parentNode && this._options.attachCamerasAndLights) {\n            // The handedness conversion at the root mirrors every node's world matrix. A camera cannot render through\n            // a mirrored parent (its view matrix would flip the image and the winding), so when the node's world\n            // determinant is negative the camera hangs from a pivot whose own mirror cancels it.\n            let cameraParent: TransformNode = parentNode;\n            if (worldMatrix.determinant() < 0) {\n                const pivot = new TransformNode(`${camData.name}__fbx_cameraPivot`, scene);\n                pivot.parent = parentNode;\n                pivot.scaling.set(1, 1, -1);\n                cameraParent = pivot;\n            }\n            camera.parent = cameraParent;\n            camera.position.set(0, 0, 0);\n            const roll = ((camData.roll ?? 0) * Math.PI) / 180;\n            camera.rotationQuaternion = Quaternion.FromRotationMatrix(Matrix.RotationZ(roll).multiply(Matrix.RotationY(Math.PI / 2)));\n        } else {\n            const target = Vector3.TransformCoordinates(new Vector3(1, 0, 0), worldMatrix);\n            camera.setTarget(target);\n        }\n\n        return camera;\n    }\n\n    private _createLight(lightData: FBXLightData, modelIdToNode: Map<number, TransformNode>, scene: Scene): PointLight | DirectionalLight | SpotLight | null {\n        const parentNode = modelIdToNode.get(lightData.modelId);\n        const worldMatrix = parentNode ? parentNode.computeWorldMatrix(true) : Matrix.Identity();\n        const position = Vector3.TransformCoordinates(Vector3.Zero(), worldMatrix);\n        const color = new Color3(lightData.color[0], lightData.color[1], lightData.color[2]);\n\n        // FBX lights point down their local -Z axis. Derive the world-space direction from two points\n        // transformed by the node's world matrix so the handedness conversion (the left-handed root\n        // applies scaling.z = -1) is reproduced correctly; transforming the direction as a normal\n        // would mirror it under that reflection and point the light the wrong way.\n        const forwardPoint = Vector3.TransformCoordinates(new Vector3(0, 0, -1), worldMatrix);\n        const direction = forwardPoint.subtract(position).normalize();\n\n        let light: PointLight | DirectionalLight | SpotLight;\n\n        // When attached, the light is parented to its node (so it follows animation) and its position and direction\n        // are expressed in node-local space: origin and local -Z. Otherwise it is placed in world space, unparented.\n        const attach = !!parentNode && this._options.attachCamerasAndLights;\n        const localPosition = attach ? Vector3.Zero() : position;\n        const localDirection = attach ? new Vector3(0, 0, -1) : direction;\n\n        switch (lightData.lightType) {\n            case 1: // Directional\n                light = new DirectionalLight(lightData.name, localDirection, scene);\n                light.diffuse = color;\n                light.intensity = lightData.intensity;\n                break;\n            case 2: {\n                // Spot\n                const angle = lightData.coneAngle * (Math.PI / 180);\n                light = new SpotLight(lightData.name, localPosition, localDirection, angle, 2, scene);\n                light.diffuse = color;\n                light.intensity = lightData.intensity;\n                if (lightData.innerAngle !== undefined) {\n                    light.innerAngle = Math.min(angle, (lightData.innerAngle * Math.PI) / 180);\n                }\n                break;\n            }\n            default: // Point (0), Area (3) and Volume (4) approximated as point lights\n                light = new PointLight(lightData.name, localPosition, scene);\n                light.diffuse = color;\n                light.intensity = lightData.intensity;\n                break;\n        }\n        if (attach && parentNode) {\n            light.parent = parentNode;\n            // Babylon only resolves a parented light's world position and direction during rendering; do it now\n            // so getAbsolutePosition() and transformedDirection are usable straight after loading.\n            light.computeTransformedInformation();\n        }\n        light.specular = color;\n        if (lightData.enableFarAttenuation && lightData.farAttenuationEnd !== undefined && lightData.farAttenuationEnd > 0) {\n            light.range = lightData.farAttenuationEnd;\n        }\n\n        light.metadata = {\n            ...((light.metadata as object) ?? {}),\n            fbxLight: {\n                lightType: lightData.lightType,\n                decayType: lightData.decayType,\n                decayStart: lightData.decayStart,\n                innerAngle: lightData.innerAngle,\n                outerAngle: lightData.outerAngle,\n                enableNearAttenuation: lightData.enableNearAttenuation,\n                enableFarAttenuation: lightData.enableFarAttenuation,\n                castShadows: lightData.castShadows,\n                farAttenuationStart: lightData.farAttenuationStart,\n                farAttenuationEnd: lightData.farAttenuationEnd,\n                areaLightShape: lightData.areaLightShape,\n                userProperties: lightData.userProperties,\n                unknownProperties: lightData.unknownProperties,\n                diagnostics: lightData.diagnostics,\n            },\n        };\n\n        return light;\n    }\n\n    private _createSkeleton(skeletonId: string, bones: FBXBoneData[], scene: Scene): Skeleton {\n        const skeleton = new Skeleton(\"Skeleton\", `skeleton_${skeletonId}`, scene);\n        const sourceBones: Bone[] = [];\n        const scaleCompensationHelpers = new Map<number, Bone>();\n        const authoredLocalMatrices: Matrix[] = [];\n        const authoredAbsoluteMatrices: Matrix[] = [];\n        const authoredRuntimeLocalMatrices: Matrix[] = [];\n\n        // Compute authored Lcl matrices for bones that do not carry FBX bind data.\n        const authoredInheritScales = FBXFileLoader._computeBoneInheritScales(\n            bones,\n            bones.map((b) => b.scale)\n        );\n        for (let i = 0; i < bones.length; i++) {\n            const boneData = bones[i];\n            const authoredLocal = FBXFileLoader._computeFBXLocalMatrix(\n                boneData.translation,\n                boneData.rotation,\n                boneData.scale,\n                boneData.preRotation,\n                boneData.postRotation,\n                boneData.rotationPivot,\n                boneData.scalingPivot,\n                boneData.rotationOffset,\n                boneData.scalingOffset,\n                boneData.rotationOrder\n            );\n            authoredLocalMatrices[i] = authoredLocal;\n            authoredRuntimeLocalMatrices[i] = FBXFileLoader._computeFBXRuntimeLocalMatrix(bones, authoredLocal, i, authoredInheritScales);\n        }\n        authoredAbsoluteMatrices.push(...FBXFileLoader._computeFBXAbsoluteMatrices(bones, authoredRuntimeLocalMatrices));\n\n        const absoluteBindMatrices = bones.map((boneData, index) =>\n            boneData.transformLinkMatrix\n                ? Matrix.FromArray(boneData.transformLinkMatrix)\n                : boneData.modelBindPoseMatrix\n                  ? Matrix.FromArray(boneData.modelBindPoseMatrix)\n                  : authoredAbsoluteMatrices[index]\n        );\n\n        const localBindMatrices = absoluteBindMatrices.map((absoluteBind, index) => {\n            const parentIndex = bones[index].parentIndex;\n            if (parentIndex < 0) {\n                return absoluteBind;\n            }\n\n            const parentAbsoluteBindInv = new Matrix();\n            absoluteBindMatrices[parentIndex].invertToRef(parentAbsoluteBindInv);\n            return absoluteBind.multiply(parentAbsoluteBindInv);\n        });\n        const useBindAsRest = FBXFileLoader._shouldUseBindMatricesAsRest(bones, authoredLocalMatrices, localBindMatrices);\n\n        // Most animation curves naturally target authored Lcl transforms. Use\n        // bind matrices as live rest pose only for rigs with severe bind/local\n        // scale disagreement, which otherwise produce invalid skin matrices.\n        // Only bones with that scale disagreement need their animation curves\n        // remapped into bind-rest space; ordinary child curves are already in\n        // the expected local animation space.\n        const restInheritScales = FBXFileLoader._computeBoneInheritScales(\n            bones,\n            bones.map((b) => b.scale)\n        );\n        for (let i = 0; i < bones.length; i++) {\n            let localMatrix = useBindAsRest ? localBindMatrices[i] : authoredRuntimeLocalMatrices[i];\n            let parentBone = bones[i].parentIndex >= 0 ? sourceBones[bones[i].parentIndex] : null;\n            if (!useBindAsRest && bones[i].inheritType !== 1 && bones[i].parentIndex >= 0 && parentBone) {\n                const split = FBXFileLoader._splitParentScaleCompensatedLocalMatrix(\n                    authoredLocalMatrices[i],\n                    restInheritScales[bones[i].parentIndex],\n                    FBXFileLoader._getBoneInheritedScale(bones, i, restInheritScales)\n                );\n                const helper = new Bone(\n                    `${bones[i].name}__fbx_scaleCompensation`,\n                    skeleton,\n                    parentBone,\n                    split.helperLocalMatrix,\n                    split.helperLocalMatrix.clone(),\n                    Matrix.Identity(),\n                    -1\n                );\n                helper.metadata = {\n                    ...((helper.metadata as object) ?? {}),\n                    fbxScaleCompensationForBoneIndex: i,\n                    fbxScaleCompensationForBoneName: bones[i].name,\n                };\n                scaleCompensationHelpers.set(i, helper);\n                parentBone = helper;\n                localMatrix = split.boneLocalMatrix;\n            }\n            const bone = new Bone(bones[i].name, skeleton, parentBone, localMatrix, useBindAsRest ? localMatrix.clone() : null, useBindAsRest ? localMatrix.clone() : null, i);\n            if (useBindAsRest && bones[i].isCluster && FBXFileLoader._getMaxScaleRatio(authoredLocalMatrices[i], localBindMatrices[i]) >= BIND_REST_SCALE_RATIO_THRESHOLD) {\n                this._bindRestBones.add(bone);\n            }\n            sourceBones.push(bone);\n        }\n        this._sourceBonesBySkeleton.set(skeleton, sourceBones);\n        this._scaleCompensationHelpersBySkeleton.set(skeleton, scaleCompensationHelpers);\n\n        if (!useBindAsRest) {\n            for (let i = 0; i < bones.length; i++) {\n                const bone = sourceBones[i];\n                bone.updateMatrix(localBindMatrices[i], false, false);\n            }\n            for (const helper of Array.from(scaleCompensationHelpers.values())) {\n                helper.updateMatrix(Matrix.Identity(), false, false);\n            }\n            for (const bone of skeleton.bones) {\n                if (!bone.getParent()) {\n                    bone._updateAbsoluteBindMatrices(undefined, true);\n                }\n            }\n        }\n\n        return skeleton;\n    }\n\n    private _rigBoneModelIds = new Set<number>();\n\n    private _isRigBone(modelId: number): boolean {\n        return this._rigBoneModelIds.has(modelId);\n    }\n\n    private _getSourceBone(skeleton: Skeleton, sourceIndex: number): Bone | undefined {\n        return this._sourceBonesBySkeleton.get(skeleton)?.[sourceIndex] ?? skeleton.bones[sourceIndex];\n    }\n\n    private _getScaleCompensationHelper(skeleton: Skeleton, sourceIndex: number): Bone | undefined {\n        return this._scaleCompensationHelpersBySkeleton.get(skeleton)?.get(sourceIndex);\n    }\n\n    private static _computeFBXAbsoluteMatrices(bones: FBXBoneData[], localMatrices: Matrix[]): Matrix[] {\n        const absoluteMatrices: Matrix[] = [];\n        for (let i = 0; i < bones.length; i++) {\n            const parentIndex = bones[i].parentIndex;\n            if (parentIndex < 0) {\n                absoluteMatrices[i] = localMatrices[i].clone();\n                continue;\n            }\n\n            absoluteMatrices[i] = localMatrices[i].multiply(absoluteMatrices[parentIndex]);\n        }\n        return absoluteMatrices;\n    }\n\n    /**\n     * Effective (\"inherit\") scale of every bone, following the FBX SDK: the local scale for RSrs bones, and for\n     * RrSs / Rrs bones the local scale multiplied by the scale of the bone's inherit-scale node (the parent for RrSs,\n     * the parent's inherit-scale node for Rrs). Bones are ordered parents first.\n     */\n    private static _computeBoneInheritScales(bones: FBXBoneData[], ownScales: [number, number, number][]): [number, number, number][] {\n        const result: [number, number, number][] = [];\n        for (let i = 0; i < bones.length; i++) {\n            const own = ownScales[i];\n            const inheritedFrom = FBXFileLoader._getBoneInheritScaleNode(bones, i);\n            if (inheritedFrom < 0 || inheritedFrom >= i) {\n                result[i] = [own[0], own[1], own[2]];\n            } else {\n                const p = result[inheritedFrom];\n                result[i] = [own[0] * p[0], own[1] * p[1], own[2] * p[2]];\n            }\n        }\n        return result;\n    }\n\n    private static _getBoneInheritScaleNode(bones: FBXBoneData[], index: number): number {\n        const parentIndex = bones[index].parentIndex;\n        if (parentIndex < 0) {\n            return -1;\n        }\n        if (bones[index].inheritType === 0) {\n            return parentIndex;\n        }\n        if (bones[index].inheritType === 2) {\n            return FBXFileLoader._getBoneInheritScaleNode(bones, parentIndex);\n        }\n        return -1;\n    }\n\n    /** Scale a bone inherits into its own scale (RrSs chains), or unit scale. */\n    private static _getBoneInheritedScale(bones: FBXBoneData[], index: number, inheritScales: [number, number, number][]): [number, number, number] {\n        const node = FBXFileLoader._getBoneInheritScaleNode(bones, index);\n        return node >= 0 ? inheritScales[node] : [1, 1, 1];\n    }\n\n    private static _computeFBXRuntimeLocalMatrix(bones: FBXBoneData[], localMatrix: Matrix, index: number, inheritScales?: [number, number, number][]): Matrix {\n        const parentIndex = bones[index].parentIndex;\n        if (bones[index].inheritType === 1 || parentIndex < 0) {\n            return localMatrix;\n        }\n\n        const scales =\n            inheritScales ??\n            FBXFileLoader._computeBoneInheritScales(\n                bones,\n                bones.map((b) => b.scale)\n            );\n        return FBXFileLoader._applyParentScaleCompensation(localMatrix, scales[parentIndex], FBXFileLoader._getBoneInheritedScale(bones, index, scales));\n    }\n\n    private static _applyParentScaleCompensation(localMatrix: Matrix, parentScale: [number, number, number], inheritedScale?: [number, number, number]): Matrix {\n        const split = FBXFileLoader._splitParentScaleCompensatedLocalMatrix(localMatrix, parentScale, inheritedScale);\n        return split.boneLocalMatrix.multiply(split.helperLocalMatrix);\n    }\n\n    /**\n     * Splits a bone's FBX local matrix into a helper (which cancels the parent scale and carries the translation,\n     * so the translation still follows the parent scale as the SDK does) and the bone's own rotation/scale. For RrSs\n     * bones the inherited scale is folded into the bone scale.\n     */\n    private static _splitParentScaleCompensatedLocalMatrix(\n        localMatrix: Matrix,\n        parentScale: [number, number, number],\n        inheritedScale?: [number, number, number]\n    ): { boneLocalMatrix: Matrix; helperLocalMatrix: Matrix } {\n        const translation = localMatrix.getTranslation();\n        let boneLocalMatrix = localMatrix.clone();\n        boneLocalMatrix.setTranslation(Vector3.Zero());\n        if (inheritedScale && (inheritedScale[0] !== 1 || inheritedScale[1] !== 1 || inheritedScale[2] !== 1)) {\n            boneLocalMatrix = Matrix.Scaling(inheritedScale[0], inheritedScale[1], inheritedScale[2]).multiply(boneLocalMatrix);\n        }\n        const helperLocalMatrix = Matrix.Compose(FBXFileLoader._getInverseScaleVector(parentScale), Quaternion.Identity(), translation);\n        return { boneLocalMatrix, helperLocalMatrix };\n    }\n\n    private static _safeInverseScale(value: number): number {\n        return Math.abs(value) > 1e-8 ? 1 / value : 1;\n    }\n\n    private static _getInverseScaleVector(scale: [number, number, number]): Vector3 {\n        return new Vector3(FBXFileLoader._safeInverseScale(scale[0]), FBXFileLoader._safeInverseScale(scale[1]), FBXFileLoader._safeInverseScale(scale[2]));\n    }\n\n    private static _shouldUseBindMatricesAsRest(bones: FBXBoneData[], authoredLocalMatrices: Matrix[], localBindMatrices: Matrix[]): boolean {\n        return bones.some((bone, index) => {\n            if (!bone.isCluster) {\n                return false;\n            }\n            return FBXFileLoader._getMaxScaleRatio(authoredLocalMatrices[index], localBindMatrices[index]) >= BIND_REST_SCALE_RATIO_THRESHOLD;\n        });\n    }\n\n    private static _getMaxScaleRatio(a: Matrix, b: Matrix): number {\n        const scaleA = new Vector3();\n        const rotationA = new Quaternion();\n        const translationA = new Vector3();\n        const scaleB = new Vector3();\n        const rotationB = new Quaternion();\n        const translationB = new Vector3();\n        a.decompose(scaleA, rotationA, translationA);\n        b.decompose(scaleB, rotationB, translationB);\n\n        return Math.max(FBXFileLoader._getScaleRatio(scaleA.x, scaleB.x), FBXFileLoader._getScaleRatio(scaleA.y, scaleB.y), FBXFileLoader._getScaleRatio(scaleA.z, scaleB.z));\n    }\n\n    private static _getScaleRatio(a: number, b: number): number {\n        const absA = Math.abs(a);\n        const absB = Math.abs(b);\n        if (absA < 1e-6 || absB < 1e-6) {\n            return absA < 1e-6 && absB < 1e-6 ? 1 : Number.POSITIVE_INFINITY;\n        }\n        return Math.max(absA / absB, absB / absA);\n    }\n\n    private static _computeFBXGeometricMatrix(translation: [number, number, number], rotation: [number, number, number], scale: [number, number, number]): Matrix {\n        return computeFBXGeometricMatrix(translation, rotation, scale);\n    }\n\n    private static _computeFBXGeometricDeltaMatrix(rotation: [number, number, number], scale: [number, number, number]): Matrix {\n        return computeFBXGeometricDeltaMatrix(rotation, scale);\n    }\n\n    private static _computeFBXGeometricNormalMatrix(rotation: [number, number, number], scale: [number, number, number]): Matrix {\n        return computeFBXGeometricNormalMatrix(rotation, scale);\n    }\n\n    /**\n     * Compute the full FBX local transform matrix:\n     * M = T * Roff * Rp * Rpre * R * Rpost^-1 * Rp^-1 * Soff * Sp * S * Sp^-1\n     *\n     * In row-vector convention: v' = v * M\n     */\n    private static _computeFBXLocalMatrix(\n        translation: [number, number, number],\n        rotation: [number, number, number],\n        scale: [number, number, number],\n        preRotation: [number, number, number],\n        postRotation: [number, number, number],\n        rotationPivot: [number, number, number],\n        scalingPivot: [number, number, number],\n        rotationOffset: [number, number, number],\n        scalingOffset: [number, number, number],\n        rotationOrder: number = 0\n    ): Matrix {\n        return computeFBXLocalMatrix({\n            translation,\n            rotation,\n            scale,\n            preRotation,\n            postRotation,\n            rotationPivot,\n            scalingPivot,\n            rotationOffset,\n            scalingOffset,\n            rotationOrder,\n        });\n    }\n\n    private _applyRestTRS(node: TransformNode, model: FBXModelData): void {\n        const trs = FBXFileLoader._computeLocalTRS(model, model.translation, model.rotation, model.scale);\n        this._adjustTRSForInheritMode(model, trs, undefined);\n        node.position = trs.position;\n        node.rotationQuaternion = trs.rotationQuaternion;\n        node.scaling = trs.scaling;\n    }\n\n    private static _computeFBXModelLocalMatrix(model: FBXModelData): Matrix {\n        return FBXFileLoader._computeFBXLocalMatrix(\n            model.translation,\n            model.rotation,\n            model.scale,\n            model.preRotation,\n            model.postRotation,\n            model.rotationPivot,\n            model.scalingPivot,\n            model.rotationOffset,\n            model.scalingOffset,\n            model.rotationOrder\n        );\n    }\n\n    private static _applyMatrixToTransform(node: TransformNode, matrix: Matrix): void {\n        const s = new Vector3();\n        const r = new Quaternion();\n        const t = new Vector3();\n        matrix.decompose(s, r, t);\n\n        node.position = t;\n        node.rotationQuaternion = r;\n        node.scaling = s;\n    }\n\n    private _createAnimationGroup(\n        animStack: FBXAnimationStackData,\n        rigs: FBXRigData[],\n        skeletonByRigId: Map<string, Skeleton>,\n        scene: Scene,\n        modelIdToNode: Map<number, TransformNode>,\n        modelIdToData: Map<number, FBXModelData>,\n        meshes: Mesh[],\n        propertyTargets: { cameraByAttributeId: Map<number, FreeCamera>; lightByAttributeId: Map<number, Light>; materialCache: Map<number, Material> }\n    ): AnimationGroup | null {\n        // Stacks may animate only properties (visibility, light colour...) without any transform curve.\n        if (animStack.curveNodes.length === 0 && !animStack.unsupportedCurveNodes.some((c) => c.targetId !== null && c.curves.length > 0)) {\n            return null;\n        }\n        this._activeLayers = animStack.layers;\n        this._curveNodesByModelId = new Map();\n        for (const curveNode of animStack.curveNodes) {\n            if (curveNode.type === \"DeformPercent\") {\n                continue;\n            }\n            const list = this._curveNodesByModelId.get(curveNode.targetModelId);\n            if (list) {\n                list.push(curveNode);\n            } else {\n                this._curveNodesByModelId.set(curveNode.targetModelId, [curveNode]);\n            }\n        }\n\n        const animGroup = new AnimationGroup(animStack.name, scene);\n        const animatedBoneTargetProperties = new Map<Bone | TransformNode, Set<string>>();\n        const addBoneAnimation = (animation: Animation, bone: Bone): void => {\n            const target = bone.getTransformNode() ?? bone;\n            let targetProperties = animatedBoneTargetProperties.get(target);\n            if (!targetProperties) {\n                targetProperties = new Set<string>();\n                animatedBoneTargetProperties.set(target, targetProperties);\n            } else if (targetProperties.has(animation.targetProperty)) {\n                return;\n            }\n\n            targetProperties.add(animation.targetProperty);\n            animGroup.addTargetedAnimation(animation, target);\n        };\n\n        // Build a map from model ID to resolved rig bones. A single FBX model ID\n        // should only appear once per resolved rig, but keeping an array preserves\n        // the previous animation fan-out behavior for any future duplicate rigs.\n        const modelIdToBones = new Map<number, Bone[]>();\n        for (const rig of rigs) {\n            const skeleton = skeletonByRigId.get(rig.id);\n            if (!skeleton) {\n                continue;\n            }\n\n            for (const boneData of rig.bones) {\n                const bone = this._getSourceBone(skeleton, boneData.index);\n                if (!bone) {\n                    continue;\n                }\n\n                const bones = modelIdToBones.get(boneData.modelId);\n                if (bones) {\n                    bones.push(bone);\n                } else {\n                    modelIdToBones.set(boneData.modelId, [bone]);\n                }\n            }\n        }\n\n        // Group curve nodes by target\n        const boneCurves = new Map<number, FBXCurveNodeData[]>();\n        const nonBoneCurves = new Map<number, FBXCurveNodeData[]>();\n        const blendShapeCurves: FBXCurveNodeData[] = [];\n\n        for (const curveNode of animStack.curveNodes) {\n            if (curveNode.type === \"DeformPercent\") {\n                blendShapeCurves.push(curveNode);\n                continue;\n            }\n\n            if (modelIdToBones.has(curveNode.targetModelId)) {\n                if (!boneCurves.has(curveNode.targetModelId)) {\n                    boneCurves.set(curveNode.targetModelId, []);\n                }\n                boneCurves.get(curveNode.targetModelId)!.push(curveNode);\n            } else {\n                if (!nonBoneCurves.has(curveNode.targetModelId)) {\n                    nonBoneCurves.set(curveNode.targetModelId, []);\n                }\n                nonBoneCurves.get(curveNode.targetModelId)!.push(curveNode);\n            }\n        }\n\n        // Process bone targets: compute full FBX local matrix per frame, decompose to TRS.\n        // For bind-rest rigs, only the bones recorded in _bindRestBones need their\n        // authored Lcl curves remapped onto the bind-rest local space.\n        const inheritedRigModelIds = new Set<number>();\n        for (const rig of rigs) {\n            const inheritType2ModelIds = new Set(rig.bones.filter((bone) => bone.inheritType !== 1 && bone.parentIndex >= 0).map((bone) => bone.modelId));\n            if (inheritType2ModelIds.size === 0) {\n                continue;\n            }\n\n            const skeleton = skeletonByRigId.get(rig.id);\n            if (!skeleton) {\n                continue;\n            }\n\n            if (skeleton.bones.some((bone) => this._bindRestBones.has(bone))) {\n                continue;\n            }\n\n            for (const modelId of Array.from(inheritType2ModelIds)) {\n                inheritedRigModelIds.add(modelId);\n            }\n            for (const { bone, animations } of this._buildInheritedRigBoneAnimations(\n                rig,\n                skeleton,\n                boneCurves,\n                modelIdToData,\n                inheritType2ModelIds,\n                animStack.startTime,\n                animStack.stopTime\n            )) {\n                for (const animation of animations) {\n                    addBoneAnimation(animation, bone);\n                }\n            }\n        }\n\n        for (const [targetId, curveNodes] of Array.from(boneCurves)) {\n            if (inheritedRigModelIds.has(targetId)) {\n                continue;\n            }\n\n            const bones = modelIdToBones.get(targetId);\n            const modelData = modelIdToData.get(targetId);\n            if (!bones || bones.length === 0 || !modelData) {\n                continue;\n            }\n\n            for (const bone of bones) {\n                const animations = this._buildBoneAnimations(\n                    curveNodes,\n                    bone.name,\n                    modelData,\n                    animStack.startTime,\n                    animStack.stopTime,\n                    this._bindRestBones.has(bone) ? bone.getBindMatrix() : undefined\n                );\n                for (const animation of animations) {\n                    addBoneAnimation(animation, bone);\n                }\n            }\n        }\n\n        // Process non-bone targets: bake full transform matrix per frame\n        for (const [targetId, curveNodes] of Array.from(nonBoneCurves)) {\n            const node = modelIdToNode.get(targetId);\n            if (!node) {\n                continue;\n            }\n\n            const modelData = modelIdToData.get(targetId);\n            if (!modelData) {\n                continue;\n            }\n\n            const animations = this._buildNodeAnimations(curveNodes, node.name, modelData, animStack.startTime, animStack.stopTime);\n            for (const animation of animations) {\n                animGroup.addTargetedAnimation(animation, node);\n            }\n        }\n\n        // Inherit-scale helpers follow the inverse of their parent's (possibly animated) scale. Children of animated\n        // parents also need re-sampling even when they carry no curves of their own, since their local transform\n        // depends on the parent scale.\n        for (const [modelId, helper] of Array.from(this._inheritScaleHelpers)) {\n            const modelData = modelIdToData.get(modelId);\n            const parentModel = modelData ? this._parentModelById.get(modelId) : undefined;\n            if (!modelData || !parentModel) {\n                continue;\n            }\n            const fps = this._frameRate;\n            // The helper mirrors the parent's animated rotation/translation (its own curves plus any inherited scale\n            // that feeds its translation), with unit scale.\n            const parentCurves = [\n                ...(this._curveNodesByModelId.get(parentModel.id) ?? []),\n                ...this._collectInheritScaleCurves(parentModel).filter((cn) => cn.targetModelId !== parentModel.id),\n            ];\n            if (parentCurves.length > 0) {\n                const baseTimes = collectAnimationSampleTimes(parentCurves, fps, animStack.startTime, animStack.stopTime);\n                const sampleParent = (time: number) =>\n                    this._computeInheritAwareLocalMatrix(parentModel, this._sampleModelLocalMatrix(parentModel, this._curveNodesByModelId.get(parentModel.id) ?? [], time), time);\n                const times = FBXFileLoader._refineSampleTimes(baseTimes, sampleParent);\n                const posKeys: { frame: number; value: Vector3 }[] = [];\n                const rotKeys: { frame: number; value: Quaternion }[] = [];\n                let prevQuat: Quaternion | null = null;\n                for (const time of times) {\n                    const sc = new Vector3();\n                    const rq = new Quaternion();\n                    const tr = new Vector3();\n                    sampleParent(time).decompose(sc, rq, tr);\n                    if (prevQuat && Quaternion.Dot(prevQuat, rq) < 0) {\n                        rq.scaleInPlace(-1);\n                    }\n                    prevQuat = rq;\n                    posKeys.push({ frame: time * fps, value: tr });\n                    rotKeys.push({ frame: time * fps, value: rq });\n                }\n                if (!this._isVector3KeysConstant(posKeys)) {\n                    const anim = new Animation(`${helper.name}_position`, \"position\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n                    anim.setKeys(posKeys);\n                    animGroup.addTargetedAnimation(anim, helper);\n                }\n                if (!areQuaternionKeysConstant(rotKeys)) {\n                    const anim = new Animation(`${helper.name}_rotation`, \"rotationQuaternion\", fps, Animation.ANIMATIONTYPE_QUATERNION, Animation.ANIMATIONLOOPMODE_CYCLE);\n                    anim.setKeys(rotKeys);\n                    animGroup.addTargetedAnimation(anim, helper);\n                }\n            }\n            // The child's own local transform depends on the parent scale; re-sample it when that scale animates.\n            const scaleCurves = this._collectInheritScaleCurves(parentModel);\n            const node = modelIdToNode.get(modelId);\n            if (node && scaleCurves.length > 0 && !nonBoneCurves.has(modelId) && !boneCurves.has(modelId)) {\n                for (const animation of this._buildNodeAnimations([], node.name, modelData, animStack.startTime, animStack.stopTime, scaleCurves)) {\n                    animGroup.addTargetedAnimation(animation, node);\n                }\n            }\n        }\n\n        // Process blend shape (morph target) animations. Every layer animating a channel contributes to one\n        // influence animation evaluated through the layer stack.\n        const blendShapeGroups = new Map<number, FBXCurveNodeData[]>();\n        for (const curveNode of blendShapeCurves) {\n            const group = blendShapeGroups.get(curveNode.targetModelId);\n            if (group) {\n                group.push(curveNode);\n            } else {\n                blendShapeGroups.set(curveNode.targetModelId, [curveNode]);\n            }\n        }\n        for (const [targetChannelId, group] of Array.from(blendShapeGroups)) {\n            group.sort((a, b) => a.layerIndex - b.layerIndex);\n            const sources: FBXLayeredPropertySource[] = group.filter((cn) => cn.curves.length > 0).map((cn) => ({ layerIndex: cn.layerIndex, curves: cn.curves }));\n            if (sources.length === 0) {\n                continue;\n            }\n\n            // Find the morph target with matching channel ID across all meshes\n            let targetFound = false;\n            for (const mesh of meshes) {\n                if (!mesh.morphTargetManager || targetFound) {\n                    continue;\n                }\n                const metadata = mesh.metadata as Record<string, unknown> | undefined;\n                const channelTargets = metadata?.fbxBlendShapeChannelTargets as Map<number, { targetIndices: number[]; fullWeights: number[] | null }> | undefined;\n                const targetInfo = channelTargets?.get(targetChannelId);\n                if (targetInfo) {\n                    const fps = this._frameRate;\n                    for (let shapeIndex = 0; shapeIndex < targetInfo.targetIndices.length; shapeIndex++) {\n                        const target = mesh.morphTargetManager.getTarget(targetInfo.targetIndices[shapeIndex]);\n                        if (!target) {\n                            continue;\n                        }\n                        const anim = new Animation(`${target.name}_influence`, \"influence\", fps, Animation.ANIMATIONTYPE_FLOAT, Animation.ANIMATIONLOOPMODE_CYCLE);\n                        const keys = this._layeredScalarKeys(\n                            sources,\n                            animStack,\n                            (value) => calculateBlendShapeInfluences(value, targetInfo.fullWeights, targetInfo.targetIndices.length)[shapeIndex] ?? 0\n                        );\n                        anim.setKeys(keys);\n                        animGroup.addTargetedAnimation(anim, target);\n                    }\n                    targetFound = true;\n                    continue;\n                }\n\n                const channelMap = metadata?.fbxBlendShapeChannelIds as Map<number, number> | undefined;\n                if (!channelMap) {\n                    continue;\n                }\n                const targetIndex = channelMap.get(targetChannelId);\n                if (targetIndex === undefined) {\n                    continue;\n                }\n\n                const target = mesh.morphTargetManager.getTarget(targetIndex);\n                if (target) {\n                    const fps = this._frameRate;\n                    const anim = new Animation(`${target.name}_influence`, \"influence\", fps, Animation.ANIMATIONTYPE_FLOAT, Animation.ANIMATIONLOOPMODE_CYCLE);\n                    anim.setKeys(this._layeredScalarKeys(sources, animStack, (value) => value / 100));\n                    animGroup.addTargetedAnimation(anim, target);\n                    targetFound = true;\n                }\n            }\n        }\n\n        // Animated non-transform properties: visibility, camera, light and material parameters. Curve nodes of\n        // several layers that animate the same property are evaluated together through the layer stack.\n        const propertyGroups = new Map<string, FBXUnsupportedCurveNodeData[]>();\n        for (const curveNode of animStack.unsupportedCurveNodes) {\n            if (curveNode.targetId === null || curveNode.curves.length === 0) {\n                continue;\n            }\n            const key = `${curveNode.targetId}|${curveNode.propertyName ?? curveNode.type}`;\n            const group = propertyGroups.get(key);\n            if (group) {\n                group.push(curveNode);\n            } else {\n                propertyGroups.set(key, [curveNode]);\n            }\n        }\n        for (const group of Array.from(propertyGroups.values())) {\n            group.sort((a, b) => a.layerIndex - b.layerIndex);\n            const built = this._buildPropertyAnimations(group, animStack, modelIdToNode, propertyTargets);\n            if (built.length > 0) {\n                for (const curveNode of group) {\n                    this._evaluatedCurveNodeIds.add(curveNode.id);\n                }\n            }\n            for (const { animation, target } of built) {\n                animGroup.addTargetedAnimation(animation, target);\n            }\n        }\n\n        // Normalize the animation group\n        if (animGroup.targetedAnimations.length > 0) {\n            animGroup.normalize(animStack.startTime * this._frameRate, animStack.stopTime * this._frameRate);\n            return animGroup;\n        }\n\n        animGroup.dispose();\n        return null;\n    }\n\n    private _buildInheritedRigBoneAnimations(\n        rig: FBXRigData,\n        skeleton: Skeleton,\n        boneCurves: Map<number, FBXCurveNodeData[]>,\n        modelIdToData: Map<number, FBXModelData>,\n        compensatedModelIds: Set<number>,\n        startTime: number,\n        stopTime: number\n    ): { bone: Bone; animations: Animation[] }[] {\n        const fps = this._frameRate;\n        const sampledModelIds = new Set<number>();\n        for (let i = 0; i < rig.bones.length; i++) {\n            if (!compensatedModelIds.has(rig.bones[i].modelId)) {\n                continue;\n            }\n\n            for (let parentIndex = i; parentIndex >= 0; parentIndex = rig.bones[parentIndex].parentIndex) {\n                sampledModelIds.add(rig.bones[parentIndex].modelId);\n            }\n        }\n        const rigCurveNodes = rig.bones.filter((bone) => sampledModelIds.has(bone.modelId)).flatMap((bone) => boneCurves.get(bone.modelId) ?? []);\n        let times = collectAnimationSampleTimes(rigCurveNodes, fps, startTime, stopTime);\n        if (times.length === 0) {\n            return [];\n        }\n        for (const boneData of rig.bones) {\n            const md = modelIdToData.get(boneData.modelId);\n            const cn = boneCurves.get(boneData.modelId) ?? [];\n            if (!sampledModelIds.has(boneData.modelId) || !md || cn.length === 0) {\n                continue;\n            }\n            times = FBXFileLoader._refineSampleTimes(times, (time) => this._sampleModelLocalMatrix(md, cn, time));\n        }\n\n        const keysByBone = rig.bones.map(() => ({\n            posKeys: [] as { frame: number; value: Vector3 }[],\n            rotKeys: [] as { frame: number; value: Quaternion }[],\n            sclKeys: [] as { frame: number; value: Vector3 }[],\n            prevQuat: null as Quaternion | null,\n        }));\n        const keysByHelper = rig.bones.map(() => ({\n            posKeys: [] as { frame: number; value: Vector3 }[],\n            rotKeys: [] as { frame: number; value: Quaternion }[],\n            sclKeys: [] as { frame: number; value: Vector3 }[],\n            prevQuat: null as Quaternion | null,\n        }));\n        const restLocalInverses = rig.bones.map((boneData, index) => {\n            const bone = this._getSourceBone(skeleton, index);\n            const modelData = modelIdToData.get(boneData.modelId);\n            if (!bone || !modelData || !this._bindRestBones.has(bone)) {\n                return null;\n            }\n\n            const restLocalMatrix = FBXFileLoader._computeFBXModelLocalMatrix(modelData);\n            const restLocalInverse = new Matrix();\n            restLocalMatrix.invertToRef(restLocalInverse);\n            return restLocalInverse;\n        });\n\n        for (const time of times) {\n            const localMatrices = rig.bones.map((boneData, index) => {\n                const modelData = modelIdToData.get(boneData.modelId);\n                const curveNodes = boneCurves.get(boneData.modelId) ?? [];\n                let localMatrix = modelData ? this._sampleModelLocalMatrix(modelData, curveNodes, time) : Matrix.Identity();\n\n                const restLocalInverse = restLocalInverses[index];\n                if (restLocalInverse) {\n                    const sourceBone = this._getSourceBone(skeleton, index);\n                    localMatrix = (sourceBone?.getBindMatrix() ?? Matrix.Identity()).multiply(restLocalInverse).multiply(localMatrix);\n                }\n                return localMatrix;\n            });\n            const sampledScales = rig.bones.map((boneData) => {\n                const modelData = modelIdToData.get(boneData.modelId);\n                const curveNodes = boneCurves.get(boneData.modelId) ?? [];\n                return modelData ? this._sampleModelScale(modelData, curveNodes, time) : boneData.scale;\n            });\n            const sampledInheritScales = FBXFileLoader._computeBoneInheritScales(rig.bones, sampledScales);\n            const frame = time * fps;\n\n            for (let i = 0; i < localMatrices.length; i++) {\n                if (!compensatedModelIds.has(rig.bones[i].modelId)) {\n                    continue;\n                }\n\n                const parentIndex = rig.bones[i].parentIndex;\n                const parentScale = parentIndex >= 0 ? sampledInheritScales[parentIndex] : rig.bones[i].scale;\n                const split = FBXFileLoader._splitParentScaleCompensatedLocalMatrix(\n                    localMatrices[i],\n                    parentScale,\n                    FBXFileLoader._getBoneInheritedScale(rig.bones, i, sampledInheritScales)\n                );\n                FBXFileLoader._pushMatrixKeys(keysByBone[i], frame, split.boneLocalMatrix);\n                FBXFileLoader._pushMatrixKeys(keysByHelper[i], frame, split.helperLocalMatrix);\n            }\n        }\n\n        const result: { bone: Bone; animations: Animation[] }[] = [];\n        for (let i = 0; i < rig.bones.length; i++) {\n            if (!compensatedModelIds.has(rig.bones[i].modelId)) {\n                continue;\n            }\n\n            const bone = this._getSourceBone(skeleton, i);\n            if (!bone) {\n                continue;\n            }\n\n            const { posKeys, rotKeys, sclKeys } = keysByBone[i];\n            const animations: Animation[] = [];\n            if (!this._isVector3KeysConstant(posKeys)) {\n                const posAnim = new Animation(`${bone.name}_position`, \"position\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n                posAnim.setKeys(posKeys);\n                animations.push(posAnim);\n            }\n            if (!areQuaternionKeysConstant(rotKeys)) {\n                const rotAnim = new Animation(`${bone.name}_rotation`, \"rotationQuaternion\", fps, Animation.ANIMATIONTYPE_QUATERNION, Animation.ANIMATIONLOOPMODE_CYCLE);\n                rotAnim.setKeys(rotKeys);\n                animations.push(rotAnim);\n            }\n            if (!this._isVector3KeysConstant(sclKeys)) {\n                const sclAnim = new Animation(`${bone.name}_scaling`, \"scaling\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n                sclAnim.setKeys(sclKeys);\n                animations.push(sclAnim);\n            }\n            if (animations.length > 0) {\n                result.push({ bone, animations });\n            }\n\n            const helper = this._getScaleCompensationHelper(skeleton, i);\n            if (!helper) {\n                continue;\n            }\n\n            const helperAnimations: Animation[] = [];\n            const { posKeys: helperPosKeys, rotKeys: helperRotKeys, sclKeys: helperSclKeys } = keysByHelper[i];\n            if (!this._isVector3KeysConstant(helperPosKeys)) {\n                const posAnim = new Animation(`${helper.name}_position`, \"position\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n                posAnim.setKeys(helperPosKeys);\n                helperAnimations.push(posAnim);\n            }\n            if (!areQuaternionKeysConstant(helperRotKeys)) {\n                const rotAnim = new Animation(`${helper.name}_rotation`, \"rotationQuaternion\", fps, Animation.ANIMATIONTYPE_QUATERNION, Animation.ANIMATIONLOOPMODE_CYCLE);\n                rotAnim.setKeys(helperRotKeys);\n                helperAnimations.push(rotAnim);\n            }\n            if (!this._isVector3KeysConstant(helperSclKeys)) {\n                const sclAnim = new Animation(`${helper.name}_scaling`, \"scaling\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n                sclAnim.setKeys(helperSclKeys);\n                helperAnimations.push(sclAnim);\n            }\n            if (helperAnimations.length > 0) {\n                result.push({ bone: helper, animations: helperAnimations });\n            }\n        }\n\n        return result;\n    }\n\n    private static _pushMatrixKeys(\n        keySet: {\n            posKeys: { frame: number; value: Vector3 }[];\n            rotKeys: { frame: number; value: Quaternion }[];\n            sclKeys: { frame: number; value: Vector3 }[];\n            prevQuat: Quaternion | null;\n        },\n        frame: number,\n        matrix: Matrix\n    ): void {\n        const s = new Vector3();\n        const r = new Quaternion();\n        const t = new Vector3();\n        matrix.decompose(s, r, t);\n\n        if (keySet.prevQuat && Quaternion.Dot(keySet.prevQuat, r) < 0) {\n            r.scaleInPlace(-1);\n        }\n        keySet.prevQuat = r;\n\n        keySet.posKeys.push({ frame, value: t });\n        keySet.rotKeys.push({ frame, value: r });\n        keySet.sclKeys.push({ frame, value: s });\n    }\n\n    /**\n     * Build animations for a non-bone node, correctly handling pivots.\n     * Computes the full FBX transform matrix at each keyframe and decomposes into TRS.\n     */\n    private _buildNodeAnimations(\n        curveNodes: FBXCurveNodeData[],\n        nodeName: string,\n        modelData: FBXModelData,\n        startTime: number,\n        stopTime: number,\n        extraTimeCurves: FBXCurveNodeData[] = []\n    ): Animation[] {\n        const fps = this._frameRate;\n\n        // Separate curves by type\n        const rNode = curveNodes.find((cn) => cn.type === \"R\");\n\n        const baseTimes = collectAnimationSampleTimes([...curveNodes, ...extraTimeCurves], fps, startTime, stopTime);\n        if (baseTimes.length === 0) {\n            return [];\n        }\n        const sampleTRS = (time: number) => {\n            const sampled = this._sampleModelTRS(modelData, curveNodes, time);\n            const trs = FBXFileLoader._computeLocalTRS(modelData, sampled.translation, sampled.rotation, sampled.scale);\n            this._adjustTRSForInheritMode(modelData, trs, time);\n            return trs;\n        };\n        const times = FBXFileLoader._refineSampleTimes(baseTimes, (time) => {\n            const trs = sampleTRS(time);\n            return Matrix.Compose(trs.scaling, trs.rotationQuaternion, trs.position);\n        });\n\n        // Build keyframes by computing the local transform at each time\n        const posKeys: { frame: number; value: Vector3; interpolation?: AnimationKeyInterpolation }[] = [];\n        const rotKeys: { frame: number; value: Quaternion; interpolation?: AnimationKeyInterpolation }[] = [];\n        const sclKeys: { frame: number; value: Vector3; interpolation?: AnimationKeyInterpolation }[] = [];\n        let prevQuat: Quaternion | null = null;\n\n        for (const time of times) {\n            const frame = time * fps;\n\n            const trs = sampleTRS(time);\n            const s = trs.scaling;\n            const r = trs.rotationQuaternion;\n            const t = trs.position;\n            const stepT = isChannelSteppedAt(curveNodes, \"T\", time);\n            const stepR = isChannelSteppedAt(curveNodes, \"R\", time);\n            const stepS = isChannelSteppedAt(curveNodes, \"S\", time);\n\n            // Ensure quaternion continuity\n            if (prevQuat && Quaternion.Dot(prevQuat, r) < 0) {\n                r.scaleInPlace(-1);\n            }\n            prevQuat = r;\n\n            posKeys.push(stepT ? { frame, value: t, interpolation: AnimationKeyInterpolation.STEP } : { frame, value: t });\n            rotKeys.push(stepR ? { frame, value: r, interpolation: AnimationKeyInterpolation.STEP } : { frame, value: r });\n            sclKeys.push(stepS ? { frame, value: s, interpolation: AnimationKeyInterpolation.STEP } : { frame, value: s });\n        }\n\n        const animations: Animation[] = [];\n\n        // Only create position animation if it's not constant\n        if (!this._isVector3KeysConstant(posKeys)) {\n            const posAnim = new Animation(`${nodeName}_position`, \"position\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n            posAnim.setKeys(posKeys);\n            animations.push(posAnim);\n        }\n\n        // Always create rotation animation (if there are rotation curves)\n        if (rNode) {\n            const rotAnim = new Animation(`${nodeName}_rotation`, \"rotationQuaternion\", fps, Animation.ANIMATIONTYPE_QUATERNION, Animation.ANIMATIONLOOPMODE_CYCLE);\n            rotAnim.setKeys(rotKeys);\n            animations.push(rotAnim);\n        }\n\n        // Only create scale animation if it's not constant\n        if (!this._isVector3KeysConstant(sclKeys)) {\n            const sclAnim = new Animation(`${nodeName}_scaling`, \"scaling\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n            sclAnim.setKeys(sclKeys);\n            animations.push(sclAnim);\n        }\n\n        return animations;\n    }\n\n    /**\n     * Baked keys are interpolated linearly by Babylon. Between two frames an FBX cubic segment can deviate from that\n     * line, so sample times are refined (midpoints inserted, up to two levels) wherever the interpolated transform\n     * differs noticeably from the curve. Flat and linear segments stay at frame resolution.\n     */\n    private static _refineSampleTimes(times: number[], sample: (time: number) => Matrix, maxDepth = 2): number[] {\n        const decompose = (time: number) => {\n            const s = new Vector3();\n            const r = new Quaternion();\n            const t = new Vector3();\n            sample(time).decompose(s, r, t);\n            return { s, r, t };\n        };\n        const out: number[] = [];\n        const refine = (t0: number, t1: number, d0: ReturnType<typeof decompose>, d1: ReturnType<typeof decompose>, depth: number) => {\n            if (depth >= maxDepth) {\n                return;\n            }\n            const tm = (t0 + t1) * 0.5;\n            if (!(tm > t0 && tm < t1)) {\n                return;\n            }\n            const dm = decompose(tm);\n            const lerpT = Vector3.Lerp(d0.t, d1.t, 0.5);\n            const lerpS = Vector3.Lerp(d0.s, d1.s, 0.5);\n            const slerpR = Quaternion.Slerp(d0.r, d1.r, 0.5);\n            const posErr = Vector3.Distance(lerpT, dm.t);\n            const sclErr = Vector3.Distance(lerpS, dm.s);\n            const dot = Math.min(1, Math.abs(Quaternion.Dot(slerpR, dm.r)));\n            const angErr = 2 * Math.acos(dot);\n            const posTol = 1e-4 * (1 + Math.max(Math.abs(dm.t.x), Math.abs(dm.t.y), Math.abs(dm.t.z)));\n            const sclTol = 1e-4 * (1 + Math.max(Math.abs(dm.s.x), Math.abs(dm.s.y), Math.abs(dm.s.z)));\n            if (posErr > posTol || sclErr > sclTol || angErr > 0.0005) {\n                refine(t0, tm, d0, dm, depth + 1);\n                out.push(tm);\n                refine(tm, t1, dm, d1, depth + 1);\n            }\n        };\n        let prev = times.length > 0 ? decompose(times[0]) : null;\n        for (let i = 0; i < times.length; i++) {\n            out.push(times[i]);\n            if (i + 1 < times.length && prev) {\n                const next = decompose(times[i + 1]);\n                refine(times[i], times[i + 1], prev, next, 0);\n                prev = next;\n            }\n        }\n        return out;\n    }\n\n    /**\n     * Keys of a scalar property animated by one or more layers: the authored keys when a single layer drives it,\n     * otherwise the frame grid evaluated through the layer stack.\n     * @param sources - Per-layer curves of the property (each with at least one curve)\n     * @param animStack - Stack being converted\n     * @param mapValue - Conversion from the FBX value to the Babylon property value\n     * @returns Animation keys\n     */\n    private _layeredScalarKeys(sources: readonly FBXLayeredPropertySource[], animStack: FBXAnimationStackData, mapValue: (value: number) => number): IAnimationKey[] {\n        const fps = this._frameRate;\n        if (sources.length === 0) {\n            return [];\n        }\n        if (sources.length === 1) {\n            return buildScalarAnimationKeys(sources[0].curves[0], fps, animStack.startTime, animStack.stopTime, mapValue);\n        }\n        const channel = sources[0].curves[0].channel;\n        const times = collectAnimationSampleTimes(\n            sources.map((source) => ({ type: \"other\", targetModelId: 0, curves: Array.from(source.curves), layerIndex: source.layerIndex })),\n            fps,\n            animStack.startTime,\n            animStack.stopTime\n        );\n        return times.map((time) => ({ frame: time * fps, value: mapValue(evaluateLayeredProperty(sources, animStack.layers, [channel], [0], time)[0]) }));\n    }\n\n    /**\n     * Maps an animated FBX property (anything other than node transforms and blend shape weights) onto the Babylon\n     * property that carries it: mesh visibility, camera field of view and clip planes, light intensity, colour and\n     * cone angles, and material colours, alpha, roughness and metalness. `group` holds the curve nodes of every\n     * layer animating that property, in layer order; several layers are evaluated through the layer stack.\n     */\n    private _buildPropertyAnimations(\n        group: readonly FBXUnsupportedCurveNodeData[],\n        animStack: FBXAnimationStackData,\n        modelIdToNode: Map<number, TransformNode>,\n        targets: { cameraByAttributeId: Map<number, FreeCamera>; lightByAttributeId: Map<number, Light>; materialCache: Map<number, Material> }\n    ): { animation: Animation; target: unknown }[] {\n        const fps = this._frameRate;\n        const curveNode = group[0];\n        const prop = curveNode.propertyName ?? curveNode.type;\n        const targetId = curveNode.targetId!;\n        const out: { animation: Animation; target: unknown }[] = [];\n        const scalarCurve = curveNode.curves.find((c) => c.channel === \"d|X\") ?? curveNode.curves[0];\n        const defaults = curveNode.defaultValues;\n        const layered = group.length > 1;\n        const sources: FBXLayeredPropertySource[] = group.map((cn) => ({ layerIndex: cn.layerIndex, curves: cn.curves, defaultValues: cn.defaultValues }));\n        const sampleTimes = (): number[] =>\n            collectAnimationSampleTimes(\n                group.map((cn) => ({ type: \"other\", targetModelId: targetId, curves: cn.curves, layerIndex: cn.layerIndex })),\n                fps,\n                animStack.startTime,\n                animStack.stopTime\n            );\n        const vectorSamples = (staticValue: [number, number, number]): { frame: number; values: number[] }[] => {\n            const cx = curveNode.curves.find((c) => c.channel === \"d|X\");\n            const cy = curveNode.curves.find((c) => c.channel === \"d|Y\");\n            const cz = curveNode.curves.find((c) => c.channel === \"d|Z\");\n            return sampleTimes().map((time) => ({\n                frame: time * fps,\n                values: layered\n                    ? evaluateLayeredProperty(sources, animStack.layers, [\"d|X\", \"d|Y\", \"d|Z\"], staticValue, time)\n                    : [sampleFBXCurveAtTime(cx, time) ?? staticValue[0], sampleFBXCurveAtTime(cy, time) ?? staticValue[1], sampleFBXCurveAtTime(cz, time) ?? staticValue[2]],\n            }));\n        };\n        const scalarKeys = (map: (v: number) => number, step = false): IAnimationKey[] => {\n            const keys: IAnimationKey[] = layered\n                ? sampleTimes().map((time) => ({\n                      frame: time * fps,\n                      value: map(evaluateLayeredProperty(sources, animStack.layers, [scalarCurve.channel], [defaults[scalarCurve.channel] ?? 0], time)[0]),\n                  }))\n                : buildScalarAnimationKeys(scalarCurve, fps, animStack.startTime, animStack.stopTime, map);\n            if (step) {\n                for (const key of keys) {\n                    key.interpolation = AnimationKeyInterpolation.STEP;\n                    delete key.inTangent;\n                    delete key.outTangent;\n                }\n            }\n            return keys;\n        };\n        const colorKeys = (): IAnimationKey[] =>\n            vectorSamples([defaults[\"d|X\"] ?? 1, defaults[\"d|Y\"] ?? 1, defaults[\"d|Z\"] ?? 1]).map(({ frame, values }) => ({\n                frame,\n                value: new Color3(values[0], values[1], values[2]),\n            }));\n        const add = (target: unknown, property: string, type: number, keys: IAnimationKey[], name: string) => {\n            if (keys.length === 0) {\n                return;\n            }\n            const animation = new Animation(`${name}_${property}`, property, fps, type, Animation.ANIMATIONLOOPMODE_CYCLE);\n            animation.setKeys(keys);\n            out.push({ animation, target });\n        };\n\n        const node = modelIdToNode.get(targetId);\n        if (node) {\n            if (prop === \"Visibility\" && node instanceof Mesh) {\n                add(\n                    node,\n                    \"visibility\",\n                    Animation.ANIMATIONTYPE_FLOAT,\n                    scalarKeys((v) => Math.min(1, Math.max(0, v)), true),\n                    node.name\n                );\n                return out;\n            }\n            // Animated user properties drive the value stored in the node's metadata.\n            const userProperties = (node.metadata as { fbxUserProperties?: Record<string, unknown> } | undefined)?.fbxUserProperties;\n            if (userProperties && prop in userProperties) {\n                const hasVector = curveNode.curves.some((c) => c.channel === \"d|Y\" || c.channel === \"d|Z\");\n                if (hasVector) {\n                    const current = userProperties[prop];\n                    const base = Array.isArray(current) ? (current as number[]) : [0, 0, 0];\n                    userProperties[prop] = new Vector3(base[0] ?? 0, base[1] ?? 0, base[2] ?? 0);\n                    const keys = vectorSamples([base[0] ?? 0, base[1] ?? 0, base[2] ?? 0]).map(({ frame, values }) => ({\n                        frame,\n                        value: new Vector3(values[0], values[1], values[2]),\n                    }));\n                    add(node, `metadata.fbxUserProperties.${prop}`, Animation.ANIMATIONTYPE_VECTOR3, keys, node.name);\n                } else {\n                    if (typeof userProperties[prop] === \"boolean\") {\n                        userProperties[prop] = userProperties[prop] ? 1 : 0;\n                    }\n                    add(\n                        node,\n                        `metadata.fbxUserProperties.${prop}`,\n                        Animation.ANIMATIONTYPE_FLOAT,\n                        scalarKeys((v) => v),\n                        node.name\n                    );\n                }\n            }\n            return out;\n        }\n\n        const camera = targets.cameraByAttributeId.get(targetId);\n        if (camera) {\n            const meta = (camera.metadata as { fbxCamera?: { aspectRatio?: number; apertureMode?: number; apertureSizeInch?: [number, number] } } | undefined)?.fbxCamera;\n            const aspect = meta?.aspectRatio || 1;\n            const apertureMode = meta?.apertureMode ?? 2;\n            switch (prop) {\n                case \"FieldOfView\":\n                    // Vertical unless the camera's aperture mode declares FieldOfView as horizontal.\n                    add(\n                        camera,\n                        \"fov\",\n                        Animation.ANIMATIONTYPE_FLOAT,\n                        scalarKeys((v) => (apertureMode === 1 ? 2 * Math.atan(Math.tan((v * Math.PI) / 360) / aspect) : (v * Math.PI) / 180)),\n                        camera.name\n                    );\n                    break;\n                case \"FieldOfViewY\":\n                    add(\n                        camera,\n                        \"fov\",\n                        Animation.ANIMATIONTYPE_FLOAT,\n                        scalarKeys((v) => (v * Math.PI) / 180),\n                        camera.name\n                    );\n                    break;\n                case \"FieldOfViewX\":\n                    if (apertureMode !== 0) {\n                        add(\n                            camera,\n                            \"fov\",\n                            Animation.ANIMATIONTYPE_FLOAT,\n                            scalarKeys((v) => 2 * Math.atan(Math.tan((v * Math.PI) / 360) / aspect)),\n                            camera.name\n                        );\n                    }\n                    break;\n                case \"FocalLength\": {\n                    const apertureY = meta?.apertureSizeInch?.[1];\n                    if (apertureY && apertureMode === 3) {\n                        add(\n                            camera,\n                            \"fov\",\n                            Animation.ANIMATIONTYPE_FLOAT,\n                            scalarKeys((v) => 2 * Math.atan((apertureY / Math.max(v / 25.4, 1e-6)) * 0.5)),\n                            camera.name\n                        );\n                    }\n                    break;\n                }\n                case \"NearPlane\":\n                    add(\n                        camera,\n                        \"minZ\",\n                        Animation.ANIMATIONTYPE_FLOAT,\n                        scalarKeys((v) => v),\n                        camera.name\n                    );\n                    break;\n                case \"FarPlane\":\n                    add(\n                        camera,\n                        \"maxZ\",\n                        Animation.ANIMATIONTYPE_FLOAT,\n                        scalarKeys((v) => v),\n                        camera.name\n                    );\n                    break;\n                default:\n                    break;\n            }\n            return out;\n        }\n\n        const light = targets.lightByAttributeId.get(targetId);\n        if (light) {\n            switch (prop) {\n                case \"Intensity\":\n                    add(\n                        light,\n                        \"intensity\",\n                        Animation.ANIMATIONTYPE_FLOAT,\n                        scalarKeys((v) => v / 100),\n                        light.name\n                    );\n                    break;\n                case \"Color\":\n                    add(light, \"diffuse\", Animation.ANIMATIONTYPE_COLOR3, colorKeys(), light.name);\n                    break;\n                case \"OuterAngle\":\n                case \"ConeAngle\":\n                    if (light instanceof SpotLight) {\n                        add(\n                            light,\n                            \"angle\",\n                            Animation.ANIMATIONTYPE_FLOAT,\n                            scalarKeys((v) => (v * Math.PI) / 180),\n                            light.name\n                        );\n                    }\n                    break;\n                case \"InnerAngle\":\n                    if (light instanceof SpotLight) {\n                        add(\n                            light,\n                            \"innerAngle\",\n                            Animation.ANIMATIONTYPE_FLOAT,\n                            scalarKeys((v) => (v * Math.PI) / 180),\n                            light.name\n                        );\n                    }\n                    break;\n                default:\n                    break;\n            }\n            return out;\n        }\n\n        const material = targets.materialCache.get(targetId);\n        if (material) {\n            const isPbr = material instanceof PBRMaterial;\n            const short = prop.substring(prop.lastIndexOf(\"|\") + 1);\n            if (prop === \"DiffuseColor\" || prop === \"Diffuse\" || short === \"baseColor\" || short === \"base_color\" || short === \"color\") {\n                add(material, isPbr ? \"albedoColor\" : \"diffuseColor\", Animation.ANIMATIONTYPE_COLOR3, colorKeys(), material.name);\n            } else if (\n                prop === \"EmissiveColor\" ||\n                prop === \"Emissive\" ||\n                short === \"emissionColor\" ||\n                short === \"emission_color\" ||\n                short === \"emissive\" ||\n                short === \"emit_color\"\n            ) {\n                add(material, \"emissiveColor\", Animation.ANIMATIONTYPE_COLOR3, colorKeys(), material.name);\n            } else if (prop === \"Opacity\") {\n                add(\n                    material,\n                    \"alpha\",\n                    Animation.ANIMATIONTYPE_FLOAT,\n                    scalarKeys((v) => v),\n                    material.name\n                );\n            } else if (prop === \"TransparencyFactor\" || prop === \"TransparentFactor\") {\n                add(\n                    material,\n                    \"alpha\",\n                    Animation.ANIMATIONTYPE_FLOAT,\n                    scalarKeys((v) => 1 - v),\n                    material.name\n                );\n            } else if (isPbr && (short === \"roughness\" || short === \"specular_roughness\" || short === \"specularRoughness\")) {\n                add(\n                    material,\n                    \"roughness\",\n                    Animation.ANIMATIONTYPE_FLOAT,\n                    scalarKeys((v) => v),\n                    material.name\n                );\n            } else if (isPbr && (short === \"metalness\" || short === \"metallic\" || short === \"base_metalness\")) {\n                add(\n                    material,\n                    \"metallic\",\n                    Animation.ANIMATIONTYPE_FLOAT,\n                    scalarKeys((v) => v),\n                    material.name\n                );\n            } else if (!isPbr && prop === \"SpecularColor\") {\n                add(material, \"specularColor\", Animation.ANIMATIONTYPE_COLOR3, colorKeys(), material.name);\n            }\n            return out;\n        }\n\n        return out;\n    }\n\n    /** Records constraints on their nodes and, unless disabled, attaches the runtime behavior that solves them. */\n    private _applyConstraints(fbxScene: FBXSceneData, modelIdToNode: Map<number, TransformNode>, rootNode: TransformNode, scene: Scene): void {\n        const nodeName = (id: number | undefined) => (id === undefined ? undefined : modelIdToNode.get(id)?.name);\n        const upSign = fbxScene.upAxisSign >= 0 ? 1 : -1;\n        const sceneUp = new Vector3(fbxScene.upAxis === 0 ? upSign : 0, fbxScene.upAxis === 1 ? upSign : 0, fbxScene.upAxis === 2 ? upSign : 0);\n        const summaries: unknown[] = [];\n        for (const c of fbxScene.constraints) {\n            const summary = {\n                name: c.name,\n                type: c.type,\n                node: nodeName(c.nodeId),\n                targets: c.targets.map((t) => ({ node: nodeName(t.modelId), weight: t.weight })),\n                weight: c.weight,\n                active: c.active,\n                ...(c.type === \"singleChainIK\" ? { firstJoint: nodeName(c.ikFirstJointId), endJoint: nodeName(c.ikEndJointId), effector: nodeName(c.ikEffectorId) } : {}),\n            };\n            summaries.push(summary);\n            const node = c.nodeId !== undefined ? modelIdToNode.get(c.nodeId) : undefined;\n            if (!node) {\n                continue;\n            }\n            const existing = ((node.metadata as { fbxConstraints?: unknown[] } | undefined)?.fbxConstraints ?? []) as unknown[];\n            node.metadata = { ...((node.metadata as object) ?? {}), fbxConstraints: [...existing, summary] };\n            if (this._options.constraints !== \"apply\" || c.type === \"singleChainIK\" || c.type === \"unknown\") {\n                continue;\n            }\n            const targets: FBXConstraintBehaviorTarget[] = [];\n            for (const t of c.targets) {\n                const targetNode = modelIdToNode.get(t.modelId);\n                if (!targetNode) {\n                    continue;\n                }\n                const d2r = Math.PI / 180;\n                const offset =\n                    c.type === \"parent\"\n                        ? Matrix.Compose(\n                              new Vector3(...t.offsetScale),\n                              Quaternion.FromRotationMatrix(eulerToMatrixXYZ(t.offsetRotation[0] * d2r, t.offsetRotation[1] * d2r, t.offsetRotation[2] * d2r)),\n                              new Vector3(...t.offsetTranslation)\n                          )\n                        : Matrix.Identity();\n                targets.push({ node: targetNode, weight: t.weight, offset });\n            }\n            if (targets.length === 0) {\n                continue;\n            }\n            const upNode = c.worldUpNodeId !== undefined ? (modelIdToNode.get(c.worldUpNodeId) ?? null) : null;\n            node.addBehavior(new FBXConstraintBehavior(c, { root: rootNode, targets, upNode, sceneUp }));\n        }\n        if (summaries.length > 0) {\n            rootNode.metadata = { ...((rootNode.metadata as object) ?? {}), fbxConstraints: summaries };\n        }\n    }\n\n    /** Collects every recoverable issue the interpreter recorded, stores it on the root node and notifies the caller. */\n    private _reportDiagnostics(fbxScene: FBXSceneData, rootNode: TransformNode, modelIdToNode: Map<number, TransformNode>): void {\n        const warnings: FBXLoaderWarning[] = [];\n        const push = (source: FBXLoaderWarning[\"source\"], d: unknown, objectName?: string) => {\n            const message = typeof d === \"string\" ? d : ((d as { message?: string })?.message ?? JSON.stringify(d));\n            warnings.push({ source, message, objectName, details: typeof d === \"string\" ? undefined : d });\n        };\n        for (const d of fbxScene.diagnostics) {\n            // Objects with several parents (shared materials, textures, instanced geometry) are normal in FBX.\n            if (d.subType === \"duplicate-parent\") {\n                continue;\n            }\n            push(\"scene\", d, d.objectName ?? d.nodeName);\n        }\n        for (const g of fbxScene.geometries) {\n            for (const d of g.diagnostics) {\n                push(\"geometry\", d, g.name);\n            }\n        }\n        for (const c of fbxScene.curves) {\n            for (const d of c.diagnostics) {\n                push(\"geometry\", d, c.name);\n            }\n        }\n        for (const skin of fbxScene.skins) {\n            for (const d of skin.diagnostics) {\n                push(\"skin\", d);\n            }\n            for (const bone of skin.bones) {\n                for (const d of bone.diagnostics) {\n                    push(\"skin\", d, bone.name);\n                }\n            }\n        }\n        for (const rig of fbxScene.rigs) {\n            for (const w of rig.warnings) {\n                push(\"rig\", w);\n            }\n        }\n        for (const stack of fbxScene.animations) {\n            for (const d of stack.diagnostics) {\n                if (d.type === \"unsupported-curve-node\" && d.curveNodeId !== undefined && this._evaluatedCurveNodeIds.has(d.curveNodeId)) {\n                    continue;\n                }\n                push(\"animation\", d, stack.name);\n            }\n        }\n        for (const cam of fbxScene.cameras) {\n            for (const d of cam.diagnostics) {\n                push(\"camera\", d, cam.name);\n            }\n        }\n        for (const light of fbxScene.lights) {\n            for (const d of light.diagnostics) {\n                push(\"light\", d, light.name);\n            }\n        }\n        const walk = (models: FBXModelData[]) => {\n            for (const m of models) {\n                for (const d of m.diagnostics) {\n                    push(\"model\", d, m.name);\n                }\n                walk(m.children);\n            }\n        };\n        walk(fbxScene.rootModels);\n\n        rootNode.metadata = {\n            ...((rootNode.metadata as object) ?? {}),\n            fbxDiagnostics: warnings,\n            fbxDisplayLayers: fbxScene.displayLayers.map((l) => ({ name: l.name, show: l.show, freeze: l.freeze, color: l.color })),\n            fbxSelectionSets: fbxScene.selectionSets.map((set) => ({\n                name: set.name,\n                members: set.members.map((m) => ({\n                    node: modelIdToNode.get(m.modelId)?.name ?? String(m.modelId),\n                    includeNode: m.includeNode,\n                    ...(m.vertices ? { vertices: m.vertices } : {}),\n                    ...(m.edges ? { edges: m.edges } : {}),\n                    ...(m.faces ? { faces: m.faces } : {}),\n                })),\n            })),\n        };\n        for (const warning of warnings) {\n            this._options.onWarning(warning);\n        }\n    }\n\n    /** Curve nodes affecting the inherit scale of a model: its own scale curves and those of its inherit-scale chain. */\n    private _collectInheritScaleCurves(modelData: FBXModelData): FBXCurveNodeData[] {\n        const result: FBXCurveNodeData[] = [];\n        let current: FBXModelData | undefined = modelData;\n        const seen = new Set<number>();\n        while (current && !seen.has(current.id)) {\n            seen.add(current.id);\n            for (const cn of this._curveNodesByModelId.get(current.id) ?? []) {\n                if (cn.type === \"S\") {\n                    result.push(cn);\n                }\n            }\n            current = this._getInheritScaleNode(current);\n        }\n        return result;\n    }\n\n    private _isVector3KeysConstant(keys: { frame: number; value: Vector3 }[]): boolean {\n        if (keys.length < 2) {\n            return true;\n        }\n        const first = keys[0].value;\n        for (let i = 1; i < keys.length; i++) {\n            const v = keys[i].value;\n            if (Math.abs(v.x - first.x) > 0.0001 || Math.abs(v.y - first.y) > 0.0001 || Math.abs(v.z - first.z) > 0.0001) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** Samples the animated Lcl Translation / Rotation / Scaling of a model, blending all layers of the active stack. */\n    private _sampleModelTRS(\n        modelData: FBXModelData,\n        curveNodes: readonly FBXCurveNodeData[],\n        time: number\n    ): { translation: [number, number, number]; rotation: [number, number, number]; scale: [number, number, number] } {\n        const layers = this._activeLayers;\n        return {\n            translation: evaluateLayeredChannel(curveNodes, layers, \"T\", modelData.translation, modelData.rotationOrder, time),\n            rotation: evaluateLayeredChannel(curveNodes, layers, \"R\", modelData.rotation, modelData.rotationOrder, time),\n            scale: evaluateLayeredChannel(curveNodes, layers, \"S\", modelData.scale, modelData.rotationOrder, time),\n        };\n    }\n\n    /**\n     * Local position/rotation/scale of a model from FBX Lcl values. Without pivots and offsets the components map\n     * directly (rotation = pre * lcl * post⁻¹), which keeps zero and negative scales exact. With pivots the full\n     * matrix is built and decomposed.\n     */\n    private static _computeLocalTRS(\n        modelData: FBXModelData,\n        translation: [number, number, number],\n        rotation: [number, number, number],\n        scale: [number, number, number]\n    ): { position: Vector3; rotationQuaternion: Quaternion; scaling: Vector3 } {\n        const nz = (v: [number, number, number]) => v[0] !== 0 || v[1] !== 0 || v[2] !== 0;\n        const d2r = Math.PI / 180;\n        let rotM = eulerToMatrix(rotation[0] * d2r, rotation[1] * d2r, rotation[2] * d2r, modelData.rotationOrder);\n        if (nz(modelData.preRotation)) {\n            rotM = rotM.multiply(eulerToMatrixXYZ(modelData.preRotation[0] * d2r, modelData.preRotation[1] * d2r, modelData.preRotation[2] * d2r));\n        }\n        if (nz(modelData.postRotation)) {\n            const post = eulerToMatrixXYZ(modelData.postRotation[0] * d2r, modelData.postRotation[1] * d2r, modelData.postRotation[2] * d2r);\n            const postInv = new Matrix();\n            post.invertToRef(postInv);\n            rotM = postInv.multiply(rotM);\n        }\n        let position = new Vector3(translation[0], translation[1], translation[2]);\n        if (nz(modelData.rotationPivot) || nz(modelData.scalingPivot) || nz(modelData.rotationOffset) || nz(modelData.scalingOffset)) {\n            // Pivots and offsets only move the translation: the linear part of the FBX local matrix is always S·R.\n            position = FBXFileLoader._computeFBXLocalMatrix(\n                translation,\n                rotation,\n                scale,\n                modelData.preRotation,\n                modelData.postRotation,\n                modelData.rotationPivot,\n                modelData.scalingPivot,\n                modelData.rotationOffset,\n                modelData.scalingOffset,\n                modelData.rotationOrder\n            ).getTranslation();\n        }\n        return {\n            position,\n            rotationQuaternion: Quaternion.FromRotationMatrix(rotM),\n            scaling: new Vector3(scale[0], scale[1], scale[2]),\n        };\n    }\n\n    /** Applies inherit-mode adjustments to a local TRS (see _computeInheritAwareLocalMatrix). */\n    private _adjustTRSForInheritMode(modelData: FBXModelData, trs: { position: Vector3; rotationQuaternion: Quaternion; scaling: Vector3 }, time: number | undefined): void {\n        const parent = this._parentModelById.get(modelData.id);\n        if (modelData.inheritType === 1 || !parent) {\n            return;\n        }\n        const parentScale = this._getInheritScale(parent, time);\n        trs.position.x *= parentScale[0];\n        trs.position.y *= parentScale[1];\n        trs.position.z *= parentScale[2];\n        const inheritNode = this._getInheritScaleNode(modelData);\n        if (inheritNode) {\n            const inherited = this._getInheritScale(inheritNode, time);\n            trs.scaling.x *= inherited[0];\n            trs.scaling.y *= inherited[1];\n            trs.scaling.z *= inherited[2];\n        }\n    }\n\n    private _sampleModelLocalMatrix(modelData: FBXModelData, curveNodes: FBXCurveNodeData[], time: number, scaleOverride?: [number, number, number]): Matrix {\n        const trs = this._sampleModelTRS(modelData, curveNodes, time);\n        return FBXFileLoader._computeFBXLocalMatrix(\n            trs.translation,\n            trs.rotation,\n            scaleOverride ?? trs.scale,\n            modelData.preRotation,\n            modelData.postRotation,\n            modelData.rotationPivot,\n            modelData.scalingPivot,\n            modelData.rotationOffset,\n            modelData.scalingOffset,\n            modelData.rotationOrder\n        );\n    }\n\n    private _sampleModelScale(modelData: FBXModelData, curveNodes: FBXCurveNodeData[], time: number): [number, number, number] {\n        return evaluateLayeredChannel(curveNodes, this._activeLayers, \"S\", modelData.scale, modelData.rotationOrder, time);\n    }\n\n    /**\n     * Effective scale of a model for inherit-mode math (`inherit_scale` in ufbx terms): its own local scale, multiplied\n     * componentwise by the inherited scale when the model uses RrSs inheritance. `time` samples animation; undefined\n     * uses the rest pose.\n     */\n    private _getInheritScale(modelData: FBXModelData | undefined, time: number | undefined): [number, number, number] {\n        if (!modelData) {\n            return [1, 1, 1];\n        }\n        const own = time === undefined ? modelData.scale : this._sampleModelScale(modelData, this._curveNodesByModelId.get(modelData.id) ?? [], time);\n        const inheritNode = this._getInheritScaleNode(modelData);\n        if (!inheritNode) {\n            return [own[0], own[1], own[2]];\n        }\n        const parentScale = this._getInheritScale(inheritNode, time);\n        return [own[0] * parentScale[0], own[1] * parentScale[1], own[2] * parentScale[2]];\n    }\n\n    /** RrSs nodes inherit scale from their parent; Rrs nodes skip their immediate parent (chaining through Rrs parents). */\n    private _getInheritScaleNode(modelData: FBXModelData): FBXModelData | undefined {\n        const parent = this._parentModelById.get(modelData.id);\n        if (!parent) {\n            return undefined;\n        }\n        if (modelData.inheritType === 0) {\n            return parent;\n        }\n        if (modelData.inheritType === 2) {\n            return this._getInheritScaleNode(parent);\n        }\n        return undefined;\n    }\n\n    /**\n     * Local matrix of a model relative to its Babylon parent frame, accounting for inherit modes. For RSrs (the\n     * default) this is the FBX local matrix. For RrSs / Rrs the node sits under a helper that removes the parent's\n     * scale, so translation is pre-scaled by the parent scale and (for RrSs) scale accumulates componentwise.\n     */\n    private _computeInheritAwareLocalMatrix(modelData: FBXModelData, localMatrix: Matrix, time: number | undefined): Matrix {\n        const parent = this._parentModelById.get(modelData.id);\n        if (modelData.inheritType === 1 || !parent) {\n            return localMatrix;\n        }\n        const s = new Vector3();\n        const r = new Quaternion();\n        const t = new Vector3();\n        localMatrix.decompose(s, r, t);\n        const parentScale = this._getInheritScale(parent, time);\n        t.x *= parentScale[0];\n        t.y *= parentScale[1];\n        t.z *= parentScale[2];\n        const inheritNode = this._getInheritScaleNode(modelData);\n        if (inheritNode) {\n            const inherited = this._getInheritScale(inheritNode, time);\n            s.x *= inherited[0];\n            s.y *= inherited[1];\n            s.z *= inherited[2];\n        }\n        return Matrix.Compose(s, r, t);\n    }\n\n    /**\n     * Build matrix-baked bone animation from full FBX local transforms.\n     * The bind matrix carries the skinning offset, so animation curves drive\n     * the same FBX local transform chain as the source skeleton.\n     */\n    private _buildBoneAnimations(\n        curveNodes: FBXCurveNodeData[],\n        boneName: string,\n        modelData: FBXModelData,\n        startTime: number,\n        stopTime: number,\n        bindLocalMatrix?: Matrix\n    ): Animation[] {\n        const fps = this._frameRate;\n\n        const rNode = curveNodes.find((cn) => cn.type === \"R\");\n\n        const baseTimes = collectAnimationSampleTimes(curveNodes, fps, startTime, stopTime);\n        if (baseTimes.length === 0) {\n            return [];\n        }\n        const times = FBXFileLoader._refineSampleTimes(baseTimes, (time) => this._sampleModelLocalMatrix(modelData, curveNodes, time));\n\n        const posKeys: { frame: number; value: Vector3 }[] = [];\n        const rotKeys: { frame: number; value: Quaternion }[] = [];\n        const sclKeys: { frame: number; value: Vector3 }[] = [];\n        let prevQuat: Quaternion | null = null;\n        let restLocalInverse: Matrix | null = null;\n        if (bindLocalMatrix) {\n            const restLocalMatrix = FBXFileLoader._computeFBXLocalMatrix(\n                modelData.translation,\n                modelData.rotation,\n                modelData.scale,\n                modelData.preRotation,\n                modelData.postRotation,\n                modelData.rotationPivot,\n                modelData.scalingPivot,\n                modelData.rotationOffset,\n                modelData.scalingOffset,\n                modelData.rotationOrder\n            );\n            restLocalInverse = new Matrix();\n            restLocalMatrix.invertToRef(restLocalInverse);\n        }\n\n        for (const time of times) {\n            const frame = time * fps;\n\n            // Compute the full FBX local matrix from animated Lcl values, blending all layers\n            const localMatrix = this._sampleModelLocalMatrix(modelData, curveNodes, time);\n\n            const correctedLocalMatrix = restLocalInverse && bindLocalMatrix ? bindLocalMatrix.multiply(restLocalInverse).multiply(localMatrix) : localMatrix;\n\n            const s = new Vector3();\n            const r = new Quaternion();\n            const t = new Vector3();\n            correctedLocalMatrix.decompose(s, r, t);\n\n            if (prevQuat && Quaternion.Dot(prevQuat, r) < 0) {\n                r.scaleInPlace(-1);\n            }\n            prevQuat = r;\n\n            posKeys.push({ frame, value: t });\n            rotKeys.push({ frame, value: r });\n            sclKeys.push({ frame, value: s });\n        }\n\n        const animations: Animation[] = [];\n\n        if (!this._isVector3KeysConstant(posKeys)) {\n            const posAnim = new Animation(`${boneName}_position`, \"position\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n            posAnim.setKeys(posKeys);\n            animations.push(posAnim);\n        }\n\n        if (rNode) {\n            const rotAnim = new Animation(`${boneName}_rotation`, \"rotationQuaternion\", fps, Animation.ANIMATIONTYPE_QUATERNION, Animation.ANIMATIONLOOPMODE_CYCLE);\n            rotAnim.setKeys(rotKeys);\n            animations.push(rotAnim);\n        }\n\n        if (!this._isVector3KeysConstant(sclKeys)) {\n            const sclAnim = new Animation(`${boneName}_scaling`, \"scaling\", fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CYCLE);\n            sclAnim.setKeys(sclKeys);\n            animations.push(sclAnim);\n        }\n\n        return animations;\n    }\n\n    private _buildNameFilter(meshesNames: string | readonly string[] | null | undefined): ((name: string) => boolean) | null {\n        if (!meshesNames) {\n            return null;\n        }\n        if (typeof meshesNames === \"string\") {\n            if (meshesNames === \"\") {\n                return null;\n            }\n            return (name: string) => name === meshesNames;\n        }\n        if (meshesNames.length === 0) {\n            return null;\n        }\n        const nameSet = new Set(meshesNames);\n        return (name: string) => nameSet.has(name);\n    }\n}\n\nfunction float64To32(arr: Float64Array): Float32Array {\n    const result = new Float32Array(arr.length);\n    for (let i = 0; i < arr.length; i++) {\n        result[i] = arr[i];\n    }\n    return result;\n}\n\nfunction applyTangentHandednessScale(tangents: Float32Array, scale: 1 | -1): void {\n    if (scale === 1) {\n        return;\n    }\n    for (let i = 3; i < tangents.length; i += 4) {\n        tangents[i] *= scale;\n    }\n}\n\nfunction generateTangents(\n    positions: ArrayLike<number>,\n    normals: ArrayLike<number>,\n    uvs: ArrayLike<number>,\n    indices: ArrayLike<number>,\n    normalMapTangentHandednessScale: 1 | -1 = 1,\n    controlPointIndices: ArrayLike<number> | null = null,\n    materialIndices: ArrayLike<number> | null = null\n): Float32Array {\n    const vertexCount = positions.length / 3;\n    const groups = new Map<string, TangentGroup>();\n    const vertexGroupKeys = new Array<string | null>(vertexCount).fill(null);\n\n    for (let i = 0; i + 2 < indices.length; i += 3) {\n        const materialIndex = materialIndices ? materialIndices[i / 3] : 0;\n        const i1 = indices[i];\n        const i2 = indices[i + 1];\n        const i3 = indices[i + 2];\n\n        const p1 = i1 * 3;\n        const p2 = i2 * 3;\n        const p3 = i3 * 3;\n        const uv1 = i1 * 2;\n        const uv2 = i2 * 2;\n        const uv3 = i3 * 2;\n\n        const x1 = positions[p2] - positions[p1];\n        const x2 = positions[p3] - positions[p1];\n        const y1 = positions[p2 + 1] - positions[p1 + 1];\n        const y2 = positions[p3 + 1] - positions[p1 + 1];\n        const z1 = positions[p2 + 2] - positions[p1 + 2];\n        const z2 = positions[p3 + 2] - positions[p1 + 2];\n\n        const s1 = uvs[uv2] - uvs[uv1];\n        const s2 = uvs[uv3] - uvs[uv1];\n        const t1 = uvs[uv2 + 1] - uvs[uv1 + 1];\n        const t2 = uvs[uv3 + 1] - uvs[uv1 + 1];\n        const denominator = s1 * t2 - s2 * t1;\n        if (Math.abs(denominator) < 1e-8) {\n            continue;\n        }\n\n        const r = 1 / denominator;\n        const sx = (t2 * x1 - t1 * x2) * r;\n        const sy = (t2 * y1 - t1 * y2) * r;\n        const sz = (t2 * z1 - t1 * z2) * r;\n        const bx = (s1 * x2 - s2 * x1) * r;\n        const by = (s1 * y2 - s2 * y1) * r;\n        const bz = (s1 * z2 - s2 * z1) * r;\n\n        accumulateTangentContribution(i1, i2, i3, sx, sy, sz, bx, by, bz, positions, normals, uvs, controlPointIndices, materialIndex, groups, vertexGroupKeys);\n        accumulateTangentContribution(i2, i3, i1, sx, sy, sz, bx, by, bz, positions, normals, uvs, controlPointIndices, materialIndex, groups, vertexGroupKeys);\n        accumulateTangentContribution(i3, i1, i2, sx, sy, sz, bx, by, bz, positions, normals, uvs, controlPointIndices, materialIndex, groups, vertexGroupKeys);\n    }\n\n    const tangents = new Float32Array(vertexCount * 4);\n    for (let i = 0; i < vertexCount; i++) {\n        const no = i * 3;\n        const to = i * 4;\n        const [nx, ny, nz] = normalizeVector(normals[no], normals[no + 1], normals[no + 2]);\n        const group = vertexGroupKeys[i] ? groups.get(vertexGroupKeys[i]!) : undefined;\n        const tx = group?.tx ?? 0;\n        const ty = group?.ty ?? 0;\n        const tz = group?.tz ?? 0;\n        const normalDotTangent = nx * tx + ny * ty + nz * tz;\n\n        let ox = tx - nx * normalDotTangent;\n        let oy = ty - ny * normalDotTangent;\n        let oz = tz - nz * normalDotTangent;\n        const tangentLength = Math.hypot(ox, oy, oz);\n        if (tangentLength > 1e-8) {\n            ox /= tangentLength;\n            oy /= tangentLength;\n            oz /= tangentLength;\n        } else {\n            [ox, oy, oz] = buildFallbackTangent(nx, ny, nz);\n        }\n\n        const bx = group?.bx ?? 0;\n        const by = group?.by ?? 0;\n        const bz = group?.bz ?? 0;\n        const cx = ny * oz - nz * oy;\n        const cy = nz * ox - nx * oz;\n        const cz = nx * oy - ny * ox;\n        const bitangentLength = Math.hypot(bx, by, bz);\n        const handedness = bitangentLength > 1e-8 && cx * bx + cy * by + cz * bz < 0 ? -1 : 1;\n\n        tangents[to] = ox;\n        tangents[to + 1] = oy;\n        tangents[to + 2] = oz;\n        tangents[to + 3] = handedness * normalMapTangentHandednessScale;\n    }\n\n    return tangents;\n}\n\ninterface TangentGroup {\n    tx: number;\n    ty: number;\n    tz: number;\n    bx: number;\n    by: number;\n    bz: number;\n}\n\nfunction accumulateTangentContribution(\n    vertexIndex: number,\n    nextIndex: number,\n    prevIndex: number,\n    tx: number,\n    ty: number,\n    tz: number,\n    bx: number,\n    by: number,\n    bz: number,\n    positions: ArrayLike<number>,\n    normals: ArrayLike<number>,\n    uvs: ArrayLike<number>,\n    controlPointIndices: ArrayLike<number> | null,\n    materialIndex: number,\n    groups: Map<string, TangentGroup>,\n    vertexGroupKeys: Array<string | null>\n): void {\n    const weight = computeCornerAngle(positions, vertexIndex, nextIndex, prevIndex);\n    if (weight <= 1e-8) {\n        return;\n    }\n\n    const key = buildTangentGroupKey(vertexIndex, tx, ty, tz, bx, by, bz, positions, normals, uvs, controlPointIndices, materialIndex);\n    let group = groups.get(key);\n    if (!group) {\n        group = { tx: 0, ty: 0, tz: 0, bx: 0, by: 0, bz: 0 };\n        groups.set(key, group);\n    }\n\n    group.tx += tx * weight;\n    group.ty += ty * weight;\n    group.tz += tz * weight;\n    group.bx += bx * weight;\n    group.by += by * weight;\n    group.bz += bz * weight;\n    vertexGroupKeys[vertexIndex] ??= key;\n}\n\nfunction buildTangentGroupKey(\n    vertexIndex: number,\n    tx: number,\n    ty: number,\n    tz: number,\n    bx: number,\n    by: number,\n    bz: number,\n    positions: ArrayLike<number>,\n    normals: ArrayLike<number>,\n    uvs: ArrayLike<number>,\n    controlPointIndices: ArrayLike<number> | null,\n    materialIndex: number\n): string {\n    const po = vertexIndex * 3;\n    const no = vertexIndex * 3;\n    const uo = vertexIndex * 2;\n    const [nx, ny, nz] = normalizeVector(normals[no], normals[no + 1], normals[no + 2]);\n    const handedness = computeTangentHandedness(nx, ny, nz, tx, ty, tz, bx, by, bz);\n    const positionKey = controlPointIndices\n        ? `cp:${controlPointIndices[vertexIndex]}`\n        : `p:${quantizeTangentKey(positions[po])},${quantizeTangentKey(positions[po + 1])},${quantizeTangentKey(positions[po + 2])}`;\n    return [\n        positionKey,\n        quantizeTangentKey(nx),\n        quantizeTangentKey(ny),\n        quantizeTangentKey(nz),\n        quantizeTangentKey(uvs[uo]),\n        quantizeTangentKey(uvs[uo + 1]),\n        handedness,\n        materialIndex,\n    ].join(\"|\");\n}\n\nfunction computeTangentHandedness(nx: number, ny: number, nz: number, tx: number, ty: number, tz: number, bx: number, by: number, bz: number): 1 | -1 {\n    const cx = ny * tz - nz * ty;\n    const cy = nz * tx - nx * tz;\n    const cz = nx * ty - ny * tx;\n    return cx * bx + cy * by + cz * bz < 0 ? -1 : 1;\n}\n\nfunction computeCornerAngle(positions: ArrayLike<number>, vertexIndex: number, nextIndex: number, prevIndex: number): number {\n    const vo = vertexIndex * 3;\n    const no = nextIndex * 3;\n    const po = prevIndex * 3;\n    const ax = positions[no] - positions[vo];\n    const ay = positions[no + 1] - positions[vo + 1];\n    const az = positions[no + 2] - positions[vo + 2];\n    const bx = positions[po] - positions[vo];\n    const by = positions[po + 1] - positions[vo + 1];\n    const bz = positions[po + 2] - positions[vo + 2];\n    const aLength = Math.hypot(ax, ay, az);\n    const bLength = Math.hypot(bx, by, bz);\n    if (aLength <= 1e-8 || bLength <= 1e-8) {\n        return 0;\n    }\n    const dot = (ax * bx + ay * by + az * bz) / (aLength * bLength);\n    return Math.acos(Math.max(-1, Math.min(1, dot)));\n}\n\nfunction normalizeVector(x: number, y: number, z: number): [number, number, number] {\n    const length = Math.hypot(x, y, z);\n    return length > 1e-8 ? [x / length, y / length, z / length] : [0, 0, 1];\n}\n\nfunction quantizeTangentKey(value: number): number {\n    const quantized = Math.round(value * 1e6);\n    return Object.is(quantized, -0) ? 0 : quantized;\n}\n\nfunction buildFallbackTangent(nx: number, ny: number, nz: number): [number, number, number] {\n    const ax = Math.abs(nx) < 0.9 ? 1 : 0;\n    const ay = ax === 1 ? 0 : 1;\n    const dot = nx * ax + ny * ay;\n    let tx = ax - nx * dot;\n    let ty = ay - ny * dot;\n    let tz = -nz * dot;\n    const length = Math.hypot(tx, ty, tz);\n    if (length <= 1e-8) {\n        return [1, 0, 0];\n    }\n    tx /= length;\n    ty /= length;\n    tz /= length;\n    return [tx, ty, tz];\n}\n\nfunction buildMorphTargetData(\n    shape: FBXShapeData,\n    cpIndices: Uint32Array,\n    basePositions: FloatArray,\n    baseNormals: FloatArray | null,\n    deltaMatrix: Matrix | null,\n    normalMatrix: Matrix | null\n): { positions: Float32Array; normals: Float32Array | null } | null {\n    const vertexCount = basePositions.length / 3;\n    const targetPositions = new Float32Array(vertexCount * 3);\n    const hasNormals = shape.normals !== null && baseNormals !== null;\n    const targetNormals = hasNormals ? new Float32Array(vertexCount * 3) : null;\n\n    for (let i = 0; i < targetPositions.length; i++) {\n        targetPositions[i] = basePositions[i];\n    }\n    if (targetNormals && baseNormals) {\n        for (let i = 0; i < targetNormals.length; i++) {\n            targetNormals[i] = baseNormals[i];\n        }\n    }\n\n    const cpToShapeIdx = new Map<number, number>();\n    for (let i = 0; i < shape.indices.length; i++) {\n        cpToShapeIdx.set(shape.indices[i], i);\n    }\n\n    for (let vi = 0; vi < vertexCount; vi++) {\n        const cpIdx = cpIndices[vi];\n        const shapeIdx = cpToShapeIdx.get(cpIdx);\n        if (shapeIdx === undefined) {\n            continue;\n        }\n\n        let dx = shape.vertices[shapeIdx * 3];\n        let dy = shape.vertices[shapeIdx * 3 + 1];\n        let dz = shape.vertices[shapeIdx * 3 + 2];\n\n        if (deltaMatrix) {\n            const rv = Vector3.TransformNormal(new Vector3(dx, dy, dz), deltaMatrix);\n            dx = rv.x;\n            dy = rv.y;\n            dz = rv.z;\n        }\n\n        targetPositions[vi * 3] += dx;\n        targetPositions[vi * 3 + 1] += dy;\n        targetPositions[vi * 3 + 2] += dz;\n\n        if (targetNormals && shape.normals) {\n            let nx = shape.normals[shapeIdx * 3];\n            let ny = shape.normals[shapeIdx * 3 + 1];\n            let nz = shape.normals[shapeIdx * 3 + 2];\n            if (normalMatrix) {\n                const rn = Vector3.TransformNormal(new Vector3(nx, ny, nz), normalMatrix);\n                if (rn.lengthSquared() > 0) {\n                    rn.normalize();\n                }\n                nx = rn.x;\n                ny = rn.y;\n                nz = rn.z;\n            }\n            targetNormals[vi * 3] += nx;\n            targetNormals[vi * 3 + 1] += ny;\n            targetNormals[vi * 3 + 2] += nz;\n        }\n    }\n\n    return { positions: targetPositions, normals: targetNormals };\n}\n\nfunction calculateBlendShapeInfluences(deformPercent: number, fullWeights: number[] | null, shapeCount: number): number[] {\n    if (shapeCount <= 0) {\n        return [];\n    }\n    if (!fullWeights || fullWeights.length !== shapeCount || shapeCount === 1) {\n        const denominator = fullWeights?.[0] && fullWeights[0] !== 0 ? fullWeights[0] : 100;\n        return [clamp01(deformPercent / denominator)];\n    }\n\n    const influences = new Array<number>(shapeCount).fill(0);\n    if (deformPercent <= fullWeights[0]) {\n        influences[0] = fullWeights[0] === 0 ? (deformPercent <= 0 ? 1 : 0) : clamp01(deformPercent / fullWeights[0]);\n        return influences;\n    }\n\n    for (let i = 1; i < fullWeights.length; i++) {\n        const previousWeight = fullWeights[i - 1];\n        const nextWeight = fullWeights[i];\n        if (deformPercent > nextWeight) {\n            continue;\n        }\n\n        const range = nextWeight - previousWeight;\n        if (Math.abs(range) < 1e-6) {\n            influences[i] = 1;\n            return influences;\n        }\n\n        const t = clamp01((deformPercent - previousWeight) / range);\n        influences[i - 1] = 1 - t;\n        influences[i] = t;\n        return influences;\n    }\n\n    influences[shapeCount - 1] = 1;\n    return influences;\n}\n\nfunction clamp01(value: number): number {\n    return Math.max(0, Math.min(1, value));\n}\n\n/** Interior frames kept between two keys when the segment is cubic or extrapolated. */\nconst MAX_DENSE_SEGMENT_SAMPLES = 512;\n/** Interior frames kept between two keys when every curve is linear or constant there. */\nconst MAX_LINEAR_SEGMENT_SAMPLES = 32;\n/** Upper bound on samples per animated node, beyond which the frame stride grows. */\nconst MAX_SAMPLES_PER_TARGET = 100000;\n\n/**\n * Times at which the animation is baked: every key time plus the frame grid between keys. Segments where every\n * curve is linear or constant only get a few interior frames (Babylon interpolates linearly between the baked\n * keys), cubic or extrapolated segments get the full frame grid up to a cap, so day-long clips with a handful of\n * keys do not explode into millions of samples.\n */\nfunction collectAnimationSampleTimes(curveNodes: FBXCurveNodeData[], fps: number, startTime: number, stopTime: number): number[] {\n    let minTime = Number.POSITIVE_INFINITY;\n    let maxTime = Number.NEGATIVE_INFINITY;\n    const anchorSet = new Set<number>();\n    const curves: FBXCurveData[] = [];\n\n    for (const curveNode of curveNodes) {\n        for (const curve of curveNode.curves) {\n            curves.push(curve);\n            for (const key of curve.keys) {\n                minTime = Math.min(minTime, key.time);\n                maxTime = Math.max(maxTime, key.time);\n                if (key.time >= startTime && key.time <= stopTime) {\n                    anchorSet.add(key.time);\n                }\n            }\n        }\n    }\n\n    if (!Number.isFinite(minTime) || !Number.isFinite(maxTime)) {\n        return [];\n    }\n\n    const rangeStart = stopTime > startTime ? startTime : minTime;\n    const rangeStop = stopTime > startTime ? stopTime : maxTime;\n    anchorSet.add(rangeStart);\n    anchorSet.add(rangeStop);\n    const anchors = Array.from(anchorSet)\n        .filter((t) => t >= rangeStart && t <= rangeStop)\n        .sort((a, b) => a - b);\n\n    // A segment needs the dense grid when any curve is cubic there or extrapolates a non-constant pattern.\n    const segmentIsDense = (t0: number): boolean => {\n        for (const curve of curves) {\n            const keys = curve.keys;\n            if (keys.length === 0) {\n                continue;\n            }\n            if (t0 < keys[0].time) {\n                if (curve.preExtrapolation && curve.preExtrapolation.mode !== \"constant\") {\n                    return true;\n                }\n                continue;\n            }\n            if (t0 >= keys[keys.length - 1].time) {\n                if (curve.postExtrapolation && curve.postExtrapolation.mode !== \"constant\") {\n                    return true;\n                }\n                continue;\n            }\n            let lo = 0;\n            let hi = keys.length - 1;\n            while (hi - lo > 1) {\n                const mid = (lo + hi) >> 1;\n                if (keys[mid].time <= t0) {\n                    lo = mid;\n                } else {\n                    hi = mid;\n                }\n            }\n            if (keys[lo].interpolation === \"cubic\") {\n                return true;\n            }\n        }\n        return false;\n    };\n\n    const times: number[] = [];\n    const totalFrames = Math.floor(rangeStop * fps) - Math.ceil(rangeStart * fps) + 1;\n    const stride = Math.max(1, Math.ceil(totalFrames / MAX_SAMPLES_PER_TARGET));\n    for (let i = 0; i < anchors.length; i++) {\n        const t0 = anchors[i];\n        times.push(t0);\n        if (i + 1 >= anchors.length) {\n            break;\n        }\n        const t1 = anchors[i + 1];\n        const firstFrame = Math.floor(t0 * fps) + 1;\n        const lastFrame = Math.ceil(t1 * fps) - 1;\n        const interior = lastFrame - firstFrame + 1;\n        if (interior <= 0) {\n            continue;\n        }\n        const cap = segmentIsDense(t0) ? MAX_DENSE_SEGMENT_SAMPLES : MAX_LINEAR_SEGMENT_SAMPLES;\n        const step = Math.max(stride, Math.ceil(interior / cap));\n        for (let frame = firstFrame; frame <= lastFrame; frame += step) {\n            times.push(frame / fps);\n        }\n    }\n\n    const sorted = times.sort((a, b) => a - b);\n    // Key times and frame times can differ by floating point noise; keep one sample per instant.\n    const deduped: number[] = [];\n    for (const t of sorted) {\n        if (t < rangeStart - 1e-9 || t > rangeStop + 1e-9) {\n            continue;\n        }\n        if (deduped.length === 0 || t - deduped[deduped.length - 1] > 1e-9) {\n            deduped.push(t);\n        }\n    }\n    return deduped;\n}\n\nfunction areQuaternionKeysConstant(keys: { frame: number; value: Quaternion }[]): boolean {\n    if (keys.length < 2) {\n        return true;\n    }\n    const first = keys[0].value;\n    for (let i = 1; i < keys.length; i++) {\n        const value = keys[i].value;\n        if (Math.abs(value.x - first.x) > 0.0001 || Math.abs(value.y - first.y) > 0.0001 || Math.abs(value.z - first.z) > 0.0001 || Math.abs(value.w - first.w) > 0.0001) {\n            return false;\n        }\n    }\n    return true;\n}\n\nfunction buildScalarAnimationKeys(curve: FBXCurveData, fps: number, startTime: number, stopTime: number, mapValue: (value: number) => number): IAnimationKey[] {\n    const range = getCurveSampleRange(curve, startTime, stopTime);\n    const keys = curve.keys\n        .filter((key) => key.time >= range.start && key.time <= range.stop)\n        .map((key) => ({\n            source: key,\n            frame: key.time * fps,\n            value: mapValue(key.value),\n        }));\n\n    if (!keys.some((key) => Math.abs(key.source.time - range.start) < 1e-6)) {\n        keys.unshift({\n            source: {\n                time: range.start,\n                value: sampleFBXCurveAtTime(curve, range.start) ?? 0,\n                interpolation: \"linear\",\n                leftDx: 0,\n                leftDy: 0,\n                rightDx: 0,\n                rightDy: 0,\n            },\n            frame: range.start * fps,\n            value: mapValue(sampleFBXCurveAtTime(curve, range.start) ?? 0),\n        });\n    }\n\n    if (!keys.some((key) => Math.abs(key.source.time - range.stop) < 1e-6)) {\n        keys.push({\n            source: {\n                time: range.stop,\n                value: sampleFBXCurveAtTime(curve, range.stop) ?? 0,\n                interpolation: \"linear\",\n                leftDx: 0,\n                leftDy: 0,\n                rightDx: 0,\n                rightDy: 0,\n            },\n            frame: range.stop * fps,\n            value: mapValue(sampleFBXCurveAtTime(curve, range.stop) ?? 0),\n        });\n    }\n\n    const animationKeys: IAnimationKey[] = keys.map((key) => ({\n        frame: key.frame,\n        value: key.value,\n    }));\n\n    for (let i = 0; i < keys.length - 1; i++) {\n        const key = keys[i].source;\n        const nextAnimationKey = animationKeys[i + 1];\n\n        if (key.interpolation === \"constant\") {\n            animationKeys[i].interpolation = AnimationKeyInterpolation.STEP;\n            continue;\n        }\n\n        if (key.interpolation !== \"cubic\") {\n            continue;\n        }\n\n        const nextKey = keys[i + 1].source;\n        const duration = Math.max(nextKey.time - key.time, 1e-6);\n        const linearSlope = (nextKey.value - key.value) / duration;\n        animationKeys[i].outTangent = mapSlope(key.rightSlope ?? linearSlope, mapValue) / fps;\n        nextAnimationKey.inTangent = mapSlope(key.nextLeftSlope ?? linearSlope, mapValue) / fps;\n    }\n\n    return animationKeys;\n}\n\nfunction mapSlope(slope: number, mapValue: (value: number) => number): number {\n    return mapValue(slope) - mapValue(0);\n}\n\nfunction getCurveSampleRange(curve: FBXCurveData, startTime: number, stopTime: number): { start: number; stop: number } {\n    if (stopTime > startTime) {\n        return { start: startTime, stop: stopTime };\n    }\n\n    return {\n        start: curve.keys[0]?.time ?? 0,\n        stop: curve.keys[curve.keys.length - 1]?.time ?? 0,\n    };\n}\n\nlet _Registered = false;\n/**\n * Registers the FBXFileLoader scene loader plugin.\n * Safe to call multiple times; only the first call has an effect.\n */\nexport function RegisterFBXFileLoader(): void {\n    if (_Registered) {\n        return;\n    }\n    _Registered = true;\n\n    RegisterSceneLoaderPlugin(new FBXFileLoader());\n}\n","/* eslint-disable github/no-then */\r\n/* eslint-disable no-restricted-syntax */\r\n/* eslint-disable @typescript-eslint/promise-function-async */\r\nimport type * as GLTF2 from \"babylonjs-gltf2interface\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\n\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\ndeclare let GLTFValidator: GLTF2.IGLTFValidator;\r\n\r\n// WorkerGlobalScope\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\ndeclare function importScripts(...urls: string[]): void;\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\ndeclare function postMessage(message: any, transfer?: any[]): void;\r\n\r\nfunction ValidateAsync(\r\n    data: string | Uint8Array,\r\n    rootUrl: string,\r\n    fileName: string,\r\n    getExternalResource: (uri: string) => Promise<Uint8Array>\r\n): Promise<GLTF2.IGLTFValidationResults> {\r\n    const options: GLTF2.IGLTFValidationOptions = {\r\n        externalResourceFunction: getExternalResource,\r\n    };\r\n\r\n    if (fileName) {\r\n        options.uri = rootUrl === \"file:\" ? fileName : rootUrl + fileName;\r\n    }\r\n\r\n    return ArrayBuffer.isView(data) ? GLTFValidator.validateBytes(data, options) : GLTFValidator.validateString(data, options);\r\n}\r\n\r\n/**\r\n * The worker function that gets converted to a blob url to pass into a worker.\r\n */\r\nfunction WorkerFunc(): void {\r\n    const pendingExternalResources: Array<{ resolve: (data: any) => void; reject: (reason: any) => void }> = [];\r\n\r\n    onmessage = (message) => {\r\n        const data = message.data;\r\n        switch (data.id) {\r\n            case \"init\": {\r\n                importScripts(data.url);\r\n                break;\r\n            }\r\n            case \"validate\": {\r\n                ValidateAsync(\r\n                    data.data,\r\n                    data.rootUrl,\r\n                    data.fileName,\r\n                    (uri) =>\r\n                        new Promise((resolve, reject) => {\r\n                            const index = pendingExternalResources.length;\r\n                            pendingExternalResources.push({ resolve, reject });\r\n                            postMessage({ id: \"getExternalResource\", index: index, uri: uri });\r\n                        })\r\n                ).then(\r\n                    (value) => {\r\n                        postMessage({ id: \"validate.resolve\", value: value });\r\n                    },\r\n                    (reason) => {\r\n                        postMessage({ id: \"validate.reject\", reason: reason });\r\n                    }\r\n                );\r\n                break;\r\n            }\r\n            case \"getExternalResource.resolve\": {\r\n                pendingExternalResources[data.index].resolve(data.value);\r\n                break;\r\n            }\r\n            case \"getExternalResource.reject\": {\r\n                pendingExternalResources[data.index].reject(data.reason);\r\n                break;\r\n            }\r\n        }\r\n    };\r\n}\r\n\r\n/**\r\n * Configuration for glTF validation\r\n */\r\nexport interface IGLTFValidationConfiguration {\r\n    /**\r\n     * The url of the glTF validator.\r\n     */\r\n    url: string;\r\n}\r\n\r\n/**\r\n * glTF validation\r\n */\r\nexport class GLTFValidation {\r\n    /**\r\n     * The configuration. Defaults to `{ url: \"https://cdn.babylonjs.com/gltf_validator.js\" }`.\r\n     */\r\n    public static Configuration: IGLTFValidationConfiguration = {\r\n        url: `${Tools._DefaultCdnUrl}/gltf_validator.js`,\r\n    };\r\n\r\n    private static _LoadScriptPromise: Promise<void>;\r\n\r\n    /**\r\n     * The most recent validation results.\r\n     * @internal - Used for back-compat in Sandbox with Inspector V2.\r\n     */\r\n    public static _LastResults: Nullable<GLTF2.IGLTFValidationResults> = null;\r\n\r\n    /**\r\n     * Validate a glTF asset using the glTF-Validator.\r\n     * @param data The JSON of a glTF or the array buffer of a binary glTF\r\n     * @param rootUrl The root url for the glTF\r\n     * @param fileName The file name for the glTF\r\n     * @param getExternalResource The callback to get external resources for the glTF validator\r\n     * @returns A promise that resolves with the glTF validation results once complete\r\n     */\r\n    public static ValidateAsync(\r\n        data: string | Uint8Array,\r\n        rootUrl: string,\r\n        fileName: string,\r\n        getExternalResource: (uri: string) => Promise<Uint8Array>\r\n    ): Promise<GLTF2.IGLTFValidationResults> {\r\n        if (typeof Worker === \"function\") {\r\n            return new Promise((resolve, reject) => {\r\n                const workerContent = `${ValidateAsync}(${WorkerFunc})()`;\r\n                const workerBlobUrl = URL.createObjectURL(new Blob([workerContent], { type: \"application/javascript\" }));\r\n                const worker = new Worker(workerBlobUrl);\r\n\r\n                const onError = (error: ErrorEvent) => {\r\n                    worker.removeEventListener(\"error\", onError);\r\n                    worker.removeEventListener(\"message\", onMessage);\r\n                    // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n                    reject(error);\r\n                };\r\n\r\n                const onMessage = (message: MessageEvent) => {\r\n                    const data = message.data;\r\n                    switch (data.id) {\r\n                        case \"getExternalResource\": {\r\n                            getExternalResource(data.uri).then(\r\n                                (value) => {\r\n                                    worker.postMessage({ id: \"getExternalResource.resolve\", index: data.index, value: value }, [value.buffer]);\r\n                                },\r\n                                (reason) => {\r\n                                    worker.postMessage({ id: \"getExternalResource.reject\", index: data.index, reason: reason });\r\n                                }\r\n                            );\r\n                            break;\r\n                        }\r\n                        case \"validate.resolve\": {\r\n                            worker.removeEventListener(\"error\", onError);\r\n                            worker.removeEventListener(\"message\", onMessage);\r\n                            GLTFValidation._LastResults = data.value;\r\n                            resolve(data.value);\r\n                            worker.terminate();\r\n                            break;\r\n                        }\r\n                        case \"validate.reject\": {\r\n                            worker.removeEventListener(\"error\", onError);\r\n                            worker.removeEventListener(\"message\", onMessage);\r\n                            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n                            reject(data.reason);\r\n                            worker.terminate();\r\n                        }\r\n                    }\r\n                };\r\n\r\n                worker.addEventListener(\"error\", onError);\r\n                worker.addEventListener(\"message\", onMessage);\r\n\r\n                worker.postMessage({ id: \"init\", url: Tools.GetBabylonScriptURL(this.Configuration.url) });\r\n\r\n                if (ArrayBuffer.isView(data)) {\r\n                    // Slice the data to avoid copying the whole array buffer.\r\n                    const slicedData = data.slice();\r\n                    worker.postMessage({ id: \"validate\", data: slicedData, rootUrl: rootUrl, fileName: fileName }, [slicedData.buffer]);\r\n                } else {\r\n                    worker.postMessage({ id: \"validate\", data: data, rootUrl: rootUrl, fileName: fileName });\r\n                }\r\n            });\r\n        } else {\r\n            if (!this._LoadScriptPromise) {\r\n                this._LoadScriptPromise = Tools.LoadBabylonScriptAsync(this.Configuration.url);\r\n            }\r\n\r\n            return this._LoadScriptPromise.then(() => {\r\n                return ValidateAsync(data, rootUrl, fileName, getExternalResource);\r\n            });\r\n        }\r\n    }\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./fbxFileLoader.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./fbxFileLoader.types\";\r\nexport * from \"./fbxFileLoader.pure\";\r\n\r\nimport { RegisterFBXFileLoader } from \"./fbxFileLoader.pure\";\r\nRegisterFBXFileLoader();\r\n","import { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const GLTFMagicBase64Encoded = \"Z2xURg\"; // \"glTF\" base64 encoded (without the quotes!)\r\n\r\nexport const GLTFFileLoaderMetadata = {\r\n    name: \"gltf\",\r\n\r\n    extensions: {\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".gltf\": { isBinary: false, mimeType: \"model/gltf+json\" },\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".glb\": { isBinary: true, mimeType: \"model/gltf-binary\" },\r\n    } as const satisfies ISceneLoaderPluginExtensions,\r\n\r\n    canDirectLoad(data: string): boolean {\r\n        return (\r\n            (data.indexOf(\"asset\") !== -1 && data.indexOf(\"version\") !== -1) ||\r\n            data.startsWith(\"data:base64,\" + GLTFMagicBase64Encoded) || // this is technically incorrect, but will continue to support for backcompat.\r\n            data.startsWith(\"data:;base64,\" + GLTFMagicBase64Encoded) ||\r\n            data.startsWith(\"data:application/octet-stream;base64,\" + GLTFMagicBase64Encoded) ||\r\n            data.startsWith(\"data:model/gltf-binary;base64,\" + GLTFMagicBase64Encoded)\r\n        );\r\n    },\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n","/* eslint-disable github/no-then */\r\n/* eslint-disable @typescript-eslint/no-floating-promises */\r\n/* eslint-disable @typescript-eslint/prefer-promise-reject-errors */\r\n/* eslint-disable no-restricted-syntax */\r\n/* eslint-disable @typescript-eslint/promise-function-async */\r\n/* eslint-disable @typescript-eslint/no-unused-vars */\r\n/* eslint-disable @typescript-eslint/naming-convention */\r\nimport type * as GLTF2 from \"babylonjs-gltf2interface\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Observer, Observable } from \"core/Misc/observable\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { type Camera } from \"core/Cameras/camera.pure\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport {\r\n    type ISceneLoaderPluginFactory,\r\n    type ISceneLoaderPluginAsync,\r\n    type ISceneLoaderProgressEvent,\r\n    type ISceneLoaderAsyncResult,\r\n    type SceneLoaderPluginOptions,\r\n    RegisterSceneLoaderPlugin,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { type Scene, type IDisposable } from \"core/scene\";\r\nimport { type WebRequest } from \"core/Misc/webRequest\";\r\nimport { type IFileRequest } from \"core/Misc/fileRequest\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { type IDataBuffer, DataReader } from \"core/Misc/dataReader\";\r\nimport { GLTFValidation } from \"./glTFValidation\";\r\nimport { GLTFFileLoaderMetadata, GLTFMagicBase64Encoded } from \"./glTFFileLoader.metadata\";\r\nimport { type LoadFileError, DecodeBase64UrlToBinary } from \"core/Misc/fileTools.pure\";\r\nimport { RuntimeError, ErrorCodes } from \"core/Misc/error\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { type MorphTargetManager } from \"core/Morph/morphTargetManager\";\r\n\r\n/**\r\n * Defines options for glTF loader extensions. This interface is extended by specific extensions.\r\n */\r\nexport interface GLTFLoaderExtensionOptions extends Record<string, Record<string, unknown> | undefined> {}\r\n\r\ninterface IFileRequestInfo extends IFileRequest {\r\n    _lengthComputable?: boolean;\r\n    _loaded?: number;\r\n    _total?: number;\r\n}\r\n\r\nfunction readAsync(arrayBuffer: ArrayBuffer, byteOffset: number, byteLength: number): Promise<Uint8Array> {\r\n    try {\r\n        return Promise.resolve(new Uint8Array(arrayBuffer, byteOffset, byteLength));\r\n    } catch (e) {\r\n        return Promise.reject(e);\r\n    }\r\n}\r\n\r\nfunction readViewAsync(arrayBufferView: ArrayBufferView, byteOffset: number, byteLength: number): Promise<Uint8Array> {\r\n    try {\r\n        if (byteOffset < 0 || byteOffset >= arrayBufferView.byteLength) {\r\n            throw new RangeError(\"Offset is out of range.\");\r\n        }\r\n\r\n        if (byteOffset + byteLength > arrayBufferView.byteLength) {\r\n            throw new RangeError(\"Length is out of range.\");\r\n        }\r\n\r\n        return Promise.resolve(new Uint8Array(arrayBufferView.buffer, arrayBufferView.byteOffset + byteOffset, byteLength));\r\n    } catch (e) {\r\n        return Promise.reject(e);\r\n    }\r\n}\r\n\r\n/**\r\n * Mode that determines the coordinate system to use.\r\n */\r\nexport enum GLTFLoaderCoordinateSystemMode {\r\n    /**\r\n     * Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.\r\n     */\r\n    AUTO,\r\n\r\n    /**\r\n     * Sets the useRightHandedSystem flag on the scene.\r\n     */\r\n    FORCE_RIGHT_HANDED,\r\n}\r\n\r\n/**\r\n * Mode that determines what animations will start.\r\n */\r\nexport enum GLTFLoaderAnimationStartMode {\r\n    /**\r\n     * No animation will start.\r\n     */\r\n    NONE,\r\n\r\n    /**\r\n     * The first animation will start.\r\n     */\r\n    FIRST,\r\n\r\n    /**\r\n     * All animations will start.\r\n     */\r\n    ALL,\r\n}\r\n\r\n/**\r\n * Interface that contains the data for the glTF asset.\r\n */\r\nexport interface IGLTFLoaderData {\r\n    /**\r\n     * The object that represents the glTF JSON.\r\n     */\r\n    json: object;\r\n\r\n    /**\r\n     * The BIN chunk of a binary glTF.\r\n     */\r\n    bin: Nullable<IDataBuffer>;\r\n}\r\n\r\n/**\r\n * Interface for extending the loader.\r\n */\r\nexport interface IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    readonly name: string;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    enabled: boolean;\r\n\r\n    /**\r\n     * Defines the order of this extension.\r\n     * The loader sorts the extensions using these values when loading.\r\n     */\r\n    order?: number;\r\n}\r\n\r\n/**\r\n * Loader state.\r\n */\r\nexport enum GLTFLoaderState {\r\n    /**\r\n     * The asset is loading.\r\n     */\r\n    LOADING,\r\n\r\n    /**\r\n     * The asset is ready for rendering.\r\n     */\r\n    READY,\r\n\r\n    /**\r\n     * The asset is completely loaded.\r\n     */\r\n    COMPLETE,\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFLoader extends IDisposable {\r\n    importMeshAsync: (\r\n        meshesNames: string | readonly string[] | null | undefined,\r\n        scene: Scene,\r\n        container: Nullable<AssetContainer>,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        fileName?: string\r\n    ) => Promise<ISceneLoaderAsyncResult>;\r\n    loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;\r\n}\r\n\r\n/**\r\n * Adds default/implicit options to extension specific options.\r\n */\r\ntype DefaultExtensionOptions<BaseExtensionOptions> = {\r\n    /**\r\n     * Defines if the extension is enabled\r\n     */\r\n    enabled?: boolean;\r\n} & BaseExtensionOptions;\r\n\r\nconst DefaultPreprocessUrlAsync = (url: string) => Promise.resolve(url);\r\n\r\n/**\r\n * This class contains all the concrete (not abstract) glTF options, excluding callbacks.\r\n * The purpose of this class is to make it easy to provide a way to mutate the default\r\n * loader options (see the GLTFLoaderDefaultOptions instance below) without duplicating\r\n * all the options in yet another object. Since this class is instantiated for the default\r\n * options object, abstract properties and callbacks are not included, it's more just\r\n * flag-type options.\r\n */\r\nclass GLTFLoaderBaseOptions {\r\n    /**\r\n     * Defines if the loader should always compute the bounding boxes of meshes and not use the min/max values from the position accessor. Defaults to false.\r\n     */\r\n    public alwaysComputeBoundingBox = false;\r\n\r\n    /**\r\n     * Defines if the loader should always compute the nearest common ancestor of the skeleton joints instead of using `skin.skeleton`. Defaults to false.\r\n     * Set this to true if loading assets with invalid `skin.skeleton` values.\r\n     */\r\n    public alwaysComputeSkeletonRootNode = false;\r\n\r\n    /**\r\n     * The animation start mode. Defaults to FIRST.\r\n     */\r\n    public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;\r\n\r\n    /**\r\n     * Defines if the loader should compile materials before raising the success callback. Defaults to false.\r\n     */\r\n    public compileMaterials = false;\r\n\r\n    /**\r\n     * Defines if the loader should compile shadow generators before raising the success callback. Defaults to false.\r\n     */\r\n    public compileShadowGenerators = false;\r\n\r\n    /**\r\n     * The coordinate system mode. Defaults to AUTO.\r\n     */\r\n    public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;\r\n\r\n    /**\r\n     * Defines if the loader should create instances when multiple glTF nodes point to the same glTF mesh. Defaults to true.\r\n     */\r\n    public createInstances = true;\r\n\r\n    /**\r\n     * If true, load all materials defined in the file, even if not used by any mesh. Defaults to false.\r\n     */\r\n    public loadAllMaterials = false;\r\n\r\n    /**\r\n     * Defines if the loader should load morph targets. Defaults to true.\r\n     */\r\n    public loadMorphTargets = true;\r\n\r\n    /**\r\n     * When loading a mesh with morph targets, configure its MorphTargetManager so the morph shader is compiled\r\n     * once for all targets (`numMaxInfluencers = numTargets`, `optimizeInfluencers = false`). This prevents the\r\n     * shader from being recompiled (and the resulting one-frame visual glitch) when an animated morph target\r\n     * influence passes through zero and the active influencer count changes.\r\n     * Disable to restore the previous behavior, where only the currently active (non-zero) influencers drive the\r\n     * shader. That is cheaper per frame for meshes with very large morph target counts, but recompiles the shader\r\n     * during animation. Defaults to true.\r\n     */\r\n    public useMaxMorphTargetInfluencers = true;\r\n\r\n    /**\r\n     * Defines if the loader should load node animations. Defaults to true.\r\n     * NOTE: The animation of this node will still load if the node is also a joint of a skin and `loadSkins` is true.\r\n     */\r\n    public loadNodeAnimations = true;\r\n\r\n    /**\r\n     * If true, load only the materials defined in the file. Defaults to false.\r\n     */\r\n    public loadOnlyMaterials = false;\r\n\r\n    /**\r\n     * Defines if the loader should load skins. Defaults to true.\r\n     */\r\n    public loadSkins = true;\r\n\r\n    /**\r\n     * If true, do not load any materials defined in the file. Defaults to false.\r\n     */\r\n    public skipMaterials = false;\r\n\r\n    /**\r\n     * When loading glTF animations, which are defined in seconds, target them to this FPS. Defaults to 60.\r\n     */\r\n    public targetFps = 60;\r\n\r\n    /**\r\n     * Defines if the Alpha blended materials are only applied as coverage.\r\n     * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.\r\n     * If true, no extra effects are applied to transparent pixels.\r\n     */\r\n    public transparencyAsCoverage = false;\r\n\r\n    /**\r\n     * Defines if the loader should also compile materials with clip planes. Defaults to false.\r\n     */\r\n    public useClipPlane = false;\r\n\r\n    /**\r\n     * If true, the loader will derive the name for Babylon textures from the glTF texture name, image name, or image url. Defaults to false.\r\n     * Note that it is possible for multiple Babylon textures to share the same name when the Babylon textures load from the same glTF texture or image.\r\n     */\r\n    public useGltfTextureNames = false;\r\n\r\n    /**\r\n     * Defines if the loader should use range requests when load binary glTF files from HTTP.\r\n     * Enabling will disable offline support and glTF validator.\r\n     * Defaults to false.\r\n     */\r\n    public useRangeRequests = false;\r\n\r\n    /**\r\n     * If true, load the color (gamma encoded) textures into sRGB buffers (if supported by the GPU), which will yield more accurate results when sampling the texture. Defaults to true.\r\n     */\r\n    public useSRGBBuffers = true;\r\n\r\n    /**\r\n     * Defines if the loader should validate the asset.\r\n     */\r\n    public validate = false;\r\n\r\n    /**\r\n     * Load the glTF files using the OpenPBR material.\r\n     * @experimental\r\n     */\r\n    public useOpenPBR = false;\r\n\r\n    /**\r\n     * If true, the loader will not use the transmission helper when loading materials with transmission.\r\n     */\r\n    public dontUseTransmissionHelper = false;\r\n}\r\n\r\n/**\r\n * The default GLTF loader options.\r\n * Override the properties of this object to globally change the default loader options.\r\n * To specify options for a specific load call, pass those options into the associated load function.\r\n */\r\nexport const GLTFLoaderDefaultOptions = new GLTFLoaderBaseOptions();\r\n\r\n/**\r\n * Base class for glTF loader options that supports copying values from a partial options object.\r\n */\r\nabstract class GLTFLoaderOptions extends GLTFLoaderBaseOptions {\r\n    // eslint-disable-next-line babylonjs/available\r\n    protected copyFrom(options?: Partial<Readonly<GLTFLoaderOptions>>) {\r\n        if (options) {\r\n            this.alwaysComputeBoundingBox = options.alwaysComputeBoundingBox ?? this.alwaysComputeBoundingBox;\r\n            this.alwaysComputeSkeletonRootNode = options.alwaysComputeSkeletonRootNode ?? this.alwaysComputeSkeletonRootNode;\r\n            this.animationStartMode = options.animationStartMode ?? this.animationStartMode;\r\n            this.capturePerformanceCounters = options.capturePerformanceCounters ?? this.capturePerformanceCounters;\r\n            this.compileMaterials = options.compileMaterials ?? this.compileMaterials;\r\n            this.compileShadowGenerators = options.compileShadowGenerators ?? this.compileShadowGenerators;\r\n            this.coordinateSystemMode = options.coordinateSystemMode ?? this.coordinateSystemMode;\r\n            this.createInstances = options.createInstances ?? this.createInstances;\r\n            this.customRootNode = options.customRootNode;\r\n            this.extensionOptions = options.extensionOptions ?? this.extensionOptions;\r\n            this.loadAllMaterials = options.loadAllMaterials ?? this.loadAllMaterials;\r\n            this.loadMorphTargets = options.loadMorphTargets ?? this.loadMorphTargets;\r\n            this.loadNodeAnimations = options.loadNodeAnimations ?? this.loadNodeAnimations;\r\n            this.loadOnlyMaterials = options.loadOnlyMaterials ?? this.loadOnlyMaterials;\r\n            this.loadSkins = options.loadSkins ?? this.loadSkins;\r\n            this.loggingEnabled = options.loggingEnabled ?? this.loggingEnabled;\r\n            this.onCameraLoaded = options.onCameraLoaded;\r\n            this.onMaterialLoaded = options.onMaterialLoaded;\r\n            this.onMeshLoaded = options.onMeshLoaded;\r\n            this.onParsed = options.onParsed;\r\n            this.onSkinLoaded = options.onSkinLoaded;\r\n            this.onTextureLoaded = options.onTextureLoaded;\r\n            this.onValidated = options.onValidated;\r\n            this.preprocessUrlAsync = options.preprocessUrlAsync ?? this.preprocessUrlAsync;\r\n            this.skipMaterials = options.skipMaterials ?? this.skipMaterials;\r\n            this.targetFps = options.targetFps ?? this.targetFps;\r\n            this.transparencyAsCoverage = options.transparencyAsCoverage ?? this.transparencyAsCoverage;\r\n            this.useClipPlane = options.useClipPlane ?? this.useClipPlane;\r\n            this.useGltfTextureNames = options.useGltfTextureNames ?? this.useGltfTextureNames;\r\n            this.useMaxMorphTargetInfluencers = options.useMaxMorphTargetInfluencers ?? this.useMaxMorphTargetInfluencers;\r\n            this.useOpenPBR = options.useOpenPBR ?? this.useOpenPBR;\r\n            this.useRangeRequests = options.useRangeRequests ?? this.useRangeRequests;\r\n            this.useSRGBBuffers = options.useSRGBBuffers ?? this.useSRGBBuffers;\r\n            this.validate = options.validate ?? this.validate;\r\n            this.dontUseTransmissionHelper = options.dontUseTransmissionHelper ?? this.dontUseTransmissionHelper;\r\n        }\r\n    }\r\n\r\n    // --------------\r\n    // Common options\r\n    // --------------\r\n\r\n    /**\r\n     * Raised when the asset has been parsed\r\n     */\r\n    public abstract onParsed?: ((loaderData: IGLTFLoaderData) => void) | undefined;\r\n\r\n    // ----------\r\n    // V2 options\r\n    // ----------\r\n\r\n    /**\r\n     * Defines if the loader should capture performance counters.\r\n     */\r\n    public abstract capturePerformanceCounters: boolean;\r\n\r\n    /**\r\n     * Defines the node to use as the root of the hierarchy when loading the scene (default: undefined). If not defined, a root node will be automatically created.\r\n     * You can also pass null if you don't want a root node to be created.\r\n     */\r\n    public customRootNode?: Nullable<TransformNode>;\r\n\r\n    /**\r\n     * Defines options for glTF extensions.\r\n     */\r\n    public extensionOptions: {\r\n        // NOTE: This type is doing two things:\r\n        // 1. Adding an implicit 'enabled' property to the options for each extension.\r\n        // 2. Creating a mapped type of all the options of all the extensions to make it just look like a consolidated plain object in intellisense for the user.\r\n        [Extension in keyof GLTFLoaderExtensionOptions]?: {\r\n            [Option in keyof DefaultExtensionOptions<GLTFLoaderExtensionOptions[Extension]>]: DefaultExtensionOptions<GLTFLoaderExtensionOptions[Extension]>[Option];\r\n        };\r\n    } = {};\r\n\r\n    /**\r\n     * If true, enable logging for the loader. Defaults to false.\r\n     */\r\n    public abstract loggingEnabled: boolean;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a camera after parsing the glTF properties of the camera.\r\n     */\r\n    public abstract onCameraLoaded?: (camera: Camera) => void;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a material after parsing the glTF properties of the material.\r\n     */\r\n    public abstract onMaterialLoaded?: (material: Material) => void;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a mesh after parsing the glTF properties of the mesh.\r\n     * Note that the callback is called as soon as the mesh object is created, meaning some data may not have been setup yet for this mesh (vertex data, morph targets, material, ...)\r\n     */\r\n    public abstract onMeshLoaded?: (mesh: AbstractMesh) => void;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a skin after parsing the glTF properties of the skin node.\r\n     * @see https://doc.babylonjs.com/features/featuresDeepDive/importers/glTF/glTFSkinning#ignoring-the-transform-of-the-skinned-mesh\r\n     */\r\n    public abstract onSkinLoaded?: (node: TransformNode, skinnedNode: TransformNode) => void;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a texture after parsing the glTF properties of the texture.\r\n     */\r\n    public abstract onTextureLoaded?: (texture: BaseTexture) => void;\r\n\r\n    /**\r\n     * Callback raised after the asset is validated.\r\n     */\r\n    public abstract onValidated?: (results: GLTF2.IGLTFValidationResults) => void;\r\n\r\n    /**\r\n     * Function called before loading a URL referenced by the asset.\r\n     * Setting this function allows parent-relative asset URIs and makes the callback responsible for URI safety.\r\n     * @param url The URL referenced by the asset\r\n     * @param rootUrl The root URL of the asset, if available\r\n     * @returns A promise that resolves to the URL to load\r\n     */\r\n    public preprocessUrlAsync: (url: string, rootUrl?: string) => Promise<string> = DefaultPreprocessUrlAsync;\r\n}\r\n\r\n/**\r\n * File loader for loading glTF files into a scene.\r\n */\r\nexport class GLTFFileLoader extends GLTFLoaderOptions implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\r\n    /** @internal */\r\n    public static _CreateGLTF1Loader: (parent: GLTFFileLoader) => IGLTFLoader;\r\n\r\n    /** @internal */\r\n    public static _CreateGLTF2Loader: (parent: GLTFFileLoader) => IGLTFLoader;\r\n\r\n    /**\r\n     * Creates a new glTF file loader.\r\n     * @param options The options for the loader\r\n     */\r\n    public constructor(options?: Partial<Readonly<GLTFLoaderOptions>>) {\r\n        super();\r\n        this.copyFrom(Object.assign({ ...GLTFLoaderDefaultOptions }, options));\r\n    }\r\n\r\n    /** @internal */\r\n    public get _isPreprocessUrlAsyncSet(): boolean {\r\n        return this.preprocessUrlAsync !== DefaultPreprocessUrlAsync;\r\n    }\r\n\r\n    // --------------------\r\n    // Begin Common options\r\n    // --------------------\r\n\r\n    /**\r\n     * Raised when the asset has been parsed\r\n     */\r\n    public onParsedObservable = new Observable<IGLTFLoaderData>();\r\n\r\n    private _onParsedObserver: Nullable<Observer<IGLTFLoaderData>>;\r\n\r\n    /**\r\n     * Raised when the asset has been parsed\r\n     */\r\n    public set onParsed(callback: ((loaderData: IGLTFLoaderData) => void) | undefined) {\r\n        if (this._onParsedObserver) {\r\n            this.onParsedObservable.remove(this._onParsedObserver);\r\n        }\r\n        if (callback) {\r\n            this._onParsedObserver = this.onParsedObservable.add(callback);\r\n        }\r\n    }\r\n\r\n    // ------------------\r\n    // End Common options\r\n    // ------------------\r\n\r\n    // ----------------\r\n    // Begin V1 options\r\n    // ----------------\r\n\r\n    /**\r\n     * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.\r\n     * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled.\r\n     * Defaults to true.\r\n     * @internal\r\n     */\r\n    public static IncrementalLoading = true;\r\n\r\n    /**\r\n     * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters.\r\n     * Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates.\r\n     * @internal\r\n     */\r\n    public static HomogeneousCoordinates = false;\r\n\r\n    // --------------\r\n    // End V1 options\r\n    // --------------\r\n\r\n    /**\r\n     * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.\r\n     * Note that the observable is raised as soon as the mesh object is created, meaning some data may not have been setup yet for this mesh (vertex data, morph targets, material, ...)\r\n     */\r\n    public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();\r\n\r\n    private _onMeshLoadedObserver: Nullable<Observer<AbstractMesh>>;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a mesh after parsing the glTF properties of the mesh.\r\n     * Note that the callback is called as soon as the mesh object is created, meaning some data may not have been setup yet for this mesh (vertex data, morph targets, material, ...)\r\n     */\r\n    public set onMeshLoaded(callback: ((mesh: AbstractMesh) => void) | undefined) {\r\n        if (this._onMeshLoadedObserver) {\r\n            this.onMeshLoadedObservable.remove(this._onMeshLoadedObserver);\r\n        }\r\n        if (callback) {\r\n            this._onMeshLoadedObserver = this.onMeshLoadedObservable.add(callback);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Observable raised when the loader creates a skin after parsing the glTF properties of the skin node.\r\n     * @see https://doc.babylonjs.com/features/featuresDeepDive/importers/glTF/glTFSkinning#ignoring-the-transform-of-the-skinned-mesh\r\n     * @param node - the transform node that corresponds to the original glTF skin node used for animations\r\n     * @param skinnedNode - the transform node that is the skinned mesh itself or the parent of the skinned meshes\r\n     */\r\n    public readonly onSkinLoadedObservable = new Observable<{ node: TransformNode; skinnedNode: TransformNode }>();\r\n\r\n    private _onSkinLoadedObserver: Nullable<Observer<{ node: TransformNode; skinnedNode: TransformNode }>>;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a skin after parsing the glTF properties of the skin node.\r\n     * @see https://doc.babylonjs.com/features/featuresDeepDive/importers/glTF/glTFSkinning#ignoring-the-transform-of-the-skinned-mesh\r\n     */\r\n    public set onSkinLoaded(callback: ((node: TransformNode, skinnedNode: TransformNode) => void) | undefined) {\r\n        if (this._onSkinLoadedObserver) {\r\n            this.onSkinLoadedObservable.remove(this._onSkinLoadedObserver);\r\n        }\r\n        if (callback) {\r\n            this._onSkinLoadedObserver = this.onSkinLoadedObservable.add((data) => callback(data.node, data.skinnedNode));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.\r\n     */\r\n    public readonly onTextureLoadedObservable = new Observable<BaseTexture>();\r\n\r\n    private _onTextureLoadedObserver: Nullable<Observer<BaseTexture>>;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a texture after parsing the glTF properties of the texture.\r\n     */\r\n    public set onTextureLoaded(callback: ((texture: BaseTexture) => void) | undefined) {\r\n        if (this._onTextureLoadedObserver) {\r\n            this.onTextureLoadedObservable.remove(this._onTextureLoadedObserver);\r\n        }\r\n        if (callback) {\r\n            this._onTextureLoadedObserver = this.onTextureLoadedObservable.add(callback);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Observable raised when the loader creates a material after parsing the glTF properties of the material.\r\n     */\r\n    public readonly onMaterialLoadedObservable = new Observable<Material>();\r\n\r\n    private _onMaterialLoadedObserver: Nullable<Observer<Material>>;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a material after parsing the glTF properties of the material.\r\n     */\r\n    public set onMaterialLoaded(callback: ((material: Material) => void) | undefined) {\r\n        if (this._onMaterialLoadedObserver) {\r\n            this.onMaterialLoadedObservable.remove(this._onMaterialLoadedObserver);\r\n        }\r\n        if (callback) {\r\n            this._onMaterialLoadedObserver = this.onMaterialLoadedObservable.add(callback);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.\r\n     */\r\n    public readonly onCameraLoadedObservable = new Observable<Camera>();\r\n\r\n    private _onCameraLoadedObserver: Nullable<Observer<Camera>>;\r\n\r\n    /**\r\n     * Callback raised when the loader creates a camera after parsing the glTF properties of the camera.\r\n     */\r\n    public set onCameraLoaded(callback: ((camera: Camera) => void) | undefined) {\r\n        if (this._onCameraLoadedObserver) {\r\n            this.onCameraLoadedObservable.remove(this._onCameraLoadedObserver);\r\n        }\r\n        if (callback) {\r\n            this._onCameraLoadedObserver = this.onCameraLoadedObservable.add(callback);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Observable raised when the asset is completely loaded, immediately before the loader is disposed.\r\n     * For assets with LODs, raised when all of the LODs are complete.\r\n     * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.\r\n     */\r\n    public readonly onCompleteObservable = new Observable<void>();\r\n\r\n    private _onCompleteObserver: Nullable<Observer<void>>;\r\n\r\n    /**\r\n     * Callback raised when the asset is completely loaded, immediately before the loader is disposed.\r\n     * For assets with LODs, raised when all of the LODs are complete.\r\n     * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.\r\n     */\r\n    public set onComplete(callback: () => void) {\r\n        if (this._onCompleteObserver) {\r\n            this.onCompleteObservable.remove(this._onCompleteObserver);\r\n        }\r\n        this._onCompleteObserver = this.onCompleteObservable.add(callback);\r\n    }\r\n\r\n    /**\r\n     * Observable raised when an error occurs.\r\n     */\r\n    public readonly onErrorObservable = new Observable<any>();\r\n\r\n    private _onErrorObserver: Nullable<Observer<any>>;\r\n\r\n    /**\r\n     * Callback raised when an error occurs.\r\n     */\r\n    public set onError(callback: (reason: any) => void) {\r\n        if (this._onErrorObserver) {\r\n            this.onErrorObservable.remove(this._onErrorObserver);\r\n        }\r\n        this._onErrorObserver = this.onErrorObservable.add(callback);\r\n    }\r\n\r\n    /**\r\n     * Observable raised after the loader is disposed.\r\n     */\r\n    public readonly onDisposeObservable = new Observable<void>();\r\n\r\n    private _onDisposeObserver: Nullable<Observer<void>>;\r\n\r\n    /**\r\n     * Callback raised after the loader is disposed.\r\n     */\r\n    public set onDispose(callback: () => void) {\r\n        if (this._onDisposeObserver) {\r\n            this.onDisposeObservable.remove(this._onDisposeObserver);\r\n        }\r\n        this._onDisposeObserver = this.onDisposeObservable.add(callback);\r\n    }\r\n\r\n    /**\r\n     * Observable raised after a loader extension is created.\r\n     * Set additional options for a loader extension in this event.\r\n     */\r\n    public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();\r\n\r\n    private _onExtensionLoadedObserver: Nullable<Observer<IGLTFLoaderExtension>>;\r\n\r\n    /**\r\n     * Callback raised after a loader extension is created.\r\n     */\r\n    public set onExtensionLoaded(callback: (extension: IGLTFLoaderExtension) => void) {\r\n        if (this._onExtensionLoadedObserver) {\r\n            this.onExtensionLoadedObservable.remove(this._onExtensionLoadedObserver);\r\n        }\r\n        this._onExtensionLoadedObserver = this.onExtensionLoadedObservable.add(callback);\r\n    }\r\n\r\n    /**\r\n     * Defines if the loader logging is enabled.\r\n     */\r\n    public get loggingEnabled(): boolean {\r\n        return this._loggingEnabled;\r\n    }\r\n\r\n    public set loggingEnabled(value: boolean) {\r\n        if (this._loggingEnabled === value) {\r\n            return;\r\n        }\r\n\r\n        this._loggingEnabled = value;\r\n\r\n        if (this._loggingEnabled) {\r\n            this._log = this._logEnabled;\r\n        } else {\r\n            this._log = this._logDisabled;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Defines if the loader should capture performance counters.\r\n     */\r\n    public get capturePerformanceCounters(): boolean {\r\n        return this._capturePerformanceCounters;\r\n    }\r\n\r\n    public set capturePerformanceCounters(value: boolean) {\r\n        if (this._capturePerformanceCounters === value) {\r\n            return;\r\n        }\r\n\r\n        this._capturePerformanceCounters = value;\r\n\r\n        if (this._capturePerformanceCounters) {\r\n            this._startPerformanceCounter = this._startPerformanceCounterEnabled;\r\n            this._endPerformanceCounter = this._endPerformanceCounterEnabled;\r\n        } else {\r\n            this._startPerformanceCounter = this._startPerformanceCounterDisabled;\r\n            this._endPerformanceCounter = this._endPerformanceCounterDisabled;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Observable raised after validation when validate is set to true. The event data is the result of the validation.\r\n     */\r\n    public readonly onValidatedObservable = new Observable<GLTF2.IGLTFValidationResults>();\r\n\r\n    private _onValidatedObserver: Nullable<Observer<GLTF2.IGLTFValidationResults>>;\r\n\r\n    /**\r\n     * Callback raised after the asset is validated.\r\n     */\r\n    public set onValidated(callback: (results: GLTF2.IGLTFValidationResults) => void) {\r\n        if (this._onValidatedObserver) {\r\n            this.onValidatedObservable.remove(this._onValidatedObserver);\r\n        }\r\n        this._onValidatedObserver = this.onValidatedObservable.add(callback);\r\n    }\r\n\r\n    private _loader: Nullable<IGLTFLoader> = null;\r\n    private _state: Nullable<GLTFLoaderState> = null;\r\n    private _progressCallback?: (event: ISceneLoaderProgressEvent) => void;\r\n    private _requests = new Array<IFileRequestInfo>();\r\n\r\n    /**\r\n     * Name of the loader (\"gltf\")\r\n     */\r\n    public readonly name = GLTFFileLoaderMetadata.name;\r\n\r\n    /** @internal */\r\n    public readonly extensions = GLTFFileLoaderMetadata.extensions;\r\n\r\n    /**\r\n     * Disposes the loader, releases resources during load, and cancels any outstanding requests.\r\n     */\r\n    public dispose(): void {\r\n        if (this._loader) {\r\n            this._loader.dispose();\r\n            this._loader = null;\r\n        }\r\n\r\n        for (const request of this._requests) {\r\n            request.abort();\r\n        }\r\n\r\n        this._requests.length = 0;\r\n\r\n        delete this._progressCallback;\r\n\r\n        this.preprocessUrlAsync = DefaultPreprocessUrlAsync;\r\n\r\n        this.onMeshLoadedObservable.clear();\r\n        this.onSkinLoadedObservable.clear();\r\n        this.onTextureLoadedObservable.clear();\r\n        this.onMaterialLoadedObservable.clear();\r\n        this.onCameraLoadedObservable.clear();\r\n        this.onCompleteObservable.clear();\r\n        this.onExtensionLoadedObservable.clear();\r\n\r\n        this.onDisposeObservable.notifyObservers(undefined);\r\n        this.onDisposeObservable.clear();\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public loadFile(\r\n        scene: Scene,\r\n        fileOrUrl: File | string | ArrayBufferView,\r\n        rootUrl: string,\r\n        onSuccess: (data: unknown, responseURL?: string) => void,\r\n        onProgress?: (ev: ISceneLoaderProgressEvent) => void,\r\n        useArrayBuffer?: boolean,\r\n        onError?: (request?: WebRequest, exception?: LoadFileError) => void,\r\n        name?: string\r\n    ): Nullable<IFileRequest> {\r\n        if (ArrayBuffer.isView(fileOrUrl)) {\r\n            this._loadBinary(scene, fileOrUrl, rootUrl, onSuccess, onError, name);\r\n            return null;\r\n        }\r\n\r\n        this._progressCallback = onProgress;\r\n\r\n        const fileName = (fileOrUrl as File).name || Tools.GetFilename(fileOrUrl as string);\r\n\r\n        if (useArrayBuffer) {\r\n            if (this.useRangeRequests) {\r\n                if (this.validate) {\r\n                    Logger.Warn(\"glTF validation is not supported when range requests are enabled\");\r\n                }\r\n\r\n                const fileRequest: IFileRequest = {\r\n                    abort: () => {},\r\n                    onCompleteObservable: new Observable<IFileRequest>(),\r\n                };\r\n\r\n                const dataBuffer = {\r\n                    readAsync: (byteOffset: number, byteLength: number) => {\r\n                        return new Promise<ArrayBufferView>((resolve, reject) => {\r\n                            this._loadFile(\r\n                                scene,\r\n                                fileOrUrl,\r\n                                (data) => {\r\n                                    resolve(new Uint8Array(data as ArrayBuffer));\r\n                                },\r\n                                true,\r\n                                (error) => {\r\n                                    reject(error);\r\n                                },\r\n                                (webRequest) => {\r\n                                    webRequest.setRequestHeader(\"Range\", `bytes=${byteOffset}-${byteOffset + byteLength - 1}`);\r\n                                }\r\n                            );\r\n                        });\r\n                    },\r\n                    byteLength: 0,\r\n                };\r\n\r\n                this._unpackBinaryAsync(new DataReader(dataBuffer)).then(\r\n                    (loaderData) => {\r\n                        fileRequest.onCompleteObservable.notifyObservers(fileRequest);\r\n                        onSuccess(loaderData);\r\n                    },\r\n                    onError ? (error) => onError(undefined, error) : undefined\r\n                );\r\n\r\n                return fileRequest;\r\n            }\r\n\r\n            return this._loadFile(\r\n                scene,\r\n                fileOrUrl,\r\n                (data) => {\r\n                    this._validate(scene, new Uint8Array(data as ArrayBuffer, 0, (data as ArrayBuffer).byteLength), rootUrl, fileName);\r\n                    this._unpackBinaryAsync(\r\n                        new DataReader({\r\n                            readAsync: (byteOffset, byteLength) => readAsync(data as ArrayBuffer, byteOffset, byteLength),\r\n                            byteLength: (data as ArrayBuffer).byteLength,\r\n                        })\r\n                    ).then(\r\n                        (loaderData) => {\r\n                            onSuccess(loaderData);\r\n                        },\r\n                        onError ? (error) => onError(undefined, error) : undefined\r\n                    );\r\n                },\r\n                true,\r\n                onError\r\n            );\r\n        } else {\r\n            return this._loadFile(\r\n                scene,\r\n                fileOrUrl,\r\n                (data) => {\r\n                    try {\r\n                        this._validate(scene, data as string, rootUrl, fileName);\r\n                        onSuccess({ json: this._parseJson(data as string) });\r\n                    } catch {\r\n                        if (onError) {\r\n                            onError();\r\n                        }\r\n                    }\r\n                },\r\n                false,\r\n                onError\r\n            );\r\n        }\r\n    }\r\n\r\n    private _loadBinary(\r\n        scene: Scene,\r\n        data: ArrayBufferView,\r\n        rootUrl: string,\r\n        onSuccess: (data: unknown, responseURL?: string) => void,\r\n        onError?: (request?: WebRequest, exception?: LoadFileError) => void,\r\n        fileName?: string\r\n    ): void {\r\n        this._validate(scene, new Uint8Array(data.buffer, data.byteOffset, data.byteLength), rootUrl, fileName);\r\n        this._unpackBinaryAsync(\r\n            new DataReader({\r\n                readAsync: (byteOffset, byteLength) => readViewAsync(data, byteOffset, byteLength),\r\n                byteLength: data.byteLength,\r\n            })\r\n        ).then(\r\n            (loaderData) => {\r\n                onSuccess(loaderData);\r\n            },\r\n            onError ? (error) => onError(undefined, error) : undefined\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public importMeshAsync(\r\n        meshesNames: string | readonly string[] | null | undefined,\r\n        scene: Scene,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        fileName?: string\r\n    ): Promise<ISceneLoaderAsyncResult> {\r\n        return Promise.resolve().then(() => {\r\n            this.onParsedObservable.notifyObservers(data);\r\n            this.onParsedObservable.clear();\r\n\r\n            this._log(`Loading ${fileName || \"\"}`);\r\n            this._loader = this._getLoader(data);\r\n            return this._loader.importMeshAsync(meshesNames, scene, null, data, rootUrl, onProgress, fileName);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void> {\r\n        return Promise.resolve().then(() => {\r\n            this.onParsedObservable.notifyObservers(data);\r\n            this.onParsedObservable.clear();\r\n\r\n            this._log(`Loading ${fileName || \"\"}`);\r\n            this._loader = this._getLoader(data);\r\n            return this._loader.loadAsync(scene, data, rootUrl, onProgress, fileName);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public loadAssetContainerAsync(\r\n        scene: Scene,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        fileName?: string\r\n    ): Promise<AssetContainer> {\r\n        return Promise.resolve().then(() => {\r\n            this.onParsedObservable.notifyObservers(data);\r\n            this.onParsedObservable.clear();\r\n\r\n            this._log(`Loading ${fileName || \"\"}`);\r\n            this._loader = this._getLoader(data);\r\n\r\n            // Prepare the asset container.\r\n            const container = new AssetContainer(scene);\r\n\r\n            // Get materials/textures when loading to add to container\r\n            const materials: Array<Material> = [];\r\n            this.onMaterialLoadedObservable.add((material) => {\r\n                materials.push(material);\r\n            });\r\n            const textures: Array<BaseTexture> = [];\r\n            this.onTextureLoadedObservable.add((texture) => {\r\n                textures.push(texture);\r\n            });\r\n            const cameras: Array<Camera> = [];\r\n            this.onCameraLoadedObservable.add((camera) => {\r\n                cameras.push(camera);\r\n            });\r\n\r\n            const morphTargetManagers: Array<MorphTargetManager> = [];\r\n            this.onMeshLoadedObservable.add((mesh) => {\r\n                if (mesh.morphTargetManager) {\r\n                    morphTargetManagers.push(mesh.morphTargetManager);\r\n                }\r\n            });\r\n\r\n            return this._loader.importMeshAsync(null, scene, container, data, rootUrl, onProgress, fileName).then((result) => {\r\n                Array.prototype.push.apply(container.geometries, result.geometries);\r\n                Array.prototype.push.apply(container.meshes, result.meshes);\r\n                Array.prototype.push.apply(container.particleSystems, result.particleSystems);\r\n                Array.prototype.push.apply(container.skeletons, result.skeletons);\r\n                Array.prototype.push.apply(container.animationGroups, result.animationGroups);\r\n                Array.prototype.push.apply(container.materials, materials);\r\n                Array.prototype.push.apply(container.textures, textures);\r\n                Array.prototype.push.apply(container.lights, result.lights);\r\n                Array.prototype.push.apply(container.transformNodes, result.transformNodes);\r\n                Array.prototype.push.apply(container.cameras, cameras);\r\n                Array.prototype.push.apply(container.morphTargetManagers, morphTargetManagers);\r\n                return container;\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public canDirectLoad(data: string): boolean {\r\n        return GLTFFileLoaderMetadata.canDirectLoad(data);\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public directLoad(scene: Scene, data: string): Promise<object> {\r\n        if (\r\n            data.startsWith(\"base64,\" + GLTFMagicBase64Encoded) || // this is technically incorrect, but will continue to support for backcompat.\r\n            data.startsWith(\";base64,\" + GLTFMagicBase64Encoded) ||\r\n            data.startsWith(\"application/octet-stream;base64,\" + GLTFMagicBase64Encoded) ||\r\n            data.startsWith(\"model/gltf-binary;base64,\" + GLTFMagicBase64Encoded)\r\n        ) {\r\n            const arrayBuffer = DecodeBase64UrlToBinary(data);\r\n\r\n            this._validate(scene, new Uint8Array(arrayBuffer, 0, arrayBuffer.byteLength));\r\n            return this._unpackBinaryAsync(\r\n                new DataReader({\r\n                    readAsync: (byteOffset, byteLength) => readAsync(arrayBuffer, byteOffset, byteLength),\r\n                    byteLength: arrayBuffer.byteLength,\r\n                })\r\n            );\r\n        }\r\n\r\n        this._validate(scene, data);\r\n        return Promise.resolve({ json: this._parseJson(data) });\r\n    }\r\n\r\n    /**\r\n     * The callback that allows custom handling of the root url based on the response url.\r\n     * @param rootUrl the original root url\r\n     * @param responseURL the response url if available\r\n     * @returns the new root url\r\n     */\r\n    public rewriteRootURL?(rootUrl: string, responseURL?: string): string;\r\n\r\n    /** @internal */\r\n    public createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\r\n        return new GLTFFileLoader(options[GLTFFileLoaderMetadata.name]);\r\n    }\r\n\r\n    /**\r\n     * The loader state or null if the loader is not active.\r\n     */\r\n    public get loaderState(): Nullable<GLTFLoaderState> {\r\n        return this._state;\r\n    }\r\n\r\n    /**\r\n     * Observable raised when the loader state changes.\r\n     */\r\n    public onLoaderStateChangedObservable = new Observable<Nullable<GLTFLoaderState>>();\r\n\r\n    /**\r\n     * Returns a promise that resolves when the asset is completely loaded.\r\n     * @returns a promise that resolves when the asset is completely loaded.\r\n     */\r\n    public whenCompleteAsync(): Promise<void> {\r\n        return new Promise((resolve, reject) => {\r\n            this.onCompleteObservable.addOnce(() => {\r\n                resolve();\r\n            });\r\n            this.onErrorObservable.addOnce((reason) => {\r\n                reject(reason);\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _setState(state: GLTFLoaderState): void {\r\n        if (this._state === state) {\r\n            return;\r\n        }\r\n\r\n        this._state = state;\r\n        this.onLoaderStateChangedObservable.notifyObservers(this._state);\r\n        this._log(GLTFLoaderState[this._state]);\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadFile(\r\n        scene: Scene,\r\n        fileOrUrl: File | string,\r\n        onSuccess: (data: string | ArrayBuffer) => void,\r\n        useArrayBuffer?: boolean,\r\n        onError?: (request?: WebRequest) => void,\r\n        onOpened?: (request: WebRequest) => void\r\n    ): IFileRequest {\r\n        const request = scene._loadFile(\r\n            fileOrUrl,\r\n            onSuccess,\r\n            (event) => {\r\n                this._onProgress(event, request);\r\n            },\r\n            true,\r\n            useArrayBuffer,\r\n            onError,\r\n            onOpened\r\n        ) as IFileRequestInfo;\r\n        request.onCompleteObservable.add(() => {\r\n            // Force the length computable to be true since we can guarantee the data is loaded.\r\n            request._lengthComputable = true;\r\n            request._total = request._loaded;\r\n        });\r\n        this._requests.push(request);\r\n        return request;\r\n    }\r\n\r\n    private _onProgress(event: ProgressEvent, request: IFileRequestInfo): void {\r\n        if (!this._progressCallback) {\r\n            return;\r\n        }\r\n\r\n        request._lengthComputable = event.lengthComputable;\r\n        request._loaded = event.loaded;\r\n        request._total = event.total;\r\n\r\n        let lengthComputable = true;\r\n        let loaded = 0;\r\n        let total = 0;\r\n        for (const request of this._requests) {\r\n            if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {\r\n                return;\r\n            }\r\n\r\n            lengthComputable = lengthComputable && request._lengthComputable;\r\n            loaded += request._loaded;\r\n            total += request._total;\r\n        }\r\n\r\n        this._progressCallback({\r\n            lengthComputable: lengthComputable,\r\n            loaded: loaded,\r\n            total: lengthComputable ? total : 0,\r\n        });\r\n    }\r\n\r\n    private _validate(scene: Scene, data: string | Uint8Array, rootUrl = \"\", fileName = \"\"): void {\r\n        if (!this.validate) {\r\n            return;\r\n        }\r\n\r\n        this._startPerformanceCounter(\"Validate JSON\");\r\n        GLTFValidation.ValidateAsync(data, rootUrl, fileName, (uri) => {\r\n            return this.preprocessUrlAsync(rootUrl + uri, rootUrl).then((url) => {\r\n                return scene._loadFileAsync(url, undefined, true, true).then((data) => {\r\n                    return new Uint8Array(data, 0, data.byteLength);\r\n                });\r\n            });\r\n        }).then(\r\n            (result) => {\r\n                this._endPerformanceCounter(\"Validate JSON\");\r\n                this.onValidatedObservable.notifyObservers(result);\r\n                this.onValidatedObservable.clear();\r\n            },\r\n            (reason) => {\r\n                this._endPerformanceCounter(\"Validate JSON\");\r\n                Tools.Warn(`Failed to validate: ${reason.message}`);\r\n                this.onValidatedObservable.clear();\r\n            }\r\n        );\r\n    }\r\n\r\n    private _getLoader(loaderData: IGLTFLoaderData): IGLTFLoader {\r\n        const asset = (<any>loaderData.json).asset || {};\r\n\r\n        this._log(`Asset version: ${asset.version}`);\r\n        asset.minVersion && this._log(`Asset minimum version: ${asset.minVersion}`);\r\n        asset.generator && this._log(`Asset generator: ${asset.generator}`);\r\n\r\n        const version = GLTFFileLoader._parseVersion(asset.version);\r\n        if (!version) {\r\n            throw new Error(\"Invalid version: \" + asset.version);\r\n        }\r\n\r\n        if (asset.minVersion !== undefined) {\r\n            const minVersion = GLTFFileLoader._parseVersion(asset.minVersion);\r\n            if (!minVersion) {\r\n                throw new Error(\"Invalid minimum version: \" + asset.minVersion);\r\n            }\r\n\r\n            if (GLTFFileLoader._compareVersion(minVersion, { major: 2, minor: 0 }) > 0) {\r\n                throw new Error(\"Incompatible minimum version: \" + asset.minVersion);\r\n            }\r\n        }\r\n\r\n        const createLoaders: { [key: number]: (parent: GLTFFileLoader) => IGLTFLoader } = {\r\n            1: GLTFFileLoader._CreateGLTF1Loader,\r\n            2: GLTFFileLoader._CreateGLTF2Loader,\r\n        };\r\n\r\n        const createLoader = createLoaders[version.major];\r\n        if (!createLoader) {\r\n            throw new Error(\"Unsupported version: \" + asset.version);\r\n        }\r\n\r\n        return createLoader(this);\r\n    }\r\n\r\n    private _parseJson(json: string): object {\r\n        this._startPerformanceCounter(\"Parse JSON\");\r\n        this._log(`JSON length: ${json.length}`);\r\n        const parsed = JSON.parse(json);\r\n        this._endPerformanceCounter(\"Parse JSON\");\r\n        return parsed;\r\n    }\r\n\r\n    private _unpackBinaryAsync(dataReader: DataReader): Promise<IGLTFLoaderData> {\r\n        this._startPerformanceCounter(\"Unpack Binary\");\r\n\r\n        // Read magic + version + length + json length + json format\r\n        return dataReader.loadAsync(20).then(() => {\r\n            const Binary = {\r\n                Magic: 0x46546c67,\r\n            };\r\n\r\n            const magic = dataReader.readUint32();\r\n            if (magic !== Binary.Magic) {\r\n                throw new RuntimeError(\"Unexpected magic: \" + magic, ErrorCodes.GLTFLoaderUnexpectedMagicError);\r\n            }\r\n\r\n            const version = dataReader.readUint32();\r\n\r\n            if (this.loggingEnabled) {\r\n                this._log(`Binary version: ${version}`);\r\n            }\r\n\r\n            const length = dataReader.readUint32();\r\n            if (!this.useRangeRequests && length !== dataReader.buffer.byteLength) {\r\n                Logger.Warn(`Length in header does not match actual data length: ${length} != ${dataReader.buffer.byteLength}`);\r\n            }\r\n\r\n            let unpacked: Promise<IGLTFLoaderData>;\r\n            switch (version) {\r\n                case 1: {\r\n                    unpacked = this._unpackBinaryV1Async(dataReader, length);\r\n                    break;\r\n                }\r\n                case 2: {\r\n                    unpacked = this._unpackBinaryV2Async(dataReader, length);\r\n                    break;\r\n                }\r\n                default: {\r\n                    throw new Error(\"Unsupported version: \" + version);\r\n                }\r\n            }\r\n\r\n            this._endPerformanceCounter(\"Unpack Binary\");\r\n\r\n            return unpacked;\r\n        });\r\n    }\r\n\r\n    private _unpackBinaryV1Async(dataReader: DataReader, length: number): Promise<IGLTFLoaderData> {\r\n        const ContentFormat = {\r\n            JSON: 0,\r\n        };\r\n\r\n        const contentLength = dataReader.readUint32();\r\n        const contentFormat = dataReader.readUint32();\r\n\r\n        if (contentFormat !== ContentFormat.JSON) {\r\n            throw new Error(`Unexpected content format: ${contentFormat}`);\r\n        }\r\n\r\n        const bodyLength = length - dataReader.byteOffset;\r\n\r\n        const data: IGLTFLoaderData = { json: this._parseJson(dataReader.readString(contentLength)), bin: null };\r\n        if (bodyLength !== 0) {\r\n            const startByteOffset = dataReader.byteOffset;\r\n            data.bin = {\r\n                readAsync: (byteOffset, byteLength) => dataReader.buffer.readAsync(startByteOffset + byteOffset, byteLength),\r\n                byteLength: bodyLength,\r\n            };\r\n        }\r\n\r\n        return Promise.resolve(data);\r\n    }\r\n\r\n    private _unpackBinaryV2Async(dataReader: DataReader, length: number): Promise<IGLTFLoaderData> {\r\n        const ChunkFormat = {\r\n            JSON: 0x4e4f534a,\r\n            BIN: 0x004e4942,\r\n        };\r\n\r\n        // Read the JSON chunk header.\r\n        const chunkLength = dataReader.readUint32();\r\n        const chunkFormat = dataReader.readUint32();\r\n        if (chunkFormat !== ChunkFormat.JSON) {\r\n            throw new Error(\"First chunk format is not JSON\");\r\n        }\r\n\r\n        // Bail if there are no other chunks.\r\n        if (dataReader.byteOffset + chunkLength === length) {\r\n            return dataReader.loadAsync(chunkLength).then(() => {\r\n                return { json: this._parseJson(dataReader.readString(chunkLength)), bin: null };\r\n            });\r\n        }\r\n\r\n        // Read the JSON chunk and the length and type of the next chunk.\r\n        return dataReader.loadAsync(chunkLength + 8).then(() => {\r\n            const data: IGLTFLoaderData = { json: this._parseJson(dataReader.readString(chunkLength)), bin: null };\r\n\r\n            const readAsync = (): Promise<IGLTFLoaderData> => {\r\n                const chunkLength = dataReader.readUint32();\r\n                const chunkFormat = dataReader.readUint32();\r\n\r\n                switch (chunkFormat) {\r\n                    case ChunkFormat.JSON: {\r\n                        throw new Error(\"Unexpected JSON chunk\");\r\n                    }\r\n                    case ChunkFormat.BIN: {\r\n                        const startByteOffset = dataReader.byteOffset;\r\n                        data.bin = {\r\n                            readAsync: (byteOffset, byteLength) => dataReader.buffer.readAsync(startByteOffset + byteOffset, byteLength),\r\n                            byteLength: chunkLength,\r\n                        };\r\n                        dataReader.skipBytes(chunkLength);\r\n                        break;\r\n                    }\r\n                    default: {\r\n                        // ignore unrecognized chunkFormat\r\n                        dataReader.skipBytes(chunkLength);\r\n                        break;\r\n                    }\r\n                }\r\n\r\n                if (dataReader.byteOffset !== length) {\r\n                    return dataReader.loadAsync(8).then(readAsync);\r\n                }\r\n\r\n                return Promise.resolve(data);\r\n            };\r\n\r\n            return readAsync();\r\n        });\r\n    }\r\n\r\n    private static _parseVersion(version: string): Nullable<{ major: number; minor: number }> {\r\n        if (version === \"1.0\" || version === \"1.0.1\") {\r\n            return {\r\n                major: 1,\r\n                minor: 0,\r\n            };\r\n        }\r\n\r\n        const match = (version + \"\").match(/^(\\d+)\\.(\\d+)/);\r\n        if (!match) {\r\n            return null;\r\n        }\r\n\r\n        return {\r\n            major: parseInt(match[1]),\r\n            minor: parseInt(match[2]),\r\n        };\r\n    }\r\n\r\n    private static _compareVersion(a: { major: number; minor: number }, b: { major: number; minor: number }): number {\r\n        if (a.major > b.major) {\r\n            return 1;\r\n        }\r\n        if (a.major < b.major) {\r\n            return -1;\r\n        }\r\n        if (a.minor > b.minor) {\r\n            return 1;\r\n        }\r\n        if (a.minor < b.minor) {\r\n            return -1;\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    private static readonly _logSpaces = \"                                \";\r\n    private _logIndentLevel = 0;\r\n    private _loggingEnabled = false;\r\n\r\n    /** @internal */\r\n    public _log = this._logDisabled;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _logOpen(message: string): void {\r\n        this._log(message);\r\n        this._logIndentLevel++;\r\n    }\r\n\r\n    /** @internal */\r\n    public _logClose(): void {\r\n        --this._logIndentLevel;\r\n    }\r\n\r\n    private _logEnabled(message: string): void {\r\n        const spaces = GLTFFileLoader._logSpaces.substring(0, this._logIndentLevel * 2);\r\n        Logger.Log(`${spaces}${message}`);\r\n    }\r\n\r\n    private _logDisabled(message: string): void {}\r\n\r\n    private _capturePerformanceCounters = false;\r\n\r\n    /** @internal */\r\n    public _startPerformanceCounter = this._startPerformanceCounterDisabled;\r\n\r\n    /** @internal */\r\n    public _endPerformanceCounter = this._endPerformanceCounterDisabled;\r\n\r\n    private _startPerformanceCounterEnabled(counterName: string): void {\r\n        Tools.StartPerformanceCounter(counterName);\r\n    }\r\n\r\n    private _startPerformanceCounterDisabled(counterName: string): void {}\r\n\r\n    private _endPerformanceCounterEnabled(counterName: string): void {\r\n        Tools.EndPerformanceCounter(counterName);\r\n    }\r\n\r\n    private _endPerformanceCounterDisabled(counterName: string): void {}\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the GLTFFileLoader scene loader plugin.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterGLTFFileLoader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    RegisterSceneLoaderPlugin(new GLTFFileLoader());\r\n}\r\n\r\nexport type { GLTFLoaderOptions };\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./glTFFileLoader.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./glTFFileLoader.types\";\r\nexport * from \"./glTFFileLoader.pure\";\r\n\r\nimport { RegisterGLTFFileLoader } from \"./glTFFileLoader.pure\";\r\nRegisterGLTFFileLoader();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type AssetContainer } from \"core/assetContainer\";\r\nimport { type Bone } from \"core/Bones/bone\";\r\nimport { type Skeleton } from \"core/Bones/skeleton\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { type Node } from \"core/node\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\n\r\n/**\r\n * Enums\r\n * @internal\r\n */\r\nexport enum EComponentType {\r\n    BYTE = 5120,\r\n    UNSIGNED_BYTE = 5121,\r\n    SHORT = 5122,\r\n    UNSIGNED_SHORT = 5123,\r\n    FLOAT = 5126,\r\n}\r\n\r\n/** @internal */\r\nexport enum EShaderType {\r\n    FRAGMENT = 35632,\r\n    VERTEX = 35633,\r\n}\r\n\r\n/** @internal */\r\nexport enum EParameterType {\r\n    BYTE = 5120,\r\n    UNSIGNED_BYTE = 5121,\r\n    SHORT = 5122,\r\n    UNSIGNED_SHORT = 5123,\r\n    INT = 5124,\r\n    UNSIGNED_INT = 5125,\r\n    FLOAT = 5126,\r\n    FLOAT_VEC2 = 35664,\r\n    FLOAT_VEC3 = 35665,\r\n    FLOAT_VEC4 = 35666,\r\n    INT_VEC2 = 35667,\r\n    INT_VEC3 = 35668,\r\n    INT_VEC4 = 35669,\r\n    BOOL = 35670,\r\n    BOOL_VEC2 = 35671,\r\n    BOOL_VEC3 = 35672,\r\n    BOOL_VEC4 = 35673,\r\n    FLOAT_MAT2 = 35674,\r\n    FLOAT_MAT3 = 35675,\r\n    FLOAT_MAT4 = 35676,\r\n    SAMPLER_2D = 35678,\r\n}\r\n\r\n/** @internal */\r\nexport enum ETextureWrapMode {\r\n    CLAMP_TO_EDGE = 33071,\r\n    MIRRORED_REPEAT = 33648,\r\n    REPEAT = 10497,\r\n}\r\n\r\n/** @internal */\r\nexport enum ETextureFilterType {\r\n    NEAREST = 9728,\r\n    LINEAR = 9728,\r\n    NEAREST_MIPMAP_NEAREST = 9984,\r\n    LINEAR_MIPMAP_NEAREST = 9985,\r\n    NEAREST_MIPMAP_LINEAR = 9986,\r\n    LINEAR_MIPMAP_LINEAR = 9987,\r\n}\r\n\r\n/** @internal */\r\nexport enum ETextureFormat {\r\n    ALPHA = 6406,\r\n    RGB = 6407,\r\n    RGBA = 6408,\r\n    LUMINANCE = 6409,\r\n    LUMINANCE_ALPHA = 6410,\r\n}\r\n\r\n/** @internal */\r\nexport enum ECullingType {\r\n    FRONT = 1028,\r\n    BACK = 1029,\r\n    FRONT_AND_BACK = 1032,\r\n}\r\n\r\n/** @internal */\r\nexport enum EBlendingFunction {\r\n    ZERO = 0,\r\n    ONE = 1,\r\n    SRC_COLOR = 768,\r\n    ONE_MINUS_SRC_COLOR = 769,\r\n    DST_COLOR = 774,\r\n    ONE_MINUS_DST_COLOR = 775,\r\n    SRC_ALPHA = 770,\r\n    ONE_MINUS_SRC_ALPHA = 771,\r\n    DST_ALPHA = 772,\r\n    ONE_MINUS_DST_ALPHA = 773,\r\n    CONSTANT_COLOR = 32769,\r\n    ONE_MINUS_CONSTANT_COLOR = 32770,\r\n    CONSTANT_ALPHA = 32771,\r\n    ONE_MINUS_CONSTANT_ALPHA = 32772,\r\n    SRC_ALPHA_SATURATE = 776,\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFProperty {\r\n    extensions?: { [key: string]: any };\r\n    extras?: object;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFChildRootProperty extends IGLTFProperty {\r\n    name?: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFAccessor extends IGLTFChildRootProperty {\r\n    bufferView: string;\r\n    byteOffset: number;\r\n    byteStride: number;\r\n    count: number;\r\n    type: string;\r\n    componentType: EComponentType;\r\n\r\n    max?: number[];\r\n    min?: number[];\r\n    name?: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFBufferView extends IGLTFChildRootProperty {\r\n    buffer: string;\r\n    byteOffset: number;\r\n    byteLength: number;\r\n    byteStride: number;\r\n\r\n    target?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFBuffer extends IGLTFChildRootProperty {\r\n    uri: string;\r\n\r\n    byteLength?: number;\r\n    type?: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFShader extends IGLTFChildRootProperty {\r\n    uri: string;\r\n    type: EShaderType;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFProgram extends IGLTFChildRootProperty {\r\n    attributes: string[];\r\n    fragmentShader: string;\r\n    vertexShader: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFTechniqueParameter {\r\n    type: number;\r\n\r\n    count?: number;\r\n    semantic?: string;\r\n    node?: string;\r\n    value?: number | boolean | string | Array<any>;\r\n    source?: string;\r\n\r\n    babylonValue?: any;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFTechniqueCommonProfile {\r\n    lightingModel: string;\r\n    texcoordBindings: object;\r\n\r\n    parameters?: Array<any>;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFTechniqueStatesFunctions {\r\n    blendColor?: number[];\r\n    blendEquationSeparate?: number[];\r\n    blendFuncSeparate?: number[];\r\n    colorMask: boolean[];\r\n    cullFace: number[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFTechniqueStates {\r\n    enable: number[];\r\n    functions: IGLTFTechniqueStatesFunctions;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFTechnique extends IGLTFChildRootProperty {\r\n    parameters: { [key: string]: IGLTFTechniqueParameter };\r\n    program: string;\r\n\r\n    attributes: { [key: string]: string };\r\n    uniforms: { [key: string]: string };\r\n    states: IGLTFTechniqueStates;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFMaterial extends IGLTFChildRootProperty {\r\n    technique?: string;\r\n    values: string[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFMeshPrimitive extends IGLTFProperty {\r\n    attributes: { [key: string]: string };\r\n    indices: string;\r\n    material: string;\r\n\r\n    mode?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFMesh extends IGLTFChildRootProperty {\r\n    primitives: IGLTFMeshPrimitive[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFImage extends IGLTFChildRootProperty {\r\n    uri: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFSampler extends IGLTFChildRootProperty {\r\n    magFilter?: number;\r\n    minFilter?: number;\r\n    wrapS?: number;\r\n    wrapT?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFTexture extends IGLTFChildRootProperty {\r\n    sampler: string;\r\n    source: string;\r\n\r\n    format?: ETextureFormat;\r\n    internalFormat?: ETextureFormat;\r\n    target?: number;\r\n    type?: number;\r\n\r\n    // Babylon.js values (optimize)\r\n    babylonTexture?: Texture;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFAmbienLight {\r\n    color?: number[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFDirectionalLight {\r\n    color?: number[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFPointLight {\r\n    color?: number[];\r\n    constantAttenuation?: number;\r\n    linearAttenuation?: number;\r\n    quadraticAttenuation?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFSpotLight {\r\n    color?: number[];\r\n    constantAttenuation?: number;\r\n    fallOfAngle?: number;\r\n    fallOffExponent?: number;\r\n    linearAttenuation?: number;\r\n    quadraticAttenuation?: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFLight extends IGLTFChildRootProperty {\r\n    type: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFCameraOrthographic {\r\n    xmag: number;\r\n    ymag: number;\r\n    zfar: number;\r\n    znear: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFCameraPerspective {\r\n    aspectRatio: number;\r\n    yfov: number;\r\n    zfar: number;\r\n    znear: number;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFCamera extends IGLTFChildRootProperty {\r\n    type: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFAnimationChannelTarget {\r\n    id: string;\r\n    path: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFAnimationChannel {\r\n    sampler: string;\r\n    target: IGLTFAnimationChannelTarget;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFAnimationSampler {\r\n    input: string;\r\n    output: string;\r\n\r\n    interpolation?: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFAnimation extends IGLTFChildRootProperty {\r\n    channels?: IGLTFAnimationChannel[];\r\n    parameters?: { [key: string]: string };\r\n    samplers?: { [key: string]: IGLTFAnimationSampler };\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFNodeInstanceSkin {\r\n    skeletons: string[];\r\n    skin: string;\r\n    meshes: string[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFSkins extends IGLTFChildRootProperty {\r\n    bindShapeMatrix: number[];\r\n    inverseBindMatrices: string;\r\n    jointNames: string[];\r\n\r\n    babylonSkeleton?: Skeleton;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFNode extends IGLTFChildRootProperty {\r\n    camera?: string;\r\n    children: string[];\r\n    skin?: string;\r\n    jointName?: string;\r\n    light?: string;\r\n    matrix: number[];\r\n    mesh?: string;\r\n    meshes?: string[];\r\n    rotation?: number[];\r\n    scale?: number[];\r\n    translation?: number[];\r\n\r\n    // Babylon.js values (optimize)\r\n    babylonNode?: Node;\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFScene extends IGLTFChildRootProperty {\r\n    nodes: string[];\r\n}\r\n\r\n/** @internal */\r\nexport interface IGLTFRuntime {\r\n    extensions: { [key: string]: any };\r\n    accessors: { [key: string]: IGLTFAccessor };\r\n    buffers: { [key: string]: IGLTFBuffer };\r\n    bufferViews: { [key: string]: IGLTFBufferView };\r\n    meshes: { [key: string]: IGLTFMesh };\r\n    lights: { [key: string]: IGLTFLight };\r\n    cameras: { [key: string]: IGLTFCamera };\r\n    nodes: { [key: string]: IGLTFNode };\r\n    images: { [key: string]: IGLTFImage };\r\n    textures: { [key: string]: IGLTFTexture };\r\n    shaders: { [key: string]: IGLTFShader };\r\n    programs: { [key: string]: IGLTFProgram };\r\n    samplers: { [key: string]: IGLTFSampler };\r\n    techniques: { [key: string]: IGLTFTechnique };\r\n    materials: { [key: string]: IGLTFMaterial };\r\n    animations: { [key: string]: IGLTFAnimation };\r\n    skins: { [key: string]: IGLTFSkins };\r\n\r\n    currentScene?: object;\r\n    scenes: { [key: string]: IGLTFScene }; // v1.1\r\n\r\n    extensionsUsed: string[];\r\n    extensionsRequired?: string[]; // v1.1\r\n\r\n    buffersCount: number;\r\n    shaderscount: number;\r\n\r\n    scene: Scene;\r\n    rootUrl: string;\r\n\r\n    loadedBufferCount: number;\r\n    loadedBufferViews: { [name: string]: ArrayBufferView };\r\n\r\n    loadedShaderCount: number;\r\n\r\n    importOnlyMeshes: boolean;\r\n    importMeshesNames?: string[];\r\n\r\n    dummyNodes: Node[];\r\n\r\n    assetContainer: Nullable<AssetContainer>;\r\n}\r\n\r\n/** @internal */\r\nexport interface INodeToRoot {\r\n    bone: Bone;\r\n    node: IGLTFNode;\r\n    id: string;\r\n}\r\n\r\n/** @internal */\r\nexport interface IJointNode {\r\n    node: IGLTFNode;\r\n    id: string;\r\n}\r\n","/* eslint-disable @typescript-eslint/no-unused-vars */\r\nimport {\r\n    type IGLTFRuntime,\r\n    type IGLTFTechniqueParameter,\r\n    type IGLTFAnimation,\r\n    type IGLTFAnimationSampler,\r\n    type IGLTFNode,\r\n    type IGLTFSkins,\r\n    type INodeToRoot,\r\n    type IJointNode,\r\n    type IGLTFMesh,\r\n    type IGLTFAccessor,\r\n    type IGLTFLight,\r\n    type IGLTFAmbienLight,\r\n    type IGLTFDirectionalLight,\r\n    type IGLTFPointLight,\r\n    type IGLTFSpotLight,\r\n    type IGLTFCamera,\r\n    type IGLTFCameraPerspective,\r\n    type IGLTFScene,\r\n    type IGLTFTechnique,\r\n    type IGLTFMaterial,\r\n    type IGLTFProgram,\r\n    type IGLTFBuffer,\r\n    type IGLTFTexture,\r\n    type IGLTFImage,\r\n    type IGLTFSampler,\r\n    type IGLTFShader,\r\n    type IGLTFTechniqueStates,\r\n    EParameterType,\r\n    ETextureFilterType,\r\n    ECullingType,\r\n    EBlendingFunction,\r\n    EShaderType,\r\n} from \"./glTFLoaderInterfaces\";\r\n\r\nimport { type FloatArray, type Nullable } from \"core/types\";\r\nimport { Quaternion, Vector3, Matrix } from \"core/Maths/math.vector.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { Camera } from \"core/Cameras/camera.pure\";\r\nimport { FreeCamera } from \"core/Cameras/freeCamera.pure\";\r\nimport { Animation } from \"core/Animations/animation.pure\";\r\nimport { Bone } from \"core/Bones/bone.pure\";\r\nimport { Skeleton } from \"core/Bones/skeleton\";\r\nimport { Effect } from \"core/Materials/effect.pure\";\r\nimport { Material } from \"core/Materials/material.pure\";\r\nimport { MultiMaterial } from \"core/Materials/multiMaterial.pure\";\r\nimport { StandardMaterial } from \"core/Materials/standardMaterial.pure\";\r\nimport { ShaderMaterial } from \"core/Materials/shaderMaterial.pure\";\r\nimport { Texture } from \"core/Materials/Textures/texture.pure\";\r\nimport { type Node } from \"core/node\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer.pure\";\r\nimport { Geometry } from \"core/Meshes/geometry\";\r\nimport { SubMesh } from \"core/Meshes/subMesh.pure\";\r\nimport { AbstractMesh } from \"core/Meshes/abstractMesh.pure\";\r\nimport { Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { HemisphericLight } from \"core/Lights/hemisphericLight.pure\";\r\nimport { DirectionalLight } from \"core/Lights/directionalLight.pure\";\r\nimport { PointLight } from \"core/Lights/pointLight.pure\";\r\nimport { SpotLight } from \"core/Lights/spotLight.pure\";\r\nimport { type ISceneLoaderAsyncResult, type ISceneLoaderProgressEvent } from \"core/Loading/sceneLoader\";\r\nimport { type Scene } from \"core/scene.pure\";\r\n\r\nimport { GLTFUtils } from \"./glTFLoaderUtils\";\r\nimport { type IGLTFLoader, type IGLTFLoaderData, GLTFFileLoader } from \"../glTFFileLoader.pure\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { type AssetContainer } from \"core/assetContainer\";\r\nimport { GetBlobBufferSource } from \"core/Buffers/bufferUtils\";\r\n\r\n/**\r\n * Tokenizer. Used for shaders compatibility\r\n * Automatically map world, view, projection, worldViewProjection, attributes and so on\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nenum ETokenType {\r\n    IDENTIFIER = 1,\r\n\r\n    UNKNOWN = 2,\r\n    END_OF_INPUT = 3,\r\n}\r\n\r\nclass Tokenizer {\r\n    private _toParse: string;\r\n    private _pos: number = 0;\r\n    private _maxPos: number;\r\n\r\n    public currentToken: ETokenType = ETokenType.UNKNOWN;\r\n    public currentIdentifier: string = \"\";\r\n    public currentString: string = \"\";\r\n    public isLetterOrDigitPattern: RegExp = /^[a-zA-Z0-9]+$/;\r\n\r\n    constructor(toParse: string) {\r\n        this._toParse = toParse;\r\n        this._maxPos = toParse.length;\r\n    }\r\n\r\n    public getNextToken(): ETokenType {\r\n        if (this.isEnd()) {\r\n            return ETokenType.END_OF_INPUT;\r\n        }\r\n\r\n        this.currentString = this.read();\r\n        this.currentToken = ETokenType.UNKNOWN;\r\n\r\n        if (this.currentString === \"_\" || this.isLetterOrDigitPattern.test(this.currentString)) {\r\n            this.currentToken = ETokenType.IDENTIFIER;\r\n            this.currentIdentifier = this.currentString;\r\n            while (!this.isEnd() && (this.isLetterOrDigitPattern.test((this.currentString = this.peek())) || this.currentString === \"_\")) {\r\n                this.currentIdentifier += this.currentString;\r\n                this.forward();\r\n            }\r\n        }\r\n\r\n        return this.currentToken;\r\n    }\r\n\r\n    public peek(): string {\r\n        return this._toParse[this._pos];\r\n    }\r\n\r\n    public read(): string {\r\n        return this._toParse[this._pos++];\r\n    }\r\n\r\n    public forward(): void {\r\n        this._pos++;\r\n    }\r\n\r\n    public isEnd(): boolean {\r\n        return this._pos >= this._maxPos;\r\n    }\r\n}\r\n\r\n/**\r\n * Values\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nconst glTFTransforms = [\"MODEL\", \"VIEW\", \"PROJECTION\", \"MODELVIEW\", \"MODELVIEWPROJECTION\", \"JOINTMATRIX\"];\r\nconst BabylonTransforms = [\"world\", \"view\", \"projection\", \"worldView\", \"worldViewProjection\", \"mBones\"];\r\n\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nconst glTFAnimationPaths = [\"translation\", \"rotation\", \"scale\"];\r\nconst BabylonAnimationPaths = [\"position\", \"rotationQuaternion\", \"scaling\"];\r\n\r\n/**\r\n * Parse\r\n * @param parsedBuffers\r\n * @param gltfRuntime\r\n */\r\nconst ParseBuffers = (parsedBuffers: any, gltfRuntime: IGLTFRuntime) => {\r\n    for (const buf in parsedBuffers) {\r\n        const parsedBuffer = parsedBuffers[buf];\r\n        gltfRuntime.buffers[buf] = parsedBuffer;\r\n        gltfRuntime.buffersCount++;\r\n    }\r\n};\r\n\r\nconst ParseShaders = (parsedShaders: any, gltfRuntime: IGLTFRuntime) => {\r\n    for (const sha in parsedShaders) {\r\n        const parsedShader = parsedShaders[sha];\r\n        gltfRuntime.shaders[sha] = parsedShader;\r\n        gltfRuntime.shaderscount++;\r\n    }\r\n};\r\n\r\nconst ParseObject = (parsedObjects: any, runtimeProperty: string, gltfRuntime: IGLTFRuntime) => {\r\n    for (const object in parsedObjects) {\r\n        const parsedObject = parsedObjects[object];\r\n        (<any>gltfRuntime)[runtimeProperty][object] = parsedObject;\r\n    }\r\n};\r\n\r\n/**\r\n * Utils\r\n * @param buffer\r\n */\r\nconst NormalizeUVs = (buffer: any) => {\r\n    if (!buffer) {\r\n        return;\r\n    }\r\n\r\n    for (let i = 0; i < buffer.length / 2; i++) {\r\n        buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];\r\n    }\r\n};\r\n\r\nconst GetAttribute = (attributeParameter: IGLTFTechniqueParameter): Nullable<string> => {\r\n    if (attributeParameter.semantic === \"NORMAL\") {\r\n        return \"normal\";\r\n    } else if (attributeParameter.semantic === \"POSITION\") {\r\n        return \"position\";\r\n    } else if (attributeParameter.semantic === \"JOINT\") {\r\n        return \"matricesIndices\";\r\n    } else if (attributeParameter.semantic === \"WEIGHT\") {\r\n        return \"matricesWeights\";\r\n    } else if (attributeParameter.semantic === \"COLOR\") {\r\n        return \"color\";\r\n    } else if (attributeParameter.semantic && attributeParameter.semantic.indexOf(\"TEXCOORD_\") !== -1) {\r\n        const channel = Number(attributeParameter.semantic.split(\"_\")[1]);\r\n        return \"uv\" + (channel === 0 ? \"\" : channel + 1);\r\n    }\r\n\r\n    return null;\r\n};\r\n\r\n/**\r\n * Loads and creates animations\r\n * @param gltfRuntime\r\n */\r\nconst LoadAnimations = (gltfRuntime: IGLTFRuntime) => {\r\n    for (const anim in gltfRuntime.animations) {\r\n        const animation: IGLTFAnimation = gltfRuntime.animations[anim];\r\n\r\n        if (!animation.channels || !animation.samplers) {\r\n            continue;\r\n        }\r\n\r\n        let lastAnimation: Nullable<Animation> = null;\r\n\r\n        for (let i = 0; i < animation.channels.length; i++) {\r\n            // Get parameters and load buffers\r\n            const channel = animation.channels[i];\r\n            const sampler: IGLTFAnimationSampler = animation.samplers[channel.sampler];\r\n\r\n            if (!sampler) {\r\n                continue;\r\n            }\r\n\r\n            let inputData: Nullable<string>;\r\n            let outputData: Nullable<string>;\r\n\r\n            if (animation.parameters) {\r\n                inputData = animation.parameters[sampler.input];\r\n                outputData = animation.parameters[sampler.output];\r\n            } else {\r\n                inputData = sampler.input;\r\n                outputData = sampler.output;\r\n            }\r\n\r\n            const bufferInput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);\r\n            const bufferOutput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);\r\n\r\n            const targetId = channel.target.id;\r\n            let targetNode: any = gltfRuntime.scene.getNodeById(targetId);\r\n\r\n            if (targetNode === null) {\r\n                targetNode = gltfRuntime.scene.getNodeByName(targetId);\r\n            }\r\n\r\n            if (targetNode === null) {\r\n                Tools.Warn(\"Creating animation named \" + anim + \". But cannot find node named \" + targetId + \" to attach to\");\r\n                continue;\r\n            }\r\n\r\n            const isBone = targetNode instanceof Bone;\r\n\r\n            // Get target path (position, rotation or scaling)\r\n            let targetPath = channel.target.path;\r\n            const targetPathIndex = glTFAnimationPaths.indexOf(targetPath);\r\n\r\n            if (targetPathIndex !== -1) {\r\n                targetPath = BabylonAnimationPaths[targetPathIndex];\r\n            }\r\n\r\n            // Determine animation type\r\n            let animationType = Animation.ANIMATIONTYPE_MATRIX;\r\n\r\n            if (!isBone) {\r\n                if (targetPath === \"rotationQuaternion\") {\r\n                    animationType = Animation.ANIMATIONTYPE_QUATERNION;\r\n                    targetNode.rotationQuaternion = new Quaternion();\r\n                } else {\r\n                    animationType = Animation.ANIMATIONTYPE_VECTOR3;\r\n                }\r\n            }\r\n\r\n            // Create animation and key frames\r\n            let babylonAnimation: Nullable<Animation> = null;\r\n            const keys = [];\r\n            let arrayOffset = 0;\r\n            let modifyKey = false;\r\n\r\n            if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {\r\n                babylonAnimation = lastAnimation;\r\n                modifyKey = true;\r\n            }\r\n\r\n            if (!modifyKey) {\r\n                gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;\r\n                babylonAnimation = new Animation(anim, isBone ? \"_matrix\" : targetPath, 1, animationType, Animation.ANIMATIONLOOPMODE_CYCLE);\r\n                gltfRuntime.scene._blockEntityCollection = false;\r\n            }\r\n\r\n            // For each frame\r\n            for (let j = 0; j < bufferInput.length; j++) {\r\n                let value: any;\r\n\r\n                if (targetPath === \"rotationQuaternion\") {\r\n                    // VEC4\r\n                    value = Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);\r\n                    arrayOffset += 4;\r\n                } else {\r\n                    // Position and scaling are VEC3\r\n                    value = Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);\r\n                    arrayOffset += 3;\r\n                }\r\n\r\n                if (isBone) {\r\n                    const bone = <Bone>targetNode;\r\n                    let translation = Vector3.Zero();\r\n                    let rotationQuaternion = new Quaternion();\r\n                    let scaling = Vector3.Zero();\r\n\r\n                    // Warning on decompose\r\n                    let mat = bone.getBaseMatrix();\r\n\r\n                    if (modifyKey && lastAnimation) {\r\n                        mat = lastAnimation.getKeys()[j].value;\r\n                    }\r\n\r\n                    mat.decompose(scaling, rotationQuaternion, translation);\r\n\r\n                    if (targetPath === \"position\") {\r\n                        translation = value;\r\n                    } else if (targetPath === \"rotationQuaternion\") {\r\n                        rotationQuaternion = value;\r\n                    } else {\r\n                        scaling = value;\r\n                    }\r\n\r\n                    value = Matrix.Compose(scaling, rotationQuaternion, translation);\r\n                }\r\n\r\n                if (!modifyKey) {\r\n                    keys.push({\r\n                        frame: bufferInput[j],\r\n                        value: value,\r\n                    });\r\n                } else if (lastAnimation) {\r\n                    lastAnimation.getKeys()[j].value = value;\r\n                }\r\n            }\r\n\r\n            // Finish\r\n            if (!modifyKey && babylonAnimation) {\r\n                babylonAnimation.setKeys(keys);\r\n                targetNode.animations.push(babylonAnimation);\r\n            }\r\n\r\n            lastAnimation = babylonAnimation;\r\n\r\n            gltfRuntime.scene.stopAnimation(targetNode);\r\n            gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);\r\n        }\r\n    }\r\n};\r\n\r\n/**\r\n * @returns the bones transformation matrix\r\n * @param node\r\n */\r\nconst ConfigureBoneTransformation = (node: IGLTFNode): Matrix => {\r\n    let mat: Nullable<Matrix>;\r\n\r\n    if (node.translation || node.rotation || node.scale) {\r\n        const scale = Vector3.FromArray(node.scale || [1, 1, 1]);\r\n        const rotation = Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);\r\n        const position = Vector3.FromArray(node.translation || [0, 0, 0]);\r\n\r\n        mat = Matrix.Compose(scale, rotation, position);\r\n    } else {\r\n        mat = Matrix.FromArray(node.matrix);\r\n    }\r\n\r\n    return mat;\r\n};\r\n\r\n/**\r\n * Returns the parent bone\r\n * @param gltfRuntime\r\n * @param skins\r\n * @param jointName\r\n * @param newSkeleton\r\n * @returns the parent bone\r\n */\r\nconst GetParentBone = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, jointName: string, newSkeleton: Skeleton): Nullable<Bone> => {\r\n    // Try to find\r\n    for (let i = 0; i < newSkeleton.bones.length; i++) {\r\n        if (newSkeleton.bones[i].name === jointName) {\r\n            return newSkeleton.bones[i];\r\n        }\r\n    }\r\n\r\n    // Not found, search in gltf nodes\r\n    const nodes = gltfRuntime.nodes;\r\n    for (const nde in nodes) {\r\n        const node: IGLTFNode = nodes[nde];\r\n\r\n        if (!node.jointName) {\r\n            continue;\r\n        }\r\n\r\n        const children = node.children;\r\n        for (let i = 0; i < children.length; i++) {\r\n            const child: IGLTFNode = gltfRuntime.nodes[children[i]];\r\n            if (!child.jointName) {\r\n                continue;\r\n            }\r\n\r\n            if (child.jointName === jointName) {\r\n                const mat = ConfigureBoneTransformation(node);\r\n                const bone = new Bone(node.name || \"\", newSkeleton, GetParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);\r\n                bone.id = nde;\r\n                return bone;\r\n            }\r\n        }\r\n    }\r\n\r\n    return null;\r\n};\r\n\r\n/**\r\n * Returns the appropriate root node\r\n * @param nodesToRoot\r\n * @param id\r\n * @returns the root node\r\n */\r\nconst GetNodeToRoot = (nodesToRoot: INodeToRoot[], id: string): Nullable<Bone> => {\r\n    for (let i = 0; i < nodesToRoot.length; i++) {\r\n        const nodeToRoot = nodesToRoot[i];\r\n\r\n        for (let j = 0; j < nodeToRoot.node.children.length; j++) {\r\n            const child = nodeToRoot.node.children[j];\r\n            if (child === id) {\r\n                return nodeToRoot.bone;\r\n            }\r\n        }\r\n    }\r\n\r\n    return null;\r\n};\r\n\r\n/**\r\n * Returns the node with the joint name\r\n * @param gltfRuntime\r\n * @param jointName\r\n * @returns the node with the joint name\r\n */\r\nconst GetJointNode = (gltfRuntime: IGLTFRuntime, jointName: string): Nullable<IJointNode> => {\r\n    const nodes = gltfRuntime.nodes;\r\n    let node: IGLTFNode = nodes[jointName];\r\n    if (node) {\r\n        return {\r\n            node: node,\r\n            id: jointName,\r\n        };\r\n    }\r\n\r\n    for (const nde in nodes) {\r\n        node = nodes[nde];\r\n        if (node.jointName === jointName) {\r\n            return {\r\n                node: node,\r\n                id: nde,\r\n            };\r\n        }\r\n    }\r\n\r\n    return null;\r\n};\r\n\r\n/**\r\n * Checks if a nodes is in joints\r\n * @param skins\r\n * @param id\r\n * @returns true if the node is in joints, else false\r\n */\r\nconst NodeIsInJoints = (skins: IGLTFSkins, id: string): boolean => {\r\n    for (let i = 0; i < skins.jointNames.length; i++) {\r\n        if (skins.jointNames[i] === id) {\r\n            return true;\r\n        }\r\n    }\r\n\r\n    return false;\r\n};\r\n\r\n/**\r\n * Fills the nodes to root for bones and builds hierarchy\r\n * @param gltfRuntime\r\n * @param newSkeleton\r\n * @param skins\r\n * @param nodesToRoot\r\n */\r\nconst GetNodesToRoot = (gltfRuntime: IGLTFRuntime, newSkeleton: Skeleton, skins: IGLTFSkins, nodesToRoot: INodeToRoot[]) => {\r\n    // Creates nodes for root\r\n    for (const nde in gltfRuntime.nodes) {\r\n        const node: IGLTFNode = gltfRuntime.nodes[nde];\r\n        const id = nde;\r\n\r\n        if (!node.jointName || NodeIsInJoints(skins, node.jointName)) {\r\n            continue;\r\n        }\r\n\r\n        // Create node to root bone\r\n        const mat = ConfigureBoneTransformation(node);\r\n        const bone = new Bone(node.name || \"\", newSkeleton, null, mat);\r\n        bone.id = id;\r\n        nodesToRoot.push({ bone: bone, node: node, id: id });\r\n    }\r\n\r\n    // Parenting\r\n    for (let i = 0; i < nodesToRoot.length; i++) {\r\n        const nodeToRoot = nodesToRoot[i];\r\n        const children = nodeToRoot.node.children;\r\n\r\n        for (let j = 0; j < children.length; j++) {\r\n            let child: Nullable<INodeToRoot> = null;\r\n\r\n            for (let k = 0; k < nodesToRoot.length; k++) {\r\n                if (nodesToRoot[k].id === children[j]) {\r\n                    child = nodesToRoot[k];\r\n                    break;\r\n                }\r\n            }\r\n\r\n            if (child) {\r\n                (<any>child.bone)._parent = nodeToRoot.bone;\r\n                nodeToRoot.bone.children.push(child.bone);\r\n            }\r\n        }\r\n    }\r\n};\r\n\r\n/**\r\n * Imports a skeleton\r\n * @param gltfRuntime\r\n * @param skins\r\n * @param mesh\r\n * @param newSkeleton\r\n * @returns the bone name\r\n */\r\nconst ImportSkeleton = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, mesh: Mesh, newSkeleton: Skeleton | undefined): Skeleton => {\r\n    if (!newSkeleton) {\r\n        newSkeleton = new Skeleton(skins.name || \"\", \"\", gltfRuntime.scene);\r\n    }\r\n\r\n    if (!skins.babylonSkeleton) {\r\n        return newSkeleton;\r\n    }\r\n\r\n    // Find the root bones\r\n    const nodesToRoot: INodeToRoot[] = [];\r\n    const nodesToRootToAdd: Bone[] = [];\r\n\r\n    GetNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot);\r\n    newSkeleton.bones = [];\r\n\r\n    // Joints\r\n    for (let i = 0; i < skins.jointNames.length; i++) {\r\n        const jointNode = GetJointNode(gltfRuntime, skins.jointNames[i]);\r\n\r\n        if (!jointNode) {\r\n            continue;\r\n        }\r\n\r\n        const node = jointNode.node;\r\n\r\n        if (!node) {\r\n            Tools.Warn(\"Joint named \" + skins.jointNames[i] + \" does not exist\");\r\n            continue;\r\n        }\r\n\r\n        const id = jointNode.id;\r\n\r\n        // Optimize, if the bone already exists...\r\n        const existingBone = gltfRuntime.scene.getBoneById(id);\r\n        if (existingBone) {\r\n            newSkeleton.bones.push(existingBone);\r\n            continue;\r\n        }\r\n\r\n        // Search for parent bone\r\n        let foundBone: boolean;\r\n        let parentBone: Nullable<Bone> = null;\r\n\r\n        for (let j = 0; j < i; j++) {\r\n            const jointNode = GetJointNode(gltfRuntime, skins.jointNames[j]);\r\n\r\n            if (!jointNode) {\r\n                continue;\r\n            }\r\n\r\n            const joint: IGLTFNode = jointNode.node;\r\n\r\n            if (!joint) {\r\n                Tools.Warn(\"Joint named \" + skins.jointNames[j] + \" does not exist when looking for parent\");\r\n                continue;\r\n            }\r\n\r\n            const children = joint.children;\r\n            if (!children) {\r\n                continue;\r\n            }\r\n            foundBone = false;\r\n\r\n            for (let k = 0; k < children.length; k++) {\r\n                if (children[k] === id) {\r\n                    parentBone = GetParentBone(gltfRuntime, skins, skins.jointNames[j], newSkeleton);\r\n                    foundBone = true;\r\n                    break;\r\n                }\r\n            }\r\n\r\n            if (foundBone) {\r\n                break;\r\n            }\r\n        }\r\n\r\n        // Create bone\r\n        const mat = ConfigureBoneTransformation(node);\r\n\r\n        if (!parentBone && nodesToRoot.length > 0) {\r\n            parentBone = GetNodeToRoot(nodesToRoot, id);\r\n\r\n            if (parentBone) {\r\n                if (nodesToRootToAdd.indexOf(parentBone) === -1) {\r\n                    nodesToRootToAdd.push(parentBone);\r\n                }\r\n            }\r\n        }\r\n\r\n        const bone = new Bone(node.jointName || \"\", newSkeleton, parentBone, mat);\r\n        bone.id = id;\r\n    }\r\n\r\n    // Polish\r\n    const bones = newSkeleton.bones;\r\n    newSkeleton.bones = [];\r\n\r\n    for (let i = 0; i < skins.jointNames.length; i++) {\r\n        const jointNode = GetJointNode(gltfRuntime, skins.jointNames[i]);\r\n\r\n        if (!jointNode) {\r\n            continue;\r\n        }\r\n\r\n        for (let j = 0; j < bones.length; j++) {\r\n            if (bones[j].id === jointNode.id) {\r\n                newSkeleton.bones.push(bones[j]);\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    newSkeleton.prepare();\r\n\r\n    // Finish\r\n    for (let i = 0; i < nodesToRootToAdd.length; i++) {\r\n        newSkeleton.bones.push(nodesToRootToAdd[i]);\r\n    }\r\n\r\n    return newSkeleton;\r\n};\r\n\r\n/**\r\n * Imports a mesh and its geometries\r\n * @param gltfRuntime\r\n * @param node\r\n * @param meshes\r\n * @param id\r\n * @param newMesh\r\n * @returns the new mesh\r\n */\r\nconst ImportMesh = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, meshes: string[], id: string, newMesh: Mesh): Mesh => {\r\n    if (!newMesh) {\r\n        gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;\r\n        newMesh = new Mesh(node.name || \"\", gltfRuntime.scene);\r\n        newMesh._parentContainer = gltfRuntime.assetContainer;\r\n        gltfRuntime.scene._blockEntityCollection = false;\r\n        newMesh.id = id;\r\n    }\r\n\r\n    if (!node.babylonNode) {\r\n        return newMesh;\r\n    }\r\n\r\n    const subMaterials: Material[] = [];\r\n\r\n    let vertexData: Nullable<VertexData> = null;\r\n    const verticesStarts: number[] = [];\r\n    const verticesCounts: number[] = [];\r\n    const indexStarts: number[] = [];\r\n    const indexCounts: number[] = [];\r\n\r\n    for (let meshIndex = 0; meshIndex < meshes.length; meshIndex++) {\r\n        const meshId = meshes[meshIndex];\r\n        const mesh: IGLTFMesh = gltfRuntime.meshes[meshId];\r\n\r\n        if (!mesh) {\r\n            continue;\r\n        }\r\n\r\n        // Positions, normals and UVs\r\n        for (let i = 0; i < mesh.primitives.length; i++) {\r\n            // Temporary vertex data\r\n            const tempVertexData = new VertexData();\r\n\r\n            const primitive = mesh.primitives[i];\r\n            if (primitive.mode !== 4) {\r\n                // continue;\r\n            }\r\n\r\n            const attributes = primitive.attributes;\r\n            let accessor: Nullable<IGLTFAccessor>;\r\n            let buffer: any;\r\n\r\n            // Set positions, normal and uvs\r\n            for (const semantic in attributes) {\r\n                // Link accessor and buffer view\r\n                accessor = gltfRuntime.accessors[attributes[semantic]];\r\n                buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);\r\n\r\n                if (semantic === \"NORMAL\") {\r\n                    tempVertexData.normals = new Float32Array(buffer.length);\r\n                    (<Float32Array>tempVertexData.normals).set(buffer);\r\n                } else if (semantic === \"POSITION\") {\r\n                    if (GLTFFileLoader.HomogeneousCoordinates) {\r\n                        tempVertexData.positions = new Float32Array(buffer.length - buffer.length / 4);\r\n\r\n                        for (let j = 0; j < buffer.length; j += 4) {\r\n                            tempVertexData.positions[j] = buffer[j];\r\n                            tempVertexData.positions[j + 1] = buffer[j + 1];\r\n                            tempVertexData.positions[j + 2] = buffer[j + 2];\r\n                        }\r\n                    } else {\r\n                        tempVertexData.positions = new Float32Array(buffer.length);\r\n                        (<Float32Array>tempVertexData.positions).set(buffer);\r\n                    }\r\n\r\n                    verticesCounts.push(tempVertexData.positions.length);\r\n                } else if (semantic.indexOf(\"TEXCOORD_\") !== -1) {\r\n                    const channel = Number(semantic.split(\"_\")[1]);\r\n                    const uvKind = VertexBuffer.UVKind + (channel === 0 ? \"\" : channel + 1);\r\n                    const uvs = new Float32Array(buffer.length);\r\n                    (<Float32Array>uvs).set(buffer);\r\n                    NormalizeUVs(uvs);\r\n                    tempVertexData.set(uvs, uvKind);\r\n                } else if (semantic === \"JOINT\") {\r\n                    tempVertexData.matricesIndices = new Float32Array(buffer.length);\r\n                    (<Float32Array>tempVertexData.matricesIndices).set(buffer);\r\n                } else if (semantic === \"WEIGHT\") {\r\n                    tempVertexData.matricesWeights = new Float32Array(buffer.length);\r\n                    (<Float32Array>tempVertexData.matricesWeights).set(buffer);\r\n                } else if (semantic === \"COLOR\") {\r\n                    tempVertexData.colors = new Float32Array(buffer.length);\r\n                    (<Float32Array>tempVertexData.colors).set(buffer);\r\n                }\r\n            }\r\n\r\n            // Indices\r\n            accessor = gltfRuntime.accessors[primitive.indices];\r\n            if (accessor) {\r\n                buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);\r\n\r\n                tempVertexData.indices = new Int32Array(buffer.length);\r\n                tempVertexData.indices.set(buffer);\r\n                indexCounts.push(tempVertexData.indices.length);\r\n            } else {\r\n                // Set indices on the fly\r\n                const indices: number[] = [];\r\n                for (let j = 0; j < (<FloatArray>tempVertexData.positions).length / 3; j++) {\r\n                    indices.push(j);\r\n                }\r\n\r\n                tempVertexData.indices = new Int32Array(indices);\r\n                indexCounts.push(tempVertexData.indices.length);\r\n            }\r\n\r\n            if (!vertexData) {\r\n                vertexData = tempVertexData;\r\n            } else {\r\n                vertexData.merge(tempVertexData);\r\n            }\r\n\r\n            // Sub material\r\n            const material = gltfRuntime.scene.getMaterialById(primitive.material);\r\n\r\n            subMaterials.push(material === null ? GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material);\r\n\r\n            // Update vertices start and index start\r\n            verticesStarts.push(verticesStarts.length === 0 ? 0 : verticesStarts[verticesStarts.length - 1] + verticesCounts[verticesCounts.length - 2]);\r\n            indexStarts.push(indexStarts.length === 0 ? 0 : indexStarts[indexStarts.length - 1] + indexCounts[indexCounts.length - 2]);\r\n        }\r\n    }\r\n    let material: StandardMaterial | MultiMaterial;\r\n    gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;\r\n    if (subMaterials.length > 1) {\r\n        material = new MultiMaterial(\"multimat\" + id, gltfRuntime.scene);\r\n        material.subMaterials = subMaterials;\r\n    } else {\r\n        material = new StandardMaterial(\"multimat\" + id, gltfRuntime.scene);\r\n    }\r\n\r\n    if (subMaterials.length === 1) {\r\n        material = subMaterials[0] as StandardMaterial;\r\n    }\r\n\r\n    material._parentContainer = gltfRuntime.assetContainer;\r\n\r\n    if (!newMesh.material) {\r\n        newMesh.material = material;\r\n    }\r\n\r\n    // Apply geometry\r\n    new Geometry(id, gltfRuntime.scene, vertexData!, false, newMesh);\r\n    newMesh.computeWorldMatrix(true);\r\n\r\n    gltfRuntime.scene._blockEntityCollection = false;\r\n\r\n    // Apply submeshes\r\n    newMesh.subMeshes = [];\r\n    let index = 0;\r\n    for (let meshIndex = 0; meshIndex < meshes.length; meshIndex++) {\r\n        const meshId = meshes[meshIndex];\r\n        const mesh: IGLTFMesh = gltfRuntime.meshes[meshId];\r\n\r\n        if (!mesh) {\r\n            continue;\r\n        }\r\n\r\n        for (let i = 0; i < mesh.primitives.length; i++) {\r\n            if (mesh.primitives[i].mode !== 4) {\r\n                //continue;\r\n            }\r\n\r\n            SubMesh.AddToMesh(index, verticesStarts[index], verticesCounts[index], indexStarts[index], indexCounts[index], newMesh, newMesh, true);\r\n            index++;\r\n        }\r\n    }\r\n\r\n    // Finish\r\n    return newMesh;\r\n};\r\n\r\n/**\r\n * Configure node transformation from position, rotation and scaling\r\n * @param newNode\r\n * @param position\r\n * @param rotation\r\n * @param scaling\r\n */\r\nconst ConfigureNode = (newNode: any, position: Vector3, rotation: Quaternion, scaling: Vector3) => {\r\n    if (newNode.position) {\r\n        newNode.position = position;\r\n    }\r\n\r\n    if (newNode.rotationQuaternion || newNode.rotation) {\r\n        newNode.rotationQuaternion = rotation;\r\n    }\r\n\r\n    if (newNode.scaling) {\r\n        newNode.scaling = scaling;\r\n    }\r\n};\r\n\r\n/**\r\n * Configures node from transformation matrix\r\n * @param newNode\r\n * @param node\r\n */\r\nconst ConfigureNodeFromMatrix = (newNode: Mesh, node: IGLTFNode) => {\r\n    if (node.matrix) {\r\n        const position = new Vector3(0, 0, 0);\r\n        const rotation = new Quaternion();\r\n        const scaling = new Vector3(0, 0, 0);\r\n        const mat = Matrix.FromArray(node.matrix);\r\n        mat.decompose(scaling, rotation, position);\r\n\r\n        ConfigureNode(newNode, position, rotation, scaling);\r\n    } else if (node.translation && node.rotation && node.scale) {\r\n        ConfigureNode(newNode, Vector3.FromArray(node.translation), Quaternion.FromArray(node.rotation), Vector3.FromArray(node.scale));\r\n    }\r\n\r\n    newNode.computeWorldMatrix(true);\r\n};\r\n\r\n/**\r\n * Imports a node\r\n * @param gltfRuntime\r\n * @param node\r\n * @param id\r\n * @returns the newly imported node\r\n */\r\nconst ImportNode = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, id: string): Nullable<Node> => {\r\n    let lastNode: Nullable<Node> = null;\r\n\r\n    if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {\r\n        if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || \"\") === -1) {\r\n            return null;\r\n        }\r\n    }\r\n\r\n    // Meshes\r\n    if (node.skin) {\r\n        if (node.meshes) {\r\n            const skin: IGLTFSkins = gltfRuntime.skins[node.skin];\r\n\r\n            const newMesh = ImportMesh(gltfRuntime, node, node.meshes, id, <Mesh>node.babylonNode);\r\n            newMesh.skeleton = gltfRuntime.scene.getLastSkeletonById(node.skin);\r\n\r\n            if (newMesh.skeleton === null) {\r\n                newMesh.skeleton = ImportSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton);\r\n\r\n                if (!skin.babylonSkeleton) {\r\n                    skin.babylonSkeleton = newMesh.skeleton;\r\n                }\r\n            }\r\n\r\n            lastNode = newMesh;\r\n        }\r\n    } else if (node.meshes) {\r\n        /**\r\n         * Improve meshes property\r\n         */\r\n        const newMesh = ImportMesh(gltfRuntime, node, node.mesh ? [node.mesh] : node.meshes, id, <Mesh>node.babylonNode);\r\n        lastNode = newMesh;\r\n    }\r\n    // Lights\r\n    else if (node.light && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {\r\n        const light: IGLTFLight = gltfRuntime.lights[node.light];\r\n\r\n        if (light) {\r\n            if (light.type === \"ambient\") {\r\n                const ambienLight: IGLTFAmbienLight = (<any>light)[light.type];\r\n                const hemiLight = new HemisphericLight(node.light, Vector3.Zero(), gltfRuntime.scene);\r\n                hemiLight.name = node.name || \"\";\r\n\r\n                if (ambienLight.color) {\r\n                    hemiLight.diffuse = Color3.FromArray(ambienLight.color);\r\n                }\r\n\r\n                lastNode = hemiLight;\r\n            } else if (light.type === \"directional\") {\r\n                const directionalLight: IGLTFDirectionalLight = (<any>light)[light.type];\r\n                const dirLight = new DirectionalLight(node.light, Vector3.Zero(), gltfRuntime.scene);\r\n                dirLight.name = node.name || \"\";\r\n\r\n                if (directionalLight.color) {\r\n                    dirLight.diffuse = Color3.FromArray(directionalLight.color);\r\n                }\r\n\r\n                lastNode = dirLight;\r\n            } else if (light.type === \"point\") {\r\n                const pointLight: IGLTFPointLight = (<any>light)[light.type];\r\n                const ptLight = new PointLight(node.light, Vector3.Zero(), gltfRuntime.scene);\r\n                ptLight.name = node.name || \"\";\r\n\r\n                if (pointLight.color) {\r\n                    ptLight.diffuse = Color3.FromArray(pointLight.color);\r\n                }\r\n\r\n                lastNode = ptLight;\r\n            } else if (light.type === \"spot\") {\r\n                const spotLight: IGLTFSpotLight = (<any>light)[light.type];\r\n                const spLight = new SpotLight(node.light, Vector3.Zero(), Vector3.Zero(), 0, 0, gltfRuntime.scene);\r\n                spLight.name = node.name || \"\";\r\n\r\n                if (spotLight.color) {\r\n                    spLight.diffuse = Color3.FromArray(spotLight.color);\r\n                }\r\n\r\n                if (spotLight.fallOfAngle) {\r\n                    spLight.angle = spotLight.fallOfAngle;\r\n                }\r\n\r\n                if (spotLight.fallOffExponent) {\r\n                    spLight.exponent = spotLight.fallOffExponent;\r\n                }\r\n\r\n                lastNode = spLight;\r\n            }\r\n        }\r\n    }\r\n    // Cameras\r\n    else if (node.camera && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {\r\n        const camera: IGLTFCamera = gltfRuntime.cameras[node.camera];\r\n\r\n        if (camera) {\r\n            gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;\r\n            if (camera.type === \"orthographic\") {\r\n                const orthoCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene, false);\r\n\r\n                orthoCamera.name = node.name || \"\";\r\n                orthoCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;\r\n                orthoCamera.attachControl();\r\n\r\n                lastNode = orthoCamera;\r\n\r\n                orthoCamera._parentContainer = gltfRuntime.assetContainer;\r\n            } else if (camera.type === \"perspective\") {\r\n                const perspectiveCamera: IGLTFCameraPerspective = (<any>camera)[camera.type];\r\n                const persCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene, false);\r\n\r\n                persCamera.name = node.name || \"\";\r\n                persCamera.attachControl();\r\n\r\n                if (!perspectiveCamera.aspectRatio) {\r\n                    perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();\r\n                }\r\n\r\n                if (perspectiveCamera.znear && perspectiveCamera.zfar) {\r\n                    persCamera.maxZ = perspectiveCamera.zfar;\r\n                    persCamera.minZ = perspectiveCamera.znear;\r\n                }\r\n\r\n                lastNode = persCamera;\r\n                persCamera._parentContainer = gltfRuntime.assetContainer;\r\n            }\r\n\r\n            gltfRuntime.scene._blockEntityCollection = false;\r\n        }\r\n    }\r\n\r\n    // Empty node\r\n    if (!node.jointName) {\r\n        if (node.babylonNode) {\r\n            return node.babylonNode;\r\n        } else if (lastNode === null) {\r\n            gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;\r\n            const dummy = new Mesh(node.name || \"\", gltfRuntime.scene);\r\n            dummy._parentContainer = gltfRuntime.assetContainer;\r\n            gltfRuntime.scene._blockEntityCollection = false;\r\n            node.babylonNode = dummy;\r\n            lastNode = dummy;\r\n        }\r\n    }\r\n\r\n    if (lastNode !== null) {\r\n        if (node.matrix && lastNode instanceof Mesh) {\r\n            ConfigureNodeFromMatrix(lastNode, node);\r\n        } else {\r\n            const translation = node.translation || [0, 0, 0];\r\n            const rotation = node.rotation || [0, 0, 0, 1];\r\n            const scale = node.scale || [1, 1, 1];\r\n            ConfigureNode(lastNode, Vector3.FromArray(translation), Quaternion.FromArray(rotation), Vector3.FromArray(scale));\r\n        }\r\n\r\n        lastNode.updateCache(true);\r\n        node.babylonNode = lastNode;\r\n    }\r\n\r\n    return lastNode;\r\n};\r\n\r\n/**\r\n * Traverses nodes and creates them\r\n * @param gltfRuntime\r\n * @param id\r\n * @param parent\r\n * @param meshIncluded\r\n */\r\nconst TraverseNodes = (gltfRuntime: IGLTFRuntime, id: string, parent: Nullable<Node>, meshIncluded: boolean = false) => {\r\n    const node: IGLTFNode = gltfRuntime.nodes[id];\r\n    let newNode: Nullable<Node> = null;\r\n\r\n    if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {\r\n        if (gltfRuntime.importMeshesNames.indexOf(node.name || \"\") !== -1 || gltfRuntime.importMeshesNames.length === 0) {\r\n            meshIncluded = true;\r\n        } else {\r\n            meshIncluded = false;\r\n        }\r\n    } else {\r\n        meshIncluded = true;\r\n    }\r\n\r\n    if (!node.jointName && meshIncluded) {\r\n        newNode = ImportNode(gltfRuntime, node, id);\r\n\r\n        if (newNode !== null) {\r\n            newNode.id = id;\r\n            newNode.parent = parent;\r\n        }\r\n    }\r\n\r\n    if (node.children) {\r\n        for (let i = 0; i < node.children.length; i++) {\r\n            TraverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);\r\n        }\r\n    }\r\n};\r\n\r\n/**\r\n * do stuff after buffers, shaders are loaded (e.g. hook up materials, load animations, etc.)\r\n * @param gltfRuntime\r\n */\r\nconst PostLoad = (gltfRuntime: IGLTFRuntime) => {\r\n    // Nodes\r\n    let currentScene: IGLTFScene = <IGLTFScene>gltfRuntime.currentScene;\r\n\r\n    if (currentScene) {\r\n        for (let i = 0; i < currentScene.nodes.length; i++) {\r\n            TraverseNodes(gltfRuntime, currentScene.nodes[i], null);\r\n        }\r\n    } else {\r\n        for (const thing in gltfRuntime.scenes) {\r\n            currentScene = gltfRuntime.scenes[thing];\r\n\r\n            for (let i = 0; i < currentScene.nodes.length; i++) {\r\n                TraverseNodes(gltfRuntime, currentScene.nodes[i], null);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Set animations\r\n    LoadAnimations(gltfRuntime);\r\n\r\n    for (let i = 0; i < gltfRuntime.scene.skeletons.length; i++) {\r\n        const skeleton = gltfRuntime.scene.skeletons[i];\r\n        gltfRuntime.scene.beginAnimation(skeleton, 0, Number.MAX_VALUE, true, 1.0);\r\n    }\r\n};\r\n\r\n/**\r\n * onBind shaderrs callback to set uniforms and matrices\r\n * @param mesh\r\n * @param gltfRuntime\r\n * @param unTreatedUniforms\r\n * @param shaderMaterial\r\n * @param technique\r\n * @param material\r\n * @param onSuccess\r\n */\r\nconst OnBindShaderMaterial = (\r\n    mesh: AbstractMesh,\r\n    gltfRuntime: IGLTFRuntime,\r\n    unTreatedUniforms: { [key: string]: IGLTFTechniqueParameter },\r\n    shaderMaterial: ShaderMaterial,\r\n    technique: IGLTFTechnique,\r\n    material: IGLTFMaterial,\r\n    onSuccess: (shaderMaterial: ShaderMaterial) => void\r\n) => {\r\n    const materialValues = material.values || technique.parameters;\r\n\r\n    for (const unif in unTreatedUniforms) {\r\n        const uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];\r\n        const type = uniform.type;\r\n\r\n        if (type === EParameterType.FLOAT_MAT2 || type === EParameterType.FLOAT_MAT3 || type === EParameterType.FLOAT_MAT4) {\r\n            if (uniform.semantic && !uniform.source && !uniform.node) {\r\n                GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());\r\n            } else if (uniform.semantic && (uniform.source || uniform.node)) {\r\n                let source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || \"\");\r\n                if (source === null) {\r\n                    source = gltfRuntime.scene.getNodeById(uniform.source || uniform.node || \"\");\r\n                }\r\n                if (source === null) {\r\n                    continue;\r\n                }\r\n\r\n                GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, shaderMaterial.getEffect());\r\n            }\r\n        } else {\r\n            const value = (<any>materialValues)[technique.uniforms[unif]];\r\n            if (!value) {\r\n                continue;\r\n            }\r\n\r\n            if (type === EParameterType.SAMPLER_2D) {\r\n                const texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;\r\n\r\n                if (texture === null || texture === undefined) {\r\n                    continue;\r\n                }\r\n\r\n                shaderMaterial.getEffect().setTexture(unif, texture);\r\n            } else {\r\n                GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);\r\n            }\r\n        }\r\n    }\r\n\r\n    onSuccess(shaderMaterial);\r\n};\r\n\r\n/**\r\n * Prepare uniforms to send the only one time\r\n * Loads the appropriate textures\r\n * @param gltfRuntime\r\n * @param shaderMaterial\r\n * @param technique\r\n * @param material\r\n */\r\nconst PrepareShaderMaterialUniforms = (\r\n    gltfRuntime: IGLTFRuntime,\r\n    shaderMaterial: ShaderMaterial,\r\n    technique: IGLTFTechnique,\r\n    material: IGLTFMaterial,\r\n    unTreatedUniforms: { [key: string]: IGLTFTechniqueParameter }\r\n) => {\r\n    const materialValues = material.values || technique.parameters;\r\n    const techniqueUniforms = technique.uniforms;\r\n\r\n    /**\r\n     * Prepare values here (not matrices)\r\n     */\r\n    for (const unif in unTreatedUniforms) {\r\n        const uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];\r\n        const type = uniform.type;\r\n        let value = (<any>materialValues)[techniqueUniforms[unif]];\r\n\r\n        if (value === undefined) {\r\n            // In case the value is the same for all materials\r\n            value = <any>uniform.value;\r\n        }\r\n\r\n        if (!value) {\r\n            continue;\r\n        }\r\n\r\n        const onLoadTexture = (uniformName: Nullable<string>) => {\r\n            return (texture: Texture) => {\r\n                if (uniform.value && uniformName) {\r\n                    // Static uniform\r\n                    shaderMaterial.setTexture(uniformName, texture);\r\n                    delete unTreatedUniforms[uniformName];\r\n                }\r\n            };\r\n        };\r\n\r\n        // Texture (sampler2D)\r\n        if (type === EParameterType.SAMPLER_2D) {\r\n            GLTFLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), () => onLoadTexture(null));\r\n        }\r\n        // Others\r\n        else {\r\n            if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {\r\n                // Static uniform\r\n                delete unTreatedUniforms[unif];\r\n            }\r\n        }\r\n    }\r\n};\r\n\r\n/**\r\n * Shader compilation failed\r\n * @param program\r\n * @param shaderMaterial\r\n * @param onError\r\n * @returns callback when shader is compiled\r\n */\r\nconst OnShaderCompileError = (program: IGLTFProgram, shaderMaterial: ShaderMaterial, onError: (message: string) => void) => {\r\n    return (effect: Effect, error: string) => {\r\n        shaderMaterial.dispose(true);\r\n        onError(\"Cannot compile program named \" + program.name + \". Error: \" + error + \". Default material will be applied\");\r\n    };\r\n};\r\n\r\n/**\r\n * Shader compilation success\r\n * @param gltfRuntime\r\n * @param shaderMaterial\r\n * @param technique\r\n * @param material\r\n * @param unTreatedUniforms\r\n * @param onSuccess\r\n * @returns callback when shader is compiled\r\n */\r\nconst OnShaderCompileSuccess = (\r\n    gltfRuntime: IGLTFRuntime,\r\n    shaderMaterial: ShaderMaterial,\r\n    technique: IGLTFTechnique,\r\n    material: IGLTFMaterial,\r\n    unTreatedUniforms: { [key: string]: IGLTFTechniqueParameter },\r\n    onSuccess: (shaderMaterial: ShaderMaterial) => void\r\n) => {\r\n    return (_: Effect) => {\r\n        PrepareShaderMaterialUniforms(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms);\r\n\r\n        shaderMaterial.onBind = (mesh: AbstractMesh) => {\r\n            OnBindShaderMaterial(mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess);\r\n        };\r\n    };\r\n};\r\n\r\n/**\r\n * Returns the appropriate uniform if already handled by babylon\r\n * @param tokenizer\r\n * @param technique\r\n * @param unTreatedUniforms\r\n * @returns the name of the uniform handled by babylon\r\n */\r\nconst ParseShaderUniforms = (tokenizer: Tokenizer, technique: IGLTFTechnique, unTreatedUniforms: { [key: string]: IGLTFTechniqueParameter }): string => {\r\n    for (const unif in technique.uniforms) {\r\n        const uniform = technique.uniforms[unif];\r\n        const uniformParameter: IGLTFTechniqueParameter = technique.parameters[uniform];\r\n\r\n        if (tokenizer.currentIdentifier === unif) {\r\n            if (uniformParameter.semantic && !uniformParameter.source && !uniformParameter.node) {\r\n                const transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);\r\n\r\n                if (transformIndex !== -1) {\r\n                    delete unTreatedUniforms[unif];\r\n                    return BabylonTransforms[transformIndex];\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    return tokenizer.currentIdentifier;\r\n};\r\n\r\n/**\r\n * All shaders loaded. Create materials one by one\r\n * @param gltfRuntime\r\n */\r\nconst ImportMaterials = (gltfRuntime: IGLTFRuntime) => {\r\n    // Create materials\r\n    for (const mat in gltfRuntime.materials) {\r\n        GLTFLoaderExtension.LoadMaterialAsync(\r\n            gltfRuntime,\r\n            mat,\r\n            () => {},\r\n            () => {}\r\n        );\r\n    }\r\n};\r\n\r\n/**\r\n * Implementation of the base glTF spec\r\n * @internal\r\n */\r\nexport class GLTFLoaderBase {\r\n    public static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime {\r\n        const gltfRuntime: IGLTFRuntime = {\r\n            extensions: {},\r\n            accessors: {},\r\n            buffers: {},\r\n            bufferViews: {},\r\n            meshes: {},\r\n            lights: {},\r\n            cameras: {},\r\n            nodes: {},\r\n            images: {},\r\n            textures: {},\r\n            shaders: {},\r\n            programs: {},\r\n            samplers: {},\r\n            techniques: {},\r\n            materials: {},\r\n            animations: {},\r\n            skins: {},\r\n            extensionsUsed: [],\r\n\r\n            scenes: {},\r\n\r\n            buffersCount: 0,\r\n            shaderscount: 0,\r\n\r\n            scene: scene,\r\n            rootUrl: rootUrl,\r\n\r\n            loadedBufferCount: 0,\r\n            loadedBufferViews: {},\r\n\r\n            loadedShaderCount: 0,\r\n\r\n            importOnlyMeshes: false,\r\n\r\n            dummyNodes: [],\r\n\r\n            assetContainer: null,\r\n        };\r\n\r\n        // Parse\r\n        if (parsedData.extensions) {\r\n            ParseObject(parsedData.extensions, \"extensions\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.extensionsUsed) {\r\n            ParseObject(parsedData.extensionsUsed, \"extensionsUsed\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.buffers) {\r\n            ParseBuffers(parsedData.buffers, gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.bufferViews) {\r\n            ParseObject(parsedData.bufferViews, \"bufferViews\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.accessors) {\r\n            ParseObject(parsedData.accessors, \"accessors\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.meshes) {\r\n            ParseObject(parsedData.meshes, \"meshes\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.lights) {\r\n            ParseObject(parsedData.lights, \"lights\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.cameras) {\r\n            ParseObject(parsedData.cameras, \"cameras\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.nodes) {\r\n            ParseObject(parsedData.nodes, \"nodes\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.images) {\r\n            ParseObject(parsedData.images, \"images\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.textures) {\r\n            ParseObject(parsedData.textures, \"textures\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.shaders) {\r\n            ParseShaders(parsedData.shaders, gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.programs) {\r\n            ParseObject(parsedData.programs, \"programs\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.samplers) {\r\n            ParseObject(parsedData.samplers, \"samplers\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.techniques) {\r\n            ParseObject(parsedData.techniques, \"techniques\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.materials) {\r\n            ParseObject(parsedData.materials, \"materials\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.animations) {\r\n            ParseObject(parsedData.animations, \"animations\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.skins) {\r\n            ParseObject(parsedData.skins, \"skins\", gltfRuntime);\r\n        }\r\n\r\n        if (parsedData.scenes) {\r\n            gltfRuntime.scenes = parsedData.scenes;\r\n        }\r\n\r\n        if (parsedData.scene && parsedData.scenes) {\r\n            gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];\r\n        }\r\n\r\n        return gltfRuntime;\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadBufferAsync(\r\n        gltfRuntime: IGLTFRuntime,\r\n        id: string,\r\n        onSuccess: (buffer: ArrayBufferView) => void,\r\n        onError: (message: string) => void,\r\n        onProgress?: () => void\r\n    ): void {\r\n        const buffer: IGLTFBuffer = gltfRuntime.buffers[id];\r\n\r\n        if (Tools.IsBase64(buffer.uri)) {\r\n            setTimeout(() => onSuccess(new Uint8Array(Tools.DecodeBase64(buffer.uri))));\r\n        } else {\r\n            Tools.LoadFile(\r\n                gltfRuntime.rootUrl + buffer.uri,\r\n                (data) => onSuccess(new Uint8Array(data as ArrayBuffer)),\r\n                onProgress,\r\n                undefined,\r\n                true,\r\n                (request) => {\r\n                    if (request) {\r\n                        onError(request.status + \" \" + request.statusText);\r\n                    }\r\n                }\r\n            );\r\n        }\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: Nullable<ArrayBufferView>) => void, onError: (message: string) => void): void {\r\n        const texture: IGLTFTexture = gltfRuntime.textures[id];\r\n\r\n        if (!texture || !texture.source) {\r\n            onError(\"\");\r\n            return;\r\n        }\r\n\r\n        if (texture.babylonTexture) {\r\n            onSuccess(null);\r\n            return;\r\n        }\r\n\r\n        const source: IGLTFImage = gltfRuntime.images[texture.source];\r\n\r\n        if (Tools.IsBase64(source.uri)) {\r\n            setTimeout(() => onSuccess(new Uint8Array(Tools.DecodeBase64(source.uri))));\r\n        } else {\r\n            Tools.LoadFile(\r\n                gltfRuntime.rootUrl + source.uri,\r\n                (data) => onSuccess(new Uint8Array(data as ArrayBuffer)),\r\n                undefined,\r\n                undefined,\r\n                true,\r\n                (request) => {\r\n                    if (request) {\r\n                        onError(request.status + \" \" + request.statusText);\r\n                    }\r\n                }\r\n            );\r\n        }\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: Nullable<ArrayBufferView>, onSuccess: (texture: Texture) => void): void {\r\n        const texture: IGLTFTexture = gltfRuntime.textures[id];\r\n\r\n        if (texture.babylonTexture) {\r\n            onSuccess(texture.babylonTexture);\r\n            return;\r\n        }\r\n\r\n        const sampler: IGLTFSampler = gltfRuntime.samplers[texture.sampler];\r\n\r\n        const createMipMaps =\r\n            sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_NEAREST ||\r\n            sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_LINEAR ||\r\n            sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_NEAREST ||\r\n            sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_LINEAR;\r\n\r\n        const samplingMode = Texture.BILINEAR_SAMPLINGMODE;\r\n        const blob = buffer == null ? new Blob() : new Blob([GetBlobBufferSource(buffer)]);\r\n        const blobURL = URL.createObjectURL(blob);\r\n        const revokeBlobURL = () => URL.revokeObjectURL(blobURL);\r\n        const newTexture = new Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);\r\n        if (sampler.wrapS !== undefined) {\r\n            newTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);\r\n        }\r\n        if (sampler.wrapT !== undefined) {\r\n            newTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);\r\n        }\r\n        newTexture.name = id;\r\n\r\n        texture.babylonTexture = newTexture;\r\n        onSuccess(newTexture);\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string | ArrayBuffer) => void, onError?: (message: string) => void): void {\r\n        const shader: IGLTFShader = gltfRuntime.shaders[id];\r\n\r\n        if (Tools.IsBase64(shader.uri)) {\r\n            const shaderString = atob(shader.uri.split(\",\")[1]);\r\n            if (onSuccess) {\r\n                onSuccess(shaderString);\r\n            }\r\n        } else {\r\n            Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, (request) => {\r\n                if (request && onError) {\r\n                    onError(request.status + \" \" + request.statusText);\r\n                }\r\n            });\r\n        }\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): void {\r\n        const material: IGLTFMaterial = gltfRuntime.materials[id];\r\n        if (!material.technique) {\r\n            if (onError) {\r\n                onError(\"No technique found.\");\r\n            }\r\n            return;\r\n        }\r\n\r\n        const technique: IGLTFTechnique = gltfRuntime.techniques[material.technique];\r\n        if (!technique) {\r\n            gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;\r\n            const defaultMaterial = new StandardMaterial(id, gltfRuntime.scene);\r\n            defaultMaterial._parentContainer = gltfRuntime.assetContainer;\r\n            gltfRuntime.scene._blockEntityCollection = false;\r\n            defaultMaterial.diffuseColor = new Color3(0.5, 0.5, 0.5);\r\n            defaultMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;\r\n            onSuccess(defaultMaterial);\r\n            return;\r\n        }\r\n\r\n        const program: IGLTFProgram = gltfRuntime.programs[technique.program];\r\n        const states: IGLTFTechniqueStates = technique.states;\r\n\r\n        const vertexShader: string = Effect.ShadersStore[program.vertexShader + \"VertexShader\"];\r\n        const pixelShader: string = Effect.ShadersStore[program.fragmentShader + \"PixelShader\"];\r\n        let newVertexShader = \"\";\r\n        let newPixelShader = \"\";\r\n\r\n        const vertexTokenizer = new Tokenizer(vertexShader);\r\n        const pixelTokenizer = new Tokenizer(pixelShader);\r\n\r\n        const unTreatedUniforms: { [key: string]: IGLTFTechniqueParameter } = {};\r\n        const uniforms: string[] = [];\r\n        const attributes: string[] = [];\r\n        const samplers: string[] = [];\r\n\r\n        // Fill uniform, sampler2D and attributes\r\n        for (const unif in technique.uniforms) {\r\n            const uniform = technique.uniforms[unif];\r\n            const uniformParameter: IGLTFTechniqueParameter = technique.parameters[uniform];\r\n\r\n            unTreatedUniforms[unif] = uniformParameter;\r\n\r\n            if (uniformParameter.semantic && !uniformParameter.node && !uniformParameter.source) {\r\n                const transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);\r\n                if (transformIndex !== -1) {\r\n                    uniforms.push(BabylonTransforms[transformIndex]);\r\n                    delete unTreatedUniforms[unif];\r\n                } else {\r\n                    uniforms.push(unif);\r\n                }\r\n            } else if (uniformParameter.type === EParameterType.SAMPLER_2D) {\r\n                samplers.push(unif);\r\n            } else {\r\n                uniforms.push(unif);\r\n            }\r\n        }\r\n\r\n        for (const attr in technique.attributes) {\r\n            const attribute = technique.attributes[attr];\r\n            const attributeParameter: IGLTFTechniqueParameter = technique.parameters[attribute];\r\n\r\n            if (attributeParameter.semantic) {\r\n                const name = GetAttribute(attributeParameter);\r\n                if (name) {\r\n                    attributes.push(name);\r\n                }\r\n            }\r\n        }\r\n\r\n        // Configure vertex shader\r\n        while (!vertexTokenizer.isEnd() && vertexTokenizer.getNextToken()) {\r\n            const tokenType = vertexTokenizer.currentToken;\r\n\r\n            if (tokenType !== ETokenType.IDENTIFIER) {\r\n                newVertexShader += vertexTokenizer.currentString;\r\n                continue;\r\n            }\r\n\r\n            let foundAttribute = false;\r\n\r\n            for (const attr in technique.attributes) {\r\n                const attribute = technique.attributes[attr];\r\n                const attributeParameter: IGLTFTechniqueParameter = technique.parameters[attribute];\r\n\r\n                if (vertexTokenizer.currentIdentifier === attr && attributeParameter.semantic) {\r\n                    newVertexShader += GetAttribute(attributeParameter);\r\n                    foundAttribute = true;\r\n                    break;\r\n                }\r\n            }\r\n\r\n            if (foundAttribute) {\r\n                continue;\r\n            }\r\n\r\n            newVertexShader += ParseShaderUniforms(vertexTokenizer, technique, unTreatedUniforms);\r\n        }\r\n\r\n        // Configure pixel shader\r\n        while (!pixelTokenizer.isEnd() && pixelTokenizer.getNextToken()) {\r\n            const tokenType = pixelTokenizer.currentToken;\r\n\r\n            if (tokenType !== ETokenType.IDENTIFIER) {\r\n                newPixelShader += pixelTokenizer.currentString;\r\n                continue;\r\n            }\r\n\r\n            newPixelShader += ParseShaderUniforms(pixelTokenizer, technique, unTreatedUniforms);\r\n        }\r\n\r\n        // Create shader material\r\n        const shaderPath = {\r\n            vertex: program.vertexShader + id,\r\n            fragment: program.fragmentShader + id,\r\n        };\r\n\r\n        const options = {\r\n            attributes: attributes,\r\n            uniforms: uniforms,\r\n            samplers: samplers,\r\n            needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1,\r\n        };\r\n\r\n        Effect.ShadersStore[program.vertexShader + id + \"VertexShader\"] = newVertexShader;\r\n        Effect.ShadersStore[program.fragmentShader + id + \"PixelShader\"] = newPixelShader;\r\n\r\n        const shaderMaterial = new ShaderMaterial(id, gltfRuntime.scene, shaderPath, options);\r\n        shaderMaterial.onError = OnShaderCompileError(program, shaderMaterial, onError);\r\n        shaderMaterial.onCompiled = OnShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);\r\n        shaderMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;\r\n\r\n        if (states && states.functions) {\r\n            const functions = states.functions;\r\n            if (functions.cullFace && functions.cullFace[0] !== ECullingType.BACK) {\r\n                shaderMaterial.backFaceCulling = false;\r\n            }\r\n\r\n            const blendFunc = functions.blendFuncSeparate;\r\n            if (blendFunc) {\r\n                if (\r\n                    blendFunc[0] === EBlendingFunction.SRC_ALPHA &&\r\n                    blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_ALPHA &&\r\n                    blendFunc[2] === EBlendingFunction.ONE &&\r\n                    blendFunc[3] === EBlendingFunction.ONE\r\n                ) {\r\n                    shaderMaterial.alphaMode = Constants.ALPHA_COMBINE;\r\n                } else if (\r\n                    blendFunc[0] === EBlendingFunction.ONE &&\r\n                    blendFunc[1] === EBlendingFunction.ONE &&\r\n                    blendFunc[2] === EBlendingFunction.ZERO &&\r\n                    blendFunc[3] === EBlendingFunction.ONE\r\n                ) {\r\n                    shaderMaterial.alphaMode = Constants.ALPHA_ONEONE;\r\n                } else if (\r\n                    blendFunc[0] === EBlendingFunction.SRC_ALPHA &&\r\n                    blendFunc[1] === EBlendingFunction.ONE &&\r\n                    blendFunc[2] === EBlendingFunction.ZERO &&\r\n                    blendFunc[3] === EBlendingFunction.ONE\r\n                ) {\r\n                    shaderMaterial.alphaMode = Constants.ALPHA_ADD;\r\n                } else if (\r\n                    blendFunc[0] === EBlendingFunction.ZERO &&\r\n                    blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_COLOR &&\r\n                    blendFunc[2] === EBlendingFunction.ONE &&\r\n                    blendFunc[3] === EBlendingFunction.ONE\r\n                ) {\r\n                    shaderMaterial.alphaMode = Constants.ALPHA_SUBTRACT;\r\n                } else if (\r\n                    blendFunc[0] === EBlendingFunction.DST_COLOR &&\r\n                    blendFunc[1] === EBlendingFunction.ZERO &&\r\n                    blendFunc[2] === EBlendingFunction.ONE &&\r\n                    blendFunc[3] === EBlendingFunction.ONE\r\n                ) {\r\n                    shaderMaterial.alphaMode = Constants.ALPHA_MULTIPLY;\r\n                } else if (\r\n                    blendFunc[0] === EBlendingFunction.SRC_ALPHA &&\r\n                    blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_COLOR &&\r\n                    blendFunc[2] === EBlendingFunction.ONE &&\r\n                    blendFunc[3] === EBlendingFunction.ONE\r\n                ) {\r\n                    shaderMaterial.alphaMode = Constants.ALPHA_MAXIMIZED;\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n/**\r\n * glTF V1 Loader\r\n * @internal\r\n * @deprecated\r\n */\r\nexport class GLTFLoader implements IGLTFLoader {\r\n    public static Extensions: { [name: string]: GLTFLoaderExtension } = {};\r\n\r\n    public static RegisterExtension(extension: GLTFLoaderExtension): void {\r\n        if (GLTFLoader.Extensions[extension.name]) {\r\n            Tools.Error('Tool with the same name \"' + extension.name + '\" already exists');\r\n            return;\r\n        }\r\n\r\n        GLTFLoader.Extensions[extension.name] = extension;\r\n    }\r\n\r\n    public dispose(): void {\r\n        // do nothing\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    private _importMeshAsync(\r\n        meshesNames: any,\r\n        scene: Scene,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        assetContainer: Nullable<AssetContainer>,\r\n        onSuccess: (meshes: AbstractMesh[], skeletons: Skeleton[]) => void,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        onError?: (message: string) => void\r\n    ): boolean {\r\n        scene.useRightHandedSystem = true;\r\n\r\n        GLTFLoaderExtension.LoadRuntimeAsync(\r\n            scene,\r\n            data,\r\n            rootUrl,\r\n            (gltfRuntime) => {\r\n                gltfRuntime.assetContainer = assetContainer;\r\n                gltfRuntime.importOnlyMeshes = true;\r\n\r\n                if (meshesNames === \"\") {\r\n                    gltfRuntime.importMeshesNames = [];\r\n                } else if (typeof meshesNames === \"string\") {\r\n                    gltfRuntime.importMeshesNames = [meshesNames];\r\n                } else if (meshesNames && !(meshesNames instanceof Array)) {\r\n                    gltfRuntime.importMeshesNames = [meshesNames];\r\n                } else {\r\n                    gltfRuntime.importMeshesNames = [];\r\n                    Tools.Warn(\"Argument meshesNames must be of type string or string[]\");\r\n                }\r\n\r\n                // Create nodes\r\n                this._createNodes(gltfRuntime);\r\n\r\n                const meshes: AbstractMesh[] = [];\r\n                const skeletons: Skeleton[] = [];\r\n\r\n                // Fill arrays of meshes and skeletons\r\n                for (const nde in gltfRuntime.nodes) {\r\n                    const node: IGLTFNode = gltfRuntime.nodes[nde];\r\n\r\n                    if (node.babylonNode instanceof AbstractMesh) {\r\n                        meshes.push(node.babylonNode);\r\n                    }\r\n                }\r\n\r\n                for (const skl in gltfRuntime.skins) {\r\n                    const skin: IGLTFSkins = gltfRuntime.skins[skl];\r\n\r\n                    if (skin.babylonSkeleton instanceof Skeleton) {\r\n                        skeletons.push(skin.babylonSkeleton);\r\n                    }\r\n                }\r\n\r\n                // Load buffers, shaders, materials, etc.\r\n                this._loadBuffersAsync(gltfRuntime, () => {\r\n                    this._loadShadersAsync(gltfRuntime, () => {\r\n                        ImportMaterials(gltfRuntime);\r\n                        PostLoad(gltfRuntime);\r\n\r\n                        if (!GLTFFileLoader.IncrementalLoading && onSuccess) {\r\n                            onSuccess(meshes, skeletons);\r\n                        }\r\n                    });\r\n                });\r\n\r\n                if (GLTFFileLoader.IncrementalLoading && onSuccess) {\r\n                    onSuccess(meshes, skeletons);\r\n                }\r\n            },\r\n            onError\r\n        );\r\n\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * Imports one or more meshes from a loaded gltf file and adds them to the scene\r\n     * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file\r\n     * @param scene the scene the meshes should be added to\r\n     * @param assetContainer defines the asset container to use (can be null)\r\n     * @param data gltf data containing information of the meshes in a loaded file\r\n     * @param rootUrl root url to load from\r\n     * @param onProgress event that fires when loading progress has occured\r\n     * @returns a promise containg the loaded meshes, particles, skeletons and animations\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    public importMeshAsync(\r\n        meshesNames: any,\r\n        scene: Scene,\r\n        assetContainer: Nullable<AssetContainer>,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void\r\n    ): Promise<ISceneLoaderAsyncResult> {\r\n        return new Promise((resolve, reject) => {\r\n            this._importMeshAsync(\r\n                meshesNames,\r\n                scene,\r\n                data,\r\n                rootUrl,\r\n                assetContainer,\r\n                (meshes, skeletons) => {\r\n                    resolve({\r\n                        meshes: meshes,\r\n                        particleSystems: [],\r\n                        skeletons: skeletons,\r\n                        animationGroups: [],\r\n                        lights: [],\r\n                        transformNodes: [],\r\n                        geometries: [],\r\n                        spriteManagers: [],\r\n                    });\r\n                },\r\n                onProgress,\r\n                (message) => {\r\n                    reject(new Error(message));\r\n                }\r\n            );\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    private _loadAsync(\r\n        scene: Scene,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onSuccess: () => void,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        onError?: (message: string) => void\r\n    ): void {\r\n        scene.useRightHandedSystem = true;\r\n\r\n        GLTFLoaderExtension.LoadRuntimeAsync(\r\n            scene,\r\n            data,\r\n            rootUrl,\r\n            (gltfRuntime) => {\r\n                // Load runtime extensios\r\n                GLTFLoaderExtension.LoadRuntimeExtensionsAsync(\r\n                    gltfRuntime,\r\n                    () => {\r\n                        // Create nodes\r\n                        this._createNodes(gltfRuntime);\r\n\r\n                        // Load buffers, shaders, materials, etc.\r\n                        this._loadBuffersAsync(gltfRuntime, () => {\r\n                            this._loadShadersAsync(gltfRuntime, () => {\r\n                                ImportMaterials(gltfRuntime);\r\n                                PostLoad(gltfRuntime);\r\n\r\n                                if (!GLTFFileLoader.IncrementalLoading) {\r\n                                    onSuccess();\r\n                                }\r\n                            });\r\n                        });\r\n\r\n                        if (GLTFFileLoader.IncrementalLoading) {\r\n                            onSuccess();\r\n                        }\r\n                    },\r\n                    onError\r\n                );\r\n            },\r\n            onError\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Imports all objects from a loaded gltf file and adds them to the scene\r\n     * @param scene the scene the objects should be added to\r\n     * @param data gltf data containing information of the meshes in a loaded file\r\n     * @param rootUrl root url to load from\r\n     * @param onProgress event that fires when loading progress has occured\r\n     * @returns a promise which completes when objects have been loaded to the scene\r\n     */\r\n    public async loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<void> {\r\n        return await new Promise((resolve, reject) => {\r\n            this._loadAsync(\r\n                scene,\r\n                data,\r\n                rootUrl,\r\n                () => {\r\n                    resolve();\r\n                },\r\n                onProgress,\r\n                (message) => {\r\n                    reject(new Error(message));\r\n                }\r\n            );\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    private _loadShadersAsync(gltfRuntime: IGLTFRuntime, onload: () => void): void {\r\n        let hasShaders = false;\r\n\r\n        const processShader = (sha: string, shader: IGLTFShader) => {\r\n            GLTFLoaderExtension.LoadShaderStringAsync(\r\n                gltfRuntime,\r\n                sha,\r\n                (shaderString) => {\r\n                    if (shaderString instanceof ArrayBuffer) {\r\n                        return;\r\n                    }\r\n\r\n                    gltfRuntime.loadedShaderCount++;\r\n\r\n                    if (shaderString) {\r\n                        Effect.ShadersStore[sha + (shader.type === EShaderType.VERTEX ? \"VertexShader\" : \"PixelShader\")] = shaderString;\r\n                    }\r\n\r\n                    if (gltfRuntime.loadedShaderCount === gltfRuntime.shaderscount) {\r\n                        onload();\r\n                    }\r\n                },\r\n                () => {\r\n                    Tools.Error(\"Error when loading shader program named \" + sha + \" located at \" + shader.uri);\r\n                }\r\n            );\r\n        };\r\n\r\n        for (const sha in gltfRuntime.shaders) {\r\n            hasShaders = true;\r\n\r\n            const shader: IGLTFShader = gltfRuntime.shaders[sha];\r\n            if (shader) {\r\n                processShader.bind(this, sha, shader)();\r\n            } else {\r\n                Tools.Error(\"No shader named: \" + sha);\r\n            }\r\n        }\r\n\r\n        if (!hasShaders) {\r\n            onload();\r\n        }\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    private _loadBuffersAsync(gltfRuntime: IGLTFRuntime, onLoad: () => void): void {\r\n        let hasBuffers = false;\r\n\r\n        const processBuffer = (buf: string, buffer: IGLTFBuffer) => {\r\n            GLTFLoaderExtension.LoadBufferAsync(\r\n                gltfRuntime,\r\n                buf,\r\n                (bufferView) => {\r\n                    gltfRuntime.loadedBufferCount++;\r\n\r\n                    if (bufferView) {\r\n                        if (bufferView.byteLength != gltfRuntime.buffers[buf].byteLength) {\r\n                            Tools.Error(\"Buffer named \" + buf + \" is length \" + bufferView.byteLength + \". Expected: \" + buffer.byteLength); // Improve error message\r\n                        }\r\n\r\n                        gltfRuntime.loadedBufferViews[buf] = bufferView;\r\n                    }\r\n\r\n                    if (gltfRuntime.loadedBufferCount === gltfRuntime.buffersCount) {\r\n                        onLoad();\r\n                    }\r\n                },\r\n                () => {\r\n                    Tools.Error(\"Error when loading buffer named \" + buf + \" located at \" + buffer.uri);\r\n                }\r\n            );\r\n        };\r\n\r\n        for (const buf in gltfRuntime.buffers) {\r\n            hasBuffers = true;\r\n\r\n            const buffer: IGLTFBuffer = gltfRuntime.buffers[buf];\r\n            if (buffer) {\r\n                processBuffer.bind(this, buf, buffer)();\r\n            } else {\r\n                Tools.Error(\"No buffer named: \" + buf);\r\n            }\r\n        }\r\n\r\n        if (!hasBuffers) {\r\n            onLoad();\r\n        }\r\n    }\r\n\r\n    private _createNodes(gltfRuntime: IGLTFRuntime): void {\r\n        let currentScene = <IGLTFScene>gltfRuntime.currentScene;\r\n\r\n        if (currentScene) {\r\n            // Only one scene even if multiple scenes are defined\r\n            for (let i = 0; i < currentScene.nodes.length; i++) {\r\n                TraverseNodes(gltfRuntime, currentScene.nodes[i], null);\r\n            }\r\n        } else {\r\n            // Load all scenes\r\n            for (const thing in gltfRuntime.scenes) {\r\n                currentScene = gltfRuntime.scenes[thing];\r\n\r\n                for (let i = 0; i < currentScene.nodes.length; i++) {\r\n                    TraverseNodes(gltfRuntime, currentScene.nodes[i], null);\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n/** @internal */\r\nexport abstract class GLTFLoaderExtension {\r\n    private _name: string;\r\n\r\n    public constructor(name: string) {\r\n        this._name = name;\r\n    }\r\n\r\n    public get name(): string {\r\n        return this._name;\r\n    }\r\n\r\n    /**\r\n     * Defines an override for loading the runtime\r\n     * Return true to stop further extensions from loading the runtime\r\n     * @param scene\r\n     * @param data\r\n     * @param rootUrl\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @returns true to stop further extensions from loading the runtime\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (gltfRuntime: IGLTFRuntime) => void, onError?: (message: string) => void): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Defines an onverride for creating gltf runtime\r\n     * Return true to stop further extensions from creating the runtime\r\n     * @param gltfRuntime\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @returns true to stop further extensions from creating the runtime\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError?: (message: string) => void): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Defines an override for loading buffers\r\n     * Return true to stop further extensions from loading this buffer\r\n     * @param gltfRuntime\r\n     * @param id\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @param onProgress\r\n     * @returns true to stop further extensions from loading this buffer\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadBufferAsync(\r\n        gltfRuntime: IGLTFRuntime,\r\n        id: string,\r\n        onSuccess: (buffer: ArrayBufferView) => void,\r\n        onError: (message: string) => void,\r\n        onProgress?: () => void\r\n    ): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Defines an override for loading texture buffers\r\n     * Return true to stop further extensions from loading this texture data\r\n     * @param gltfRuntime\r\n     * @param id\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @returns true to stop further extensions from loading this texture data\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Defines an override for creating textures\r\n     * Return true to stop further extensions from loading this texture\r\n     * @param gltfRuntime\r\n     * @param id\r\n     * @param buffer\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @returns true to stop further extensions from loading this texture\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public createTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: (message: string) => void): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Defines an override for loading shader strings\r\n     * Return true to stop further extensions from loading this shader data\r\n     * @param gltfRuntime\r\n     * @param id\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @returns true to stop further extensions from loading this shader data\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: (message: string) => void): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Defines an override for loading materials\r\n     * Return true to stop further extensions from loading this material\r\n     * @param gltfRuntime\r\n     * @param id\r\n     * @param onSuccess\r\n     * @param onError\r\n     * @returns true to stop further extensions from loading this material\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): boolean {\r\n        return false;\r\n    }\r\n\r\n    // ---------\r\n    // Utilities\r\n    // ---------\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadRuntimeAsync(\r\n        scene: Scene,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onSuccess?: (gltfRuntime: IGLTFRuntime) => void,\r\n        onError?: (message: string) => void\r\n    ): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);\r\n            },\r\n            () => {\r\n                setTimeout(() => {\r\n                    if (!onSuccess) {\r\n                        return;\r\n                    }\r\n                    onSuccess(GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));\r\n                });\r\n            }\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError?: (message: string) => void): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError);\r\n            },\r\n            () => {\r\n                setTimeout(() => {\r\n                    onSuccess();\r\n                });\r\n            }\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadBufferAsync(\r\n        gltfRuntime: IGLTFRuntime,\r\n        id: string,\r\n        onSuccess: (bufferView: ArrayBufferView) => void,\r\n        onError: (message: string) => void,\r\n        onProgress?: () => void\r\n    ): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.loadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);\r\n            },\r\n            () => {\r\n                GLTFLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);\r\n            }\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadTextureAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (texture: Texture) => void, onError: (message: string) => void): void {\r\n        GLTFLoaderExtension._LoadTextureBufferAsync(\r\n            gltfRuntime,\r\n            id,\r\n            (buffer) => {\r\n                if (buffer) {\r\n                    GLTFLoaderExtension._CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);\r\n                }\r\n            },\r\n            onError\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderData: string | ArrayBuffer) => void, onError: (message: string) => void): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.loadShaderStringAsync(gltfRuntime, id, onSuccess, onError);\r\n            },\r\n            () => {\r\n                GLTFLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError);\r\n            }\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.loadMaterialAsync(gltfRuntime, id, onSuccess, onError);\r\n            },\r\n            () => {\r\n                GLTFLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError);\r\n            }\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    private static _LoadTextureBufferAsync(\r\n        gltfRuntime: IGLTFRuntime,\r\n        id: string,\r\n        onSuccess: (buffer: Nullable<ArrayBufferView>) => void,\r\n        onError: (message: string) => void\r\n    ): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);\r\n            },\r\n            () => {\r\n                GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);\r\n            }\r\n        );\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    private static _CreateTextureAsync(\r\n        gltfRuntime: IGLTFRuntime,\r\n        id: string,\r\n        buffer: ArrayBufferView,\r\n        onSuccess: (texture: Texture) => void,\r\n        onError: (message: string) => void\r\n    ): void {\r\n        GLTFLoaderExtension._ApplyExtensions(\r\n            (loaderExtension) => {\r\n                return loaderExtension.createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);\r\n            },\r\n            () => {\r\n                GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess);\r\n            }\r\n        );\r\n    }\r\n\r\n    private static _ApplyExtensions(func: (loaderExtension: GLTFLoaderExtension) => boolean, defaultFunc: () => void): void {\r\n        for (const extensionName in GLTFLoader.Extensions) {\r\n            const loaderExtension = GLTFLoader.Extensions[extensionName];\r\n            if (func(loaderExtension)) {\r\n                return;\r\n            }\r\n        }\r\n\r\n        defaultFunc();\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n\r\n/**\r\n * Registers the glTF 1.0 loader factory.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterGLTF1Loader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    GLTFFileLoader._CreateGLTF1Loader = () => new GLTFLoader();\r\n}\r\n","import {\r\n    type IGLTFTechniqueParameter,\r\n    type IGLTFAccessor,\r\n    type IGLTFRuntime,\r\n    type IGLTFBufferView,\r\n    EParameterType,\r\n    ETextureWrapMode,\r\n    ETextureFilterType,\r\n    EComponentType,\r\n} from \"./glTFLoaderInterfaces\";\r\n\r\nimport { type Nullable } from \"core/types\";\r\nimport { Vector2, Vector3, Vector4, Matrix } from \"core/Maths/math.vector.pure\";\r\nimport { Color4 } from \"core/Maths/math.color.pure\";\r\nimport { Effect } from \"core/Materials/effect.pure\";\r\nimport { ShaderMaterial } from \"core/Materials/shaderMaterial.pure\";\r\nimport { Texture } from \"core/Materials/Textures/texture.pure\";\r\nimport { type Node } from \"core/node\";\r\nimport { type Scene } from \"core/scene\";\r\n\r\n/**\r\n * Utils functions for GLTF\r\n * @internal\r\n * @deprecated\r\n */\r\nexport class GLTFUtils {\r\n    /**\r\n     * Sets the given \"parameter\" matrix\r\n     * @param scene the Scene object\r\n     * @param source the source node where to pick the matrix\r\n     * @param parameter the GLTF technique parameter\r\n     * @param uniformName the name of the shader's uniform\r\n     * @param shaderMaterial the shader material\r\n     */\r\n    public static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void {\r\n        let mat: Nullable<Matrix> = null;\r\n\r\n        if (parameter.semantic === \"MODEL\") {\r\n            mat = source.getWorldMatrix();\r\n        } else if (parameter.semantic === \"PROJECTION\") {\r\n            mat = scene.getProjectionMatrix();\r\n        } else if (parameter.semantic === \"VIEW\") {\r\n            mat = scene.getViewMatrix();\r\n        } else if (parameter.semantic === \"MODELVIEWINVERSETRANSPOSE\") {\r\n            mat = Matrix.Transpose(source.getWorldMatrix().multiply(scene.getViewMatrix()).invert());\r\n        } else if (parameter.semantic === \"MODELVIEW\") {\r\n            mat = source.getWorldMatrix().multiply(scene.getViewMatrix());\r\n        } else if (parameter.semantic === \"MODELVIEWPROJECTION\") {\r\n            mat = source.getWorldMatrix().multiply(scene.getTransformMatrix());\r\n        } else if (parameter.semantic === \"MODELINVERSE\") {\r\n            mat = source.getWorldMatrix().invert();\r\n        } else if (parameter.semantic === \"VIEWINVERSE\") {\r\n            mat = scene.getViewMatrix().invert();\r\n        } else if (parameter.semantic === \"PROJECTIONINVERSE\") {\r\n            mat = scene.getProjectionMatrix().invert();\r\n        } else if (parameter.semantic === \"MODELVIEWINVERSE\") {\r\n            mat = source.getWorldMatrix().multiply(scene.getViewMatrix()).invert();\r\n        } else if (parameter.semantic === \"MODELVIEWPROJECTIONINVERSE\") {\r\n            mat = source.getWorldMatrix().multiply(scene.getTransformMatrix()).invert();\r\n        } else if (parameter.semantic === \"MODELINVERSETRANSPOSE\") {\r\n            mat = Matrix.Transpose(source.getWorldMatrix().invert());\r\n        }\r\n\r\n        if (mat) {\r\n            switch (parameter.type) {\r\n                case EParameterType.FLOAT_MAT2:\r\n                    shaderMaterial.setMatrix2x2(uniformName, Matrix.GetAsMatrix2x2(mat));\r\n                    break;\r\n                case EParameterType.FLOAT_MAT3:\r\n                    shaderMaterial.setMatrix3x3(uniformName, Matrix.GetAsMatrix3x3(mat));\r\n                    break;\r\n                case EParameterType.FLOAT_MAT4:\r\n                    shaderMaterial.setMatrix(uniformName, mat);\r\n                    break;\r\n                default:\r\n                    break;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Sets the given \"parameter\" matrix\r\n     * @param shaderMaterial the shader material\r\n     * @param uniform the name of the shader's uniform\r\n     * @param value the value of the uniform\r\n     * @param type the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4)\r\n     * @returns true if set, else false\r\n     */\r\n    public static SetUniform(shaderMaterial: ShaderMaterial | Effect, uniform: string, value: any, type: number): boolean {\r\n        switch (type) {\r\n            case EParameterType.FLOAT:\r\n                shaderMaterial.setFloat(uniform, value);\r\n                return true;\r\n            case EParameterType.FLOAT_VEC2:\r\n                shaderMaterial.setVector2(uniform, Vector2.FromArray(value));\r\n                return true;\r\n            case EParameterType.FLOAT_VEC3:\r\n                shaderMaterial.setVector3(uniform, Vector3.FromArray(value));\r\n                return true;\r\n            case EParameterType.FLOAT_VEC4:\r\n                shaderMaterial.setVector4(uniform, Vector4.FromArray(value));\r\n                return true;\r\n            default:\r\n                return false;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Returns the wrap mode of the texture\r\n     * @param mode the mode value\r\n     * @returns the wrap mode (TEXTURE_WRAP_ADDRESSMODE, MIRROR_ADDRESSMODE or CLAMP_ADDRESSMODE)\r\n     */\r\n    public static GetWrapMode(mode: number): number {\r\n        switch (mode) {\r\n            case ETextureWrapMode.CLAMP_TO_EDGE:\r\n                return Texture.CLAMP_ADDRESSMODE;\r\n            case ETextureWrapMode.MIRRORED_REPEAT:\r\n                return Texture.MIRROR_ADDRESSMODE;\r\n            case ETextureWrapMode.REPEAT:\r\n                return Texture.WRAP_ADDRESSMODE;\r\n            default:\r\n                return Texture.WRAP_ADDRESSMODE;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Returns the byte stride giving an accessor\r\n     * @param accessor the GLTF accessor objet\r\n     * @returns the byte stride\r\n     */\r\n    public static GetByteStrideFromType(accessor: IGLTFAccessor): number {\r\n        // Needs this function since \"byteStride\" isn't requiered in glTF format\r\n        const type = accessor.type;\r\n\r\n        switch (type) {\r\n            case \"VEC2\":\r\n                return 2;\r\n            case \"VEC3\":\r\n                return 3;\r\n            case \"VEC4\":\r\n                return 4;\r\n            case \"MAT2\":\r\n                return 4;\r\n            case \"MAT3\":\r\n                return 9;\r\n            case \"MAT4\":\r\n                return 16;\r\n            default:\r\n                return 1;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Returns the texture filter mode giving a mode value\r\n     * @param mode the filter mode value\r\n     * @returns the filter mode (TODO - needs to be a type?)\r\n     */\r\n    public static GetTextureFilterMode(mode: number): number {\r\n        switch (mode) {\r\n            case ETextureFilterType.LINEAR:\r\n            case ETextureFilterType.LINEAR_MIPMAP_NEAREST:\r\n            case ETextureFilterType.LINEAR_MIPMAP_LINEAR:\r\n                return Texture.TRILINEAR_SAMPLINGMODE;\r\n            case ETextureFilterType.NEAREST:\r\n            case ETextureFilterType.NEAREST_MIPMAP_NEAREST:\r\n                return Texture.NEAREST_SAMPLINGMODE;\r\n            default:\r\n                return Texture.BILINEAR_SAMPLINGMODE;\r\n        }\r\n    }\r\n\r\n    public static GetBufferFromBufferView(\r\n        gltfRuntime: IGLTFRuntime,\r\n        bufferView: IGLTFBufferView,\r\n        byteOffset: number,\r\n        byteLength: number,\r\n        componentType: EComponentType\r\n    ): ArrayBufferView {\r\n        byteOffset = bufferView.byteOffset + byteOffset;\r\n\r\n        const loadedBufferView = gltfRuntime.loadedBufferViews[bufferView.buffer];\r\n        if (byteOffset + byteLength > loadedBufferView.byteLength) {\r\n            throw new Error(\"Buffer access is out of range\");\r\n        }\r\n\r\n        const buffer = loadedBufferView.buffer;\r\n        byteOffset += loadedBufferView.byteOffset;\r\n\r\n        switch (componentType) {\r\n            case EComponentType.BYTE:\r\n                return new Int8Array(buffer, byteOffset, byteLength);\r\n            case EComponentType.UNSIGNED_BYTE:\r\n                return new Uint8Array(buffer, byteOffset, byteLength);\r\n            case EComponentType.SHORT:\r\n                return new Int16Array(buffer, byteOffset, byteLength);\r\n            case EComponentType.UNSIGNED_SHORT:\r\n                return new Uint16Array(buffer, byteOffset, byteLength);\r\n            default:\r\n                return new Float32Array(buffer, byteOffset, byteLength);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Returns a buffer from its accessor\r\n     * @param gltfRuntime the GLTF runtime\r\n     * @param accessor the GLTF accessor\r\n     * @returns an array buffer view\r\n     */\r\n    public static GetBufferFromAccessor(gltfRuntime: IGLTFRuntime, accessor: IGLTFAccessor): any {\r\n        const bufferView: IGLTFBufferView = gltfRuntime.bufferViews[accessor.bufferView];\r\n        const byteLength = accessor.count * GLTFUtils.GetByteStrideFromType(accessor);\r\n        return GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, accessor.byteOffset, byteLength, accessor.componentType);\r\n    }\r\n\r\n    /**\r\n     * Decodes a buffer view into a string\r\n     * @param view the buffer view\r\n     * @returns a string\r\n     */\r\n    public static DecodeBufferToText(view: ArrayBufferView): string {\r\n        let result = \"\";\r\n        const length = view.byteLength;\r\n\r\n        for (let i = 0; i < length; ++i) {\r\n            result += String.fromCharCode((<any>view)[i]);\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * Returns the default material of gltf. Related to\r\n     * https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material\r\n     * @param scene the Babylon.js scene\r\n     * @returns the default Babylon material\r\n     */\r\n    public static GetDefaultMaterial(scene: Scene): ShaderMaterial {\r\n        if (!GLTFUtils._DefaultMaterial) {\r\n            Effect.ShadersStore[\"GLTFDefaultMaterialVertexShader\"] = [\r\n                \"precision highp float;\",\r\n                \"\",\r\n                \"uniform mat4 worldView;\",\r\n                \"uniform mat4 projection;\",\r\n                \"\",\r\n                \"attribute vec3 position;\",\r\n                \"\",\r\n                \"void main(void)\",\r\n                \"{\",\r\n                \"    gl_Position = projection * worldView * vec4(position, 1.0);\",\r\n                \"}\",\r\n            ].join(\"\\n\");\r\n\r\n            Effect.ShadersStore[\"GLTFDefaultMaterialPixelShader\"] = [\r\n                \"precision highp float;\",\r\n                \"\",\r\n                \"uniform vec4 u_emission;\",\r\n                \"\",\r\n                \"void main(void)\",\r\n                \"{\",\r\n                \"    gl_FragColor = u_emission;\",\r\n                \"}\",\r\n            ].join(\"\\n\");\r\n\r\n            const shaderPath = {\r\n                vertex: \"GLTFDefaultMaterial\",\r\n                fragment: \"GLTFDefaultMaterial\",\r\n            };\r\n\r\n            const options = {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"worldView\", \"projection\", \"u_emission\"],\r\n                samplers: new Array<string>(),\r\n                needAlphaBlending: false,\r\n            };\r\n\r\n            GLTFUtils._DefaultMaterial = new ShaderMaterial(\"GLTFDefaultMaterial\", scene, shaderPath, options);\r\n            GLTFUtils._DefaultMaterial.setColor4(\"u_emission\", new Color4(0.5, 0.5, 0.5, 1.0));\r\n        }\r\n\r\n        return GLTFUtils._DefaultMaterial;\r\n    }\r\n\r\n    // The GLTF default material\r\n    private static _DefaultMaterial: Nullable<ShaderMaterial> = null;\r\n}\r\n","import { GLTFLoaderExtension, GLTFLoader, GLTFLoaderBase } from \"./glTFLoader.pure\";\r\nimport { GLTFUtils } from \"./glTFLoaderUtils\";\r\nimport { type Scene } from \"core/scene.pure\";\r\nimport { type IGLTFLoaderData } from \"../glTFFileLoader.pure\";\r\nimport { type IGLTFRuntime, type IGLTFTexture, type IGLTFImage, type IGLTFBufferView, type IGLTFShader, EComponentType } from \"./glTFLoaderInterfaces\";\r\n\r\nimport { type IDataBuffer } from \"core/Misc/dataReader\";\r\n\r\nconst BinaryExtensionBufferName = \"binary_glTF\";\r\n\r\ninterface IGLTFBinaryExtensionShader {\r\n    bufferView: string;\r\n}\r\n\r\ninterface IGLTFBinaryExtensionImage {\r\n    bufferView: string;\r\n    mimeType: string;\r\n    height: number;\r\n    width: number;\r\n}\r\n\r\n/**\r\n * @internal\r\n * @deprecated\r\n */\r\nexport class GLTFBinaryExtension extends GLTFLoaderExtension {\r\n    private _bin: IDataBuffer;\r\n\r\n    public constructor() {\r\n        super(\"KHR_binary_glTF\");\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public override loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void): boolean {\r\n        const extensionsUsed = (<any>data.json).extensionsUsed;\r\n        if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {\r\n            return false;\r\n        }\r\n\r\n        this._bin = data.bin;\r\n        onSuccess(GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));\r\n        return true;\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public override loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: (message: string) => void): boolean {\r\n        if (gltfRuntime.extensionsUsed.indexOf(this.name) === -1) {\r\n            return false;\r\n        }\r\n\r\n        if (id !== BinaryExtensionBufferName) {\r\n            return false;\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        this._bin.readAsync(0, this._bin.byteLength).then(onSuccess, (error) => onError(error.message));\r\n        return true;\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public override loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void): boolean {\r\n        const texture: IGLTFTexture = gltfRuntime.textures[id];\r\n        const source: IGLTFImage = gltfRuntime.images[texture.source];\r\n        if (!source.extensions || !(this.name in source.extensions)) {\r\n            return false;\r\n        }\r\n\r\n        const sourceExt: IGLTFBinaryExtensionImage = source.extensions[this.name];\r\n        const bufferView: IGLTFBufferView = gltfRuntime.bufferViews[sourceExt.bufferView];\r\n        const buffer = GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, EComponentType.UNSIGNED_BYTE);\r\n        onSuccess(buffer);\r\n        return true;\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public override loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void): boolean {\r\n        const shader: IGLTFShader = gltfRuntime.shaders[id];\r\n        if (!shader.extensions || !(this.name in shader.extensions)) {\r\n            return false;\r\n        }\r\n\r\n        const binaryExtensionShader: IGLTFBinaryExtensionShader = shader.extensions[this.name];\r\n        const bufferView: IGLTFBufferView = gltfRuntime.bufferViews[binaryExtensionShader.bufferView];\r\n        const shaderBytes = GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, EComponentType.UNSIGNED_BYTE);\r\n\r\n        setTimeout(() => {\r\n            const shaderString = GLTFUtils.DecodeBufferToText(shaderBytes);\r\n            onSuccess(shaderString);\r\n        });\r\n\r\n        return true;\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n\r\n/**\r\n * Registers the KHR_binary_glTF extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterGLTFBinaryExtension(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    GLTFLoader.RegisterExtension(new GLTFBinaryExtension());\r\n}\r\n","/**\n * Re-exports the pure implementation and applies the runtime registration side effect.\n * Import \"./glTFLoader.pure\" for tree-shakeable, side-effect-free usage.\n */\nexport * from \"./glTFLoader.pure\";\n\nimport { RegisterGLTF1Loader } from \"./glTFLoader.pure\";\nimport { RegisterGLTFFileLoader } from \"../glTFFileLoader.pure\";\nRegisterGLTF1Loader();\nRegisterGLTFFileLoader();\n","/**\n * Re-exports the pure implementation and applies the runtime registration side effect.\n * Import \"./glTFBinaryExtension.pure\" for tree-shakeable, side-effect-free usage.\n */\nexport * from \"./glTFBinaryExtension.pure\";\n\nimport \"./glTFLoader\";\nimport { RegisterGLTFBinaryExtension } from \"./glTFBinaryExtension.pure\";\nRegisterGLTFBinaryExtension();\n","import { GLTFLoaderExtension, GLTFLoaderBase, GLTFLoader } from \"./glTFLoader.pure\";\r\n\r\nimport { type IGLTFRuntime, type IGLTFMaterial } from \"./glTFLoaderInterfaces\";\r\n\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { Material } from \"core/Materials/material.pure\";\r\nimport { StandardMaterial } from \"core/Materials/standardMaterial.pure\";\r\nimport { HemisphericLight } from \"core/Lights/hemisphericLight.pure\";\r\nimport { DirectionalLight } from \"core/Lights/directionalLight.pure\";\r\nimport { PointLight } from \"core/Lights/pointLight.pure\";\r\nimport { SpotLight } from \"core/Lights/spotLight.pure\";\r\n\r\ninterface IGLTFMaterialsCommonExtensionValues {\r\n    ambient?: number[] | string;\r\n    diffuse?: number[] | string;\r\n    emission?: number[] | string;\r\n    specular?: number[] | string;\r\n    shininess?: number;\r\n    transparency?: number;\r\n}\r\n\r\ninterface IGLTFMaterialsCommonExtension {\r\n    technique: string;\r\n    transparent?: number;\r\n    doubleSided?: boolean;\r\n    values: IGLTFMaterialsCommonExtensionValues;\r\n}\r\n\r\ninterface IGLTFRuntimeCommonExtension {\r\n    lights: { [key: string]: IGLTFLightCommonExtension };\r\n}\r\n\r\ninterface IGLTFLightCommonExtension {\r\n    name: string;\r\n    type: string;\r\n\r\n    ambient?: IGLTFAmbientLightCommonExtension;\r\n    point?: IGLTFPointLightCommonExtension;\r\n    directional?: IGLTFDirectionalLightCommonExtension;\r\n    spot?: IGLTFSpotLightCommonExtension;\r\n}\r\n\r\ninterface IGLTFPointLightCommonExtension {\r\n    color: number[];\r\n    constantAttenuation: number;\r\n    linearAttenuation: number;\r\n    quadraticAttenuation: number;\r\n}\r\n\r\ninterface IGLTFAmbientLightCommonExtension {\r\n    color: number[];\r\n}\r\n\r\ninterface IGLTFDirectionalLightCommonExtension {\r\n    color: number[];\r\n}\r\n\r\ninterface IGLTFSpotLightCommonExtension {\r\n    color: number[];\r\n    constantAttenuation: number;\r\n    fallOffAngle: number;\r\n    fallOffExponent: number;\r\n    linearAttenuation: number;\r\n    quadraticAttenuation: number;\r\n}\r\n\r\n/**\r\n * @internal\r\n * @deprecated\r\n */\r\nexport class GLTFMaterialsCommonExtension extends GLTFLoaderExtension {\r\n    constructor() {\r\n        super(\"KHR_materials_common\");\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public override loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime): boolean {\r\n        if (!gltfRuntime.extensions) {\r\n            return false;\r\n        }\r\n\r\n        const extension: IGLTFRuntimeCommonExtension = gltfRuntime.extensions[this.name];\r\n        if (!extension) {\r\n            return false;\r\n        }\r\n\r\n        // Create lights\r\n        const lights = extension.lights;\r\n        if (lights) {\r\n            for (const thing in lights) {\r\n                const light: IGLTFLightCommonExtension = lights[thing];\r\n\r\n                switch (light.type) {\r\n                    case \"ambient\": {\r\n                        const ambientLight = new HemisphericLight(light.name, new Vector3(0, 1, 0), gltfRuntime.scene);\r\n                        const ambient = light.ambient;\r\n                        if (ambient) {\r\n                            ambientLight.diffuse = Color3.FromArray(ambient.color || [1, 1, 1]);\r\n                        }\r\n                        break;\r\n                    }\r\n                    case \"point\": {\r\n                        const pointLight = new PointLight(light.name, new Vector3(10, 10, 10), gltfRuntime.scene);\r\n                        const point = light.point;\r\n                        if (point) {\r\n                            pointLight.diffuse = Color3.FromArray(point.color || [1, 1, 1]);\r\n                        }\r\n                        break;\r\n                    }\r\n                    case \"directional\": {\r\n                        const dirLight = new DirectionalLight(light.name, new Vector3(0, -1, 0), gltfRuntime.scene);\r\n                        const directional = light.directional;\r\n                        if (directional) {\r\n                            dirLight.diffuse = Color3.FromArray(directional.color || [1, 1, 1]);\r\n                        }\r\n                        break;\r\n                    }\r\n                    case \"spot\": {\r\n                        const spot = light.spot;\r\n                        if (spot) {\r\n                            const spotLight = new SpotLight(\r\n                                light.name,\r\n                                new Vector3(0, 10, 0),\r\n                                new Vector3(0, -1, 0),\r\n                                spot.fallOffAngle || Math.PI,\r\n                                spot.fallOffExponent || 0.0,\r\n                                gltfRuntime.scene\r\n                            );\r\n                            spotLight.diffuse = Color3.FromArray(spot.color || [1, 1, 1]);\r\n                        }\r\n                        break;\r\n                    }\r\n                    default:\r\n                        Tools.Warn('GLTF Material Common extension: light type \"' + light.type + \"” not supported\");\r\n                        break;\r\n                }\r\n            }\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public override loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: (message: string) => void): boolean {\r\n        const material: IGLTFMaterial = gltfRuntime.materials[id];\r\n        if (!material || !material.extensions) {\r\n            return false;\r\n        }\r\n\r\n        const extension: IGLTFMaterialsCommonExtension = material.extensions[this.name];\r\n        if (!extension) {\r\n            return false;\r\n        }\r\n\r\n        const standardMaterial = new StandardMaterial(id, gltfRuntime.scene);\r\n        standardMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;\r\n\r\n        if (extension.technique === \"CONSTANT\") {\r\n            standardMaterial.disableLighting = true;\r\n        }\r\n\r\n        standardMaterial.backFaceCulling = extension.doubleSided === undefined ? false : !extension.doubleSided;\r\n        standardMaterial.alpha = extension.values.transparency === undefined ? 1.0 : extension.values.transparency;\r\n        standardMaterial.specularPower = extension.values.shininess === undefined ? 0.0 : extension.values.shininess;\r\n\r\n        // Ambient\r\n        if (typeof extension.values.ambient === \"string\") {\r\n            this._loadTexture(gltfRuntime, extension.values.ambient, standardMaterial, \"ambientTexture\", onError);\r\n        } else {\r\n            standardMaterial.ambientColor = Color3.FromArray(extension.values.ambient || [0, 0, 0]);\r\n        }\r\n\r\n        // Diffuse\r\n        if (typeof extension.values.diffuse === \"string\") {\r\n            this._loadTexture(gltfRuntime, extension.values.diffuse, standardMaterial, \"diffuseTexture\", onError);\r\n        } else {\r\n            standardMaterial.diffuseColor = Color3.FromArray(extension.values.diffuse || [0, 0, 0]);\r\n        }\r\n\r\n        // Emission\r\n        if (typeof extension.values.emission === \"string\") {\r\n            this._loadTexture(gltfRuntime, extension.values.emission, standardMaterial, \"emissiveTexture\", onError);\r\n        } else {\r\n            standardMaterial.emissiveColor = Color3.FromArray(extension.values.emission || [0, 0, 0]);\r\n        }\r\n\r\n        // Specular\r\n        if (typeof extension.values.specular === \"string\") {\r\n            this._loadTexture(gltfRuntime, extension.values.specular, standardMaterial, \"specularTexture\", onError);\r\n        } else {\r\n            standardMaterial.specularColor = Color3.FromArray(extension.values.specular || [0, 0, 0]);\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    private _loadTexture(gltfRuntime: IGLTFRuntime, id: string, material: StandardMaterial, propertyPath: string, onError: (message: string) => void): void {\r\n        // Create buffer from texture url\r\n        GLTFLoaderBase.LoadTextureBufferAsync(\r\n            gltfRuntime,\r\n            id,\r\n            (buffer) => {\r\n                // Create texture from buffer\r\n                GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, (texture) => ((<any>material)[propertyPath] = texture));\r\n            },\r\n            onError\r\n        );\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n\r\n/**\r\n * Registers the KHR_materials_common extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterGLTFMaterialsCommonExtension(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    GLTFLoader.RegisterExtension(new GLTFMaterialsCommonExtension());\r\n}\r\n","/**\n * Re-exports the pure implementation and applies the runtime registration side effect.\n * Import \"./glTFMaterialsCommonExtension.pure\" for tree-shakeable, side-effect-free usage.\n */\nexport * from \"./glTFMaterialsCommonExtension.pure\";\n\nimport \"./glTFLoader\";\nimport { RegisterGLTFMaterialsCommonExtension } from \"./glTFMaterialsCommonExtension.pure\";\nRegisterGLTFMaterialsCommonExtension();\n","import { type GLTFLoader } from \"./glTFLoader\";\r\nimport { type IGLTFLoaderExtension } from \"./glTFLoaderExtension\";\r\n\r\nimport { Logger } from \"core/Misc/logger\";\r\n\r\ninterface IRegisteredGLTFExtension {\r\n    isGLTFExtension: boolean;\r\n    factory: GLTFExtensionFactory;\r\n}\r\n\r\nexport type GLTFExtensionFactory = (loader: GLTFLoader) => IGLTFLoaderExtension | Promise<IGLTFLoaderExtension>;\r\n\r\nconst RegisteredGLTFExtensions = new Map<string, IRegisteredGLTFExtension>();\r\n\r\n/**\r\n * All currently registered glTF 2.0 loader extensions.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const registeredGLTFExtensions: ReadonlyMap<string, Readonly<IRegisteredGLTFExtension>> = RegisteredGLTFExtensions;\r\n\r\n/**\r\n * Registers a loader extension.\r\n * @param name The name of the loader extension.\r\n * @param isGLTFExtension If the loader extension is a glTF extension, then it will only be used for glTF files that use the corresponding glTF extension. Otherwise, it will be used for all loaded glTF files.\r\n * @param factory The factory function that creates the loader extension.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function registerGLTFExtension(name: string, isGLTFExtension: boolean, factory: GLTFExtensionFactory): void {\r\n    if (unregisterGLTFExtension(name)) {\r\n        Logger.Warn(`Extension with the name '${name}' already exists`);\r\n    }\r\n\r\n    RegisteredGLTFExtensions.set(name, {\r\n        isGLTFExtension,\r\n        factory,\r\n    });\r\n}\r\n\r\n/**\r\n * Unregisters a loader extension.\r\n * @param name The name of the loader extension.\r\n * @returns A boolean indicating whether the extension has been unregistered\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function unregisterGLTFExtension(name: string): boolean {\r\n    return RegisteredGLTFExtensions.delete(name);\r\n}\r\n","import { type IObjectInfo, type IPathToObjectConverter } from \"core/ObjectModel/objectModelInterfaces\";\r\nimport { type IGLTF } from \"../glTFLoaderInterfaces\";\r\nimport { type IObjectAccessor } from \"core/FlowGraph/typeDefinitions\";\r\n\r\n/**\r\n * Adding an exception here will break traversing through the glTF object tree.\r\n * This is used for properties that might not be in the glTF object model, but are optional and have a default value.\r\n * For example, the path /nodes/\\{\\}/extensions/KHR_node_visibility/visible is optional - the object can be deferred without the object fully existing.\r\n */\r\nexport const OptionalPathExceptionsList: {\r\n    regex: RegExp;\r\n}[] = [\r\n    {\r\n        // get the node as object when reading an extension\r\n        regex: new RegExp(`^/nodes/\\\\d+/extensions/`),\r\n    },\r\n    {\r\n        // KHR_interactivity animation pointers (e.g. /animations/{}/extensions/KHR_interactivity/maxTime)\r\n        // are virtual: they are computed from the Babylon animation group and are not stored in the\r\n        // glTF JSON, so the animation object has no `extensions` member to traverse into.\r\n        regex: new RegExp(`^/animations/\\\\d+/extensions/`),\r\n    },\r\n    {\r\n        // weights may be undefined on nodes without morph targets\r\n        regex: new RegExp(`^/nodes/\\\\d+/weights`),\r\n    },\r\n    {\r\n        // weights may be undefined on meshes without morph targets\r\n        regex: new RegExp(`^/meshes/\\\\d+/weights`),\r\n    },\r\n    {\r\n        // KHR_texture_transform may not be present on texture info objects\r\n        regex: new RegExp(`/extensions/KHR_texture_transform/`),\r\n    },\r\n];\r\n\r\n/**\r\n * A converter that takes a glTF Object Model JSON Pointer\r\n * and transforms it into an ObjectAccessorContainer, allowing\r\n * objects referenced in the glTF to be associated with their\r\n * respective Babylon.js objects.\r\n */\r\nexport class GLTFPathToObjectConverter<T, BabylonType, BabylonValue> implements IPathToObjectConverter<IObjectAccessor<T, BabylonType, BabylonValue>> {\r\n    public constructor(\r\n        private _gltf: IGLTF,\r\n        private _infoTree: any\r\n    ) {}\r\n\r\n    /**\r\n     * The pointer string is represented by a [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901).\r\n     * See also https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc#core-pointers\r\n     * <animationPointer> := /<rootNode>/<assetIndex>/<propertyPath>\r\n     * <rootNode> := \"nodes\" | \"materials\" | \"meshes\" | \"cameras\" | \"extensions\"\r\n     * <assetIndex> := <digit> | <name>\r\n     * <propertyPath> := <extensionPath> | <standardPath>\r\n     * <extensionPath> := \"extensions\"/<name>/<standardPath>\r\n     * <standardPath> := <name> | <name>/<standardPath>\r\n     * <name> := W+\r\n     * <digit> := D+\r\n     *\r\n     * Examples:\r\n     *  - \"/nodes/0/rotation\"\r\n     * - \"/nodes.length\"\r\n     *  - \"/materials/2/emissiveFactor\"\r\n     *  - \"/materials/2/pbrMetallicRoughness/baseColorFactor\"\r\n     *  - \"/materials/2/extensions/KHR_materials_emissive_strength/emissiveStrength\"\r\n     *\r\n     * @param path The path to convert\r\n     * @returns The object and info associated with the path\r\n     */\r\n    public convert(path: string): IObjectInfo<IObjectAccessor<T, BabylonType, BabylonValue>> {\r\n        let objectTree: any = this._gltf;\r\n        let infoTree: any = this._infoTree;\r\n        let target: any = undefined;\r\n\r\n        if (!path.startsWith(\"/\")) {\r\n            throw new Error(\"Path must start with a /\");\r\n        }\r\n        const parts = path.split(\"/\");\r\n        parts.shift();\r\n\r\n        //if the last part has \".length\" in it, separate that as an extra part\r\n        if (parts[parts.length - 1].includes(\".length\")) {\r\n            const lastPart = parts[parts.length - 1];\r\n            const split = lastPart.split(\".\");\r\n            parts.pop();\r\n            parts.push(...split);\r\n        }\r\n\r\n        let ignoreObjectTree = false;\r\n\r\n        for (const part of parts) {\r\n            const isLength = part === \"length\";\r\n            if (isLength) {\r\n                // For .length, check if the current level has a 'length' accessor\r\n                if (infoTree.length) {\r\n                    infoTree = infoTree.length;\r\n                } else if (infoTree.__array__) {\r\n                    // Fallback: length of an array that doesn't have explicit length accessor\r\n                    throw new Error(`Path ${path} is invalid - no length accessor`);\r\n                } else {\r\n                    throw new Error(`Path ${path} is invalid`);\r\n                }\r\n                // Set target to the current object tree (the array itself)\r\n                // Only update target if objectTree is defined, otherwise keep the last valid target\r\n                if (objectTree !== undefined) {\r\n                    target = objectTree;\r\n                }\r\n                continue;\r\n            }\r\n            if (infoTree.__ignoreObjectTree__) {\r\n                ignoreObjectTree = true;\r\n            }\r\n            if (infoTree.__array__) {\r\n                infoTree = infoTree.__array__;\r\n            } else {\r\n                infoTree = infoTree[part];\r\n                if (!infoTree) {\r\n                    throw new Error(`Path ${path} is invalid`);\r\n                }\r\n            }\r\n            // __passThroughTarget__: skip objectTree traversal for this property.\r\n            // The accessor functions will receive the parent target (e.g., the INode)\r\n            // instead of the child property (e.g., node.weights which may be undefined).\r\n            if (infoTree.__passThroughTarget__) {\r\n                ignoreObjectTree = true;\r\n            } else if (!ignoreObjectTree) {\r\n                if (objectTree === undefined) {\r\n                    // check if the path is in the exception list. If it is, break and return the last object that was found\r\n                    const exception = OptionalPathExceptionsList.find((e) => e.regex.test(path));\r\n                    if (!exception) {\r\n                        throw new Error(`Path ${path} is invalid`);\r\n                    }\r\n                } else {\r\n                    objectTree = objectTree?.[part];\r\n                }\r\n            } else {\r\n                // When ignoring object tree traversal and encountering a numeric array index,\r\n                // wrap the accessor functions to pass the index through as the second argument.\r\n                // The remaining arguments are forwarded unchanged so context-aware accessors, which\r\n                // receive the runtime context as their payload, keep working. Require an all-digits\r\n                // segment: parseInt would otherwise accept \"1/foo\" as 1 and bind to the wrong index.\r\n                const numericIndex = /^\\d+$/.test(part) ? parseInt(part, 10) : NaN;\r\n                if (!isNaN(numericIndex) && typeof infoTree.get === \"function\") {\r\n                    const orig = infoTree;\r\n                    infoTree = { ...orig };\r\n                    infoTree.get = (target: any, _index?: number, ...rest: any[]) => orig.get(target, numericIndex, ...rest);\r\n                    if (typeof orig.set === \"function\") {\r\n                        infoTree.set = (value: any, target: any, _index?: number, ...rest: any[]) => orig.set(value, target, numericIndex, ...rest);\r\n                    }\r\n                    if (typeof orig.getTarget === \"function\") {\r\n                        infoTree.getTarget = (target: any, _index?: number, ...rest: any[]) => orig.getTarget(target, numericIndex, ...rest);\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (infoTree.__target__) {\r\n                // Only update target if objectTree is defined, otherwise keep the last valid target\r\n                if (objectTree !== undefined) {\r\n                    target = objectTree;\r\n                }\r\n            }\r\n        }\r\n\r\n        return {\r\n            object: target,\r\n            info: infoTree,\r\n        };\r\n    }\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\n\nimport { type TransformNode } from \"core/Meshes/transformNode\";\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\nimport { type MorphTargetManager } from \"core/Morph/morphTargetManager\";\nimport {\n    type IAnimation,\n    type ICamera,\n    type IGLTF,\n    type IKHRLightsPunctual_Light,\n    type IEXTLightsArea_Light,\n    type IMaterial,\n    type IMesh,\n    type IMeshPrimitive,\n    type INode,\n    type IScene,\n    type ISkin,\n} from \"../glTFLoaderInterfaces\";\nimport { type Vector3, Matrix, Quaternion, Vector2 } from \"core/Maths/math.vector.pure\";\nimport { Constants } from \"core/Engines/constants\";\nimport { type Color3, Color4 } from \"core/Maths/math.color.pure\";\nimport { type PBRMaterial } from \"core/Materials/PBR/pbrMaterial\";\nimport { type Light } from \"core/Lights/light\";\nimport { type Nullable } from \"core/types\";\nimport { SpotLight } from \"core/Lights/spotLight.pure\";\nimport { type IEXTLightsImageBased_LightImageBased } from \"babylonjs-gltf2interface\";\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\nimport { type IInterpolationPropertyInfo, type IObjectAccessor } from \"core/FlowGraph/typeDefinitions\";\nimport { FlowGraphInteger } from \"core/FlowGraph/CustomTypes/flowGraphInteger.pure\";\nimport { FlowGraphTypes } from \"core/FlowGraph/flowGraphRichTypes.pure\";\nimport { GLTFPathToObjectConverter } from \"./gltfPathToObjectConverter\";\nimport { type AnimationGroup } from \"core/Animations/animationGroup\";\nimport { type Mesh } from \"core/Meshes/mesh\";\nimport { type RectAreaLight } from \"core/Lights/rectAreaLight\";\n\n/**\n * Top-level shape of the glTF Object Model accessor tree. Each property\n * describes a navigable section of the JSON-Pointer namespace (e.g. `/nodes`,\n * `/materials`, `/scenes`) that KHR_interactivity, KHR_animation_pointer and\n * other extensions consume via {@link GetMappingForKey}.\n */\nexport interface IGLTFObjectModelTree {\n    /** Read-only accessor for the active scene index (`/scene`). */\n    scene: { __target__: boolean } & IObjectAccessor<number | undefined, any, number>;\n    /** Accessor tree for `/cameras`. */\n    cameras: IGLTFObjectModelTreeCamerasObject;\n    /** Accessor tree for `/nodes`. */\n    nodes: IGLTFObjectModelTreeNodesObject;\n    /** Accessor tree for `/materials`. */\n    materials: IGLTFObjectModelTreeMaterialsObject;\n    /** Accessor tree for `/extensions` (root-level glTF extensions). */\n    extensions: IGLTFObjectModelTreeExtensionsObject;\n    /** Accessor tree for `/animations`. */\n    animations: {\n        length: IObjectAccessor<IAnimation[], AnimationGroup[], FlowGraphInteger>;\n        __array__: {};\n    };\n    /** Accessor tree for `/meshes`. */\n    meshes: IGLTFObjectModelTreeMeshesObject;\n    /** Accessor tree for `/scenes`. */\n    scenes: IGLTFObjectModelTreeScenesObject;\n    /** Accessor tree for `/skins`. */\n    skins: IGLTFObjectModelTreeSkinsObject;\n}\n\n/**\n * Accessor tree describing the `/nodes` section of the glTF Object Model.\n * Exposes per-node TRS, ref-typed parent/children/camera/mesh/skin links,\n * morph-target weights and node-extension properties.\n */\nexport interface IGLTFObjectModelTreeNodesObject<GLTFTargetType = INode, BabylonTargetType = TransformNode> {\n    /** Number of nodes in the array. */\n    length: IObjectAccessor<GLTFTargetType[], BabylonTargetType[], FlowGraphInteger>;\n    __array__: {\n        __target__: boolean;\n        translation: IObjectAccessor<GLTFTargetType, BabylonTargetType, Vector3>;\n        rotation: IObjectAccessor<GLTFTargetType, BabylonTargetType, Quaternion>;\n        scale: IObjectAccessor<GLTFTargetType, BabylonTargetType, Vector3>;\n        matrix: IObjectAccessor<GLTFTargetType, BabylonTargetType, Matrix>;\n        globalMatrix: IObjectAccessor<GLTFTargetType, BabylonTargetType, Matrix>;\n        camera: IObjectAccessor<GLTFTargetType, any, string | undefined>;\n        mesh: IObjectAccessor<GLTFTargetType, any, string | undefined>;\n        skin: IObjectAccessor<GLTFTargetType, any, string | undefined>;\n        parent: IObjectAccessor<GLTFTargetType, any, string | undefined>;\n        children: {\n            length: IObjectAccessor<number[], any, FlowGraphInteger>;\n            __array__: { __target__: boolean } & IObjectAccessor<any, any, string>;\n        };\n        weights: {\n            /** When true, the path converter skips objectTree traversal for this property, keeping the parent target. */\n            __passThroughTarget__?: boolean;\n            length: IObjectAccessor<GLTFTargetType, BabylonTargetType, FlowGraphInteger>;\n            // The per-element target alternates between TransformNode (when the index is\n            // out of range or no morph host is reachable) and MorphTarget (when it is),\n            // so we widen the BabylonTargetType to `any` here.\n            __array__: { __target__: boolean } & IObjectAccessor<GLTFTargetType, any, number>;\n        } & IObjectAccessor<GLTFTargetType, BabylonTargetType, number[]>;\n        extensions: {\n            EXT_lights_ies?: {\n                multiplier: IObjectAccessor<INode, Light, number>;\n                color: IObjectAccessor<INode, Light, Color3>;\n            };\n            KHR_node_visibility?: {\n                visible: IObjectAccessor<INode, Mesh, boolean>;\n            };\n        };\n    };\n}\n\n/**\n * Accessor tree describing the `/cameras` section of the glTF Object Model.\n * Exposes orthographic and perspective camera properties.\n */\nexport interface IGLTFObjectModelTreeCamerasObject {\n    /** Number of cameras in the array. */\n    length: IObjectAccessor<ICamera[], any, FlowGraphInteger>;\n    __array__: {\n        __target__: boolean;\n        orthographic: {\n            xmag: IObjectAccessor<ICamera, ICamera, Vector2>;\n            ymag: IObjectAccessor<ICamera, ICamera, Vector2>;\n            zfar: IObjectAccessor<ICamera, ICamera, number>;\n            znear: IObjectAccessor<ICamera, ICamera, number>;\n        };\n        perspective: {\n            yfov: IObjectAccessor<ICamera, ICamera, number>;\n            zfar: IObjectAccessor<ICamera, ICamera, number>;\n            znear: IObjectAccessor<ICamera, ICamera, number>;\n            aspectRatio: IObjectAccessor<ICamera, ICamera, Nullable<number>>;\n        };\n    };\n}\n\n/**\n * Accessor tree describing the `/materials` section of the glTF Object Model.\n * Covers core PBR properties as well as the family of KHR_materials_* extensions.\n */\nexport interface IGLTFObjectModelTreeMaterialsObject {\n    /** Number of materials in the array. */\n    length: IObjectAccessor<IMaterial[], PBRMaterial[], FlowGraphInteger>;\n    __array__: {\n        __target__: boolean;\n        doubleSided: IObjectAccessor<IMaterial, PBRMaterial, boolean>;\n        alphaCutoff: IObjectAccessor<IMaterial, PBRMaterial, number>;\n        pbrMetallicRoughness: {\n            baseColorFactor: IObjectAccessor<IMaterial, PBRMaterial, Color4>;\n            metallicFactor: IObjectAccessor<IMaterial, PBRMaterial, Nullable<number>>;\n            roughnessFactor: IObjectAccessor<IMaterial, PBRMaterial, Nullable<number>>;\n            baseColorTexture: {\n                extensions: {\n                    KHR_texture_transform: ITextureDefinition;\n                };\n            };\n            metallicRoughnessTexture: {\n                extensions: {\n                    KHR_texture_transform: ITextureDefinition;\n                };\n            };\n        };\n        emissiveFactor: IObjectAccessor<IMaterial, PBRMaterial, Color3>;\n        normalTexture: {\n            scale: IObjectAccessor<IMaterial, PBRMaterial, number>;\n            extensions: {\n                KHR_texture_transform: ITextureDefinition;\n            };\n        };\n        occlusionTexture: {\n            strength: IObjectAccessor<IMaterial, PBRMaterial, number>;\n            extensions: {\n                KHR_texture_transform: ITextureDefinition;\n            };\n        };\n        emissiveTexture: {\n            extensions: {\n                KHR_texture_transform: ITextureDefinition;\n            };\n        };\n        extensions: {\n            KHR_materials_anisotropy: {\n                anisotropyStrength: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                anisotropyRotation: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                anisotropyTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_clearcoat: {\n                clearcoatFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                clearcoatRoughnessFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                clearcoatTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n                clearcoatNormalTexture: {\n                    scale: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n                clearcoatRoughnessTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_dispersion: {\n                dispersion: IObjectAccessor<IMaterial, PBRMaterial, number>;\n            };\n            KHR_materials_emissive_strength: {\n                emissiveStrength: IObjectAccessor<IMaterial, PBRMaterial, number>;\n            };\n            KHR_materials_ior: {\n                ior: IObjectAccessor<IMaterial, PBRMaterial, number>;\n            };\n            KHR_materials_iridescence: {\n                iridescenceFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                iridescenceIor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                iridescenceThicknessMinimum: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                iridescenceThicknessMaximum: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                iridescenceTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n                iridescenceThicknessTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_sheen: {\n                sheenColorFactor: IObjectAccessor<IMaterial, PBRMaterial, Color3>;\n                sheenRoughnessFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                sheenColorTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n                sheenRoughnessTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_specular: {\n                specularFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                specularColorFactor: IObjectAccessor<IMaterial, PBRMaterial, Color3>;\n                specularTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n                specularColorTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_transmission: {\n                transmissionFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                transmissionTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_diffuse_transmission: {\n                diffuseTransmissionFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                diffuseTransmissionTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n                diffuseTransmissionColorFactor: IObjectAccessor<IMaterial, PBRMaterial, Nullable<Color3>>;\n                diffuseTransmissionColorTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n            KHR_materials_volume: {\n                thicknessFactor: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                attenuationColor: IObjectAccessor<IMaterial, PBRMaterial, Color3>;\n                attenuationDistance: IObjectAccessor<IMaterial, PBRMaterial, number>;\n                thicknessTexture: {\n                    extensions: {\n                        KHR_texture_transform: ITextureDefinition;\n                    };\n                };\n            };\n        };\n    };\n}\n\ninterface ITextureDefinition {\n    offset: IObjectAccessor<IMaterial, PBRMaterial, Vector2>;\n    rotation: IObjectAccessor<IMaterial, PBRMaterial, number>;\n    scale: IObjectAccessor<IMaterial, PBRMaterial, Vector2>;\n}\n\n/**\n * Accessor tree describing the `/meshes` section of the glTF Object Model.\n * Exposes per-mesh primitives (and their material refs) and the mesh-level\n * morph-target weights array.\n */\nexport interface IGLTFObjectModelTreeMeshesObject {\n    /** Number of meshes in the array. */\n    length: IObjectAccessor<IMesh[], (Mesh | undefined)[], FlowGraphInteger>;\n    __array__: {\n        __target__: boolean;\n        primitives: {\n            length: IObjectAccessor<IMeshPrimitive[], any, FlowGraphInteger>;\n            __array__: {\n                __target__: boolean;\n                material: IObjectAccessor<any, any, string | undefined>;\n            };\n        };\n        weights: {\n            length: IObjectAccessor<number[], any, FlowGraphInteger>;\n            __array__: { __target__: boolean } & IObjectAccessor<any, any, number>;\n        };\n    };\n}\n\n/**\n * Accessor tree describing the `/scenes` section of the glTF Object Model.\n * Per-scene root-node refs are exposed under `nodes/{i}`.\n */\nexport interface IGLTFObjectModelTreeScenesObject {\n    /** Number of scenes in the array. */\n    length: IObjectAccessor<IScene[], any, FlowGraphInteger>;\n    __array__: {\n        __target__: boolean;\n        nodes: {\n            length: IObjectAccessor<number[], any, FlowGraphInteger>;\n            __array__: { __target__: boolean } & IObjectAccessor<any, any, string>;\n        };\n    };\n}\n\n/**\n * Accessor tree describing the `/skins` section of the glTF Object Model.\n * Joint and skeleton properties are exposed as JSON-Pointer refs.\n */\nexport interface IGLTFObjectModelTreeSkinsObject {\n    /** Number of skins in the array. */\n    length: IObjectAccessor<ISkin[], any, FlowGraphInteger>;\n    __array__: {\n        __target__: boolean;\n        joints: {\n            length: IObjectAccessor<number[], any, FlowGraphInteger>;\n            __array__: { __target__: boolean } & IObjectAccessor<any, any, string>;\n        };\n        skeleton: IObjectAccessor<ISkin, any, string | undefined>;\n    };\n}\n\n/**\n * Accessor tree describing root-level glTF extensions exposed through the\n * Object Model. Currently covers the punctual / area / IES / image-based\n * light extension families.\n */\nexport interface IGLTFObjectModelTreeExtensionsObject {\n    /** Accessor tree for `/extensions/KHR_lights_punctual`. */\n    KHR_lights_punctual: {\n        lights: {\n            length: IObjectAccessor<IKHRLightsPunctual_Light[], Light[], FlowGraphInteger>;\n            __array__: {\n                __target__: boolean;\n                color: IObjectAccessor<IKHRLightsPunctual_Light, Light, Color3>;\n                intensity: IObjectAccessor<IKHRLightsPunctual_Light, Light, number>;\n                range: IObjectAccessor<IKHRLightsPunctual_Light, Light, number>;\n                spot: {\n                    innerConeAngle: IObjectAccessor<IKHRLightsPunctual_Light, Light, number>;\n                    outerConeAngle: IObjectAccessor<IKHRLightsPunctual_Light, Light, number>;\n                };\n            };\n        };\n    };\n    /** Accessor tree for `/extensions/EXT_lights_area`. */\n    EXT_lights_area: {\n        lights: {\n            length: IObjectAccessor<IEXTLightsArea_Light[], Light[], FlowGraphInteger>;\n            __array__: {\n                __target__: boolean;\n                color: IObjectAccessor<IEXTLightsArea_Light, Light, Color3>;\n                intensity: IObjectAccessor<IEXTLightsArea_Light, Light, number>;\n                size: IObjectAccessor<IEXTLightsArea_Light, Light, number>;\n                rect: {\n                    aspect: IObjectAccessor<IEXTLightsArea_Light, Light, number>;\n                };\n            };\n        };\n    };\n    /** Accessor tree for `/extensions/EXT_lights_ies`. */\n    EXT_lights_ies: {\n        lights: {\n            length: IObjectAccessor<IKHRLightsPunctual_Light[], Light[], FlowGraphInteger>;\n        };\n    };\n    /** Accessor tree for `/extensions/EXT_lights_image_based`. */\n    EXT_lights_image_based: {\n        lights: {\n            __array__: {\n                __target__: boolean;\n                intensity: IObjectAccessor<IEXTLightsImageBased_LightImageBased, BaseTexture, number>;\n                rotation: IObjectAccessor<IEXTLightsImageBased_LightImageBased, BaseTexture, Quaternion>;\n            };\n            length: IObjectAccessor<IEXTLightsImageBased_LightImageBased[], BaseTexture[], FlowGraphInteger>;\n        };\n    };\n}\n\n/**\n * Builds an accessor for an array `length` pointer (e.g. `/nodes.length`, `/meshes/{}/primitives.length`).\n *\n * The KHR object model types these `length` values as `int`, so the accessor reports the count as a\n * {@link FlowGraphInteger} (type {@link FlowGraphTypes.Integer}). Keeping the representation an integer\n * at the source lets integer-typed consumers such as `FlowGraphIntToFloat` accept the precise\n * `RichTypeFlowGraphInteger` instead of a widened `RichTypeAny`.\n * @param getLength returns the raw count for the addressed array; may be `undefined` when the array is not addressable\n * @param getTarget returns the Babylon object(s) backing the array\n * @returns an object accessor whose value is the count as a {@link FlowGraphInteger}\n */\nfunction _CreateLengthAccessor<GLTFTargetType, BabylonTargetType>(\n    getLength: (target: GLTFTargetType) => number | undefined,\n    getTarget: (target: GLTFTargetType) => BabylonTargetType\n): IObjectAccessor<GLTFTargetType, BabylonTargetType, FlowGraphInteger> {\n    return {\n        type: FlowGraphTypes.Integer,\n        get: (target: GLTFTargetType) => {\n            const length = getLength(target);\n            return length === undefined ? undefined : FlowGraphInteger.FromValue(length);\n        },\n        getTarget,\n        getPropertyName: [() => \"length\"],\n    };\n}\n\nconst nodesTree: IGLTFObjectModelTreeNodesObject = {\n    length: _CreateLengthAccessor(\n        (nodes: INode[]) => nodes.length,\n        (nodes: INode[]) => nodes.map((node) => node._babylonTransformNode!)\n    ),\n    __array__: {\n        __target__: true,\n        translation: {\n            type: \"Vector3\",\n            get: (node: INode) => node._babylonTransformNode?.position,\n            set: (value: Vector3, node: INode) => node._babylonTransformNode?.position.copyFrom(value),\n            getTarget: (node: INode) => node._babylonTransformNode,\n            getPropertyName: [() => \"position\"],\n        },\n        rotation: {\n            type: \"Quaternion\",\n            get: (node: INode) => node._babylonTransformNode?.rotationQuaternion!,\n            set: (value: Quaternion, node: INode) => node._babylonTransformNode?.rotationQuaternion?.copyFrom(value),\n            getTarget: (node: INode) => node._babylonTransformNode,\n            getPropertyName: [() => \"rotationQuaternion\"],\n        },\n        scale: {\n            type: \"Vector3\",\n            get: (node: INode) => node._babylonTransformNode?.scaling,\n            set: (value: Vector3, node: INode) => node._babylonTransformNode?.scaling.copyFrom(value),\n            getTarget: (node: INode) => node._babylonTransformNode,\n            getPropertyName: [() => \"scaling\"],\n        },\n        weights: {\n            // Skip glTF objectTree traversal — weights may be undefined on the glTF node\n            // but accessible via the Babylon MorphTargetManager on the INode's meshes\n            __passThroughTarget__: true,\n            length: _CreateLengthAccessor(\n                (node: INode) => {\n                    const found = _findNodeMorphTargets(node);\n                    return found ? found.mtm.numTargets : node?.mesh !== undefined ? 0 : undefined;\n                },\n                (node: INode) => node?._babylonTransformNode!\n            ),\n            __array__: {\n                __target__: true,\n                type: \"number\",\n                get: (node: INode, index?: number) => {\n                    const found = _findNodeMorphTargets(node);\n                    if (found && index !== undefined && index >= 0 && index < found.mtm.numTargets) {\n                        return _roundFloat32Artifact(found.mtm.getTarget(index).influence);\n                    }\n                    return undefined;\n                },\n                set: (value: any, node: INode, index?: number) => {\n                    const numValue = typeof value === \"number\" ? value : typeof value?.value === \"number\" ? value.value : value;\n                    const found = _findNodeMorphTargets(node);\n                    if (!found || index === undefined || index < 0 || index >= found.mtm.numTargets) {\n                        return;\n                    }\n                    // Fan out to every mesh that shares this morph target manager so\n                    // multi-primitive meshes stay in sync.\n                    for (const mesh of found.meshes) {\n                        const target = mesh.morphTargetManager?.getTarget(index);\n                        if (target) {\n                            target.influence = numValue;\n                        }\n                    }\n                },\n                getTarget: (node: INode, index?: number) => {\n                    const found = _findNodeMorphTargets(node);\n                    if (found && index !== undefined && index >= 0 && index < found.mtm.numTargets) {\n                        return found.mtm.getTarget(index);\n                    }\n                    return node?._babylonTransformNode;\n                },\n                getPropertyName: [() => \"influence\"],\n            },\n            type: \"number[]\",\n            get: (node: INode) => {\n                const found = _findNodeMorphTargets(node);\n                if (!found) {\n                    return [];\n                }\n                const weights: number[] = [];\n                for (let i = 0; i < found.mtm.numTargets; i++) {\n                    weights.push(_roundFloat32Artifact(found.mtm.getTarget(i).influence));\n                }\n                return weights;\n            },\n            getTarget: (node: INode) => node?._babylonTransformNode,\n            getPropertyName: [() => \"influence\"],\n        },\n        // readonly!\n        matrix: {\n            type: \"Matrix\",\n            get: (node: INode) => Matrix.Compose(node._babylonTransformNode?.scaling!, node._babylonTransformNode?.rotationQuaternion!, node._babylonTransformNode?.position!),\n            getTarget: (node: INode) => node._babylonTransformNode,\n            isReadOnly: true,\n        },\n        globalMatrix: {\n            type: \"Matrix\",\n            get: (node: INode) => {\n                const matrix = Matrix.Identity();\n                // RHS/LHS support\n                let rootNode = node.parent;\n                while (rootNode && rootNode.parent) {\n                    rootNode = rootNode.parent;\n                }\n                const forceUpdate =\n                    node._babylonTransformNode?.position._isDirty || node._babylonTransformNode?.rotationQuaternion?._isDirty || node._babylonTransformNode?.scaling._isDirty;\n                if (rootNode) {\n                    // take the parent root node's world matrix, invert it, and multiply it with the current node's world matrix\n                    // This will provide the global matrix, ignoring the RHS->LHS conversion\n                    const rootMatrix = rootNode._babylonTransformNode?.computeWorldMatrix(true).invert();\n                    if (rootMatrix) {\n                        node._babylonTransformNode?.computeWorldMatrix(forceUpdate)?.multiplyToRef(rootMatrix, matrix);\n                    }\n                } else if (node._babylonTransformNode) {\n                    matrix.copyFrom(node._babylonTransformNode.computeWorldMatrix(forceUpdate));\n                }\n                return matrix;\n            },\n            getTarget: (node: INode) => node._babylonTransformNode,\n            isReadOnly: true,\n        },\n        camera: {\n            type: \"string\",\n            // Per KHR_interactivity Object Model: read-only ref pointing to the\n            // attached camera, encoded as a JSON Pointer string. Empty string\n            // when no camera is attached (the spec's null-ref convention).\n            get: (node: INode) => (node.camera !== undefined ? `/cameras/${node.camera}` : \"\"),\n            getTarget: (node: INode) => node,\n            isReadOnly: true,\n        },\n        mesh: {\n            type: \"string\",\n            get: (node: INode) => (node.mesh !== undefined ? `/meshes/${node.mesh}` : \"\"),\n            getTarget: (node: INode) => node,\n            isReadOnly: true,\n        },\n        skin: {\n            type: \"string\",\n            get: (node: INode) => (node.skin !== undefined ? `/skins/${node.skin}` : \"\"),\n            getTarget: (node: INode) => node,\n            isReadOnly: true,\n        },\n        parent: {\n            type: \"string\",\n            get: (node: INode) => (node.parent && node.parent.index !== undefined ? `/nodes/${node.parent.index}` : \"\"),\n            getTarget: (node: INode) => node,\n            isReadOnly: true,\n        },\n        children: {\n            length: _CreateLengthAccessor(\n                (children: number[]) => children?.length ?? 0,\n                (children: number[]) => children ?? []\n            ),\n            __array__: {\n                __target__: true,\n                type: \"string\",\n                // The wrapping converter passes the indexed child value (an\n                // INode index); convert it to a JSON Pointer ref string.\n                get: (childIndex: any) => (typeof childIndex === \"number\" ? `/nodes/${childIndex}` : \"\"),\n                getTarget: () => ({ __nodeIndex: true }),\n                isReadOnly: true,\n            },\n        },\n        extensions: {\n            EXT_lights_ies: {\n                multiplier: {\n                    type: \"number\",\n                    get: (node: INode) => {\n                        return node._babylonTransformNode?.getChildren((child) => child instanceof SpotLight, true)[0]?.intensity;\n                    },\n                    getTarget: (node: INode) => node._babylonTransformNode?.getChildren((child) => child instanceof SpotLight, true)[0],\n                    set: (value, node) => {\n                        if (node._babylonTransformNode) {\n                            const light = node._babylonTransformNode.getChildren((child) => child instanceof SpotLight, true)[0];\n                            if (light) {\n                                light.intensity = value;\n                            }\n                        }\n                    },\n                },\n                color: {\n                    type: \"Color3\",\n                    get: (node: INode) => {\n                        return node._babylonTransformNode?.getChildren((child) => child instanceof SpotLight, true)[0]?.diffuse;\n                    },\n                    getTarget: (node: INode) => node._babylonTransformNode?.getChildren((child) => child instanceof SpotLight, true)[0],\n                    set: (value, node: INode) => {\n                        if (node._babylonTransformNode) {\n                            const light = node._babylonTransformNode.getChildren((child) => child instanceof SpotLight, true)[0];\n                            if (light) {\n                                light.diffuse = value;\n                            }\n                        }\n                    },\n                },\n            },\n            KHR_node_visibility: {\n                visible: {\n                    type: \"boolean\",\n                    get: (node: INode) => {\n                        return node._primitiveBabylonMeshes ? node._primitiveBabylonMeshes[0].isVisible : false;\n                    },\n                    getTarget: () => undefined, // TODO: what should this return?\n                    set: (value: boolean, node: INode) => {\n                        if (node._primitiveBabylonMeshes) {\n                            node._primitiveBabylonMeshes.forEach((mesh) => (mesh.isVisible = value));\n                        }\n                    },\n                },\n            },\n        },\n    },\n};\n\nconst animationsTree = {\n    length: _CreateLengthAccessor(\n        (animations: IAnimation[]) => animations.length,\n        (animations: IAnimation[]) => animations.map((animation) => animation._babylonAnimationGroup!)\n    ),\n    __array__: {\n        // Indexed access to the animation, surfaced as a JSON Pointer ref string so blocks like\n        // ``animation/start`` can consume it directly. Uses the animation's own ``index`` property\n        // (populated by the loader's ArrayItem.Assign step) so the ref is resolved without needing\n        // a separate index payload from the path converter.\n        __target__: true,\n        type: \"string\",\n        get: (animation: IAnimation) => (animation && typeof animation.index === \"number\" ? `/animations/${animation.index}` : \"\"),\n        getTarget: (animation: IAnimation) => animation._babylonAnimationGroup,\n        isReadOnly: true,\n    },\n};\n\nconst meshesTree: IGLTFObjectModelTreeMeshesObject = {\n    length: _CreateLengthAccessor(\n        (meshes: IMesh[]) => meshes.length,\n        (meshes: IMesh[]) => meshes.map((mesh) => mesh.primitives[0]._instanceData?.babylonSourceMesh)\n    ),\n    __array__: {\n        __target__: true,\n        primitives: {\n            length: _CreateLengthAccessor(\n                (primitives: IMeshPrimitive[]) => primitives?.length ?? 0,\n                (primitives: IMeshPrimitive[]) => primitives ?? []\n            ),\n            __array__: {\n                __target__: true,\n                material: {\n                    type: \"string\",\n                    // Read-only ref to the assigned material, JSON Pointer encoded.\n                    get: (primitive: IMeshPrimitive) => (primitive.material !== undefined ? `/materials/${primitive.material}` : \"\"),\n                    getTarget: (primitive: IMeshPrimitive) => primitive,\n                    isReadOnly: true,\n                },\n            },\n        },\n        weights: {\n            length: _CreateLengthAccessor(\n                (weights: number[]) => weights?.length ?? 0,\n                (weights: number[]) => weights ?? []\n            ),\n            __array__: {\n                __target__: true,\n                type: \"number\",\n                get: (weightValue: any) => weightValue,\n                getTarget: () => ({ __weightValue: true }),\n                isReadOnly: true,\n            },\n        },\n    },\n};\n\nconst camerasTree: IGLTFObjectModelTreeCamerasObject = {\n    length: _CreateLengthAccessor(\n        (cameras: ICamera[]) => cameras.length,\n        (cameras: ICamera[]) => cameras.map((camera) => camera._babylonCamera!)\n    ),\n    __array__: {\n        __target__: true,\n        orthographic: {\n            xmag: {\n                componentsCount: 2,\n                type: \"Vector2\",\n                get: (camera) => new Vector2(camera._babylonCamera?.orthoLeft ?? 0, camera._babylonCamera?.orthoRight ?? 0),\n                set: (value, camera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.orthoLeft = value.x;\n                        camera._babylonCamera.orthoRight = value.y;\n                    }\n                },\n                getTarget: (camera) => camera,\n                getPropertyName: [() => \"orthoLeft\", () => \"orthoRight\"],\n            },\n            ymag: {\n                componentsCount: 2,\n                type: \"Vector2\",\n                get: (camera: ICamera) => new Vector2(camera._babylonCamera?.orthoBottom ?? 0, camera._babylonCamera?.orthoTop ?? 0),\n                set: (value: Vector2, camera: ICamera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.orthoBottom = value.x;\n                        camera._babylonCamera.orthoTop = value.y;\n                    }\n                },\n                getTarget: (camera) => camera,\n                getPropertyName: [() => \"orthoBottom\", () => \"orthoTop\"],\n            },\n            zfar: {\n                type: \"number\",\n                get: (camera: ICamera) => camera._babylonCamera?.maxZ,\n                set: (value: number, camera: ICamera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.maxZ = value;\n                    }\n                },\n                getTarget: (camera: ICamera) => camera,\n                getPropertyName: [() => \"maxZ\"],\n            },\n            znear: {\n                type: \"number\",\n                get: (camera: ICamera) => camera._babylonCamera?.minZ,\n                set: (value: number, camera: ICamera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.minZ = value;\n                    }\n                },\n                getTarget: (camera: ICamera) => camera,\n                getPropertyName: [() => \"minZ\"],\n            },\n        },\n        perspective: {\n            aspectRatio: {\n                type: \"number\",\n                get: (camera: ICamera) => camera._babylonCamera?.getEngine().getAspectRatio(camera._babylonCamera),\n                getTarget: (camera: ICamera) => camera,\n                getPropertyName: [() => \"aspectRatio\"],\n                isReadOnly: true, // might not be the case for glTF?\n            },\n            yfov: {\n                type: \"number\",\n                get: (camera: ICamera) => camera._babylonCamera?.fov,\n                set: (value: number, camera: ICamera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.fov = value;\n                    }\n                },\n                getTarget: (camera: ICamera) => camera,\n                getPropertyName: [() => \"fov\"],\n            },\n            zfar: {\n                type: \"number\",\n                get: (camera: ICamera) => camera._babylonCamera?.maxZ,\n                set: (value: number, camera: ICamera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.maxZ = value;\n                    }\n                },\n                getTarget: (camera: ICamera) => camera,\n                getPropertyName: [() => \"maxZ\"],\n            },\n            znear: {\n                type: \"number\",\n                get: (camera: ICamera) => camera._babylonCamera?.minZ,\n                set: (value: number, camera: ICamera) => {\n                    if (camera._babylonCamera) {\n                        camera._babylonCamera.minZ = value;\n                    }\n                },\n                getTarget: (camera: ICamera) => camera,\n                getPropertyName: [() => \"minZ\"],\n            },\n        },\n    },\n};\n\nconst materialsTree: IGLTFObjectModelTreeMaterialsObject = {\n    length: _CreateLengthAccessor(\n        (materials: IMaterial[]) => materials.length,\n        (materials: IMaterial[]) => materials.map((material) => material._data?.[Constants.MATERIAL_TriangleFillMode]?.babylonMaterial as PBRMaterial)\n    ),\n    __array__: {\n        __target__: true,\n        doubleSided: {\n            type: \"boolean\",\n            get: (material, index?, payload?) => !GetMaterial(material, index, payload)?.backFaceCulling,\n            set: (value: boolean, material, index?, payload?) => {\n                const mat = GetMaterial(material, index, payload);\n                if (mat) {\n                    mat.backFaceCulling = !value;\n                }\n            },\n            getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n            getPropertyName: [() => \"backFaceCulling\"],\n        },\n        alphaCutoff: {\n            type: \"number\",\n            get: (material, index?, payload?) => GetMaterial(material, index, payload)?.alphaCutOff,\n            set: (value: number, material, index?, payload?) => {\n                const mat = GetMaterial(material, index, payload);\n                if (mat) {\n                    mat.alphaCutOff = value;\n                }\n            },\n            getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n            getPropertyName: [() => \"alphaCutOff\"],\n        },\n        emissiveFactor: {\n            type: \"Color3\",\n            get: (material, index?, payload?) => GetMaterial(material, index, payload).emissiveColor,\n            set: (value: Color3, material, index?, payload?) => GetMaterial(material, index, payload).emissiveColor.copyFrom(value),\n            getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n            getPropertyName: [() => \"emissiveColor\"],\n        },\n        emissiveTexture: {\n            extensions: {\n                KHR_texture_transform: GenerateTextureMap(\"emissiveTexture\"),\n            },\n        },\n        normalTexture: {\n            scale: {\n                type: \"number\",\n                get: (material, index?, payload?) => GetTexture(material, payload, \"bumpTexture\")?.level,\n                set: (value: number, material, index?, payload?) => {\n                    const texture = GetTexture(material, payload, \"bumpTexture\");\n                    if (texture) {\n                        texture.level = value;\n                    }\n                },\n                getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                getPropertyName: [() => \"level\"],\n            },\n            extensions: {\n                KHR_texture_transform: GenerateTextureMap(\"bumpTexture\"),\n            },\n        },\n        occlusionTexture: {\n            strength: {\n                type: \"number\",\n                get: (material, index?, payload?) => GetMaterial(material, index, payload).ambientTextureStrength,\n                set: (value: number, material, index?, payload?) => {\n                    const mat = GetMaterial(material, index, payload);\n                    if (mat) {\n                        mat.ambientTextureStrength = value;\n                    }\n                },\n                getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                getPropertyName: [() => \"ambientTextureStrength\"],\n            },\n            extensions: {\n                KHR_texture_transform: GenerateTextureMap(\"ambientTexture\"),\n            },\n        },\n        pbrMetallicRoughness: {\n            baseColorFactor: {\n                type: \"Color4\",\n                get: (material, index?, payload?) => {\n                    const mat = GetMaterial(material, index, payload);\n                    return Color4.FromColor3(mat.albedoColor, mat.alpha);\n                },\n                set: (value: Color4, material, index?, payload?) => {\n                    const mat = GetMaterial(material, index, payload);\n                    mat.albedoColor.set(value.r, value.g, value.b);\n                    mat.alpha = value.a;\n                },\n                getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                // This is correct on the animation level, but incorrect as a single property of a type Color4\n                getPropertyName: [() => \"albedoColor\", () => \"alpha\"],\n            },\n            baseColorTexture: {\n                extensions: {\n                    KHR_texture_transform: GenerateTextureMap(\"albedoTexture\"),\n                },\n            },\n            metallicFactor: {\n                type: \"number\",\n                get: (material, index?, payload?) => GetMaterial(material, index, payload).metallic,\n                set: (value, material, index?, payload?) => {\n                    const mat = GetMaterial(material, index, payload);\n                    if (mat) {\n                        mat.metallic = value;\n                    }\n                },\n                getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                getPropertyName: [() => \"metallic\"],\n            },\n            roughnessFactor: {\n                type: \"number\",\n                get: (material, index?, payload?) => GetMaterial(material, index, payload).roughness,\n                set: (value, material, index?, payload?) => {\n                    const mat = GetMaterial(material, index, payload);\n                    if (mat) {\n                        mat.roughness = value;\n                    }\n                },\n                getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                getPropertyName: [() => \"roughness\"],\n            },\n            metallicRoughnessTexture: {\n                extensions: {\n                    KHR_texture_transform: GenerateTextureMap(\"metallicTexture\"),\n                },\n            },\n        },\n        extensions: {\n            KHR_materials_anisotropy: {\n                anisotropyStrength: {\n                    type: \"number\",\n                    get: (material, index?, payload?) => GetMaterial(material, index, payload)?.anisotropy?.intensity,\n                    set: (value: number, material, index?, payload?) => {\n                        const mat = GetMaterial(material, index, payload);\n                        if (mat) {\n                            mat.anisotropy.intensity = value;\n                        }\n                    },\n                    getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                    getPropertyName: [() => \"anisotropy.intensity\"],\n                },\n                anisotropyRotation: {\n                    type: \"number\",\n                    get: (material, index?, payload?) => GetMaterial(material, index, payload)?.anisotropy?.angle,\n                    set: (value: number, material, index?, payload?) => {\n                        const mat = GetMaterial(material, index, payload);\n                        if (mat) {\n                            mat.anisotropy.angle = value;\n                        }\n                    },\n                    getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                    getPropertyName: [() => \"anisotropy.angle\"],\n                },\n                anisotropyTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"anisotropy\", \"texture\"),\n                    },\n                },\n            },\n            KHR_materials_clearcoat: {\n                clearcoatFactor: {\n                    type: \"number\",\n                    get: (material, index?, payload?) => GetMaterial(material, index, payload).clearCoat.intensity,\n                    set: (value, material, index?, payload?) => {\n                        GetMaterial(material, index, payload).clearCoat.intensity = value;\n                    },\n                    getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                    getPropertyName: [() => \"clearCoat.intensity\"],\n                },\n                clearcoatRoughnessFactor: {\n                    type: \"number\",\n                    get: (material, index?, payload?) => GetMaterial(material, index, payload).clearCoat.roughness,\n                    set: (value, material, index?, payload?) => {\n                        GetMaterial(material, index, payload).clearCoat.roughness = value;\n                    },\n                    getTarget: (material, index?, payload?) => GetMaterial(material, index, payload),\n                    getPropertyName: [() => \"clearCoat.roughness\"],\n                },\n                clearcoatTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"clearCoat\", \"texture\"),\n                    },\n                },\n                clearcoatNormalTexture: {\n                    scale: {\n                        type: \"number\",\n                        get: (material, index, payload) => GetMaterial(material, index, payload).clearCoat.bumpTexture?.level,\n                        getTarget: GetMaterial,\n                        set: (value, material, index, payload) => (GetMaterial(material, index, payload).clearCoat.bumpTexture!.level = value),\n                    },\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"clearCoat\", \"bumpTexture\"),\n                    },\n                },\n                clearcoatRoughnessTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"clearCoat\", \"textureRoughness\"),\n                    },\n                },\n            },\n            KHR_materials_dispersion: {\n                dispersion: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.dispersion,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).subSurface.dispersion = value),\n                },\n            },\n            KHR_materials_emissive_strength: {\n                emissiveStrength: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).emissiveIntensity,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).emissiveIntensity = value),\n                },\n            },\n            KHR_materials_ior: {\n                ior: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).indexOfRefraction,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).indexOfRefraction = value),\n                },\n            },\n            KHR_materials_iridescence: {\n                iridescenceFactor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).iridescence.intensity,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).iridescence.intensity = value),\n                },\n                iridescenceIor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).iridescence.indexOfRefraction,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).iridescence.indexOfRefraction = value),\n                },\n                iridescenceTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"iridescence\", \"texture\"),\n                    },\n                },\n                iridescenceThicknessMaximum: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).iridescence.maximumThickness,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).iridescence.maximumThickness = value),\n                },\n                iridescenceThicknessMinimum: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).iridescence.minimumThickness,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).iridescence.minimumThickness = value),\n                },\n                iridescenceThicknessTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"iridescence\", \"thicknessTexture\"),\n                    },\n                },\n            },\n            KHR_materials_sheen: {\n                sheenColorFactor: {\n                    type: \"Color3\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).sheen.color,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => GetMaterial(material, index, payload).sheen.color.copyFrom(value),\n                },\n                sheenColorTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"sheen\", \"texture\"),\n                    },\n                },\n                sheenRoughnessFactor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).sheen.intensity,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).sheen.intensity = value),\n                },\n                sheenRoughnessTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"sheen\", \"textureRoughness\"),\n                    },\n                },\n            },\n            KHR_materials_specular: {\n                specularFactor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).metallicF0Factor,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).metallicF0Factor = value),\n                    getPropertyName: [() => \"metallicF0Factor\"],\n                },\n                specularColorFactor: {\n                    type: \"Color3\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).metallicReflectanceColor,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => GetMaterial(material, index, payload).metallicReflectanceColor.copyFrom(value),\n                    getPropertyName: [() => \"metallicReflectanceColor\"],\n                },\n                specularTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"metallicReflectanceTexture\"),\n                    },\n                },\n                specularColorTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"reflectanceTexture\"),\n                    },\n                },\n            },\n            KHR_materials_transmission: {\n                transmissionFactor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.refractionIntensity,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).subSurface.refractionIntensity = value),\n                    getPropertyName: [() => \"subSurface.refractionIntensity\"],\n                },\n                transmissionTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"subSurface\", \"refractionIntensityTexture\", {\n                            extensionKey: \"KHR_materials_transmission\",\n                            texturePath: [\"transmissionTexture\"],\n                        }),\n                    },\n                },\n            },\n            KHR_materials_diffuse_transmission: {\n                diffuseTransmissionFactor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.translucencyIntensity,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).subSurface.translucencyIntensity = value),\n                },\n                diffuseTransmissionTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"subSurface\", \"translucencyIntensityTexture\", {\n                            extensionKey: \"KHR_materials_diffuse_transmission\",\n                            texturePath: [\"diffuseTransmissionTexture\"],\n                        }),\n                    },\n                },\n                diffuseTransmissionColorFactor: {\n                    type: \"Color3\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.translucencyColor,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => value && GetMaterial(material, index, payload).subSurface.translucencyColor?.copyFrom(value),\n                },\n                diffuseTransmissionColorTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"subSurface\", \"translucencyColorTexture\", {\n                            extensionKey: \"KHR_materials_diffuse_transmission\",\n                            texturePath: [\"diffuseTransmissionColorTexture\"],\n                        }),\n                    },\n                },\n            },\n            KHR_materials_volume: {\n                attenuationColor: {\n                    type: \"Color3\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.tintColor,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => GetMaterial(material, index, payload).subSurface.tintColor.copyFrom(value),\n                },\n                attenuationDistance: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.tintColorAtDistance,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).subSurface.tintColorAtDistance = value),\n                },\n                thicknessFactor: {\n                    type: \"number\",\n                    get: (material, index, payload) => GetMaterial(material, index, payload).subSurface.maximumThickness,\n                    getTarget: GetMaterial,\n                    set: (value, material, index, payload) => (GetMaterial(material, index, payload).subSurface.maximumThickness = value),\n                },\n                thicknessTexture: {\n                    extensions: {\n                        KHR_texture_transform: GenerateTextureMap(\"subSurface\", \"thicknessTexture\", { extensionKey: \"KHR_materials_volume\", texturePath: [\"thicknessTexture\"] }),\n                    },\n                },\n            },\n        },\n    },\n};\n\nconst extensionsTree: IGLTFObjectModelTreeExtensionsObject = {\n    KHR_lights_punctual: {\n        lights: {\n            length: _CreateLengthAccessor(\n                (lights: IKHRLightsPunctual_Light[]) => lights.length,\n                (lights: IKHRLightsPunctual_Light[]) => lights.map((light) => light._babylonLight!)\n            ),\n            __array__: {\n                __target__: true,\n                color: {\n                    type: \"Color3\",\n                    get: (light: IKHRLightsPunctual_Light) => light._babylonLight?.diffuse,\n                    set: (value: Color3, light: IKHRLightsPunctual_Light) => light._babylonLight?.diffuse.copyFrom(value),\n                    getTarget: (light: IKHRLightsPunctual_Light) => light._babylonLight,\n                    getPropertyName: [(_light: IKHRLightsPunctual_Light) => \"diffuse\"],\n                },\n                intensity: {\n                    type: \"number\",\n                    get: (light: IKHRLightsPunctual_Light) => light._babylonLight?.intensity,\n                    set: (value: number, light: IKHRLightsPunctual_Light) => (light._babylonLight ? (light._babylonLight.intensity = value) : undefined),\n                    getTarget: (light: IKHRLightsPunctual_Light) => light._babylonLight,\n                    getPropertyName: [(_light: IKHRLightsPunctual_Light) => \"intensity\"],\n                },\n                range: {\n                    type: \"number\",\n                    get: (light: IKHRLightsPunctual_Light) => light._babylonLight?.range,\n                    set: (value: number, light: IKHRLightsPunctual_Light) => (light._babylonLight ? (light._babylonLight.range = value) : undefined),\n                    getTarget: (light: IKHRLightsPunctual_Light) => light._babylonLight,\n                    getPropertyName: [(_light: IKHRLightsPunctual_Light) => \"range\"],\n                },\n                spot: {\n                    innerConeAngle: {\n                        type: \"number\",\n                        get: (light: IKHRLightsPunctual_Light) => (light._babylonLight as SpotLight)?.innerAngle,\n                        set: (value: number, light: IKHRLightsPunctual_Light) => (light._babylonLight ? ((light._babylonLight as SpotLight).innerAngle = value) : undefined),\n                        getTarget: (light: IKHRLightsPunctual_Light) => light._babylonLight,\n                        getPropertyName: [(_light: IKHRLightsPunctual_Light) => \"innerConeAngle\"],\n                    },\n                    outerConeAngle: {\n                        type: \"number\",\n                        get: (light: IKHRLightsPunctual_Light) => (light._babylonLight as SpotLight)?.angle,\n                        set: (value: number, light: IKHRLightsPunctual_Light) => (light._babylonLight ? ((light._babylonLight as SpotLight).angle = value) : undefined),\n                        getTarget: (light: IKHRLightsPunctual_Light) => light._babylonLight,\n                        getPropertyName: [(_light: IKHRLightsPunctual_Light) => \"outerConeAngle\"],\n                    },\n                },\n            },\n        },\n    },\n    EXT_lights_area: {\n        lights: {\n            length: _CreateLengthAccessor(\n                (lights: IEXTLightsArea_Light[]) => lights.length,\n                (lights: IEXTLightsArea_Light[]) => lights.map((light) => light._babylonLight!)\n            ),\n            __array__: {\n                __target__: true,\n                color: {\n                    type: \"Color3\",\n                    get: (light: IEXTLightsArea_Light) => light._babylonLight?.diffuse,\n                    set: (value: Color3, light: IEXTLightsArea_Light) => light._babylonLight?.diffuse.copyFrom(value),\n                    getTarget: (light: IEXTLightsArea_Light) => light._babylonLight,\n                    getPropertyName: [(_light: IEXTLightsArea_Light) => \"diffuse\"],\n                },\n                intensity: {\n                    type: \"number\",\n                    get: (light: IEXTLightsArea_Light) => light._babylonLight?.intensity,\n                    set: (value: number, light: IEXTLightsArea_Light) => (light._babylonLight ? (light._babylonLight.intensity = value) : undefined),\n                    getTarget: (light: IEXTLightsArea_Light) => light._babylonLight,\n                    getPropertyName: [(_light: IEXTLightsArea_Light) => \"intensity\"],\n                },\n                size: {\n                    type: \"number\",\n                    get: (light: IEXTLightsArea_Light) => (light._babylonLight as RectAreaLight)?.height,\n                    set: (value: number, light: IEXTLightsArea_Light) => (light._babylonLight ? ((light._babylonLight as RectAreaLight).height = value) : undefined),\n                    getTarget: (light: IEXTLightsArea_Light) => light._babylonLight,\n                    getPropertyName: [(_light: IEXTLightsArea_Light) => \"size\"],\n                },\n                rect: {\n                    aspect: {\n                        type: \"number\",\n                        get: (light: IEXTLightsArea_Light) => (light._babylonLight as RectAreaLight)?.width / (light._babylonLight as RectAreaLight)?.height,\n                        set: (value: number, light: IEXTLightsArea_Light) =>\n                            light._babylonLight ? ((light._babylonLight as RectAreaLight).width = value * (light._babylonLight as RectAreaLight).height) : undefined,\n                        getTarget: (light: IEXTLightsArea_Light) => light._babylonLight,\n                        getPropertyName: [(_light: IEXTLightsArea_Light) => \"aspect\"],\n                    },\n                },\n            },\n        },\n    },\n    EXT_lights_ies: {\n        lights: {\n            length: _CreateLengthAccessor(\n                (lights: IKHRLightsPunctual_Light[]) => lights.length,\n                (lights: IKHRLightsPunctual_Light[]) => lights.map((light) => light._babylonLight!)\n            ),\n        },\n    },\n    EXT_lights_image_based: {\n        lights: {\n            length: _CreateLengthAccessor(\n                (lights: IEXTLightsImageBased_LightImageBased[]) => lights.length,\n                (lights: IEXTLightsImageBased_LightImageBased[]) => lights.map((light) => light._babylonTexture!)\n            ),\n            __array__: {\n                __target__: true,\n                intensity: {\n                    type: \"number\",\n                    get: (light) => light._babylonTexture?.level,\n                    set: (value, light) => {\n                        if (light._babylonTexture) {\n                            light._babylonTexture.level = value;\n                        }\n                    },\n\n                    getTarget: (light) => light._babylonTexture,\n                },\n                rotation: {\n                    type: \"Quaternion\",\n                    get: (light) => light._babylonTexture && Quaternion.FromRotationMatrix(light._babylonTexture?.getReflectionTextureMatrix()),\n                    set: (value, light) => {\n                        if (!light._babylonTexture) {\n                            return;\n                        }\n                        // Invert the rotation so that positive rotation is counter-clockwise.\n                        if (!light._babylonTexture.getScene()?.useRightHandedSystem) {\n                            value = Quaternion.Inverse(value);\n                        }\n\n                        Matrix.FromQuaternionToRef(value, light._babylonTexture.getReflectionTextureMatrix());\n                    },\n                    getTarget: (light) => light._babylonTexture,\n                },\n            },\n        },\n    },\n};\n\nfunction GetTexture(material: IMaterial, payload: any, textureType: keyof PBRMaterial, textureInObject?: string) {\n    const babylonMaterial = GetMaterial(material, payload);\n    return textureInObject ? babylonMaterial[textureType][textureInObject] : babylonMaterial[textureType];\n}\nfunction GetMaterial(material: IMaterial, _index?: number, payload?: any) {\n    return material._data?.[payload?.fillMode ?? Constants.MATERIAL_TriangleFillMode]?.babylonMaterial as PBRMaterial;\n}\nfunction _getNodeMorphTargetManager(node: INode): any {\n    const tn = node?._babylonTransformNode;\n    if (!tn) {\n        return undefined;\n    }\n    // Single primitive: transform node IS the mesh with morphTargetManager\n    if ((tn as any).morphTargetManager) {\n        return (tn as any).morphTargetManager;\n    }\n    // Multiple primitives: check each primitive mesh and its source\n    const primMeshes = node._primitiveBabylonMeshes;\n    if (primMeshes) {\n        for (const mesh of primMeshes) {\n            if (mesh?.morphTargetManager) {\n                return mesh.morphTargetManager;\n            }\n            // Check source mesh for instanced meshes\n            if ((mesh as any)?.sourceMesh?.morphTargetManager) {\n                return (mesh as any).sourceMesh.morphTargetManager;\n            }\n        }\n    }\n    return undefined;\n}\n\n/**\n * Result of a morph-target lookup: the active manager plus every Babylon mesh\n * that shares it, so writes (set) can fan out across all primitives.\n */\ninterface IMorphTargetLookup {\n    mtm: MorphTargetManager;\n    meshes: AbstractMesh[];\n}\n\n/**\n * KHR_interactivity test assets routinely use a glTF hierarchy where the\n * **parent** node has no `mesh` but a descendant does. The Khronos morph-weight\n * tests query `/nodes/<parent>/weights/*` and expect the result to come from\n * the morph targets of the first descendant mesh. To support this we walk the\n * Babylon-side scene graph below the queried INode looking for a Mesh that has\n * a morphTargetManager.\n *\n * For multi-primitive meshes (one INode → several Babylon meshes parented to a\n * wrapper TransformNode) we also collect the sibling primitives so a `set`\n * touches every mesh that shares the manager.\n * @param node the glTF node to start the lookup from\n * @returns the active morph target manager and every Babylon mesh that shares\n * it, or `undefined` when no morph target manager is reachable from the node.\n */\nfunction _findNodeMorphTargets(node: INode): IMorphTargetLookup | undefined {\n    const tn = node?._babylonTransformNode;\n    if (!tn) {\n        return undefined;\n    }\n    // Direct: this node's own mesh has a morph target manager.\n    const directMtm: MorphTargetManager | undefined = _getNodeMorphTargetManager(node);\n    if (directMtm && node._primitiveBabylonMeshes && node._primitiveBabylonMeshes.length > 0) {\n        return { mtm: directMtm, meshes: node._primitiveBabylonMeshes as AbstractMesh[] };\n    }\n    // Fallback: search descendants in the Babylon scene graph for the first\n    // mesh that has a morph target manager, then collect every sibling mesh\n    // that shares it (covers the multi-primitive case).\n    const descendants = tn.getDescendants(false);\n    for (const desc of descendants) {\n        const candidate = desc as AbstractMesh;\n        const mtm: MorphTargetManager | undefined = (candidate as any).morphTargetManager ?? (candidate as any).sourceMesh?.morphTargetManager;\n        if (!mtm) {\n            continue;\n        }\n        const meshes: AbstractMesh[] = [];\n        const parent = candidate.parent;\n        if (parent) {\n            for (const sib of parent.getChildMeshes(true)) {\n                const sibMtm: MorphTargetManager | undefined = (sib as any).morphTargetManager ?? (sib as any).sourceMesh?.morphTargetManager;\n                if (sibMtm === mtm) {\n                    meshes.push(sib);\n                }\n            }\n        }\n        if (meshes.length === 0) {\n            meshes.push(candidate);\n        }\n        return { mtm, meshes };\n    }\n    return undefined;\n}\n\n/**\n * Collapse float32-precision artifacts back to the closest \"clean\" double.\n *\n * glTF stores numbers as JSON, but tools usually serialize float32 morph weights\n * with their full double-precision text — `0.1` becomes `0.10000000149011612`.\n * KHR_interactivity tests then compare the read-back weight via strict `math/eq`\n * against literals like `0.1`, which fails because the two doubles aren't bitwise\n * equal. Rounding the value to 7 significant figures (the precision of a float32)\n * recovers the original \"clean\" double for any value that survived a float32\n * round-trip while leaving genuinely high-precision doubles essentially intact.\n * @param v the value to round\n * @returns the rounded value, or the input unchanged if it is not finite\n */\nfunction _roundFloat32Artifact(v: number): number {\n    if (!Number.isFinite(v)) {\n        return v;\n    }\n    return parseFloat(v.toPrecision(7));\n}\n/**\n * Coordinate where a Babylon `Texture` lives on a PBRMaterial vs where its\n * KHR_texture_transform definition lives in the source glTF JSON. Used by\n * {@link GenerateTextureMap} to provide a glTF-side fallback when the loader\n * extension that owns the texture decided not to materialise it on the\n * Babylon material (e.g. KHR_materials_volume early-returns when there is no\n * `thicknessFactor`, leaving `subSurface.thicknessTexture` null even though\n * the glTF JSON has the texture+transform fully defined).\n *\n * The fallback gives KHR_interactivity `pointer/get` and `pointer/set` a\n * place to read/write the transform values so round-trip tests succeed even\n * when the texture is not yet active in the renderer. If/when the loader\n * later activates the texture, the seeded values can be picked up from the\n * glTF JSON.\n */\ninterface IGltfTextureTransformPath {\n    /**\n     * The path of nested keys under `material.extensions.<ext>` to reach the\n     * texture-info object. For example `[\"thicknessTexture\"]` for\n     * `KHR_materials_volume.thicknessTexture`.\n     */\n    extensionKey: string;\n    texturePath: string[];\n}\n\n/**\n * Read the KHR_texture_transform object stored in the source glTF JSON for a\n * texture-info that lives under one of the material's extensions, creating\n * empty parent objects on demand so callers can write through it. Returns\n * `undefined` when the input shape is incompatible.\n * @param material the source IMaterial owning the extension\n * @param gltfPath the path describing where the texture-info lives\n * @param createMissing when true, create missing parent objects so writes succeed\n * @returns the glTF-side KHR_texture_transform object, or undefined\n */\nfunction _gltfTextureTransform(material: IMaterial, gltfPath: IGltfTextureTransformPath, createMissing: boolean): any | undefined {\n    if (!material) {\n        return undefined;\n    }\n    let extensions = material.extensions;\n    if (!extensions) {\n        if (!createMissing) {\n            return undefined;\n        }\n        extensions = {};\n        material.extensions = extensions;\n    }\n    let cursor: any = extensions[gltfPath.extensionKey];\n    if (!cursor) {\n        if (!createMissing) {\n            return undefined;\n        }\n        cursor = {};\n        extensions[gltfPath.extensionKey] = cursor;\n    }\n    for (const key of gltfPath.texturePath) {\n        let next = cursor[key];\n        if (!next) {\n            if (!createMissing) {\n                return undefined;\n            }\n            next = {};\n            cursor[key] = next;\n        }\n        cursor = next;\n    }\n    if (!cursor.extensions) {\n        if (!createMissing) {\n            return undefined;\n        }\n        cursor.extensions = {};\n    }\n    let xform = cursor.extensions.KHR_texture_transform;\n    if (!xform) {\n        if (!createMissing) {\n            return undefined;\n        }\n        xform = {};\n        cursor.extensions.KHR_texture_transform = xform;\n    }\n    return xform;\n}\n\nfunction GenerateTextureMap(textureType: keyof PBRMaterial, textureInObject?: string, gltfPath?: IGltfTextureTransformPath): ITextureDefinition {\n    return {\n        offset: {\n            componentsCount: 2,\n            // assuming two independent values for u and v, and NOT a Vector2\n            type: \"Vector2\",\n            get: (material, _index?, payload?) => {\n                const texture = GetTexture(material, payload, textureType, textureInObject);\n                if (texture) {\n                    return new Vector2(texture.uOffset, texture.vOffset);\n                }\n                if (gltfPath) {\n                    const xform = _gltfTextureTransform(material, gltfPath, false);\n                    const o = xform?.offset;\n                    return new Vector2(o?.[0] ?? 0, o?.[1] ?? 0);\n                }\n                return new Vector2(0, 0);\n            },\n            getTarget: GetMaterial,\n            set: (value, material, _index?, payload?) => {\n                const texture = GetTexture(material, payload, textureType, textureInObject);\n                if (texture) {\n                    texture.uOffset = value.x;\n                    texture.vOffset = value.y;\n                }\n                if (gltfPath) {\n                    const xform = _gltfTextureTransform(material, gltfPath, true);\n                    if (xform) {\n                        xform.offset = [value.x, value.y];\n                    }\n                }\n            },\n            getPropertyName: [\n                () => `${textureType}${textureInObject ? \".\" + textureInObject : \"\"}.uOffset`,\n                () => `${textureType}${textureInObject ? \".\" + textureInObject : \"\"}.vOffset`,\n            ],\n        },\n        rotation: {\n            type: \"number\",\n            get: (material, _index?, payload?) => {\n                const texture = GetTexture(material, payload, textureType, textureInObject);\n                if (texture) {\n                    return texture.wAng;\n                }\n                if (gltfPath) {\n                    const xform = _gltfTextureTransform(material, gltfPath, false);\n                    return xform?.rotation ?? 0;\n                }\n                return 0;\n            },\n            getTarget: GetMaterial,\n            set: (value, material, _index?, payload?) => {\n                const texture = GetTexture(material, payload, textureType, textureInObject);\n                if (texture) {\n                    texture.wAng = value;\n                }\n                if (gltfPath) {\n                    const xform = _gltfTextureTransform(material, gltfPath, true);\n                    if (xform) {\n                        xform.rotation = value;\n                    }\n                }\n            },\n            getPropertyName: [() => `${textureType}${textureInObject ? \".\" + textureInObject : \"\"}.wAng`],\n        },\n        scale: {\n            componentsCount: 2,\n            type: \"Vector2\",\n            get: (material, _index?, payload?) => {\n                const texture = GetTexture(material, payload, textureType, textureInObject);\n                if (texture) {\n                    return new Vector2(texture.uScale, texture.vScale);\n                }\n                if (gltfPath) {\n                    const xform = _gltfTextureTransform(material, gltfPath, false);\n                    const s = xform?.scale;\n                    return new Vector2(s?.[0] ?? 1, s?.[1] ?? 1);\n                }\n                return new Vector2(1, 1);\n            },\n            getTarget: GetMaterial,\n            set: (value, material, index?, payload?) => {\n                const texture = GetTexture(material, payload, textureType, textureInObject);\n                if (texture) {\n                    texture.uScale = value.x;\n                    texture.vScale = value.y;\n                }\n                if (gltfPath) {\n                    const xform = _gltfTextureTransform(material, gltfPath, true);\n                    if (xform) {\n                        xform.scale = [value.x, value.y];\n                    }\n                }\n            },\n            getPropertyName: [\n                () => `${textureType}${textureInObject ? \".\" + textureInObject : \"\"}.uScale`,\n                () => `${textureType}${textureInObject ? \".\" + textureInObject : \"\"}.vScale`,\n            ],\n        },\n    };\n}\n\nconst scenesTree: IGLTFObjectModelTreeScenesObject = {\n    length: _CreateLengthAccessor(\n        (scenes: IScene[]) => scenes.length,\n        (scenes: IScene[]) => scenes\n    ),\n    __array__: {\n        __target__: true,\n        nodes: {\n            length: _CreateLengthAccessor(\n                (nodes: number[]) => nodes?.length ?? 0,\n                (nodes: number[]) => nodes ?? []\n            ),\n            __array__: {\n                __target__: true,\n                type: \"string\",\n                // Indexed scene root: the underlying value is the INode index;\n                // KHR_interactivity expects a ref-typed JSON Pointer string.\n                get: (nodeIndex: any) => (typeof nodeIndex === \"number\" ? `/nodes/${nodeIndex}` : \"\"),\n                getTarget: () => ({ __nodeIndex: true }),\n                isReadOnly: true,\n            },\n        },\n    },\n};\n\nconst skinsTree: IGLTFObjectModelTreeSkinsObject = {\n    length: _CreateLengthAccessor(\n        (skins: ISkin[]) => skins.length,\n        (skins: ISkin[]) => skins.map((skin) => skin._data?.babylonSkeleton)\n    ),\n    __array__: {\n        __target__: true,\n        joints: {\n            length: _CreateLengthAccessor(\n                (joints: number[]) => joints?.length ?? 0,\n                (joints: number[]) => joints ?? []\n            ),\n            __array__: {\n                __target__: true,\n                type: \"string\",\n                // Indexed skin joint: returns a ref to the joint node.\n                get: (jointIndex: any) => (typeof jointIndex === \"number\" ? `/nodes/${jointIndex}` : \"\"),\n                getTarget: () => ({ __nodeIndex: true }),\n                isReadOnly: true,\n            },\n        },\n        skeleton: {\n            type: \"string\",\n            // Skin's skeleton root: returns a ref to the root node, or empty\n            // (null ref) when no skeleton root is declared.\n            get: (skin: ISkin) => {\n                const skeleton = (skin as any).skeleton;\n                return typeof skeleton === \"number\" ? `/nodes/${skeleton}` : \"\";\n            },\n            getTarget: (skin: ISkin) => skin,\n            isReadOnly: true,\n        },\n    },\n};\n\nconst objectModelMapping: IGLTFObjectModelTree = {\n    scene: {\n        __target__: true,\n        type: \"number\",\n        get: (sceneIndex: any) => sceneIndex ?? 0,\n        getTarget: () => ({ __gltfRoot: true }),\n        isReadOnly: true,\n        getPropertyName: [() => \"scene\"],\n    },\n    cameras: camerasTree,\n    nodes: nodesTree,\n    materials: materialsTree,\n    extensions: extensionsTree,\n    animations: animationsTree,\n    meshes: meshesTree,\n    scenes: scenesTree,\n    skins: skinsTree,\n};\n\n/**\n * Creates a detached copy so asset-local accessors cannot mutate other converters.\n * @param value mapping value to clone\n * @returns the cloned mapping value\n */\nfunction _cloneObjectModelMapping<T>(value: T): T {\n    if (Array.isArray(value)) {\n        return value.map((entry) => _cloneObjectModelMapping(entry)) as T;\n    }\n    if (value !== null && typeof value === \"object\") {\n        const prototype = Object.getPrototypeOf(value);\n        if (prototype !== Object.prototype && prototype !== null) {\n            return value;\n        }\n        const clone: Record<string, unknown> = {};\n        for (const [key, entry] of Object.entries(value)) {\n            clone[key] = _cloneObjectModelMapping(entry);\n        }\n        return clone as T;\n    }\n    return value;\n}\n\n/**\n * get a path-to-object converter for the given glTF tree\n * @param gltf the glTF tree to use\n * @param configure optional callback for adding asset-local accessors to this converter\n * @returns a path-to-object converter for the given glTF tree\n */\nexport function GetPathToObjectConverter(gltf: IGLTF, configure?: (mapping: object) => void) {\n    if (!configure) {\n        return new GLTFPathToObjectConverter(gltf, objectModelMapping);\n    }\n    const assetMapping = _cloneObjectModelMapping(objectModelMapping);\n    configure(assetMapping);\n    return new GLTFPathToObjectConverter(gltf, assetMapping);\n}\n\n/**\n * This function will return the object accessor for the given key in the object model\n * If the key is not found, it will return undefined\n * @param key the key to get the mapping for, for example /materials/\\{\\}/emissiveFactor\n * @returns an object accessor for the given key, or undefined if the key is not found\n */\nexport function GetMappingForKey(key: string): IObjectAccessor | undefined {\n    // replace every `{}` in key with __array__ to match the object model\n    const keyParts = key.split(\"/\").map((part) => part.replace(/{}/g, \"__array__\"));\n    let current = objectModelMapping as any;\n    for (const part of keyParts) {\n        // make sure part is not empty\n        if (!part) {\n            continue;\n        }\n        current = current[part];\n    }\n    // validate that current is an object accessor\n    if (current && current.type && current.get) {\n        return current;\n    }\n    return undefined;\n}\n\n/**\n * Set interpolation for a specific key in the object model\n * @param key the key to set, for example /materials/\\{\\}/emissiveFactor\n * @param interpolation the interpolation elements array\n */\nexport function SetInterpolationForKey(key: string, interpolation?: IInterpolationPropertyInfo[]): void {\n    // replace every `{}` in key with __array__ to match the object model\n    const keyParts = key.split(\"/\").map((part) => part.replace(/{}/g, \"__array__\"));\n    let current = objectModelMapping as any;\n    for (const part of keyParts) {\n        // make sure part is not empty\n        if (!part) {\n            continue;\n        }\n        current = current[part];\n    }\n    // validate that the current object is an object accessor\n    if (current && current.type && current.get) {\n        (current as IObjectAccessor).interpolation = interpolation;\n    }\n}\n\n/**\n * This will ad a new object accessor in the object model at the given key.\n * Note that this will NOT change the typescript types. To do that you will need to change the interface itself (extending it in the module that uses it)\n * @param key the key to add the object accessor at. For example /cameras/\\{\\}/perspective/aspectRatio\n * @param accessor the object accessor to add\n * @param mapping object-model mapping to update; defaults to the process-wide mapping used as the template for new converters\n */\nexport function AddObjectAccessorToKey<GLTFTargetType = any, BabylonTargetType = any, BabylonValueType = any>(\n    key: string,\n    accessor: IObjectAccessor<GLTFTargetType, BabylonTargetType, BabylonValueType>,\n    mapping: object = objectModelMapping\n): void {\n    // replace every `{}` in key with __array__ to match the object model\n    const keyParts = key.split(\"/\").map((part) => part.replace(/{}/g, \"__array__\"));\n    let current = mapping as any;\n    for (const part of keyParts) {\n        // make sure part is not empty\n        if (!part) {\n            continue;\n        }\n        if (!current[part]) {\n            if (part === \"?\") {\n                current.__ignoreObjectTree__ = true;\n                continue;\n            }\n            current[part] = {};\n            // if the part is __array__ then add the __target__ property\n            if (part === \"__array__\") {\n                current[part].__target__ = true;\n            }\n        }\n        current = current[part];\n    }\n    Object.assign(current, accessor);\n}\n","/* eslint-disable @typescript-eslint/promise-function-async */\r\n/* eslint-disable no-restricted-syntax */\r\n/* eslint-disable github/no-then */\r\nimport { type IndicesArray, type Nullable, type TypedArray, type TypedArrayConstructor } from \"core/types\";\r\nimport { Deferred } from \"core/Misc/deferred\";\r\nimport { Quaternion, Vector3, Matrix, TmpVectors } from \"core/Maths/math.vector.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { Camera } from \"core/Cameras/camera.pure\";\r\nimport { FreeCamera } from \"core/Cameras/freeCamera.pure\";\r\nimport { type Animation } from \"core/Animations/animation\";\r\nimport { type IAnimatable } from \"core/Animations/animatable.interface\";\r\nimport { type IAnimationKey, AnimationKeyInterpolation } from \"core/Animations/animationKey\";\r\nimport { type AnimationGroup } from \"core/Animations/animationGroup.pure\";\r\nimport { Bone } from \"core/Bones/bone\";\r\nimport { Skeleton } from \"core/Bones/skeleton\";\r\nimport { Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type ITextureCreationOptions, Texture } from \"core/Materials/Textures/texture.pure\";\r\nimport { TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { Buffer, VertexBuffer, VertexBufferForEach, VertexBufferGetTypeByteLength } from \"core/Buffers/buffer.pure\";\r\nimport { Geometry } from \"core/Meshes/geometry\";\r\nimport { AbstractMesh } from \"core/Meshes/abstractMesh.pure\";\r\nimport { Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { MorphTarget } from \"core/Morph/morphTarget\";\r\nimport { MorphTargetManager } from \"core/Morph/morphTargetManager\";\r\nimport { type ISceneLoaderAsyncResult, type ISceneLoaderProgressEvent } from \"core/Loading/sceneLoader\";\r\nimport { type Scene } from \"core/scene\";\r\nimport {\r\n    type IProperty,\r\n    AnimationChannelTargetPath,\r\n    AnimationSamplerInterpolation,\r\n    AccessorType,\r\n    CameraType,\r\n    AccessorComponentType,\r\n    MaterialAlphaMode,\r\n    TextureMinFilter,\r\n    TextureWrapMode,\r\n    TextureMagFilter,\r\n    MeshPrimitiveMode,\r\n} from \"babylonjs-gltf2interface\";\r\nimport {\r\n    type IGLTF,\r\n    type ISampler,\r\n    type INode,\r\n    type IScene,\r\n    type IMesh,\r\n    type IAccessor,\r\n    type ISkin,\r\n    type ICamera,\r\n    type IAnimation,\r\n    type IBuffer,\r\n    type IBufferView,\r\n    type IMaterialPbrMetallicRoughness,\r\n    type IMaterial,\r\n    type ITextureInfo,\r\n    type ITexture,\r\n    type IImage,\r\n    type IMeshPrimitive,\r\n    type IArrayItem,\r\n    type _ISamplerData,\r\n    type IAnimationChannel,\r\n    type IAnimationSampler,\r\n    type _IAnimationSamplerData,\r\n} from \"./glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"./glTFLoaderExtension\";\r\nimport { type IGLTFLoader, type IGLTFLoaderData, GLTFFileLoader, GLTFLoaderState, GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode } from \"../glTFFileLoader.pure\";\r\nimport { type IDataBuffer } from \"core/Misc/dataReader\";\r\nimport { DecodeBase64UrlToBinary, GetMimeType, IsBase64DataUrl, LoadFileError } from \"core/Misc/fileTools.pure\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { RandomGUID } from \"core/Misc/guid\";\r\nimport { type Light } from \"core/Lights/light\";\r\nimport { BoundingInfo } from \"core/Culling/boundingInfo\";\r\nimport { type AssetContainer } from \"core/assetContainer\";\r\nimport { type AnimationPropertyInfo } from \"./glTFLoaderAnimation.pure\";\r\nimport { type IObjectInfo } from \"core/ObjectModel/objectModelInterfaces\";\r\nimport { registeredGLTFExtensions, registerGLTFExtension, unregisterGLTFExtension, type GLTFExtensionFactory } from \"./glTFLoaderExtensionRegistry\";\r\nimport { type IInterpolationPropertyInfo } from \"core/FlowGraph/typeDefinitions\";\r\nimport { GetMappingForKey } from \"./Extensions/objectModelMapping\";\r\nimport { deepMerge } from \"core/Misc/deepMerger\";\r\nimport { GetTypedArrayConstructor } from \"core/Buffers/bufferUtils\";\r\nimport { Lazy } from \"core/Misc/lazy\";\r\nimport { type IMaterialLoadingAdapter } from \"./materialLoadingAdapter\";\r\n\r\n// Caching these dynamic imports gives a surprising perf boost (compared to importing them directly each time).\r\nconst LazyAnimationGroupModulePromise = /*#__PURE__*/ new Lazy(() => import(\"core/Animations/animationGroup.pure\"));\r\nconst LazyLoaderAnimationModulePromise = /*#__PURE__*/ new Lazy(() => import(\"./glTFLoaderAnimation.pure\"));\r\n\r\nexport { GLTFFileLoader };\r\n\r\ninterface ILoaderProperty extends IProperty {\r\n    _activeLoaderExtensionFunctions: {\r\n        [id: string]: boolean;\r\n    };\r\n}\r\n\r\ninterface IWithMetadata {\r\n    metadata: any;\r\n    _internalMetadata: any;\r\n}\r\n\r\n/**\r\n * Helper class for working with arrays when loading the glTF asset\r\n */\r\nexport class ArrayItem {\r\n    /**\r\n     * Gets an item from the given array.\r\n     * @param context The context when loading the asset\r\n     * @param array The array to get the item from\r\n     * @param index The index to the array\r\n     * @returns The array item\r\n     */\r\n    public static Get<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T {\r\n        if (!array || index == undefined || !array[index]) {\r\n            throw new Error(`${context}: Failed to find index (${index})`);\r\n        }\r\n\r\n        return array[index];\r\n    }\r\n\r\n    /**\r\n     * Gets an item from the given array or returns null if not available.\r\n     * @param array The array to get the item from\r\n     * @param index The index to the array\r\n     * @returns The array item or null\r\n     */\r\n    public static TryGet<T>(array: ArrayLike<T> | undefined, index: number | undefined): Nullable<T> {\r\n        if (!array || index == undefined || !array[index]) {\r\n            return null;\r\n        }\r\n\r\n        return array[index];\r\n    }\r\n\r\n    /**\r\n     * Assign an `index` field to each item of the given array.\r\n     * @param array The array of items\r\n     */\r\n    public static Assign(array?: IArrayItem[]): void {\r\n        if (array) {\r\n            for (let index = 0; index < array.length; index++) {\r\n                array[index].index = index;\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n/** @internal */\r\nexport interface IAnimationTargetInfo {\r\n    /** @internal */\r\n    target: unknown;\r\n\r\n    /** @internal */\r\n    properties: Array<AnimationPropertyInfo>;\r\n}\r\n\r\n/** @internal */\r\nexport function LoadBoundingInfoFromPositionAccessor(accessor: IAccessor): Nullable<BoundingInfo> {\r\n    if (accessor.min && accessor.max) {\r\n        const minArray = accessor.min as [number, number, number];\r\n        const maxArray = accessor.max as [number, number, number];\r\n        const minVector = TmpVectors.Vector3[0].copyFromFloats(minArray[0], minArray[1], minArray[2]);\r\n        const maxVector = TmpVectors.Vector3[1].copyFromFloats(maxArray[0], maxArray[1], maxArray[2]);\r\n        if (accessor.normalized && accessor.componentType !== AccessorComponentType.FLOAT) {\r\n            let divider = 1;\r\n            switch (accessor.componentType) {\r\n                case AccessorComponentType.BYTE:\r\n                    divider = 127.0;\r\n                    break;\r\n                case AccessorComponentType.UNSIGNED_BYTE:\r\n                    divider = 255.0;\r\n                    break;\r\n                case AccessorComponentType.SHORT:\r\n                    divider = 32767.0;\r\n                    break;\r\n                case AccessorComponentType.UNSIGNED_SHORT:\r\n                    divider = 65535.0;\r\n                    break;\r\n            }\r\n            const oneOverDivider = 1 / divider;\r\n            minVector.scaleInPlace(oneOverDivider);\r\n            maxVector.scaleInPlace(oneOverDivider);\r\n        }\r\n        return new BoundingInfo(minVector, maxVector);\r\n    }\r\n    return null;\r\n}\r\n\r\ntype PBRMaterialImplementation = {\r\n    materialClass: typeof Material;\r\n    adapterClass: new (material: Material) => IMaterialLoadingAdapter;\r\n};\r\n\r\n/**\r\n * The glTF 2.0 loader\r\n */\r\nexport class GLTFLoader implements IGLTFLoader {\r\n    /** @internal */\r\n    public readonly _completePromises = new Array<Promise<unknown>>();\r\n\r\n    /** @internal */\r\n    public _assetContainer: Nullable<AssetContainer> = null;\r\n\r\n    /** Storage */\r\n    public _babylonLights: Light[] = [];\r\n\r\n    /** @internal */\r\n    public _disableInstancedMesh = 0;\r\n\r\n    /** @internal */\r\n    public _allMaterialsDirtyRequired = false;\r\n\r\n    /** @internal */\r\n    public _skipStartAnimationStep = false;\r\n\r\n    private readonly _parent: GLTFFileLoader;\r\n    private readonly _extensions = new Array<IGLTFLoaderExtension>();\r\n    /** @internal */\r\n    public _disposed = false;\r\n    private _rootUrl: Nullable<string> = null;\r\n    private _fileName: Nullable<string> = null;\r\n    private _uniqueRootUrl: Nullable<string> = null;\r\n    private _gltf: IGLTF;\r\n    private _bin: Nullable<IDataBuffer> = null;\r\n    private _babylonScene: Scene;\r\n    private _rootBabylonMesh: Nullable<TransformNode> = null;\r\n    private _defaultBabylonMaterialData: { [drawMode: number]: Material } = {};\r\n    private readonly _postSceneLoadActions = new Array<() => void>();\r\n    private readonly _materialAdapterCache = new WeakMap<Material, IMaterialLoadingAdapter>();\r\n    private readonly _materialAdapters = new Set<IMaterialLoadingAdapter>();\r\n\r\n    /**\r\n     * Loaded PBR material implementations, keyed by their identifier (e.g. \"pbr\", \"openpbr\").\r\n     * Only populated after the load has started and only for the types actually needed by the asset.\r\n     * Empty when PBR materials are disabled (skipMaterials).\r\n     * @internal\r\n     */\r\n    public readonly _pbrMaterialImpls = new Map<string, Readonly<PBRMaterialImplementation>>();\r\n\r\n    /**\r\n     * Test if the given material is an instance of any PBR material type known to this loader.\r\n     * @param material The material to test\r\n     * @returns true if the material matches one of the loaded PBR implementations\r\n     */\r\n    public isMatchingMaterialType(material: Nullable<Material>): boolean {\r\n        if (!material) {\r\n            return false;\r\n        }\r\n        const materialImpls = Array.from(this._pbrMaterialImpls.values());\r\n        for (const impl of materialImpls) {\r\n            if (material instanceof impl.materialClass) {\r\n                return true;\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * The default glTF sampler.\r\n     */\r\n    public static readonly DefaultSampler: ISampler = { index: -1 };\r\n\r\n    /**\r\n     * Registers a loader extension.\r\n     * @param name The name of the loader extension.\r\n     * @param factory The factory function that creates the loader extension.\r\n     * @deprecated Please use registerGLTFExtension instead.\r\n     */\r\n    public static RegisterExtension(name: string, factory: GLTFExtensionFactory): void {\r\n        registerGLTFExtension(name, false, factory);\r\n    }\r\n\r\n    /**\r\n     * Unregisters a loader extension.\r\n     * @param name The name of the loader extension.\r\n     * @returns A boolean indicating whether the extension has been unregistered\r\n     * @deprecated Please use unregisterGLTFExtension instead.\r\n     */\r\n    public static UnregisterExtension(name: string): boolean {\r\n        return unregisterGLTFExtension(name);\r\n    }\r\n\r\n    /**\r\n     * The object that represents the glTF JSON.\r\n     */\r\n    public get gltf(): IGLTF {\r\n        if (!this._gltf) {\r\n            throw new Error(\"glTF JSON is not available\");\r\n        }\r\n\r\n        return this._gltf;\r\n    }\r\n\r\n    /**\r\n     * The BIN chunk of a binary glTF.\r\n     */\r\n    public get bin(): Nullable<IDataBuffer> {\r\n        return this._bin;\r\n    }\r\n\r\n    /**\r\n     * The parent file loader.\r\n     */\r\n    public get parent(): GLTFFileLoader {\r\n        return this._parent;\r\n    }\r\n\r\n    /**\r\n     * The Babylon scene when loading the asset.\r\n     */\r\n    public get babylonScene(): Scene {\r\n        if (!this._babylonScene) {\r\n            throw new Error(\"Scene is not available\");\r\n        }\r\n\r\n        return this._babylonScene;\r\n    }\r\n\r\n    /**\r\n     * The root Babylon node when loading the asset.\r\n     */\r\n    public get rootBabylonMesh(): Nullable<TransformNode> {\r\n        return this._rootBabylonMesh;\r\n    }\r\n\r\n    /**\r\n     * The root url when loading the asset.\r\n     */\r\n    public get rootUrl(): Nullable<string> {\r\n        return this._rootUrl;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(parent: GLTFFileLoader) {\r\n        this._parent = parent;\r\n    }\r\n\r\n    /**\r\n     * Creates or gets a cached material loading adapter with dynamic imports\r\n     * @param material The material to adapt\r\n     * @returns Promise that resolves to the appropriate adapter\r\n     * @internal\r\n     */\r\n    public _getOrCreateMaterialAdapter(material: Material): IMaterialLoadingAdapter {\r\n        let adapter = this._materialAdapterCache.get(material);\r\n        if (!adapter) {\r\n            const materialImpls = Array.from(this._pbrMaterialImpls.values());\r\n            for (const impl of materialImpls) {\r\n                if (material instanceof impl.materialClass) {\r\n                    adapter = new impl.adapterClass(material);\r\n                    break;\r\n                }\r\n            }\r\n            if (!adapter) {\r\n                throw new Error(`Appropriate material adapter class not found`);\r\n            }\r\n            const createdAdapter = adapter;\r\n            this._materialAdapterCache.set(material, createdAdapter);\r\n            this._materialAdapters.add(createdAdapter);\r\n        }\r\n        return adapter;\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose(): void {\r\n        if (this._disposed) {\r\n            return;\r\n        }\r\n\r\n        this._disposed = true;\r\n\r\n        this._completePromises.length = 0;\r\n\r\n        this._extensions.forEach((extension) => extension.dispose && extension.dispose());\r\n        this._extensions.length = 0;\r\n\r\n        this._materialAdapters.clear();\r\n\r\n        (this._gltf as Nullable<IGLTF>) = null; // TODO\r\n        this._bin = null;\r\n        (this._babylonScene as Nullable<Scene>) = null; // TODO\r\n        this._rootBabylonMesh = null;\r\n        this._defaultBabylonMaterialData = {};\r\n        this._postSceneLoadActions.length = 0;\r\n\r\n        this._parent.dispose();\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public async importMeshAsync(\r\n        meshesNames: string | readonly string[] | null | undefined,\r\n        scene: Scene,\r\n        container: Nullable<AssetContainer>,\r\n        data: IGLTFLoaderData,\r\n        rootUrl: string,\r\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        fileName = \"\"\r\n    ): Promise<ISceneLoaderAsyncResult> {\r\n        return await Promise.resolve().then(async () => {\r\n            this._babylonScene = scene;\r\n            this._assetContainer = container;\r\n            this._loadData(data);\r\n\r\n            let nodes: Nullable<Array<number>> = null;\r\n\r\n            if (meshesNames) {\r\n                const nodeMap: { [name: string]: number } = {};\r\n                if (this._gltf.nodes) {\r\n                    for (const node of this._gltf.nodes) {\r\n                        if (node.name) {\r\n                            nodeMap[node.name] = node.index;\r\n                        }\r\n                    }\r\n                }\r\n\r\n                const names = meshesNames instanceof Array ? meshesNames : [meshesNames];\r\n                nodes = names.map((name) => {\r\n                    const node = nodeMap[name];\r\n                    if (node === undefined) {\r\n                        throw new Error(`Failed to find node '${name}'`);\r\n                    }\r\n\r\n                    return node;\r\n                });\r\n            }\r\n\r\n            return await this._loadAsync(rootUrl, fileName, nodes, () => {\r\n                return {\r\n                    meshes: this._getMeshes(),\r\n                    particleSystems: [],\r\n                    skeletons: this._getSkeletons(),\r\n                    animationGroups: this._getAnimationGroups(),\r\n                    lights: this._babylonLights,\r\n                    transformNodes: this._getTransformNodes(),\r\n                    geometries: this._getGeometries(),\r\n                    spriteManagers: [],\r\n                };\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public async loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName = \"\"): Promise<void> {\r\n        this._babylonScene = scene;\r\n        this._loadData(data);\r\n        return await this._loadAsync(rootUrl, fileName, null, () => undefined);\r\n    }\r\n\r\n    private async _loadAsync<T>(rootUrl: string, fileName: string, nodes: Nullable<Array<number>>, resultFunc: () => T): Promise<T> {\r\n        return await Promise.resolve()\r\n            .then(async () => {\r\n                this._rootUrl = rootUrl;\r\n                this._uniqueRootUrl = !rootUrl.startsWith(\"file:\") && fileName ? rootUrl : `${rootUrl}${RandomGUID()}/`;\r\n                this._fileName = fileName;\r\n                this._allMaterialsDirtyRequired = false;\r\n\r\n                await this._loadExtensionsAsync();\r\n\r\n                if (!this.parent.skipMaterials) {\r\n                    const needsOpenPBR = this.parent.useOpenPBR || this.isExtensionUsed(\"KHR_materials_openpbr\");\r\n\r\n                    let needsPBR = false;\r\n                    if (!this.parent.useOpenPBR) {\r\n                        // PBR is needed when useOpenPBR is turned off.\r\n                        needsPBR = true;\r\n                    } else if (this._gltf.materials?.length && this._gltf.materials.some((m) => !m.extensions?.[\"KHR_materials_openpbr\"])) {\r\n                        // PBR is needed if there is at least one material that does not use the KHR_materials_openpbr extension (i.e. relies on the default PBR implementation).\r\n                        needsPBR = true;\r\n                    }\r\n\r\n                    const implPromises: Promise<void>[] = [];\r\n\r\n                    if (needsOpenPBR && !this._pbrMaterialImpls.has(\"openpbr\")) {\r\n                        implPromises.push(\r\n                            // Import the .pure module (which directly declares the class and its registration\r\n                            // function) rather than the side-effect wrapper. The wrapper re-exports the class via\r\n                            // `export *`, and some bundlers fail to surface star-re-exported bindings on a dynamic\r\n                            // import namespace across a chunk boundary (e.g. a Web Worker chunk), which would leave\r\n                            // materialClass undefined and throw a cryptic \"materialClass is not a constructor\" later.\r\n                            // A direct named export is reliable everywhere; we trigger registration explicitly.\r\n                            Promise.all([import(\"core/Materials/PBR/openpbrMaterial.pure\"), import(\"./openpbrMaterialLoadingAdapter\")]).then(\r\n                                ([\r\n                                    { OpenPBRMaterial: openPBRMaterialClass, RegisterOpenpbrMaterial: registerOpenPBRMaterial },\r\n                                    { OpenPBRMaterialLoadingAdapter: openPBRAdapterClass },\r\n                                ]) => {\r\n                                    registerOpenPBRMaterial();\r\n                                    this._pbrMaterialImpls.set(\"openpbr\", {\r\n                                        materialClass: openPBRMaterialClass,\r\n                                        adapterClass: openPBRAdapterClass,\r\n                                    });\r\n                                }\r\n                            )\r\n                        );\r\n                    }\r\n\r\n                    if (needsPBR && !this._pbrMaterialImpls.has(\"pbr\")) {\r\n                        implPromises.push(\r\n                            // See the openpbr note above: import the .pure module for a reliable class binding and\r\n                            // register the class explicitly instead of relying on the wrapper's `export *` re-export.\r\n                            Promise.all([import(\"core/Materials/PBR/pbrMaterial.pure\"), import(\"./pbrMaterialLoadingAdapter\")]).then(\r\n                                ([{ PBRMaterial: pbrMaterialClass, RegisterPbrMaterial: registerPBRMaterial }, { PBRMaterialLoadingAdapter: pbrAdapterClass }]) => {\r\n                                    registerPBRMaterial();\r\n                                    this._pbrMaterialImpls.set(\"pbr\", {\r\n                                        materialClass: pbrMaterialClass,\r\n                                        adapterClass: pbrAdapterClass,\r\n                                    });\r\n                                }\r\n                            )\r\n                        );\r\n                    }\r\n\r\n                    await Promise.all(implPromises);\r\n                }\r\n\r\n                const loadingToReadyCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.READY]}`;\r\n                const loadingToCompleteCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.COMPLETE]}`;\r\n\r\n                this._parent._startPerformanceCounter(loadingToReadyCounterName);\r\n                this._parent._startPerformanceCounter(loadingToCompleteCounterName);\r\n\r\n                this._parent._setState(GLTFLoaderState.LOADING);\r\n                this._extensionsOnLoading();\r\n\r\n                const promises = new Array<Promise<unknown>>();\r\n\r\n                // Block the marking of materials dirty until the scene is loaded.\r\n                const oldBlockMaterialDirtyMechanism = this._babylonScene.blockMaterialDirtyMechanism;\r\n                this._babylonScene.blockMaterialDirtyMechanism = true;\r\n\r\n                if (!this.parent.loadOnlyMaterials) {\r\n                    if (nodes) {\r\n                        promises.push(this.loadSceneAsync(\"/nodes\", { nodes: nodes, index: -1 }));\r\n                    } else if (this._gltf.scene != undefined || (this._gltf.scenes && this._gltf.scenes[0])) {\r\n                        const scene = ArrayItem.Get(`/scene`, this._gltf.scenes, this._gltf.scene || 0);\r\n                        promises.push(this.loadSceneAsync(`/scenes/${scene.index}`, scene));\r\n                    }\r\n                }\r\n\r\n                if (!this.parent.skipMaterials && this.parent.loadAllMaterials && this._gltf.materials) {\r\n                    for (let m = 0; m < this._gltf.materials.length; ++m) {\r\n                        const material = this._gltf.materials[m];\r\n                        const context = \"/materials/\" + m;\r\n                        const babylonDrawMode = Material.TriangleFillMode;\r\n\r\n                        promises.push(this._loadMaterialAsync(context, material, null, babylonDrawMode, () => {}));\r\n                    }\r\n                }\r\n\r\n                // Restore the blocking of material dirty.\r\n                if (this._allMaterialsDirtyRequired) {\r\n                    // This can happen if we add a light for instance as it will impact the whole scene.\r\n                    // This automatically resets everything if needed.\r\n                    this._babylonScene.blockMaterialDirtyMechanism = oldBlockMaterialDirtyMechanism;\r\n                } else {\r\n                    // By default a newly created material is dirty so there is no need to flag the full scene as dirty.\r\n                    // For perf reasons, we then bypass blockMaterialDirtyMechanism as this would \"dirty\" the entire scene.\r\n                    this._babylonScene._forceBlockMaterialDirtyMechanism(oldBlockMaterialDirtyMechanism);\r\n                }\r\n\r\n                if (this._parent.compileMaterials) {\r\n                    promises.push(this._compileMaterialsAsync());\r\n                }\r\n\r\n                if (this._parent.compileShadowGenerators) {\r\n                    promises.push(this._compileShadowGeneratorsAsync());\r\n                }\r\n\r\n                const resultPromise = Promise.all(promises).then(async () => {\r\n                    if (this._rootBabylonMesh && this._rootBabylonMesh !== this._parent.customRootNode) {\r\n                        this._rootBabylonMesh.setEnabled(true);\r\n                    }\r\n\r\n                    // Making sure we enable enough lights to have all lights together\r\n                    for (const material of this._babylonScene.materials) {\r\n                        const mat = material as any;\r\n\r\n                        if (mat.maxSimultaneousLights !== undefined) {\r\n                            mat.maxSimultaneousLights = Math.max(mat.maxSimultaneousLights, this._babylonScene.lights.length);\r\n                        }\r\n                    }\r\n\r\n                    // Finalize all material adapters. finalizeAsync() may return a Promise for async\r\n                    // work (e.g. GPU texture processing); any returned Promise is pushed into\r\n                    // _completePromises so it is awaited before the COMPLETE state is reached.\r\n                    for (const adapter of Array.from(this._materialAdapters)) {\r\n                        this._completePromises.push(adapter.finalizeAsync(this));\r\n                    }\r\n\r\n                    await this._extensionsOnReadyAsync();\r\n                    this._parent._setState(GLTFLoaderState.READY);\r\n                    if (!this._skipStartAnimationStep) {\r\n                        this._startAnimations();\r\n                    }\r\n\r\n                    return resultFunc();\r\n                });\r\n\r\n                return await resultPromise.then((result) => {\r\n                    this._parent._endPerformanceCounter(loadingToReadyCounterName);\r\n\r\n                    Tools.SetImmediate(() => {\r\n                        if (!this._disposed) {\r\n                            Promise.all(this._completePromises).then(\r\n                                () => {\r\n                                    this._parent._endPerformanceCounter(loadingToCompleteCounterName);\r\n\r\n                                    this._parent._setState(GLTFLoaderState.COMPLETE);\r\n\r\n                                    this._parent.onCompleteObservable.notifyObservers(undefined);\r\n                                    this._parent.onCompleteObservable.clear();\r\n\r\n                                    this.dispose();\r\n                                },\r\n                                (error) => {\r\n                                    this._parent.onErrorObservable.notifyObservers(error);\r\n                                    this._parent.onErrorObservable.clear();\r\n\r\n                                    this.dispose();\r\n                                }\r\n                            );\r\n                        }\r\n                    });\r\n\r\n                    return result;\r\n                });\r\n            })\r\n            .catch((error) => {\r\n                if (!this._disposed) {\r\n                    this._parent.onErrorObservable.notifyObservers(error);\r\n                    this._parent.onErrorObservable.clear();\r\n\r\n                    this.dispose();\r\n                }\r\n\r\n                throw error;\r\n            });\r\n    }\r\n\r\n    private _loadData(data: IGLTFLoaderData): void {\r\n        this._gltf = data.json as IGLTF;\r\n        this._setupData();\r\n\r\n        if (data.bin) {\r\n            const buffers = this._gltf.buffers;\r\n            if (buffers && buffers[0] && !buffers[0].uri) {\r\n                const binaryBuffer = buffers[0];\r\n                if (binaryBuffer.byteLength < data.bin.byteLength - 3 || binaryBuffer.byteLength > data.bin.byteLength) {\r\n                    Logger.Warn(`Binary buffer length (${binaryBuffer.byteLength}) from JSON does not match chunk length (${data.bin.byteLength})`);\r\n                }\r\n\r\n                this._bin = data.bin;\r\n            } else {\r\n                Logger.Warn(\"Unexpected BIN chunk\");\r\n            }\r\n        }\r\n    }\r\n\r\n    private _setupData(): void {\r\n        ArrayItem.Assign(this._gltf.accessors);\r\n        ArrayItem.Assign(this._gltf.animations);\r\n        ArrayItem.Assign(this._gltf.buffers);\r\n        ArrayItem.Assign(this._gltf.bufferViews);\r\n        ArrayItem.Assign(this._gltf.cameras);\r\n        ArrayItem.Assign(this._gltf.images);\r\n        ArrayItem.Assign(this._gltf.materials);\r\n        ArrayItem.Assign(this._gltf.meshes);\r\n        ArrayItem.Assign(this._gltf.nodes);\r\n        ArrayItem.Assign(this._gltf.samplers);\r\n        ArrayItem.Assign(this._gltf.scenes);\r\n        ArrayItem.Assign(this._gltf.skins);\r\n        ArrayItem.Assign(this._gltf.textures);\r\n\r\n        if (this._gltf.nodes) {\r\n            const nodeParents: { [index: number]: number } = {};\r\n            for (const node of this._gltf.nodes) {\r\n                if (node.children) {\r\n                    for (const index of node.children) {\r\n                        nodeParents[index] = node.index;\r\n                    }\r\n                }\r\n            }\r\n\r\n            const rootNode = this._createRootNode();\r\n            for (const node of this._gltf.nodes) {\r\n                const parentIndex = nodeParents[node.index];\r\n                node.parent = parentIndex === undefined ? rootNode : this._gltf.nodes[parentIndex];\r\n            }\r\n        }\r\n    }\r\n\r\n    private async _loadExtensionsAsync() {\r\n        const extensionPromises: Promise<IGLTFLoaderExtension>[] = [];\r\n\r\n        registeredGLTFExtensions.forEach((registeredExtension, name) => {\r\n            // Don't load explicitly disabled extensions.\r\n            if (this.parent.extensionOptions[name]?.enabled === false) {\r\n                // But warn if the disabled extension is used by the model.\r\n                if (registeredExtension.isGLTFExtension && this.isExtensionUsed(name)) {\r\n                    Logger.Warn(`Extension ${name} is used but has been explicitly disabled.`);\r\n                }\r\n            }\r\n            // Load loader extensions that are not a glTF extension, as well as extensions that are glTF extensions and are used by the model.\r\n            else if (!registeredExtension.isGLTFExtension || this.isExtensionUsed(name)) {\r\n                extensionPromises.push(\r\n                    (async () => {\r\n                        const extension = await registeredExtension.factory(this);\r\n                        if (extension.name !== name) {\r\n                            Logger.Warn(`The name of the glTF loader extension instance does not match the registered name: ${extension.name} !== ${name}`);\r\n                        }\r\n\r\n                        this._parent.onExtensionLoadedObservable.notifyObservers(extension);\r\n                        return extension;\r\n                    })()\r\n                );\r\n            }\r\n        });\r\n\r\n        this._extensions.push(...(await Promise.all(extensionPromises)));\r\n\r\n        this._extensions.sort((a, b) => (a.order || Number.MAX_VALUE) - (b.order || Number.MAX_VALUE));\r\n        this._parent.onExtensionLoadedObservable.clear();\r\n\r\n        if (this._gltf.extensionsRequired) {\r\n            for (const name of this._gltf.extensionsRequired) {\r\n                const available = this._extensions.some((extension) => extension.name === name && extension.enabled);\r\n                if (!available) {\r\n                    if (this.parent.extensionOptions[name]?.enabled === false) {\r\n                        throw new Error(`Required extension ${name} is disabled`);\r\n                    }\r\n                    throw new Error(`Required extension ${name} is not available`);\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    private _createRootNode(): INode {\r\n        if (this._parent.customRootNode !== undefined) {\r\n            this._rootBabylonMesh = this._parent.customRootNode;\r\n            return {\r\n                _babylonTransformNode: this._rootBabylonMesh === null ? undefined : this._rootBabylonMesh,\r\n                index: -1,\r\n            };\r\n        }\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        const rootMesh = new Mesh(\"__root__\", this._babylonScene);\r\n        this._rootBabylonMesh = rootMesh;\r\n        this._rootBabylonMesh._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n        this._rootBabylonMesh.setEnabled(false);\r\n\r\n        const rootNode: INode = {\r\n            _babylonTransformNode: this._rootBabylonMesh,\r\n            index: -1,\r\n        };\r\n\r\n        switch (this._parent.coordinateSystemMode) {\r\n            case GLTFLoaderCoordinateSystemMode.AUTO: {\r\n                if (!this._babylonScene.useRightHandedSystem) {\r\n                    rootNode.rotation = [0, 1, 0, 0];\r\n                    rootNode.scale = [1, 1, -1];\r\n                    GLTFLoader._LoadTransform(rootNode, this._rootBabylonMesh);\r\n                }\r\n                break;\r\n            }\r\n            case GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED: {\r\n                this._babylonScene.useRightHandedSystem = true;\r\n                break;\r\n            }\r\n            default: {\r\n                throw new Error(`Invalid coordinate system mode (${this._parent.coordinateSystemMode})`);\r\n            }\r\n        }\r\n\r\n        this._parent.onMeshLoadedObservable.notifyObservers(rootMesh);\r\n        return rootNode;\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF scene.\r\n     * @param context The context when loading the asset\r\n     * @param scene The glTF scene property\r\n     * @returns A promise that resolves when the load is complete\r\n     */\r\n\r\n    public loadSceneAsync(context: string, scene: IScene): Promise<void> {\r\n        const extensionPromise = this._extensionsLoadSceneAsync(context, scene);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        this.logOpen(`${context} ${scene.name || \"\"}`);\r\n\r\n        if (scene.nodes) {\r\n            for (const index of scene.nodes) {\r\n                const node = ArrayItem.Get(`${context}/nodes/${index}`, this._gltf.nodes, index);\r\n                promises.push(\r\n                    this.loadNodeAsync(`/nodes/${node.index}`, node, (babylonMesh) => {\r\n                        babylonMesh.parent = this._rootBabylonMesh;\r\n                    })\r\n                );\r\n            }\r\n        }\r\n\r\n        for (const action of this._postSceneLoadActions) {\r\n            action();\r\n        }\r\n\r\n        promises.push(this._loadAnimationsAsync());\r\n\r\n        this.logClose();\r\n\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n\r\n    private _forEachPrimitive(node: INode, callback: (babylonMesh: AbstractMesh) => void): void {\r\n        if (node._primitiveBabylonMeshes) {\r\n            for (const babylonMesh of node._primitiveBabylonMeshes) {\r\n                callback(babylonMesh);\r\n            }\r\n        }\r\n    }\r\n\r\n    private _getGeometries(): Geometry[] {\r\n        const geometries: Geometry[] = [];\r\n\r\n        const nodes = this._gltf.nodes;\r\n        if (nodes) {\r\n            for (const node of nodes) {\r\n                this._forEachPrimitive(node, (babylonMesh) => {\r\n                    const geometry = (babylonMesh as Mesh).geometry;\r\n                    if (geometry && geometries.indexOf(geometry) === -1) {\r\n                        geometries.push(geometry);\r\n                    }\r\n                });\r\n            }\r\n        }\r\n\r\n        return geometries;\r\n    }\r\n\r\n    private _getMeshes(): AbstractMesh[] {\r\n        const meshes: AbstractMesh[] = [];\r\n\r\n        // Root mesh is always first, if available.\r\n        if (this._rootBabylonMesh instanceof AbstractMesh) {\r\n            meshes.push(this._rootBabylonMesh);\r\n        }\r\n\r\n        const nodes = this._gltf.nodes;\r\n        if (nodes) {\r\n            for (const node of nodes) {\r\n                this._forEachPrimitive(node, (babylonMesh) => {\r\n                    meshes.push(babylonMesh);\r\n                });\r\n            }\r\n        }\r\n\r\n        return meshes;\r\n    }\r\n\r\n    private _getTransformNodes(): TransformNode[] {\r\n        const transformNodes: TransformNode[] = [];\r\n\r\n        const nodes = this._gltf.nodes;\r\n        if (nodes) {\r\n            for (const node of nodes) {\r\n                if (node._babylonTransformNode && node._babylonTransformNode.getClassName() === \"TransformNode\") {\r\n                    transformNodes.push(node._babylonTransformNode);\r\n                }\r\n                if (node._babylonTransformNodeForSkin) {\r\n                    transformNodes.push(node._babylonTransformNodeForSkin);\r\n                }\r\n            }\r\n        }\r\n\r\n        return transformNodes;\r\n    }\r\n\r\n    private _getSkeletons(): Skeleton[] {\r\n        const skeletons: Skeleton[] = [];\r\n\r\n        const skins = this._gltf.skins;\r\n        if (skins) {\r\n            for (const skin of skins) {\r\n                if (skin._data) {\r\n                    skeletons.push(skin._data.babylonSkeleton);\r\n                }\r\n            }\r\n        }\r\n\r\n        return skeletons;\r\n    }\r\n\r\n    private _getAnimationGroups(): AnimationGroup[] {\r\n        const animationGroups: AnimationGroup[] = [];\r\n\r\n        const animations = this._gltf.animations;\r\n        if (animations) {\r\n            for (const animation of animations) {\r\n                if (animation._babylonAnimationGroup) {\r\n                    animationGroups.push(animation._babylonAnimationGroup);\r\n                }\r\n            }\r\n        }\r\n\r\n        return animationGroups;\r\n    }\r\n\r\n    private _startAnimations(): void {\r\n        switch (this._parent.animationStartMode) {\r\n            case GLTFLoaderAnimationStartMode.NONE: {\r\n                // do nothing\r\n                break;\r\n            }\r\n            case GLTFLoaderAnimationStartMode.FIRST: {\r\n                const babylonAnimationGroups = this._getAnimationGroups();\r\n                if (babylonAnimationGroups.length !== 0) {\r\n                    babylonAnimationGroups[0].start(true);\r\n                }\r\n                break;\r\n            }\r\n            case GLTFLoaderAnimationStartMode.ALL: {\r\n                const babylonAnimationGroups = this._getAnimationGroups();\r\n                for (const babylonAnimationGroup of babylonAnimationGroups) {\r\n                    babylonAnimationGroup.start(true);\r\n                }\r\n                break;\r\n            }\r\n            default: {\r\n                Logger.Error(`Invalid animation start mode (${this._parent.animationStartMode})`);\r\n                return;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF node.\r\n     * @param context The context when loading the asset\r\n     * @param node The glTF node property\r\n     * @param assign A function called synchronously after parsing the glTF properties\r\n     * @returns A promise that resolves with the loaded Babylon mesh when the load is complete\r\n     */\r\n\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void = () => {}): Promise<TransformNode> {\r\n        const extensionPromise = this._extensionsLoadNodeAsync(context, node, assign);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        if (node._babylonTransformNode) {\r\n            throw new Error(`${context}: Invalid recursive node hierarchy`);\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        this.logOpen(`${context} ${node.name || \"\"}`);\r\n\r\n        const loadNode = (babylonTransformNode: TransformNode) => {\r\n            GLTFLoader.AddPointerMetadata(babylonTransformNode, context);\r\n            GLTFLoader._LoadTransform(node, babylonTransformNode);\r\n\r\n            if (node.camera != undefined) {\r\n                const camera = ArrayItem.Get(`${context}/camera`, this._gltf.cameras, node.camera);\r\n                promises.push(\r\n                    this.loadCameraAsync(`/cameras/${camera.index}`, camera, (babylonCamera) => {\r\n                        babylonCamera.parent = babylonTransformNode;\r\n                        if (!this._babylonScene.useRightHandedSystem) {\r\n                            babylonTransformNode.scaling.x = -1; // Cancelling root node scaling for handedness so the view matrix does not end up flipped.\r\n                        }\r\n                    })\r\n                );\r\n            }\r\n\r\n            if (node.children) {\r\n                for (const index of node.children) {\r\n                    const childNode = ArrayItem.Get(`${context}/children/${index}`, this._gltf.nodes, index);\r\n                    promises.push(\r\n                        this.loadNodeAsync(`/nodes/${childNode.index}`, childNode, (childBabylonMesh) => {\r\n                            childBabylonMesh.parent = babylonTransformNode;\r\n                        })\r\n                    );\r\n                }\r\n            }\r\n\r\n            assign(babylonTransformNode);\r\n        };\r\n\r\n        const hasMesh = node.mesh != undefined;\r\n        const hasSkin = this._parent.loadSkins && node.skin != undefined;\r\n\r\n        if (!hasMesh || hasSkin) {\r\n            const nodeName = node.name || `node${node.index}`;\r\n            this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n            const transformNode = new TransformNode(nodeName, this._babylonScene);\r\n            transformNode._parentContainer = this._assetContainer;\r\n            this._babylonScene._blockEntityCollection = false;\r\n            if (node.mesh == undefined) {\r\n                node._babylonTransformNode = transformNode;\r\n            } else {\r\n                node._babylonTransformNodeForSkin = transformNode;\r\n            }\r\n            loadNode(transformNode);\r\n        }\r\n\r\n        if (hasMesh) {\r\n            if (hasSkin) {\r\n                // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)\r\n                // This code path will place the skinned mesh as a sibling of the skeleton root node without loading the\r\n                // transform, which effectively ignores the transform of the skinned mesh, as per spec.\r\n\r\n                const mesh = ArrayItem.Get(`${context}/mesh`, this._gltf.meshes, node.mesh);\r\n                promises.push(\r\n                    this._loadMeshAsync(`/meshes/${mesh.index}`, node, mesh, (babylonTransformNode) => {\r\n                        const babylonTransformNodeForSkin = node._babylonTransformNodeForSkin!;\r\n\r\n                        // Merge the metadata from the skin node to the skinned mesh in case a loader extension added metadata.\r\n                        babylonTransformNode.metadata = deepMerge(babylonTransformNodeForSkin.metadata, babylonTransformNode.metadata || {});\r\n\r\n                        const skin = ArrayItem.Get(`${context}/skin`, this._gltf.skins, node.skin);\r\n                        promises.push(\r\n                            this._loadSkinAsync(`/skins/${skin.index}`, node, skin, (babylonSkeleton) => {\r\n                                this._forEachPrimitive(node, (babylonMesh) => {\r\n                                    babylonMesh.skeleton = babylonSkeleton;\r\n                                });\r\n\r\n                                // Wait until all the nodes are parented before parenting the skinned mesh.\r\n                                this._postSceneLoadActions.push(() => {\r\n                                    if (skin.skeleton != undefined) {\r\n                                        // Place the skinned mesh node as a sibling of the skeleton root node.\r\n                                        // Handle special case when the parent of the skeleton root is the skinned mesh.\r\n                                        const parentNode = ArrayItem.Get(`/skins/${skin.index}/skeleton`, this._gltf.nodes, skin.skeleton).parent!;\r\n                                        if (node.index === parentNode.index) {\r\n                                            babylonTransformNode.parent = babylonTransformNodeForSkin.parent;\r\n                                        } else {\r\n                                            babylonTransformNode.parent = parentNode._babylonTransformNode!;\r\n                                        }\r\n                                    } else {\r\n                                        babylonTransformNode.parent = this._rootBabylonMesh;\r\n                                    }\r\n\r\n                                    this._parent.onSkinLoadedObservable.notifyObservers({ node: babylonTransformNodeForSkin, skinnedNode: babylonTransformNode });\r\n                                });\r\n                            })\r\n                        );\r\n                    })\r\n                );\r\n            } else {\r\n                const mesh = ArrayItem.Get(`${context}/mesh`, this._gltf.meshes, node.mesh);\r\n                promises.push(this._loadMeshAsync(`/meshes/${mesh.index}`, node, mesh, loadNode));\r\n            }\r\n        }\r\n\r\n        this.logClose();\r\n\r\n        return Promise.all(promises).then(() => {\r\n            this._forEachPrimitive(node, (babylonMesh) => {\r\n                const asMesh = babylonMesh as Mesh;\r\n                if (!asMesh.isAnInstance && asMesh.geometry && asMesh.geometry.useBoundingInfoFromGeometry) {\r\n                    // simply apply the world matrices to the bounding info - the extends are already ok\r\n                    babylonMesh._updateBoundingInfo();\r\n                } else {\r\n                    babylonMesh.refreshBoundingInfo(true, true);\r\n                }\r\n            });\r\n\r\n            return node._babylonTransformNode!;\r\n        });\r\n    }\r\n\r\n    private _loadMeshAsync(context: string, node: INode, mesh: IMesh, assign: (babylonTransformNode: TransformNode) => void): Promise<TransformNode> {\r\n        const primitives = mesh.primitives;\r\n        if (!primitives || !primitives.length) {\r\n            throw new Error(`${context}: Primitives are missing`);\r\n        }\r\n\r\n        if (primitives[0].index == undefined) {\r\n            ArrayItem.Assign(primitives);\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        this.logOpen(`${context} ${mesh.name || \"\"}`);\r\n\r\n        const name = node.name || `node${node.index}`;\r\n\r\n        if (primitives.length === 1) {\r\n            const primitive = mesh.primitives[0];\r\n            promises.push(\r\n                this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}`, name, node, mesh, primitive, (babylonMesh) => {\r\n                    node._babylonTransformNode = babylonMesh;\r\n                    node._primitiveBabylonMeshes = [babylonMesh];\r\n                })\r\n            );\r\n        } else {\r\n            this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n            node._babylonTransformNode = new TransformNode(name, this._babylonScene);\r\n            node._babylonTransformNode._parentContainer = this._assetContainer;\r\n            this._babylonScene._blockEntityCollection = false;\r\n            node._primitiveBabylonMeshes = [];\r\n            for (const primitive of primitives) {\r\n                promises.push(\r\n                    this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}`, `${name}_primitive${primitive.index}`, node, mesh, primitive, (babylonMesh) => {\r\n                        babylonMesh.parent = node._babylonTransformNode!;\r\n                        node._primitiveBabylonMeshes!.push(babylonMesh);\r\n                    })\r\n                );\r\n            }\r\n        }\r\n\r\n        assign(node._babylonTransformNode!);\r\n\r\n        this.logClose();\r\n\r\n        return Promise.all(promises).then(() => {\r\n            return node._babylonTransformNode!;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal Define this method to modify the default behavior when loading data for mesh primitives.\r\n     * @param context The context when loading the asset\r\n     * @param name The mesh name when loading the asset\r\n     * @param node The glTF node when loading the asset\r\n     * @param mesh The glTF mesh when loading the asset\r\n     * @param primitive The glTF mesh primitive property\r\n     * @param assign A function called synchronously after parsing the glTF properties\r\n     * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled\r\n     */\r\n\r\n    public _loadMeshPrimitiveAsync(\r\n        context: string,\r\n        name: string,\r\n        node: INode,\r\n        mesh: IMesh,\r\n        primitive: IMeshPrimitive,\r\n        assign: (babylonMesh: AbstractMesh) => void\r\n    ): Promise<AbstractMesh> {\r\n        const extensionPromise = this._extensionsLoadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        this.logOpen(`${context}`);\r\n\r\n        const shouldInstance = this._disableInstancedMesh === 0 && this._parent.createInstances && node.skin == undefined && !mesh.primitives[0].targets;\r\n\r\n        let babylonAbstractMesh: AbstractMesh;\r\n        let promise: Promise<unknown>;\r\n\r\n        if (shouldInstance && primitive._instanceData) {\r\n            this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n            babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);\r\n            babylonAbstractMesh._parentContainer = this._assetContainer;\r\n            this._babylonScene._blockEntityCollection = false;\r\n            promise = primitive._instanceData.promise;\r\n        } else {\r\n            const promises = new Array<Promise<unknown>>();\r\n\r\n            this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n            const babylonMesh = new Mesh(name, this._babylonScene);\r\n            babylonMesh._parentContainer = this._assetContainer;\r\n            this._babylonScene._blockEntityCollection = false;\r\n            babylonMesh.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;\r\n\r\n            this._createMorphTargets(context, node, mesh, primitive, babylonMesh);\r\n            promises.push(\r\n                this._loadVertexDataAsync(context, primitive, babylonMesh).then(async (babylonGeometry) => {\r\n                    return await this._loadMorphTargetsAsync(context, primitive, babylonMesh, babylonGeometry).then(() => {\r\n                        if (this._disposed) {\r\n                            return;\r\n                        }\r\n\r\n                        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n                        babylonGeometry.applyToMesh(babylonMesh);\r\n                        babylonGeometry._parentContainer = this._assetContainer;\r\n                        this._babylonScene._blockEntityCollection = false;\r\n                    });\r\n                })\r\n            );\r\n\r\n            if (!this.parent.skipMaterials) {\r\n                const babylonDrawMode = GLTFLoader._GetDrawMode(context, primitive.mode);\r\n                if (primitive.material == undefined) {\r\n                    let babylonMaterial = this._defaultBabylonMaterialData[babylonDrawMode];\r\n                    if (!babylonMaterial) {\r\n                        babylonMaterial = this._createDefaultMaterial(\"__GLTFLoader._default\", babylonDrawMode, this._getDefaultImpl());\r\n                        this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);\r\n                        this._defaultBabylonMaterialData[babylonDrawMode] = babylonMaterial;\r\n                    }\r\n                    babylonMesh.material = babylonMaterial;\r\n                } else {\r\n                    const material = ArrayItem.Get(`${context}/material`, this._gltf.materials, primitive.material);\r\n                    promises.push(\r\n                        this._loadMaterialAsync(`/materials/${material.index}`, material, babylonMesh, babylonDrawMode, (babylonMaterial) => {\r\n                            babylonMesh.material = babylonMaterial;\r\n                        })\r\n                    );\r\n                }\r\n            }\r\n\r\n            promise = Promise.all(promises);\r\n\r\n            if (shouldInstance) {\r\n                primitive._instanceData = {\r\n                    babylonSourceMesh: babylonMesh,\r\n                    promise: promise,\r\n                };\r\n            }\r\n\r\n            babylonAbstractMesh = babylonMesh;\r\n        }\r\n\r\n        GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);\r\n        this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);\r\n        assign(babylonAbstractMesh);\r\n\r\n        this.logClose();\r\n\r\n        return promise.then(() => {\r\n            return babylonAbstractMesh;\r\n        });\r\n    }\r\n\r\n    private _loadVertexDataAsync(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Promise<Geometry> {\r\n        const extensionPromise = this._extensionsLoadVertexDataAsync(context, primitive, babylonMesh);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        const attributes = primitive.attributes;\r\n        if (!attributes) {\r\n            throw new Error(`${context}: Attributes are missing`);\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        const babylonGeometry = new Geometry(babylonMesh.name, this._babylonScene);\r\n\r\n        if (primitive.indices == undefined) {\r\n            babylonMesh.isUnIndexed = true;\r\n        } else {\r\n            const accessor = ArrayItem.Get(`${context}/indices`, this._gltf.accessors, primitive.indices);\r\n            promises.push(\r\n                this._loadIndicesAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {\r\n                    babylonGeometry.setIndices(data);\r\n                })\r\n            );\r\n        }\r\n\r\n        const loadAttribute = (name: string, kind: string, callback?: (accessor: IAccessor) => void) => {\r\n            if (attributes[name] == undefined) {\r\n                return;\r\n            }\r\n\r\n            babylonMesh._delayInfo = babylonMesh._delayInfo || [];\r\n            if (babylonMesh._delayInfo.indexOf(kind) === -1) {\r\n                babylonMesh._delayInfo.push(kind);\r\n            }\r\n\r\n            const accessor = ArrayItem.Get(`${context}/attributes/${name}`, this._gltf.accessors, attributes[name]);\r\n            promises.push(\r\n                this._loadVertexAccessorAsync(`/accessors/${accessor.index}`, accessor, kind).then((babylonVertexBuffer) => {\r\n                    if (babylonVertexBuffer.getKind() === VertexBuffer.PositionKind && !this.parent.alwaysComputeBoundingBox && !babylonMesh.skeleton) {\r\n                        const babylonBoundingInfo = LoadBoundingInfoFromPositionAccessor(accessor);\r\n                        if (babylonBoundingInfo) {\r\n                            babylonGeometry._boundingInfo = babylonBoundingInfo;\r\n                            babylonGeometry.useBoundingInfoFromGeometry = true;\r\n                        }\r\n                    }\r\n                    babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);\r\n                })\r\n            );\r\n\r\n            if (kind == VertexBuffer.MatricesIndicesExtraKind) {\r\n                babylonMesh.numBoneInfluencers = 8;\r\n            }\r\n\r\n            if (callback) {\r\n                callback(accessor);\r\n            }\r\n        };\r\n\r\n        loadAttribute(\"POSITION\", VertexBuffer.PositionKind);\r\n        loadAttribute(\"NORMAL\", VertexBuffer.NormalKind);\r\n        loadAttribute(\"TANGENT\", VertexBuffer.TangentKind);\r\n        loadAttribute(\"TEXCOORD_0\", VertexBuffer.UVKind);\r\n        loadAttribute(\"TEXCOORD_1\", VertexBuffer.UV2Kind);\r\n        loadAttribute(\"TEXCOORD_2\", VertexBuffer.UV3Kind);\r\n        loadAttribute(\"TEXCOORD_3\", VertexBuffer.UV4Kind);\r\n        loadAttribute(\"TEXCOORD_4\", VertexBuffer.UV5Kind);\r\n        loadAttribute(\"TEXCOORD_5\", VertexBuffer.UV6Kind);\r\n        loadAttribute(\"JOINTS_0\", VertexBuffer.MatricesIndicesKind);\r\n        loadAttribute(\"WEIGHTS_0\", VertexBuffer.MatricesWeightsKind);\r\n        loadAttribute(\"JOINTS_1\", VertexBuffer.MatricesIndicesExtraKind);\r\n        loadAttribute(\"WEIGHTS_1\", VertexBuffer.MatricesWeightsExtraKind);\r\n        loadAttribute(\"COLOR_0\", VertexBuffer.ColorKind, (accessor) => {\r\n            if (accessor.type === AccessorType.VEC4) {\r\n                babylonMesh.hasVertexAlpha = true;\r\n            }\r\n        });\r\n\r\n        return Promise.all(promises).then(() => {\r\n            return babylonGeometry;\r\n        });\r\n    }\r\n\r\n    private _createMorphTargets(context: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, babylonMesh: Mesh): void {\r\n        if (!primitive.targets || !this._parent.loadMorphTargets) {\r\n            return;\r\n        }\r\n\r\n        if (node._numMorphTargets == undefined) {\r\n            node._numMorphTargets = primitive.targets.length;\r\n        } else if (primitive.targets.length !== node._numMorphTargets) {\r\n            throw new Error(`${context}: Primitives do not have the same number of targets`);\r\n        }\r\n\r\n        const targetNames = mesh.extras ? mesh.extras.targetNames : null;\r\n\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        babylonMesh.morphTargetManager = new MorphTargetManager(this._babylonScene);\r\n        babylonMesh.morphTargetManager._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n\r\n        babylonMesh.morphTargetManager.areUpdatesFrozen = true;\r\n\r\n        for (let index = 0; index < primitive.targets.length; index++) {\r\n            const weight = node.weights ? node.weights[index] : mesh.weights ? mesh.weights[index] : 0;\r\n            const name = targetNames ? targetNames[index] : `morphTarget${index}`;\r\n            babylonMesh.morphTargetManager.addTarget(new MorphTarget(name, weight, babylonMesh.getScene()));\r\n            // TODO: tell the target whether it has positions, normals, tangents\r\n        }\r\n    }\r\n\r\n    private _loadMorphTargetsAsync(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh, babylonGeometry: Geometry): Promise<void> {\r\n        if (!primitive.targets || !this._parent.loadMorphTargets) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        const morphTargetManager = babylonMesh.morphTargetManager!;\r\n        for (let index = 0; index < morphTargetManager.numTargets; index++) {\r\n            const babylonMorphTarget = morphTargetManager.getTarget(index);\r\n            promises.push(this._loadMorphTargetVertexDataAsync(`${context}/targets/${index}`, babylonGeometry, primitive.targets[index], babylonMorphTarget));\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {\r\n            morphTargetManager.areUpdatesFrozen = false;\r\n\r\n            if (this._parent.useMaxMorphTargetInfluencers) {\r\n                // Compile the morph shader once for all targets so it is not recompiled (causing a one-frame visual\r\n                // glitch) when an animated influence passes through zero and the active influencer count changes.\r\n                // optimizeInfluencers is disabled too so the active influencer set - and thus the bound\r\n                // influences/attributes - matches NUM_MORPH_INFLUENCERS.\r\n                // In the vertex-attribute fallback path the active set is hard-capped at\r\n                // MaxActiveMorphTargetsInVertexAttributeMode, so only pin when texture storage is used or the target\r\n                // count fits within that cap; otherwise NUM_MORPH_INFLUENCERS would exceed the bound attributes.\r\n                if (morphTargetManager.isUsingTextureForTargets || morphTargetManager.numTargets <= MorphTargetManager.MaxActiveMorphTargetsInVertexAttributeMode) {\r\n                    morphTargetManager.optimizeInfluencers = false;\r\n                    morphTargetManager.numMaxInfluencers = morphTargetManager.numTargets;\r\n                }\r\n            }\r\n        });\r\n    }\r\n\r\n    private async _loadMorphTargetVertexDataAsync(\r\n        context: string,\r\n        babylonGeometry: Geometry,\r\n        attributes: { [name: string]: number },\r\n        babylonMorphTarget: MorphTarget\r\n    ): Promise<void> {\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        const loadAttribute = (attribute: string, kind: string, setData: (babylonVertexBuffer: VertexBuffer, data: Float32Array) => void) => {\r\n            if (attributes[attribute] == undefined) {\r\n                return;\r\n            }\r\n\r\n            const babylonVertexBuffer = babylonGeometry.getVertexBuffer(kind);\r\n            if (!babylonVertexBuffer) {\r\n                return;\r\n            }\r\n\r\n            const accessor = ArrayItem.Get(`${context}/${attribute}`, this._gltf.accessors, attributes[attribute]);\r\n            promises.push(\r\n                this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {\r\n                    setData(babylonVertexBuffer, data);\r\n                })\r\n            );\r\n        };\r\n\r\n        loadAttribute(\"POSITION\", VertexBuffer.PositionKind, (babylonVertexBuffer, data) => {\r\n            const positions = new Float32Array(data.length);\r\n            babylonVertexBuffer.forEach(data.length, (value, index) => {\r\n                positions[index] = data[index] + value;\r\n            });\r\n\r\n            babylonMorphTarget.setPositions(positions);\r\n        });\r\n\r\n        loadAttribute(\"NORMAL\", VertexBuffer.NormalKind, (babylonVertexBuffer, data) => {\r\n            const normals = new Float32Array(data.length);\r\n            babylonVertexBuffer.forEach(normals.length, (value, index) => {\r\n                normals[index] = data[index] + value;\r\n            });\r\n\r\n            babylonMorphTarget.setNormals(normals);\r\n        });\r\n\r\n        loadAttribute(\"TANGENT\", VertexBuffer.TangentKind, (babylonVertexBuffer, data) => {\r\n            const tangents = new Float32Array((data.length / 3) * 4);\r\n            let dataIndex = 0;\r\n            babylonVertexBuffer.forEach((data.length / 3) * 4, (value, index) => {\r\n                // Tangent data for morph targets is stored as xyz delta.\r\n                // The vertexData.tangent is stored as xyzw.\r\n                // So we need to skip every fourth vertexData.tangent.\r\n                if ((index + 1) % 4 !== 0) {\r\n                    tangents[dataIndex] = data[dataIndex] + value;\r\n                    dataIndex++;\r\n                }\r\n            });\r\n            babylonMorphTarget.setTangents(tangents);\r\n        });\r\n\r\n        loadAttribute(\"TEXCOORD_0\", VertexBuffer.UVKind, (babylonVertexBuffer, data) => {\r\n            const uvs = new Float32Array(data.length);\r\n            babylonVertexBuffer.forEach(data.length, (value, index) => {\r\n                uvs[index] = data[index] + value;\r\n            });\r\n\r\n            babylonMorphTarget.setUVs(uvs);\r\n        });\r\n\r\n        loadAttribute(\"TEXCOORD_1\", VertexBuffer.UV2Kind, (babylonVertexBuffer, data) => {\r\n            const uvs = new Float32Array(data.length);\r\n            babylonVertexBuffer.forEach(data.length, (value, index) => {\r\n                uvs[index] = data[index] + value;\r\n            });\r\n\r\n            babylonMorphTarget.setUV2s(uvs);\r\n        });\r\n\r\n        loadAttribute(\"COLOR_0\", VertexBuffer.ColorKind, (babylonVertexBuffer, data) => {\r\n            let colors = null;\r\n            const componentSize = babylonVertexBuffer.getSize();\r\n            if (componentSize === 3) {\r\n                colors = new Float32Array((data.length / 3) * 4);\r\n                babylonVertexBuffer.forEach(data.length, (value, index) => {\r\n                    const pixid = Math.floor(index / 3);\r\n                    const channel = index % 3;\r\n                    colors[4 * pixid + channel] = data[3 * pixid + channel] + value;\r\n                });\r\n                for (let i = 0; i < data.length / 3; ++i) {\r\n                    colors[4 * i + 3] = 1;\r\n                }\r\n            } else if (componentSize === 4) {\r\n                colors = new Float32Array(data.length);\r\n                babylonVertexBuffer.forEach(data.length, (value, index) => {\r\n                    colors[index] = data[index] + value;\r\n                });\r\n            } else {\r\n                throw new Error(`${context}: Invalid number of components (${componentSize}) for COLOR_0 attribute`);\r\n            }\r\n            babylonMorphTarget.setColors(colors);\r\n        });\r\n\r\n        return await Promise.all(promises).then(() => {});\r\n    }\r\n\r\n    private static _LoadTransform(node: INode, babylonNode: TransformNode): void {\r\n        // Ignore the TRS of skinned nodes.\r\n        // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)\r\n        if (node.skin != undefined) {\r\n            return;\r\n        }\r\n\r\n        let position = Vector3.Zero();\r\n        let rotation = Quaternion.Identity();\r\n        let scaling = Vector3.One();\r\n\r\n        if (node.matrix) {\r\n            const matrix = Matrix.FromArray(node.matrix);\r\n            matrix.decompose(scaling, rotation, position);\r\n        } else {\r\n            if (node.translation) {\r\n                position = Vector3.FromArray(node.translation);\r\n            }\r\n            if (node.rotation) {\r\n                rotation = Quaternion.FromArray(node.rotation);\r\n            }\r\n            if (node.scale) {\r\n                scaling = Vector3.FromArray(node.scale);\r\n            }\r\n        }\r\n\r\n        babylonNode.position = position;\r\n        babylonNode.rotationQuaternion = rotation;\r\n        babylonNode.scaling = scaling;\r\n    }\r\n\r\n    private _loadSkinAsync(context: string, node: INode, skin: ISkin, assign: (babylonSkeleton: Skeleton) => void): Promise<void> {\r\n        if (!this._parent.loadSkins) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        const extensionPromise = this._extensionsLoadSkinAsync(context, node, skin);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        if (skin._data) {\r\n            assign(skin._data.babylonSkeleton);\r\n            return skin._data.promise;\r\n        }\r\n\r\n        const skeletonId = `skeleton${skin.index}`;\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        const babylonSkeleton = new Skeleton(skin.name || skeletonId, skeletonId, this._babylonScene);\r\n        babylonSkeleton._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n\r\n        this._loadBones(context, skin, babylonSkeleton);\r\n        const promise = this._loadSkinInverseBindMatricesDataAsync(context, skin).then((inverseBindMatricesData) => {\r\n            this._updateBoneMatrices(babylonSkeleton, inverseBindMatricesData);\r\n        });\r\n\r\n        skin._data = {\r\n            babylonSkeleton: babylonSkeleton,\r\n            promise: promise,\r\n        };\r\n\r\n        assign(babylonSkeleton);\r\n\r\n        return promise;\r\n    }\r\n\r\n    private _loadBones(context: string, skin: ISkin, babylonSkeleton: Skeleton): void {\r\n        if (skin.skeleton == undefined || this._parent.alwaysComputeSkeletonRootNode) {\r\n            const rootNode = this._findSkeletonRootNode(`${context}/joints`, skin.joints);\r\n            if (rootNode) {\r\n                if (skin.skeleton === undefined) {\r\n                    skin.skeleton = rootNode.index;\r\n                } else {\r\n                    const isParent = (a: INode, b: INode): boolean => {\r\n                        for (; b.parent; b = b.parent) {\r\n                            if (b.parent === a) {\r\n                                return true;\r\n                            }\r\n                        }\r\n\r\n                        return false;\r\n                    };\r\n\r\n                    const skeletonNode = ArrayItem.Get(`${context}/skeleton`, this._gltf.nodes, skin.skeleton);\r\n                    if (skeletonNode !== rootNode && !isParent(skeletonNode, rootNode)) {\r\n                        Logger.Warn(`${context}/skeleton: Overriding with nearest common ancestor as skeleton node is not a common root`);\r\n                        skin.skeleton = rootNode.index;\r\n                    }\r\n                }\r\n            } else {\r\n                Logger.Warn(`${context}: Failed to find common root`);\r\n            }\r\n        }\r\n\r\n        const babylonBones: { [index: number]: Bone } = {};\r\n        for (const index of skin.joints) {\r\n            const node = ArrayItem.Get(`${context}/joints/${index}`, this._gltf.nodes, index);\r\n            this._loadBone(node, skin, babylonSkeleton, babylonBones);\r\n        }\r\n    }\r\n\r\n    private _findSkeletonRootNode(context: string, joints: Array<number>): Nullable<INode> {\r\n        if (joints.length === 0) {\r\n            return null;\r\n        }\r\n\r\n        const paths: { [joint: number]: Array<INode> } = {};\r\n        for (const index of joints) {\r\n            const path: INode[] = [];\r\n            let node = ArrayItem.Get(`${context}/${index}`, this._gltf.nodes, index);\r\n            while (node.index !== -1) {\r\n                path.unshift(node);\r\n                node = node.parent!;\r\n            }\r\n            paths[index] = path;\r\n        }\r\n\r\n        let rootNode: Nullable<INode> = null;\r\n        for (let i = 0; ; ++i) {\r\n            let path = paths[joints[0]];\r\n            if (i >= path.length) {\r\n                return rootNode;\r\n            }\r\n\r\n            const node = path[i];\r\n            for (let j = 1; j < joints.length; ++j) {\r\n                path = paths[joints[j]];\r\n                if (i >= path.length || node !== path[i]) {\r\n                    return rootNode;\r\n                }\r\n            }\r\n\r\n            rootNode = node;\r\n        }\r\n    }\r\n\r\n    private _loadBone(node: INode, skin: ISkin, babylonSkeleton: Skeleton, babylonBones: { [index: number]: Bone }): Bone {\r\n        node._isJoint = true;\r\n\r\n        let babylonBone = babylonBones[node.index];\r\n        if (babylonBone) {\r\n            return babylonBone;\r\n        }\r\n\r\n        let parentBabylonBone: Nullable<Bone> = null;\r\n        if (node.index !== skin.skeleton) {\r\n            if (node.parent && node.parent.index !== -1) {\r\n                parentBabylonBone = this._loadBone(node.parent, skin, babylonSkeleton, babylonBones);\r\n            } else if (skin.skeleton !== undefined) {\r\n                Logger.Warn(`/skins/${skin.index}/skeleton: Skeleton node is not a common root`);\r\n            }\r\n        }\r\n\r\n        const boneIndex = skin.joints.indexOf(node.index);\r\n        babylonBone = new Bone(node.name || `joint${node.index}`, babylonSkeleton, parentBabylonBone, this._getNodeMatrix(node), null, null, boneIndex);\r\n        babylonBones[node.index] = babylonBone;\r\n\r\n        // Wait until the scene is loaded to ensure the transform nodes are loaded.\r\n        this._postSceneLoadActions.push(() => {\r\n            // Link the Babylon bone with the corresponding Babylon transform node.\r\n            // A glTF joint is a pointer to a glTF node in the glTF node hierarchy similar to Unity3D.\r\n            babylonBone.linkTransformNode(node._babylonTransformNode!);\r\n        });\r\n\r\n        return babylonBone;\r\n    }\r\n\r\n    private _loadSkinInverseBindMatricesDataAsync(context: string, skin: ISkin): Promise<Nullable<Float32Array>> {\r\n        if (skin.inverseBindMatrices == undefined) {\r\n            return Promise.resolve(null);\r\n        }\r\n\r\n        const accessor = ArrayItem.Get(`${context}/inverseBindMatrices`, this._gltf.accessors, skin.inverseBindMatrices);\r\n        return this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor);\r\n    }\r\n\r\n    private _updateBoneMatrices(babylonSkeleton: Skeleton, inverseBindMatricesData: Nullable<Float32Array>): void {\r\n        for (const babylonBone of babylonSkeleton.bones) {\r\n            const baseMatrix = Matrix.Identity();\r\n            const boneIndex = babylonBone._index!;\r\n            if (inverseBindMatricesData && boneIndex !== -1) {\r\n                Matrix.FromArrayToRef(inverseBindMatricesData, boneIndex * 16, baseMatrix);\r\n                baseMatrix.invertToRef(baseMatrix);\r\n            }\r\n\r\n            const babylonParentBone = babylonBone.getParent();\r\n            if (babylonParentBone) {\r\n                baseMatrix.multiplyToRef(babylonParentBone.getAbsoluteInverseBindMatrix(), baseMatrix);\r\n            }\r\n\r\n            babylonBone.updateMatrix(baseMatrix, false, false);\r\n            babylonBone._updateAbsoluteBindMatrices(undefined, false);\r\n        }\r\n    }\r\n\r\n    private _getNodeMatrix(node: INode): Matrix {\r\n        return node.matrix\r\n            ? Matrix.FromArray(node.matrix)\r\n            : Matrix.Compose(\r\n                  node.scale ? Vector3.FromArray(node.scale) : Vector3.One(),\r\n                  node.rotation ? Quaternion.FromArray(node.rotation) : Quaternion.Identity(),\r\n                  node.translation ? Vector3.FromArray(node.translation) : Vector3.Zero()\r\n              );\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF camera.\r\n     * @param context The context when loading the asset\r\n     * @param camera The glTF camera property\r\n     * @param assign A function called synchronously after parsing the glTF properties\r\n     * @returns A promise that resolves with the loaded Babylon camera when the load is complete\r\n     */\r\n    public loadCameraAsync(context: string, camera: ICamera, assign: (babylonCamera: Camera) => void = () => {}): Promise<Camera> {\r\n        const extensionPromise = this._extensionsLoadCameraAsync(context, camera, assign);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        this.logOpen(`${context} ${camera.name || \"\"}`);\r\n\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        const babylonCamera = new FreeCamera(camera.name || `camera${camera.index}`, Vector3.Zero(), this._babylonScene, false);\r\n        babylonCamera._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n        camera._babylonCamera = babylonCamera;\r\n\r\n        // glTF cameras look towards the local -Z axis.\r\n        babylonCamera.setTarget(new Vector3(0, 0, -1));\r\n\r\n        switch (camera.type) {\r\n            case CameraType.PERSPECTIVE: {\r\n                const perspective = camera.perspective;\r\n                if (!perspective) {\r\n                    throw new Error(`${context}: Camera perspective properties are missing`);\r\n                }\r\n\r\n                babylonCamera.fov = perspective.yfov;\r\n                babylonCamera.minZ = perspective.znear;\r\n                babylonCamera.maxZ = perspective.zfar || 0;\r\n                break;\r\n            }\r\n            case CameraType.ORTHOGRAPHIC: {\r\n                if (!camera.orthographic) {\r\n                    throw new Error(`${context}: Camera orthographic properties are missing`);\r\n                }\r\n\r\n                babylonCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;\r\n                babylonCamera.orthoLeft = -camera.orthographic.xmag;\r\n                babylonCamera.orthoRight = camera.orthographic.xmag;\r\n                babylonCamera.orthoBottom = -camera.orthographic.ymag;\r\n                babylonCamera.orthoTop = camera.orthographic.ymag;\r\n                babylonCamera.minZ = camera.orthographic.znear;\r\n                babylonCamera.maxZ = camera.orthographic.zfar;\r\n                break;\r\n            }\r\n            default: {\r\n                throw new Error(`${context}: Invalid camera type (${camera.type})`);\r\n            }\r\n        }\r\n\r\n        GLTFLoader.AddPointerMetadata(babylonCamera, context);\r\n        this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);\r\n        assign(babylonCamera);\r\n\r\n        this.logClose();\r\n\r\n        return Promise.all(promises).then(() => {\r\n            return babylonCamera;\r\n        });\r\n    }\r\n\r\n    private _loadAnimationsAsync(): Promise<void> {\r\n        this._parent._startPerformanceCounter(\"Load animations\");\r\n\r\n        const animations = this._gltf.animations;\r\n        if (!animations) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        const promises = new Array<Promise<void>>();\r\n\r\n        for (let index = 0; index < animations.length; index++) {\r\n            const animation = animations[index];\r\n            promises.push(\r\n                this.loadAnimationAsync(`/animations/${animation.index}`, animation).then((animationGroup) => {\r\n                    // Delete the animation group if it ended up not having any animations in it.\r\n                    if (animationGroup.targetedAnimations.length === 0) {\r\n                        animationGroup.dispose();\r\n                    }\r\n                })\r\n            );\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {\r\n            this._parent._endPerformanceCounter(\"Load animations\");\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF animation.\r\n     * @param context The context when loading the asset\r\n     * @param animation The glTF animation property\r\n     * @returns A promise that resolves with the loaded Babylon animation group when the load is complete\r\n     */\r\n    public loadAnimationAsync(context: string, animation: IAnimation): Promise<AnimationGroup> {\r\n        this._parent._startPerformanceCounter(\"Load animation\");\r\n\r\n        const promise = this._extensionsLoadAnimationAsync(context, animation);\r\n        if (promise) {\r\n            return promise;\r\n        }\r\n\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        return LazyAnimationGroupModulePromise.value.then(({ AnimationGroup }) => {\r\n            this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n            const babylonAnimationGroup = new AnimationGroup(animation.name || `animation${animation.index}`, this._babylonScene);\r\n            babylonAnimationGroup._parentContainer = this._assetContainer;\r\n            this._babylonScene._blockEntityCollection = false;\r\n            animation._babylonAnimationGroup = babylonAnimationGroup;\r\n\r\n            const promises = new Array<Promise<unknown>>();\r\n\r\n            ArrayItem.Assign(animation.channels);\r\n            ArrayItem.Assign(animation.samplers);\r\n\r\n            for (const channel of animation.channels) {\r\n                promises.push(\r\n                    this._loadAnimationChannelAsync(`${context}/channels/${channel.index}`, context, animation, channel, (babylonTarget, babylonAnimation) => {\r\n                        babylonTarget.animations = babylonTarget.animations || [];\r\n                        babylonTarget.animations.push(babylonAnimation);\r\n                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonTarget);\r\n                    })\r\n                );\r\n            }\r\n\r\n            this._parent._endPerformanceCounter(\"Load animation\");\r\n\r\n            return Promise.all(promises).then(() => {\r\n                babylonAnimationGroup.normalize(0);\r\n                return babylonAnimationGroup;\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @hidden\r\n     * Loads a glTF animation channel.\r\n     * @param context The context when loading the asset\r\n     * @param animationContext The context of the animation when loading the asset\r\n     * @param animation The glTF animation property\r\n     * @param channel The glTF animation channel property\r\n     * @param onLoad Called for each animation loaded\r\n     * @returns A void promise that resolves when the load is complete\r\n     */\r\n    public _loadAnimationChannelAsync(\r\n        context: string,\r\n        animationContext: string,\r\n        animation: IAnimation,\r\n        channel: IAnimationChannel,\r\n        onLoad: (babylonAnimatable: IAnimatable, babylonAnimation: Animation) => void\r\n    ): Promise<void> {\r\n        const promise = this._extensionsLoadAnimationChannelAsync(context, animationContext, animation, channel, onLoad);\r\n        if (promise) {\r\n            return promise;\r\n        }\r\n\r\n        if (channel.target.node == undefined) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        const targetNode = ArrayItem.Get(`${context}/target/node`, this._gltf.nodes, channel.target.node);\r\n        const channelTargetPath = channel.target.path;\r\n        const pathIsWeights = channelTargetPath === AnimationChannelTargetPath.WEIGHTS;\r\n\r\n        // Ignore animations that have no animation targets.\r\n        if ((pathIsWeights && !targetNode._numMorphTargets) || (!pathIsWeights && !targetNode._babylonTransformNode)) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        // Don't load node animations if disabled.\r\n        if (!this._parent.loadNodeAnimations && !pathIsWeights && !targetNode._isJoint) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        // async-load the animation sampler to provide the interpolation of the channelTargetPath\r\n        return LazyLoaderAnimationModulePromise.value.then(({ RegisterGLTFLoaderAnimation: registerGLTFLoaderAnimation }) => {\r\n            registerGLTFLoaderAnimation();\r\n            let properties: IInterpolationPropertyInfo[];\r\n            switch (channelTargetPath) {\r\n                case AnimationChannelTargetPath.TRANSLATION: {\r\n                    properties = GetMappingForKey(\"/nodes/{}/translation\")?.interpolation!;\r\n                    break;\r\n                }\r\n                case AnimationChannelTargetPath.ROTATION: {\r\n                    properties = GetMappingForKey(\"/nodes/{}/rotation\")?.interpolation!;\r\n                    break;\r\n                }\r\n                case AnimationChannelTargetPath.SCALE: {\r\n                    properties = GetMappingForKey(\"/nodes/{}/scale\")?.interpolation!;\r\n                    break;\r\n                }\r\n                case AnimationChannelTargetPath.WEIGHTS: {\r\n                    properties = GetMappingForKey(\"/nodes/{}/weights\")?.interpolation!;\r\n                    break;\r\n                }\r\n                default: {\r\n                    throw new Error(`${context}/target/path: Invalid value (${channel.target.path})`);\r\n                }\r\n            }\r\n            // stay safe\r\n            if (!properties) {\r\n                throw new Error(`${context}/target/path: Could not find interpolation properties for target path (${channel.target.path})`);\r\n            }\r\n\r\n            const targetInfo: IObjectInfo<IInterpolationPropertyInfo[]> = {\r\n                object: targetNode,\r\n                info: properties,\r\n            };\r\n\r\n            return this._loadAnimationChannelFromTargetInfoAsync(context, animationContext, animation, channel, targetInfo, onLoad);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @hidden\r\n     * Loads a glTF animation channel.\r\n     * @param context The context when loading the asset\r\n     * @param animationContext The context of the animation when loading the asset\r\n     * @param animation The glTF animation property\r\n     * @param channel The glTF animation channel property\r\n     * @param targetInfo The glTF target and properties\r\n     * @param onLoad Called for each animation loaded\r\n     * @returns A void promise that resolves when the load is complete\r\n     */\r\n    public _loadAnimationChannelFromTargetInfoAsync(\r\n        context: string,\r\n        animationContext: string,\r\n        animation: IAnimation,\r\n        channel: IAnimationChannel,\r\n        targetInfo: IObjectInfo<IInterpolationPropertyInfo[]>,\r\n        onLoad: (babylonAnimatable: IAnimatable, babylonAnimation: Animation) => void\r\n    ): Promise<void> {\r\n        const fps = this.parent.targetFps;\r\n        const invfps = 1 / fps;\r\n\r\n        const sampler = ArrayItem.Get(`${context}/sampler`, animation.samplers, channel.sampler);\r\n        return this._loadAnimationSamplerAsync(`${animationContext}/samplers/${channel.sampler}`, sampler).then((data) => {\r\n            let numAnimations = 0;\r\n\r\n            const target = targetInfo.object;\r\n            const propertyInfos = targetInfo.info;\r\n            // Extract the corresponding values from the read value.\r\n            // GLTF values may be dispatched to several Babylon properties.\r\n            // For example, baseColorFactor [`r`, `g`, `b`, `a`] is dispatched to\r\n            // - albedoColor as Color3(`r`, `g`, `b`)\r\n            // - alpha as `a`\r\n            for (const propertyInfo of propertyInfos) {\r\n                const stride = propertyInfo.getStride(target);\r\n                const input = data.input;\r\n                const output = data.output;\r\n                const keys = new Array<IAnimationKey>(input.length);\r\n                let outputOffset = 0;\r\n\r\n                switch (data.interpolation) {\r\n                    case AnimationSamplerInterpolation.STEP: {\r\n                        for (let index = 0; index < input.length; index++) {\r\n                            const value = propertyInfo.getValue(target, output, outputOffset, 1);\r\n                            outputOffset += stride;\r\n\r\n                            keys[index] = {\r\n                                frame: input[index] * fps,\r\n                                value: value,\r\n                                interpolation: AnimationKeyInterpolation.STEP,\r\n                            };\r\n                        }\r\n                        break;\r\n                    }\r\n                    case AnimationSamplerInterpolation.CUBICSPLINE: {\r\n                        for (let index = 0; index < input.length; index++) {\r\n                            const inTangent = propertyInfo.getValue(target, output, outputOffset, invfps);\r\n                            outputOffset += stride;\r\n                            const value = propertyInfo.getValue(target, output, outputOffset, 1);\r\n                            outputOffset += stride;\r\n                            const outTangent = propertyInfo.getValue(target, output, outputOffset, invfps);\r\n                            outputOffset += stride;\r\n\r\n                            keys[index] = {\r\n                                frame: input[index] * fps,\r\n                                inTangent: inTangent,\r\n                                value: value,\r\n                                outTangent: outTangent,\r\n                            };\r\n                        }\r\n                        break;\r\n                    }\r\n                    case AnimationSamplerInterpolation.LINEAR: {\r\n                        for (let index = 0; index < input.length; index++) {\r\n                            const value = propertyInfo.getValue(target, output, outputOffset, 1);\r\n                            outputOffset += stride;\r\n\r\n                            keys[index] = {\r\n                                frame: input[index] * fps,\r\n                                value: value,\r\n                            };\r\n                        }\r\n                        break;\r\n                    }\r\n                }\r\n\r\n                if (outputOffset > 0) {\r\n                    const name = `${animation.name || `animation${animation.index}`}_channel${channel.index}_${numAnimations}`;\r\n                    const babylonAnimations = propertyInfo.buildAnimations(target, name, fps, keys);\r\n                    for (const babylonAnimation of babylonAnimations) {\r\n                        numAnimations++;\r\n                        onLoad(babylonAnimation.babylonAnimatable, babylonAnimation.babylonAnimation);\r\n                    }\r\n                }\r\n            }\r\n        });\r\n    }\r\n\r\n    private _loadAnimationSamplerAsync(context: string, sampler: IAnimationSampler): Promise<_IAnimationSamplerData> {\r\n        if (sampler._data) {\r\n            return sampler._data;\r\n        }\r\n\r\n        const interpolation = sampler.interpolation || AnimationSamplerInterpolation.LINEAR;\r\n        switch (interpolation) {\r\n            case AnimationSamplerInterpolation.STEP:\r\n            case AnimationSamplerInterpolation.LINEAR:\r\n            case AnimationSamplerInterpolation.CUBICSPLINE: {\r\n                break;\r\n            }\r\n            default: {\r\n                throw new Error(`${context}/interpolation: Invalid value (${sampler.interpolation})`);\r\n            }\r\n        }\r\n\r\n        const inputAccessor = ArrayItem.Get(`${context}/input`, this._gltf.accessors, sampler.input);\r\n        const outputAccessor = ArrayItem.Get(`${context}/output`, this._gltf.accessors, sampler.output);\r\n        sampler._data = Promise.all([\r\n            this._loadFloatAccessorAsync(`/accessors/${inputAccessor.index}`, inputAccessor),\r\n            this._loadFloatAccessorAsync(`/accessors/${outputAccessor.index}`, outputAccessor),\r\n        ]).then(([inputData, outputData]) => {\r\n            return {\r\n                input: inputData,\r\n                interpolation: interpolation,\r\n                output: outputData,\r\n            };\r\n        });\r\n\r\n        return sampler._data;\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF buffer.\r\n     * @param context The context when loading the asset\r\n     * @param buffer The glTF buffer property\r\n     * @param byteOffset The byte offset to use\r\n     * @param byteLength The byte length to use\r\n     * @returns A promise that resolves with the loaded data when the load is complete\r\n     */\r\n    public loadBufferAsync(context: string, buffer: IBuffer, byteOffset: number, byteLength: number): Promise<ArrayBufferView> {\r\n        const extensionPromise = this._extensionsLoadBufferAsync(context, buffer, byteOffset, byteLength);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        if (!buffer._data) {\r\n            if (buffer.uri) {\r\n                buffer._data = this.loadUriAsync(`${context}/uri`, buffer, buffer.uri);\r\n            } else {\r\n                if (!this._bin) {\r\n                    throw new Error(`${context}: Uri is missing or the binary glTF is missing its binary chunk`);\r\n                }\r\n\r\n                buffer._data = this._bin.readAsync(0, buffer.byteLength);\r\n            }\r\n        }\r\n\r\n        return buffer._data.then((data) => {\r\n            try {\r\n                return new Uint8Array(data.buffer, data.byteOffset + byteOffset, byteLength);\r\n            } catch (e) {\r\n                throw new Error(`${context}: ${e.message}`, { cause: e });\r\n            }\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF buffer view.\r\n     * @param context The context when loading the asset\r\n     * @param bufferView The glTF buffer view property\r\n     * @returns A promise that resolves with the loaded data when the load is complete\r\n     */\r\n    public loadBufferViewAsync(context: string, bufferView: IBufferView): Promise<ArrayBufferView> {\r\n        const extensionPromise = this._extensionsLoadBufferViewAsync(context, bufferView);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        if (bufferView._data) {\r\n            return bufferView._data;\r\n        }\r\n\r\n        const buffer = ArrayItem.Get(`${context}/buffer`, this._gltf.buffers, bufferView.buffer);\r\n        bufferView._data = this.loadBufferAsync(`/buffers/${buffer.index}`, buffer, bufferView.byteOffset || 0, bufferView.byteLength);\r\n\r\n        return bufferView._data;\r\n    }\r\n\r\n    private _loadAccessorAsync(context: string, accessor: IAccessor, constructor: TypedArrayConstructor): Promise<ArrayBufferView> {\r\n        if (accessor._data) {\r\n            return accessor._data;\r\n        }\r\n\r\n        const numComponents = GLTFLoader._GetNumComponents(context, accessor.type);\r\n        const byteStride = numComponents * VertexBufferGetTypeByteLength(accessor.componentType);\r\n        const length = numComponents * accessor.count;\r\n\r\n        if (accessor.bufferView == undefined) {\r\n            accessor._data = Promise.resolve(new constructor(length));\r\n        } else {\r\n            const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);\r\n            accessor._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {\r\n                if (accessor.componentType === AccessorComponentType.FLOAT && !accessor.normalized && (!bufferView.byteStride || bufferView.byteStride === byteStride)) {\r\n                    return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);\r\n                } else {\r\n                    const typedArray = new constructor(length);\r\n                    VertexBufferForEach(\r\n                        data,\r\n                        accessor.byteOffset || 0,\r\n                        bufferView.byteStride || byteStride,\r\n                        numComponents,\r\n                        accessor.componentType,\r\n                        typedArray.length,\r\n                        accessor.normalized || false,\r\n                        (value, index) => {\r\n                            typedArray[index] = value;\r\n                        }\r\n                    );\r\n                    return typedArray;\r\n                }\r\n            });\r\n        }\r\n\r\n        if (accessor.sparse) {\r\n            const sparse = accessor.sparse;\r\n            accessor._data = accessor._data.then((data) => {\r\n                const typedArray = data as TypedArray;\r\n                const indicesBufferView = ArrayItem.Get(`${context}/sparse/indices/bufferView`, this._gltf.bufferViews, sparse.indices.bufferView);\r\n                const valuesBufferView = ArrayItem.Get(`${context}/sparse/values/bufferView`, this._gltf.bufferViews, sparse.values.bufferView);\r\n                return Promise.all([\r\n                    this.loadBufferViewAsync(`/bufferViews/${indicesBufferView.index}`, indicesBufferView),\r\n                    this.loadBufferViewAsync(`/bufferViews/${valuesBufferView.index}`, valuesBufferView),\r\n                ]).then(([indicesData, valuesData]) => {\r\n                    const indices = GLTFLoader._GetTypedArray(\r\n                        `${context}/sparse/indices`,\r\n                        sparse.indices.componentType,\r\n                        indicesData,\r\n                        sparse.indices.byteOffset,\r\n                        sparse.count\r\n                    ) as IndicesArray;\r\n\r\n                    const sparseLength = numComponents * sparse.count;\r\n                    let values: TypedArray;\r\n\r\n                    if (accessor.componentType === AccessorComponentType.FLOAT && !accessor.normalized) {\r\n                        values = GLTFLoader._GetTypedArray(`${context}/sparse/values`, accessor.componentType, valuesData, sparse.values.byteOffset, sparseLength);\r\n                    } else {\r\n                        const sparseData = GLTFLoader._GetTypedArray(`${context}/sparse/values`, accessor.componentType, valuesData, sparse.values.byteOffset, sparseLength);\r\n                        values = new constructor(sparseLength);\r\n                        VertexBufferForEach(sparseData, 0, byteStride, numComponents, accessor.componentType, values.length, accessor.normalized || false, (value, index) => {\r\n                            values[index] = value;\r\n                        });\r\n                    }\r\n\r\n                    let valuesIndex = 0;\r\n                    for (let indicesIndex = 0; indicesIndex < indices.length; indicesIndex++) {\r\n                        let dataIndex = indices[indicesIndex] * numComponents;\r\n                        for (let componentIndex = 0; componentIndex < numComponents; componentIndex++) {\r\n                            typedArray[dataIndex++] = values[valuesIndex++];\r\n                        }\r\n                    }\r\n\r\n                    return typedArray;\r\n                });\r\n            });\r\n        }\r\n\r\n        return accessor._data;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadFloatAccessorAsync(context: string, accessor: IAccessor): Promise<Float32Array> {\r\n        return this._loadAccessorAsync(context, accessor, Float32Array) as Promise<Float32Array>;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadIndicesAccessorAsync(context: string, accessor: IAccessor): Promise<IndicesArray> {\r\n        if (accessor.type !== AccessorType.SCALAR) {\r\n            throw new Error(`${context}/type: Invalid value ${accessor.type}`);\r\n        }\r\n\r\n        if (\r\n            accessor.componentType !== AccessorComponentType.UNSIGNED_BYTE &&\r\n            accessor.componentType !== AccessorComponentType.UNSIGNED_SHORT &&\r\n            accessor.componentType !== AccessorComponentType.UNSIGNED_INT\r\n        ) {\r\n            throw new Error(`${context}/componentType: Invalid value ${accessor.componentType}`);\r\n        }\r\n\r\n        if (accessor._data) {\r\n            return accessor._data as Promise<IndicesArray>;\r\n        }\r\n\r\n        if (accessor.sparse) {\r\n            const constructor = GLTFLoader._GetTypedArrayConstructor(`${context}/componentType`, accessor.componentType);\r\n            accessor._data = this._loadAccessorAsync(context, accessor, constructor);\r\n        } else {\r\n            const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);\r\n            accessor._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {\r\n                return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);\r\n            });\r\n        }\r\n\r\n        return accessor._data as Promise<IndicesArray>;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadVertexBufferViewAsync(bufferView: IBufferView): Promise<Buffer> {\r\n        if (bufferView._babylonBuffer) {\r\n            return bufferView._babylonBuffer;\r\n        }\r\n\r\n        const engine = this._babylonScene.getEngine();\r\n        bufferView._babylonBuffer = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {\r\n            return new Buffer(engine, data, false);\r\n        });\r\n\r\n        return bufferView._babylonBuffer;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadVertexAccessorAsync(context: string, accessor: IAccessor, kind: string): Promise<VertexBuffer> {\r\n        if (accessor._babylonVertexBuffer?.[kind]) {\r\n            return accessor._babylonVertexBuffer[kind];\r\n        }\r\n\r\n        if (!accessor._babylonVertexBuffer) {\r\n            accessor._babylonVertexBuffer = {};\r\n        }\r\n\r\n        const engine = this._babylonScene.getEngine();\r\n\r\n        if (accessor.sparse || accessor.bufferView == undefined) {\r\n            accessor._babylonVertexBuffer[kind] = this._loadFloatAccessorAsync(context, accessor).then((data) => {\r\n                return new VertexBuffer(engine, data, kind, false);\r\n            });\r\n        } else {\r\n            const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);\r\n            accessor._babylonVertexBuffer[kind] = this._loadVertexBufferViewAsync(bufferView).then((babylonBuffer) => {\r\n                const numComponents = GLTFLoader._GetNumComponents(context, accessor.type);\r\n                return new VertexBuffer(\r\n                    engine,\r\n                    babylonBuffer,\r\n                    kind,\r\n                    false,\r\n                    undefined,\r\n                    bufferView.byteStride,\r\n                    undefined,\r\n                    accessor.byteOffset,\r\n                    numComponents,\r\n                    accessor.componentType,\r\n                    accessor.normalized,\r\n                    true,\r\n                    undefined,\r\n                    true\r\n                );\r\n            });\r\n        }\r\n\r\n        return accessor._babylonVertexBuffer[kind];\r\n    }\r\n\r\n    private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise<void> {\r\n        const promises = new Array<Promise<unknown>>();\r\n        const adapter = this._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n        if (properties) {\r\n            // Set base color and alpha using adapter\r\n            if (properties.baseColorFactor) {\r\n                adapter.baseColor = Color3.FromArray(properties.baseColorFactor);\r\n                adapter.geometryOpacity = properties.baseColorFactor[3];\r\n            } else {\r\n                adapter.baseColor = Color3.White();\r\n            }\r\n\r\n            // Set metallic and roughness using adapter\r\n            adapter.baseMetalness = properties.metallicFactor == undefined ? 1 : properties.metallicFactor;\r\n            adapter.specularRoughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;\r\n\r\n            if (properties.baseColorTexture) {\r\n                promises.push(\r\n                    this.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => {\r\n                        texture.name = `${babylonMaterial.name} (Base Color)`;\r\n                        adapter.baseColorTexture = texture;\r\n                    })\r\n                );\r\n            }\r\n\r\n            if (properties.metallicRoughnessTexture) {\r\n                properties.metallicRoughnessTexture.nonColorData = true;\r\n                promises.push(\r\n                    this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => {\r\n                        texture.name = `${babylonMaterial.name} (Metallic Roughness)`;\r\n                        adapter.baseMetalnessTexture = texture;\r\n                        adapter.specularRoughnessTexture = texture;\r\n                    })\r\n                );\r\n\r\n                // Configure texture channel usage using adapter\r\n                adapter.useRoughnessFromMetallicTextureGreen = true;\r\n                adapter.useMetallicFromMetallicTextureBlue = true;\r\n            }\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadMaterialAsync(\r\n        context: string,\r\n        material: IMaterial,\r\n        babylonMesh: Nullable<Mesh>,\r\n        babylonDrawMode: number,\r\n        assign: (babylonMaterial: Material) => void = () => {}\r\n    ): Promise<Material> {\r\n        const extensionPromise = this._extensionsLoadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        material._data = material._data || {};\r\n        let babylonData = material._data[babylonDrawMode];\r\n        if (!babylonData) {\r\n            this.logOpen(`${context} ${material.name || \"\"}`);\r\n\r\n            const babylonMaterial = this.createMaterial(context, material, babylonDrawMode);\r\n\r\n            babylonData = {\r\n                babylonMaterial: babylonMaterial,\r\n                babylonMeshes: [],\r\n                promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial),\r\n            };\r\n\r\n            material._data[babylonDrawMode] = babylonData;\r\n\r\n            GLTFLoader.AddPointerMetadata(babylonMaterial, context);\r\n            this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);\r\n\r\n            this.logClose();\r\n        }\r\n\r\n        if (babylonMesh) {\r\n            babylonData.babylonMeshes.push(babylonMesh);\r\n\r\n            babylonMesh.onDisposeObservable.addOnce(() => {\r\n                const index = babylonData.babylonMeshes.indexOf(babylonMesh);\r\n                if (index !== -1) {\r\n                    babylonData.babylonMeshes.splice(index, 1);\r\n                }\r\n            });\r\n        }\r\n\r\n        assign(babylonData.babylonMaterial);\r\n\r\n        return babylonData.promise.then(() => {\r\n            return babylonData.babylonMaterial;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Selects the appropriate PBR material implementation for a given glTF material.\r\n     * Uses OpenPBR when the material carries a \"KHR_materials_openpbr\" extension or when\r\n     * the loader-level `useOpenPBR` flag is set; falls back to standard PBR otherwise.\r\n     * @param material The glTF material\r\n     * @returns The matching loaded implementation\r\n     */\r\n    private _selectImplForGltfMaterial(material: IMaterial): Readonly<PBRMaterialImplementation> {\r\n        if (this.parent.useOpenPBR || material.extensions?.[\"KHR_materials_openpbr\"]) {\r\n            const impl = this._pbrMaterialImpls.get(\"openpbr\");\r\n            if (impl) {\r\n                return impl;\r\n            }\r\n        }\r\n        const impl = this._pbrMaterialImpls.get(\"pbr\");\r\n        if (impl) {\r\n            return impl;\r\n        }\r\n        throw new Error(\"No PBR material implementation loaded\");\r\n    }\r\n\r\n    /**\r\n     * Returns the default PBR material implementation used when there is no per-material\r\n     * selection context (e.g. when creating the built-in default material for primitives\r\n     * that have no glTF material assigned).  Prefers OpenPBR when `useOpenPBR` is set.\r\n     * @returns The default loaded implementation\r\n     */\r\n    private _getDefaultImpl(): Readonly<PBRMaterialImplementation> {\r\n        if (this.parent.useOpenPBR) {\r\n            const impl = this._pbrMaterialImpls.get(\"openpbr\");\r\n            if (impl) {\r\n                return impl;\r\n            }\r\n        }\r\n        const impl = this._pbrMaterialImpls.get(\"pbr\") ?? this._pbrMaterialImpls.values().next().value;\r\n        if (impl) {\r\n            return impl;\r\n        }\r\n        throw new Error(\"No PBR material implementation loaded\");\r\n    }\r\n\r\n    private _createDefaultMaterial(name: string, babylonDrawMode: number, impl: Readonly<PBRMaterialImplementation>): Material {\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        const babylonMaterial = new impl.materialClass(name, this._babylonScene);\r\n        babylonMaterial._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n        babylonMaterial.fillMode = babylonDrawMode;\r\n        babylonMaterial.transparencyMode = impl.materialClass.MATERIAL_OPAQUE;\r\n        // Create the material adapter and set some default properties.\r\n        // We don't need to wait for the promise to resolve here.\r\n        const adapter = this._getOrCreateMaterialAdapter(babylonMaterial);\r\n        adapter.transparencyAsAlphaCoverage = this._parent.transparencyAsCoverage;\r\n\r\n        // Set default metallic and roughness values\r\n        adapter.baseMetalness = 1.0;\r\n        adapter.specularRoughness = 1.0;\r\n\r\n        return babylonMaterial;\r\n    }\r\n\r\n    /**\r\n     * Creates a Babylon material from a glTF material.\r\n     * @param context The context when loading the asset\r\n     * @param material The glTF material property\r\n     * @param babylonDrawMode The draw mode for the Babylon material\r\n     * @returns The Babylon material\r\n     */\r\n    public createMaterial(context: string, material: IMaterial, babylonDrawMode: number): Material {\r\n        const extensionMaterial = this._extensionsCreateMaterial(context, material, babylonDrawMode);\r\n        if (extensionMaterial) {\r\n            return extensionMaterial;\r\n        }\r\n\r\n        const name = material.name || `material${material.index}`;\r\n        const babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode, this._selectImplForGltfMaterial(material));\r\n\r\n        return babylonMaterial;\r\n    }\r\n\r\n    /**\r\n     * Loads properties from a glTF material into a Babylon material.\r\n     * @param context The context when loading the asset\r\n     * @param material The glTF material property\r\n     * @param babylonMaterial The Babylon material\r\n     * @returns A promise that resolves when the load is complete\r\n     */\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<void> {\r\n        const extensionPromise = this._extensionsLoadMaterialPropertiesAsync(context, material, babylonMaterial);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        promises.push(this.loadMaterialBasePropertiesAsync(context, material, babylonMaterial));\r\n\r\n        if (material.pbrMetallicRoughness) {\r\n            promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(`${context}/pbrMetallicRoughness`, material.pbrMetallicRoughness, babylonMaterial));\r\n        }\r\n\r\n        this.loadMaterialAlphaProperties(context, material, babylonMaterial);\r\n\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n\r\n    /**\r\n     * Loads the normal, occlusion, and emissive properties from a glTF material into a Babylon material.\r\n     * @param context The context when loading the asset\r\n     * @param material The glTF material property\r\n     * @param babylonMaterial The Babylon material\r\n     * @returns A promise that resolves when the load is complete\r\n     */\r\n    public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<void> {\r\n        const promises = new Array<Promise<unknown>>();\r\n        const adapter = this._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n        // Set emission color using adapter\r\n        adapter.emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);\r\n\r\n        // Set double-sided properties using adapter\r\n        if (material.doubleSided) {\r\n            adapter.backFaceCulling = false;\r\n            adapter.twoSidedLighting = true;\r\n        }\r\n\r\n        if (material.normalTexture) {\r\n            material.normalTexture.nonColorData = true;\r\n            promises.push(\r\n                this.loadTextureInfoAsync(`${context}/normalTexture`, material.normalTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Normal)`;\r\n                    adapter.geometryNormalTexture = texture;\r\n                    if (material.normalTexture?.scale != undefined) {\r\n                        texture.level = material.normalTexture.scale;\r\n                    }\r\n                })\r\n            );\r\n\r\n            // Set normal map inversions using adapter\r\n            adapter.setNormalMapInversions(!this._babylonScene.useRightHandedSystem, this._babylonScene.useRightHandedSystem);\r\n        }\r\n\r\n        let aoTexture: BaseTexture;\r\n        let aoStrength: number = 1.0;\r\n        let emissionTexture: BaseTexture;\r\n\r\n        if (material.occlusionTexture) {\r\n            material.occlusionTexture.nonColorData = true;\r\n            promises.push(\r\n                this.loadTextureInfoAsync(`${context}/occlusionTexture`, material.occlusionTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Occlusion)`;\r\n                    aoTexture = texture;\r\n                })\r\n            );\r\n\r\n            if (material.occlusionTexture.strength != undefined) {\r\n                aoStrength = material.occlusionTexture.strength;\r\n            }\r\n        }\r\n\r\n        if (material.emissiveTexture) {\r\n            promises.push(\r\n                this.loadTextureInfoAsync(`${context}/emissiveTexture`, material.emissiveTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Emissive)`;\r\n                    emissionTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {\r\n            // Set ambient occlusion and emissive textures using adapter\r\n            if (aoTexture) {\r\n                adapter.ambientOcclusionTexture = aoTexture;\r\n                adapter.ambientOcclusionTextureStrength = aoStrength;\r\n            }\r\n\r\n            if (emissionTexture) {\r\n                adapter.emissionColorTexture = emissionTexture;\r\n            }\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Loads the alpha properties from a glTF material into a Babylon material.\r\n     * Must be called after the setting the albedo texture of the Babylon material when the material has an albedo texture.\r\n     * @param context The context when loading the asset\r\n     * @param material The glTF material property\r\n     * @param babylonMaterial The Babylon material\r\n     */\r\n    public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void {\r\n        if (this._pbrMaterialImpls.size === 0) {\r\n            throw new Error(`${context}: Material type not supported`);\r\n        }\r\n\r\n        const adapter = this._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const baseColorTexture = adapter.baseColorTexture;\r\n\r\n        const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE;\r\n        switch (alphaMode) {\r\n            case MaterialAlphaMode.OPAQUE: {\r\n                babylonMaterial.transparencyMode = Material.MATERIAL_OPAQUE;\r\n                babylonMaterial.alpha = 1.0; // Force alpha to 1.0 for opaque mode.\r\n                break;\r\n            }\r\n            case MaterialAlphaMode.MASK: {\r\n                babylonMaterial.transparencyMode = Material.MATERIAL_ALPHATEST;\r\n                adapter.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff;\r\n                if (baseColorTexture) {\r\n                    baseColorTexture.hasAlpha = true;\r\n                    adapter.useAlphaFromBaseColorTexture = true;\r\n                }\r\n                break;\r\n            }\r\n            case MaterialAlphaMode.BLEND: {\r\n                babylonMaterial.transparencyMode = Material.MATERIAL_ALPHABLEND;\r\n                if (baseColorTexture) {\r\n                    baseColorTexture.hasAlpha = true;\r\n                    adapter.useAlphaFromBaseColorTexture = true;\r\n                }\r\n                break;\r\n            }\r\n            default: {\r\n                throw new Error(`${context}/alphaMode: Invalid value (${material.alphaMode})`);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF texture info.\r\n     * @param context The context when loading the asset\r\n     * @param textureInfo The glTF texture info property\r\n     * @param assign A function called synchronously after parsing the glTF properties\r\n     * @returns A promise that resolves with the loaded Babylon texture when the load is complete\r\n     */\r\n    public loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void = () => {}): Promise<BaseTexture> {\r\n        const extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);\r\n        if (extensionPromise) {\r\n            return extensionPromise.then((babylonTexture) => {\r\n                const texture = this._gltf.textures?.[textureInfo.index];\r\n                if (texture) {\r\n                    this._trackTexture(texture, babylonTexture);\r\n                }\r\n                return babylonTexture;\r\n            });\r\n        }\r\n\r\n        this.logOpen(`${context}`);\r\n\r\n        if (textureInfo.texCoord! >= 6) {\r\n            throw new Error(`${context}/texCoord: Invalid value (${textureInfo.texCoord})`);\r\n        }\r\n\r\n        const texture = ArrayItem.Get(`${context}/index`, this._gltf.textures, textureInfo.index);\r\n        texture._textureInfo = textureInfo;\r\n\r\n        const promise = this._loadTextureAsync(`/textures/${textureInfo.index}`, texture, (babylonTexture) => {\r\n            babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;\r\n            GLTFLoader.AddPointerMetadata(babylonTexture, context);\r\n            this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);\r\n            assign(babylonTexture);\r\n        });\r\n\r\n        this.logClose();\r\n\r\n        return promise;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void = () => {}): Promise<BaseTexture> {\r\n        const trackAndAssign = (babylonTexture: BaseTexture) => {\r\n            this._trackTexture(texture, babylonTexture);\r\n            assign(babylonTexture);\r\n        };\r\n        const extensionPromise = this._extensionsLoadTextureAsync(context, texture, trackAndAssign);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        this.logOpen(`${context} ${texture.name || \"\"}`);\r\n\r\n        const sampler = texture.sampler == undefined ? GLTFLoader.DefaultSampler : ArrayItem.Get(`${context}/sampler`, this._gltf.samplers, texture.sampler);\r\n        const image = ArrayItem.Get(`${context}/source`, this._gltf.images, texture.source);\r\n        const promise = this._createTextureAsync(context, sampler, image, trackAndAssign, undefined, !texture._textureInfo.nonColorData, texture);\r\n\r\n        this.logClose();\r\n\r\n        return promise;\r\n    }\r\n\r\n    private _trackTexture(texture: ITexture, babylonTexture: BaseTexture, imageIndex?: number, samplerIndex?: number): void {\r\n        texture._babylonTextures ||= [];\r\n        if (!texture._babylonTextures.includes(babylonTexture)) {\r\n            texture._babylonTextures.push(babylonTexture);\r\n        }\r\n        texture._babylonTextureSources ||= [];\r\n        const existing = texture._babylonTextureSources.find((source) => source.babylonTexture === babylonTexture);\r\n        const fallback = texture._babylonTextureSources[texture._babylonTextureSources.length - 1];\r\n        const resolvedImageIndex = imageIndex ?? existing?.imageIndex ?? fallback?.imageIndex;\r\n        if (resolvedImageIndex === undefined) {\r\n            return;\r\n        }\r\n        if (existing) {\r\n            existing.imageIndex = resolvedImageIndex;\r\n            existing.samplerIndex = samplerIndex ?? existing.samplerIndex ?? fallback?.samplerIndex;\r\n        } else {\r\n            texture._babylonTextureSources.push({\r\n                babylonTexture,\r\n                imageIndex: resolvedImageIndex,\r\n                samplerIndex: samplerIndex ?? fallback?.samplerIndex,\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public _createTextureAsync(\r\n        context: string,\r\n        sampler: ISampler,\r\n        image: IImage,\r\n        assign: (babylonTexture: BaseTexture) => void = () => {},\r\n        textureLoaderOptions?: unknown,\r\n        useSRGBBuffer?: boolean,\r\n        sourceTexture?: ITexture\r\n    ): Promise<BaseTexture> {\r\n        const samplerData = this._loadSampler(`/samplers/${sampler.index}`, sampler);\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        const deferred = new Deferred<void>();\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        const textureCreationOptions: ITextureCreationOptions = {\r\n            noMipmap: samplerData.noMipMaps,\r\n            invertY: false,\r\n            samplingMode: samplerData.samplingMode,\r\n            onLoad: () => {\r\n                if (!this._disposed) {\r\n                    deferred.resolve();\r\n                }\r\n            },\r\n            onError: (message?: string, exception?: any) => {\r\n                if (!this._disposed) {\r\n                    deferred.reject(new Error(`${context}: ${exception && exception.message ? exception.message : message || \"Failed to load texture\"}`));\r\n                }\r\n            },\r\n            mimeType: image.mimeType ?? GetMimeType(image.uri ?? \"\"),\r\n            loaderOptions: textureLoaderOptions,\r\n            useSRGBBuffer: !!useSRGBBuffer && this._parent.useSRGBBuffers,\r\n        };\r\n        const babylonTexture = new Texture(null, this._babylonScene, textureCreationOptions);\r\n        if (sourceTexture) {\r\n            this._trackTexture(sourceTexture, babylonTexture, image.index, sampler.index >= 0 ? sampler.index : undefined);\r\n        }\r\n        babylonTexture._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n        promises.push(deferred.promise);\r\n\r\n        const nonBase64Uri = image.uri && !IsBase64DataUrl(image.uri) ? image.uri : undefined;\r\n        const imageId = nonBase64Uri ?? `${this._fileName}#image${image.index}`;\r\n\r\n        promises.push(\r\n            this.loadImageAsync(`/images/${image.index}`, image).then((data) => {\r\n                const dataUrl = `data:${this._uniqueRootUrl}${imageId}`;\r\n                babylonTexture.updateURL(dataUrl, data);\r\n\r\n                // Set the internal texture label.\r\n                const internalTexture = babylonTexture.getInternalTexture();\r\n                if (internalTexture) {\r\n                    internalTexture.label = image.name;\r\n                }\r\n            })\r\n        );\r\n\r\n        babylonTexture.wrapU = samplerData.wrapU;\r\n        babylonTexture.wrapV = samplerData.wrapV;\r\n        assign(babylonTexture);\r\n\r\n        if (this._parent.useGltfTextureNames) {\r\n            const textureName = image.name || nonBase64Uri || `image${image.index}`;\r\n            babylonTexture.name = textureName;\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {\r\n            return babylonTexture;\r\n        });\r\n    }\r\n\r\n    private _loadSampler(context: string, sampler: ISampler): _ISamplerData {\r\n        if (!sampler._data) {\r\n            sampler._data = {\r\n                noMipMaps: sampler.minFilter === TextureMinFilter.NEAREST || sampler.minFilter === TextureMinFilter.LINEAR,\r\n                samplingMode: GLTFLoader._GetTextureSamplingMode(context, sampler),\r\n                wrapU: GLTFLoader._GetTextureWrapMode(`${context}/wrapS`, sampler.wrapS),\r\n                wrapV: GLTFLoader._GetTextureWrapMode(`${context}/wrapT`, sampler.wrapT),\r\n            };\r\n        }\r\n\r\n        return sampler._data;\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF image.\r\n     * @param context The context when loading the asset\r\n     * @param image The glTF image property\r\n     * @returns A promise that resolves with the loaded data when the load is complete\r\n     */\r\n    public loadImageAsync(context: string, image: IImage): Promise<ArrayBufferView> {\r\n        if (!image._data) {\r\n            this.logOpen(`${context} ${image.name || \"\"}`);\r\n\r\n            if (image.uri) {\r\n                image._data = this.loadUriAsync(`${context}/uri`, image, image.uri);\r\n            } else {\r\n                const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, image.bufferView);\r\n                image._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView);\r\n            }\r\n\r\n            this.logClose();\r\n        }\r\n\r\n        return image._data;\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF uri.\r\n     * @param context The context when loading the asset\r\n     * @param property The glTF property associated with the uri\r\n     * @param uri The base64 or relative uri\r\n     * @returns A promise that resolves with the loaded data when the load is complete\r\n     */\r\n    public loadUriAsync(context: string, property: IProperty, uri: string): Promise<ArrayBufferView> {\r\n        const extensionPromise = this._extensionsLoadUriAsync(context, property, uri);\r\n        if (extensionPromise) {\r\n            return extensionPromise;\r\n        }\r\n\r\n        if (!this._parent._isPreprocessUrlAsyncSet && !GLTFLoader._ValidateUri(uri)) {\r\n            throw new Error(`${context}: '${uri}' is invalid`);\r\n        }\r\n\r\n        if (IsBase64DataUrl(uri)) {\r\n            const data = new Uint8Array(DecodeBase64UrlToBinary(uri));\r\n            this.log(`${context}: Decoded ${uri.substring(0, 64)}... (${data.length} bytes)`);\r\n            return Promise.resolve(data);\r\n        }\r\n\r\n        this.log(`${context}: Loading ${uri}`);\r\n\r\n        return this._parent.preprocessUrlAsync(this._rootUrl + uri, this._rootUrl ?? undefined).then((url) => {\r\n            return new Promise((resolve, reject) => {\r\n                this._parent._loadFile(\r\n                    this._babylonScene,\r\n                    url,\r\n                    (data) => {\r\n                        if (!this._disposed) {\r\n                            this.log(`${context}: Loaded ${uri} (${(data as ArrayBuffer).byteLength} bytes)`);\r\n                            resolve(new Uint8Array(data as ArrayBuffer));\r\n                        }\r\n                    },\r\n                    true,\r\n                    (request) => {\r\n                        reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? \": \" + request.status + \" \" + request.statusText : \"\"}`, request));\r\n                    }\r\n                );\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Adds a JSON pointer to the _internalMetadata of the Babylon object at `<object>._internalMetadata.gltf.pointers`.\r\n     * @param babylonObject the Babylon object with _internalMetadata\r\n     * @param pointer the JSON pointer\r\n     */\r\n    public static AddPointerMetadata(babylonObject: IWithMetadata, pointer: string): void {\r\n        babylonObject.metadata = babylonObject.metadata || {};\r\n        const metadata = (babylonObject._internalMetadata = babylonObject._internalMetadata || {});\r\n        const gltf = (metadata.gltf = metadata.gltf || {});\r\n        const pointers = (gltf.pointers = gltf.pointers || []);\r\n        pointers.push(pointer);\r\n    }\r\n\r\n    private static _GetTextureWrapMode(context: string, mode: TextureWrapMode | undefined): number {\r\n        // Set defaults if undefined\r\n        mode = mode == undefined ? TextureWrapMode.REPEAT : mode;\r\n\r\n        switch (mode) {\r\n            case TextureWrapMode.CLAMP_TO_EDGE:\r\n                return Texture.CLAMP_ADDRESSMODE;\r\n            case TextureWrapMode.MIRRORED_REPEAT:\r\n                return Texture.MIRROR_ADDRESSMODE;\r\n            case TextureWrapMode.REPEAT:\r\n                return Texture.WRAP_ADDRESSMODE;\r\n            default:\r\n                Logger.Warn(`${context}: Invalid value (${mode})`);\r\n                return Texture.WRAP_ADDRESSMODE;\r\n        }\r\n    }\r\n\r\n    private static _GetTextureSamplingMode(context: string, sampler: ISampler): number {\r\n        // Set defaults if undefined\r\n        const magFilter = sampler.magFilter == undefined ? TextureMagFilter.LINEAR : sampler.magFilter;\r\n        const minFilter = sampler.minFilter == undefined ? TextureMinFilter.LINEAR_MIPMAP_LINEAR : sampler.minFilter;\r\n\r\n        if (magFilter === TextureMagFilter.LINEAR) {\r\n            switch (minFilter) {\r\n                case TextureMinFilter.NEAREST:\r\n                    return Texture.LINEAR_NEAREST;\r\n                case TextureMinFilter.LINEAR:\r\n                    return Texture.LINEAR_LINEAR;\r\n                case TextureMinFilter.NEAREST_MIPMAP_NEAREST:\r\n                    return Texture.LINEAR_NEAREST_MIPNEAREST;\r\n                case TextureMinFilter.LINEAR_MIPMAP_NEAREST:\r\n                    return Texture.LINEAR_LINEAR_MIPNEAREST;\r\n                case TextureMinFilter.NEAREST_MIPMAP_LINEAR:\r\n                    return Texture.LINEAR_NEAREST_MIPLINEAR;\r\n                case TextureMinFilter.LINEAR_MIPMAP_LINEAR:\r\n                    return Texture.LINEAR_LINEAR_MIPLINEAR;\r\n                default:\r\n                    Logger.Warn(`${context}/minFilter: Invalid value (${minFilter})`);\r\n                    return Texture.LINEAR_LINEAR_MIPLINEAR;\r\n            }\r\n        } else {\r\n            if (magFilter !== TextureMagFilter.NEAREST) {\r\n                Logger.Warn(`${context}/magFilter: Invalid value (${magFilter})`);\r\n            }\r\n\r\n            switch (minFilter) {\r\n                case TextureMinFilter.NEAREST:\r\n                    return Texture.NEAREST_NEAREST;\r\n                case TextureMinFilter.LINEAR:\r\n                    return Texture.NEAREST_LINEAR;\r\n                case TextureMinFilter.NEAREST_MIPMAP_NEAREST:\r\n                    return Texture.NEAREST_NEAREST_MIPNEAREST;\r\n                case TextureMinFilter.LINEAR_MIPMAP_NEAREST:\r\n                    return Texture.NEAREST_LINEAR_MIPNEAREST;\r\n                case TextureMinFilter.NEAREST_MIPMAP_LINEAR:\r\n                    return Texture.NEAREST_NEAREST_MIPLINEAR;\r\n                case TextureMinFilter.LINEAR_MIPMAP_LINEAR:\r\n                    return Texture.NEAREST_LINEAR_MIPLINEAR;\r\n                default:\r\n                    Logger.Warn(`${context}/minFilter: Invalid value (${minFilter})`);\r\n                    return Texture.NEAREST_NEAREST_MIPNEAREST;\r\n            }\r\n        }\r\n    }\r\n\r\n    private static _GetTypedArrayConstructor(context: string, componentType: AccessorComponentType): TypedArrayConstructor {\r\n        try {\r\n            return GetTypedArrayConstructor(componentType);\r\n        } catch (e) {\r\n            throw new Error(`${context}: ${e.message}`, { cause: e });\r\n        }\r\n    }\r\n\r\n    private static _GetTypedArray(context: string, componentType: AccessorComponentType, bufferView: ArrayBufferView, byteOffset: number | undefined, length: number): TypedArray {\r\n        const buffer = bufferView.buffer;\r\n        byteOffset = bufferView.byteOffset + (byteOffset || 0);\r\n\r\n        const constructor = GLTFLoader._GetTypedArrayConstructor(`${context}/componentType`, componentType);\r\n\r\n        const componentTypeLength = VertexBufferGetTypeByteLength(componentType);\r\n        if (byteOffset % componentTypeLength !== 0) {\r\n            // HACK: Copy the buffer if byte offset is not a multiple of component type byte length.\r\n            Logger.Warn(`${context}: Copying buffer as byte offset (${byteOffset}) is not a multiple of component type byte length (${componentTypeLength})`);\r\n            return new constructor(buffer.slice(byteOffset, byteOffset + length * componentTypeLength), 0);\r\n        }\r\n\r\n        return new constructor(buffer, byteOffset, length);\r\n    }\r\n\r\n    private static _GetNumComponents(context: string, type: string): number {\r\n        switch (type) {\r\n            case \"SCALAR\":\r\n                return 1;\r\n            case \"VEC2\":\r\n                return 2;\r\n            case \"VEC3\":\r\n                return 3;\r\n            case \"VEC4\":\r\n                return 4;\r\n            case \"MAT2\":\r\n                return 4;\r\n            case \"MAT3\":\r\n                return 9;\r\n            case \"MAT4\":\r\n                return 16;\r\n        }\r\n\r\n        throw new Error(`${context}: Invalid type (${type})`);\r\n    }\r\n\r\n    private static _ValidateUri(uri: string): boolean {\r\n        return Tools.IsBase64(uri) || uri.indexOf(\"..\") === -1;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public static _GetDrawMode(context: string, mode: number | undefined): number {\r\n        if (mode == undefined) {\r\n            mode = MeshPrimitiveMode.TRIANGLES;\r\n        }\r\n\r\n        switch (mode) {\r\n            case MeshPrimitiveMode.POINTS:\r\n                return Material.PointListDrawMode;\r\n            case MeshPrimitiveMode.LINES:\r\n                return Material.LineListDrawMode;\r\n            case MeshPrimitiveMode.LINE_LOOP:\r\n                return Material.LineLoopDrawMode;\r\n            case MeshPrimitiveMode.LINE_STRIP:\r\n                return Material.LineStripDrawMode;\r\n            case MeshPrimitiveMode.TRIANGLES:\r\n                return Material.TriangleFillMode;\r\n            case MeshPrimitiveMode.TRIANGLE_STRIP:\r\n                return Material.TriangleStripDrawMode;\r\n            case MeshPrimitiveMode.TRIANGLE_FAN:\r\n                return Material.TriangleFanDrawMode;\r\n        }\r\n\r\n        throw new Error(`${context}: Invalid mesh primitive mode (${mode})`);\r\n    }\r\n\r\n    private _compileMaterialsAsync(): Promise<void> {\r\n        this._parent._startPerformanceCounter(\"Compile materials\");\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        if (this._gltf.materials) {\r\n            for (const material of this._gltf.materials) {\r\n                if (material._data) {\r\n                    for (const babylonDrawMode in material._data) {\r\n                        const babylonData = material._data[babylonDrawMode];\r\n                        for (const babylonMesh of babylonData.babylonMeshes) {\r\n                            // Ensure nonUniformScaling is set if necessary.\r\n                            babylonMesh.computeWorldMatrix(true);\r\n\r\n                            const babylonMaterial = babylonData.babylonMaterial;\r\n                            promises.push(babylonMaterial.forceCompilationAsync(babylonMesh));\r\n                            promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { useInstances: true }));\r\n                            if (this._parent.useClipPlane) {\r\n                                promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true }));\r\n                                promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true, useInstances: true }));\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {\r\n            this._parent._endPerformanceCounter(\"Compile materials\");\r\n        });\r\n    }\r\n\r\n    private _compileShadowGeneratorsAsync(): Promise<void> {\r\n        this._parent._startPerformanceCounter(\"Compile shadow generators\");\r\n\r\n        const promises = new Array<Promise<unknown>>();\r\n\r\n        const lights = this._babylonScene.lights;\r\n        for (const light of lights) {\r\n            const generator = light.getShadowGenerator();\r\n            if (generator) {\r\n                promises.push(generator.forceCompilationAsync());\r\n            }\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {\r\n            this._parent._endPerformanceCounter(\"Compile shadow generators\");\r\n        });\r\n    }\r\n\r\n    private _forEachExtensions(action: (extension: IGLTFLoaderExtension) => void): void {\r\n        for (const extension of this._extensions) {\r\n            if (extension.enabled) {\r\n                action(extension);\r\n            }\r\n        }\r\n    }\r\n\r\n    private _applyExtensions<T>(property: IProperty, functionName: string, actionAsync: (extension: IGLTFLoaderExtension) => Nullable<T> | undefined): Nullable<T> {\r\n        for (const extension of this._extensions) {\r\n            if (extension.enabled) {\r\n                const id = `${extension.name}.${functionName}`;\r\n                const loaderProperty = property as ILoaderProperty;\r\n                loaderProperty._activeLoaderExtensionFunctions = loaderProperty._activeLoaderExtensionFunctions || {};\r\n                const activeLoaderExtensionFunctions = loaderProperty._activeLoaderExtensionFunctions;\r\n                if (!activeLoaderExtensionFunctions[id]) {\r\n                    activeLoaderExtensionFunctions[id] = true;\r\n\r\n                    try {\r\n                        const result = actionAsync(extension);\r\n                        if (result) {\r\n                            return result;\r\n                        }\r\n                    } finally {\r\n                        delete activeLoaderExtensionFunctions[id];\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        return null;\r\n    }\r\n\r\n    private _extensionsOnLoading(): void {\r\n        this._forEachExtensions((extension) => extension.onLoading && extension.onLoading());\r\n    }\r\n\r\n    private async _extensionsOnReadyAsync(): Promise<void> {\r\n        for (const extension of this._extensions) {\r\n            if (extension.enabled && extension.onReady) {\r\n                // eslint-disable-next-line no-await-in-loop -- extension order can define readiness dependencies\r\n                await extension.onReady();\r\n            }\r\n        }\r\n    }\r\n\r\n    private _extensionsLoadSceneAsync(context: string, scene: IScene): Nullable<Promise<void>> {\r\n        return this._applyExtensions(scene, \"loadScene\", (extension) => extension.loadSceneAsync && extension.loadSceneAsync(context, scene));\r\n    }\r\n\r\n    private _extensionsLoadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return this._applyExtensions(node, \"loadNode\", (extension) => extension.loadNodeAsync && extension.loadNodeAsync(context, node, assign));\r\n    }\r\n\r\n    private _extensionsLoadCameraAsync(context: string, camera: ICamera, assign: (babylonCamera: Camera) => void): Nullable<Promise<Camera>> {\r\n        return this._applyExtensions(camera, \"loadCamera\", (extension) => extension.loadCameraAsync && extension.loadCameraAsync(context, camera, assign));\r\n    }\r\n\r\n    private _extensionsLoadVertexDataAsync(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {\r\n        return this._applyExtensions(primitive, \"loadVertexData\", (extension) => extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh));\r\n    }\r\n\r\n    private _extensionsLoadMeshPrimitiveAsync(\r\n        context: string,\r\n        name: string,\r\n        node: INode,\r\n        mesh: IMesh,\r\n        primitive: IMeshPrimitive,\r\n        assign: (babylonMesh: AbstractMesh) => void\r\n    ): Nullable<Promise<AbstractMesh>> {\r\n        return this._applyExtensions(\r\n            primitive,\r\n            \"loadMeshPrimitive\",\r\n            (extension) => extension._loadMeshPrimitiveAsync && extension._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign)\r\n        );\r\n    }\r\n\r\n    private _extensionsLoadMaterialAsync(\r\n        context: string,\r\n        material: IMaterial,\r\n        babylonMesh: Nullable<Mesh>,\r\n        babylonDrawMode: number,\r\n        assign: (babylonMaterial: Material) => void\r\n    ): Nullable<Promise<Material>> {\r\n        return this._applyExtensions(\r\n            material,\r\n            \"loadMaterial\",\r\n            (extension) => extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign)\r\n        );\r\n    }\r\n\r\n    private _extensionsCreateMaterial(context: string, material: IMaterial, babylonDrawMode: number): Nullable<Material> {\r\n        return this._applyExtensions(material, \"createMaterial\", (extension) => extension.createMaterial && extension.createMaterial(context, material, babylonDrawMode));\r\n    }\r\n\r\n    private _extensionsLoadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return this._applyExtensions(\r\n            material,\r\n            \"loadMaterialProperties\",\r\n            (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial)\r\n        );\r\n    }\r\n\r\n    private _extensionsLoadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {\r\n        return this._applyExtensions(textureInfo, \"loadTextureInfo\", (extension) => extension.loadTextureInfoAsync && extension.loadTextureInfoAsync(context, textureInfo, assign));\r\n    }\r\n\r\n    private _extensionsLoadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {\r\n        return this._applyExtensions(texture, \"loadTexture\", (extension) => extension._loadTextureAsync && extension._loadTextureAsync(context, texture, assign));\r\n    }\r\n\r\n    private _extensionsLoadAnimationAsync(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>> {\r\n        return this._applyExtensions(animation, \"loadAnimation\", (extension) => extension.loadAnimationAsync && extension.loadAnimationAsync(context, animation));\r\n    }\r\n\r\n    private _extensionsLoadAnimationChannelAsync(\r\n        context: string,\r\n        animationContext: string,\r\n        animation: IAnimation,\r\n        channel: IAnimationChannel,\r\n        onLoad: (babylonAnimatable: IAnimatable, babylonAnimation: Animation) => void\r\n    ): Nullable<Promise<void>> {\r\n        return this._applyExtensions(\r\n            animation,\r\n            \"loadAnimationChannel\",\r\n            (extension) => extension._loadAnimationChannelAsync && extension._loadAnimationChannelAsync(context, animationContext, animation, channel, onLoad)\r\n        );\r\n    }\r\n\r\n    private _extensionsLoadSkinAsync(context: string, node: INode, skin: ISkin): Nullable<Promise<void>> {\r\n        return this._applyExtensions(skin, \"loadSkin\", (extension) => extension._loadSkinAsync && extension._loadSkinAsync(context, node, skin));\r\n    }\r\n\r\n    private _extensionsLoadUriAsync(context: string, property: IProperty, uri: string): Nullable<Promise<ArrayBufferView>> {\r\n        return this._applyExtensions(property, \"loadUri\", (extension) => extension._loadUriAsync && extension._loadUriAsync(context, property, uri));\r\n    }\r\n\r\n    private _extensionsLoadBufferViewAsync(context: string, bufferView: IBufferView): Nullable<Promise<ArrayBufferView>> {\r\n        return this._applyExtensions(bufferView, \"loadBufferView\", (extension) => extension.loadBufferViewAsync && extension.loadBufferViewAsync(context, bufferView));\r\n    }\r\n\r\n    private _extensionsLoadBufferAsync(context: string, buffer: IBuffer, byteOffset: number, byteLength: number): Nullable<Promise<ArrayBufferView>> {\r\n        return this._applyExtensions(buffer, \"loadBuffer\", (extension) => extension.loadBufferAsync && extension.loadBufferAsync(context, buffer, byteOffset, byteLength));\r\n    }\r\n\r\n    /**\r\n     * Helper method called by a loader extension to load an glTF extension.\r\n     * @param context The context when loading the asset\r\n     * @param property The glTF property to load the extension from\r\n     * @param extensionName The name of the extension to load\r\n     * @param actionAsync The action to run\r\n     * @returns The promise returned by actionAsync or null if the extension does not exist\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/naming-convention\r\n    public static LoadExtensionAsync<TExtension = unknown, TResult = void>(\r\n        context: string,\r\n        property: IProperty,\r\n        extensionName: string,\r\n        actionAsync: (extensionContext: string, extension: TExtension) => Nullable<Promise<TResult>>\r\n    ): Nullable<Promise<TResult>> {\r\n        if (!property.extensions) {\r\n            return null;\r\n        }\r\n\r\n        const extensions = property.extensions;\r\n\r\n        const extension = extensions[extensionName] as TExtension;\r\n        if (!extension) {\r\n            return null;\r\n        }\r\n\r\n        return actionAsync(`${context}/extensions/${extensionName}`, extension);\r\n    }\r\n\r\n    /**\r\n     * Helper method called by a loader extension to load a glTF extra.\r\n     * @param context The context when loading the asset\r\n     * @param property The glTF property to load the extra from\r\n     * @param extensionName The name of the extension to load\r\n     * @param actionAsync The action to run\r\n     * @returns The promise returned by actionAsync or null if the extra does not exist\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/naming-convention\r\n    public static LoadExtraAsync<TExtra = unknown, TResult = void>(\r\n        context: string,\r\n        property: IProperty,\r\n        extensionName: string,\r\n        actionAsync: (extraContext: string, extra: TExtra) => Nullable<Promise<TResult>>\r\n    ): Nullable<Promise<TResult>> {\r\n        if (!property.extras) {\r\n            return null;\r\n        }\r\n\r\n        const extras = property.extras;\r\n\r\n        const extra = extras[extensionName] as TExtra;\r\n        if (!extra) {\r\n            return null;\r\n        }\r\n\r\n        return actionAsync(`${context}/extras/${extensionName}`, extra);\r\n    }\r\n\r\n    /**\r\n     * Checks for presence of an extension.\r\n     * @param name The name of the extension to check\r\n     * @returns A boolean indicating the presence of the given extension name in `extensionsUsed`\r\n     */\r\n    public isExtensionUsed(name: string): boolean {\r\n        return !!this._gltf.extensionsUsed && this._gltf.extensionsUsed.indexOf(name) !== -1;\r\n    }\r\n\r\n    /**\r\n     * Increments the indentation level and logs a message.\r\n     * @param message The message to log\r\n     */\r\n    public logOpen(message: string): void {\r\n        this._parent._logOpen(message);\r\n    }\r\n\r\n    /**\r\n     * Decrements the indentation level.\r\n     */\r\n    public logClose(): void {\r\n        this._parent._logClose();\r\n    }\r\n\r\n    /**\r\n     * Logs a message\r\n     * @param message The message to log\r\n     */\r\n    public log(message: string): void {\r\n        this._parent._log(message);\r\n    }\r\n\r\n    /**\r\n     * Starts a performance counter.\r\n     * @param counterName The name of the performance counter\r\n     */\r\n    public startPerformanceCounter(counterName: string): void {\r\n        this._parent._startPerformanceCounter(counterName);\r\n    }\r\n\r\n    /**\r\n     * Ends a performance counter.\r\n     * @param counterName The name of the performance counter\r\n     */\r\n    public endPerformanceCounter(counterName: string): void {\r\n        this._parent._endPerformanceCounter(counterName);\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n\r\n/**\r\n * Registers the GLTF 2.0 loader factory on the GLTFFileLoader. Idempotent.\r\n * @internal\r\n */\r\nexport function RegisterGLTF2Loader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n    GLTFFileLoader._CreateGLTF2Loader = (parent) => new GLTFLoader(parent);\r\n}\r\n","/** This file must only contain pure code and pure imports */\r\n\r\nimport { Animation } from \"core/Animations/animation.pure\";\r\nimport { Quaternion, Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { type INode } from \"./glTFLoaderInterfaces\";\r\nimport { type IAnimatable } from \"core/Animations/animatable.interface\";\r\nimport { SetInterpolationForKey } from \"./Extensions/objectModelMapping\";\r\n\r\n/** @internal */\r\nexport type GetValueFn = (target: any, source: Float32Array, offset: number, scale: number) => any;\r\n\r\n/** @internal */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function getVector3(_target: any, source: Float32Array, offset: number, scale: number): Vector3 {\r\n    return Vector3.FromArray(source, offset).scaleInPlace(scale);\r\n}\r\n\r\n/** @internal */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function getQuaternion(_target: any, source: Float32Array, offset: number, scale: number): Quaternion {\r\n    return Quaternion.FromArray(source, offset).scaleInPlace(scale);\r\n}\r\n\r\n/** @internal */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function getWeights(target: INode, source: Float32Array, offset: number, scale: number): Array<number> {\r\n    const value = new Array<number>(target._numMorphTargets!);\r\n    for (let i = 0; i < value.length; i++) {\r\n        value[i] = source[offset++] * scale;\r\n    }\r\n\r\n    return value;\r\n}\r\n\r\n/** @internal */\r\nexport abstract class AnimationPropertyInfo {\r\n    /** @internal */\r\n    public constructor(\r\n        public readonly type: number,\r\n        public readonly name: string,\r\n        public readonly getValue: GetValueFn,\r\n        public readonly getStride: (target: any) => number\r\n    ) {}\r\n\r\n    protected _buildAnimation(name: string, fps: number, keys: any[]): Animation {\r\n        const babylonAnimation = new Animation(name, this.name, fps, this.type);\r\n        babylonAnimation.setKeys(keys, true);\r\n        return babylonAnimation;\r\n    }\r\n\r\n    /** @internal */\r\n    public abstract buildAnimations(target: any, name: string, fps: number, keys: any[]): { babylonAnimatable: IAnimatable; babylonAnimation: Animation }[];\r\n}\r\n\r\n/** @internal */\r\nexport class TransformNodeAnimationPropertyInfo extends AnimationPropertyInfo {\r\n    /** @internal */\r\n    public buildAnimations(target: INode, name: string, fps: number, keys: any[]) {\r\n        const babylonAnimations: { babylonAnimatable: IAnimatable; babylonAnimation: Animation }[] = [];\r\n        babylonAnimations.push({ babylonAnimatable: target._babylonTransformNode!, babylonAnimation: this._buildAnimation(name, fps, keys) });\r\n        return babylonAnimations;\r\n    }\r\n}\r\n\r\n/** @internal */\r\nexport class WeightAnimationPropertyInfo extends AnimationPropertyInfo {\r\n    public buildAnimations(target: INode, name: string, fps: number, keys: any[]) {\r\n        const babylonAnimations: { babylonAnimatable: IAnimatable; babylonAnimation: Animation }[] = [];\r\n        if (target._numMorphTargets) {\r\n            for (let targetIndex = 0; targetIndex < target._numMorphTargets; targetIndex++) {\r\n                const babylonAnimation = new Animation(`${name}_${targetIndex}`, this.name, fps, this.type);\r\n                babylonAnimation.setKeys(\r\n                    keys.map((key) => ({\r\n                        frame: key.frame,\r\n                        inTangent: key.inTangent ? key.inTangent[targetIndex] : undefined,\r\n                        value: key.value[targetIndex],\r\n                        outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined,\r\n                        interpolation: key.interpolation,\r\n                    })),\r\n                    true\r\n                );\r\n\r\n                if (target._primitiveBabylonMeshes) {\r\n                    for (const babylonMesh of target._primitiveBabylonMeshes) {\r\n                        if (babylonMesh.morphTargetManager) {\r\n                            const morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);\r\n                            const babylonAnimationClone = babylonAnimation.clone();\r\n                            morphTarget.animations.push(babylonAnimationClone);\r\n                            babylonAnimations.push({ babylonAnimatable: morphTarget, babylonAnimation: babylonAnimationClone });\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        return babylonAnimations;\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n\r\n/**\r\n * Registers the core glTF animation interpolation mappings.\r\n */\r\nexport function RegisterGLTFLoaderAnimation(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    SetInterpolationForKey(\"/nodes/{}/translation\", [new TransformNodeAnimationPropertyInfo(Animation.ANIMATIONTYPE_VECTOR3, \"position\", getVector3, () => 3)]);\r\n    SetInterpolationForKey(\"/nodes/{}/rotation\", [new TransformNodeAnimationPropertyInfo(Animation.ANIMATIONTYPE_QUATERNION, \"rotationQuaternion\", getQuaternion, () => 4)]);\r\n    SetInterpolationForKey(\"/nodes/{}/scale\", [new TransformNodeAnimationPropertyInfo(Animation.ANIMATIONTYPE_VECTOR3, \"scaling\", getVector3, () => 3)]);\r\n    SetInterpolationForKey(\"/nodes/{}/weights\", [new WeightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"influence\", getWeights, (target) => target._numMorphTargets!)]);\r\n}\r\n","export * from \"./glTFLoader.pure\";\n\nimport \"core/Meshes/instancedMesh\";\nimport { RegisterGLTF2Loader } from \"./glTFLoader.pure\";\nimport { RegisterGLTFFileLoader } from \"../glTFFileLoader.pure\";\n\nRegisterGLTF2Loader();\n\n// Auto-register the .gltf/.glb SceneLoader plugin so that importing\n// \"@babylonjs/loaders/glTF/2.0\" restores the pre-9.15 behavior of making\n// SceneLoader able to load glTF 2.0 assets. This registers the version-aware\n// GLTFFileLoader plugin only; it does not pull in the legacy glTF 1.0 loader.\nRegisterGLTFFileLoader();\n","export * from \"./glTFLoaderAnimation.pure\";\n\nimport { RegisterGLTFLoaderAnimation } from \"./glTFLoaderAnimation.pure\";\n\nRegisterGLTFLoaderAnimation();\n","import { type OpenPBRMaterial } from \"core/Materials/PBR/openpbrMaterial\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { Color3, Color4 } from \"core/Maths/math.color\";\r\nimport { type IMaterialLoadingAdapter } from \"./materialLoadingAdapter\";\r\nimport { type GLTFLoader } from \"./glTFLoader\";\r\nimport {\r\n    MultiplyTexturesAsync,\r\n    LerpTexturesAsync,\r\n    CreateTextureWithFactorOperand,\r\n    TextureChannel,\r\n    TextureColorSpace,\r\n    InvertTextureAsync,\r\n    ExtractChannelAsync,\r\n    ChannelMask,\r\n    ExtractMaxChannelAsync,\r\n} from \"core/Materials/Textures/textureProcessor\";\r\n\r\n/**\r\n * Material Loading Adapter for OpenPBR materials that provides a unified OpenPBR-like interface.\r\n */\r\nexport class OpenPBRMaterialLoadingAdapter implements IMaterialLoadingAdapter {\r\n    private _material: OpenPBRMaterial;\r\n    private _specWorkflow: boolean = false;\r\n    /**\r\n     * Creates a new instance of the OpenPBRMaterialLoadingAdapter.\r\n     * @param material - The OpenPBR material to adapt.\r\n     */\r\n    constructor(material: Material) {\r\n        this._material = material as OpenPBRMaterial;\r\n    }\r\n\r\n    /**\r\n     * Gets the underlying material\r\n     */\r\n    public get material(): OpenPBRMaterial {\r\n        return this._material;\r\n    }\r\n\r\n    /**\r\n     * Whether the material should be treated as unlit\r\n     */\r\n    public get isUnlit(): boolean {\r\n        return this._material.unlit;\r\n    }\r\n\r\n    /**\r\n     * Sets whether the material should be treated as unlit\r\n     */\r\n    public set isUnlit(value: boolean) {\r\n        this._material.unlit = value;\r\n    }\r\n\r\n    // ========================================\r\n    // CULLING PROPERTIES\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets whether back face culling is enabled.\r\n     * @param value True to enable back face culling\r\n     */\r\n    public set backFaceCulling(value: boolean) {\r\n        this._material.backFaceCulling = value;\r\n    }\r\n\r\n    /**\r\n     * Gets whether back face culling is enabled.\r\n     * @returns True if back face culling is enabled\r\n     */\r\n    public get backFaceCulling(): boolean {\r\n        return this._material.backFaceCulling;\r\n    }\r\n\r\n    /**\r\n     * Sets whether two-sided lighting is enabled.\r\n     * @param value True to enable two-sided lighting\r\n     */\r\n    public set twoSidedLighting(value: boolean) {\r\n        this._material.twoSidedLighting = value;\r\n    }\r\n\r\n    /**\r\n     * Gets whether two-sided lighting is enabled.\r\n     * @returns True if two-sided lighting is enabled\r\n     */\r\n    public get twoSidedLighting(): boolean {\r\n        return this._material.twoSidedLighting;\r\n    }\r\n\r\n    // ========================================\r\n    // ALPHA PROPERTIES\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the alpha cutoff value for alpha testing.\r\n     * Note: OpenPBR doesn't have a direct equivalent, so this is a no-op.\r\n     * @param value The alpha cutoff threshold (ignored for OpenPBR)\r\n     */\r\n    public set alphaCutOff(value: number) {\r\n        this._material.alphaCutOff = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the alpha cutoff value.\r\n     * @returns Default value of 0.5 (OpenPBR doesn't support this directly)\r\n     */\r\n    public get alphaCutOff(): number {\r\n        return this._material.alphaCutOff;\r\n    }\r\n\r\n    /**\r\n     * Sets whether to use alpha from the base color texture.\r\n     * Note: OpenPBR handles this differently through the baseColorTexture alpha channel.\r\n     * @param value True to use alpha from base color texture (handled automatically in OpenPBR)\r\n     */\r\n    public set useAlphaFromBaseColorTexture(value: boolean) {\r\n        this._material._useAlphaFromBaseColorTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets whether alpha is used from the base color texture.\r\n     * @returns True if alpha is used from the base color texture\r\n     */\r\n    public get useAlphaFromBaseColorTexture(): boolean {\r\n        return this._material._useAlphaFromBaseColorTexture;\r\n    }\r\n\r\n    /**\r\n     * Gets whether the transparency is treated as alpha coverage.\r\n     */\r\n    public get transparencyAsAlphaCoverage(): boolean {\r\n        // OpenPBR doesn't support treating transparency as alpha coverage.\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Sets/Gets whether the transparency is treated as alpha coverage\r\n     */\r\n    public set transparencyAsAlphaCoverage(value: boolean) {\r\n        // OpenPBR doesn't support treating transparency as alpha coverage.\r\n    }\r\n\r\n    // ========================================\r\n    // BASE PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the base color of the OpenPBR material.\r\n     * @param value The base color as a Color3\r\n     */\r\n    public set baseColor(value: Color3) {\r\n        this._material.baseColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base color of the OpenPBR material.\r\n     * @returns The base color as a Color3\r\n     */\r\n    public get baseColor(): Color3 {\r\n        return this._material.baseColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the base color texture of the OpenPBR material.\r\n     * @param value The base color texture or null\r\n     */\r\n    public set baseColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.baseColorTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base color texture of the OpenPBR material.\r\n     * @returns The base color texture or null\r\n     */\r\n    public get baseColorTexture(): Nullable<BaseTexture> {\r\n        return this._material.baseColorTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the base diffuse roughness of the OpenPBR material.\r\n     * @param value The diffuse roughness value (0-1)\r\n     */\r\n    public set baseDiffuseRoughness(value: number) {\r\n        this._material.baseDiffuseRoughness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base diffuse roughness of the OpenPBR material.\r\n     * @returns The diffuse roughness value (0-1)\r\n     */\r\n    public get baseDiffuseRoughness(): number {\r\n        return this._material.baseDiffuseRoughness;\r\n    }\r\n\r\n    /**\r\n     * Sets the base diffuse roughness texture of the OpenPBR material.\r\n     * @param value The diffuse roughness texture or null\r\n     */\r\n    public set baseDiffuseRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.baseDiffuseRoughnessTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base diffuse roughness texture of the OpenPBR material.\r\n     * @returns The diffuse roughness texture or null\r\n     */\r\n    public get baseDiffuseRoughnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.baseDiffuseRoughnessTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the base metalness value of the OpenPBR material.\r\n     * @param value The metalness value (0-1)\r\n     */\r\n    public set baseMetalness(value: number) {\r\n        this._material.baseMetalness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base metalness value of the OpenPBR material.\r\n     * @returns The metalness value (0-1)\r\n     */\r\n    public get baseMetalness(): number {\r\n        return this._material.baseMetalness;\r\n    }\r\n\r\n    /**\r\n     * Sets the base metalness texture of the OpenPBR material.\r\n     * @param value The metalness texture or null\r\n     */\r\n    public set baseMetalnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.baseMetalnessTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base metalness texture of the OpenPBR material.\r\n     * @returns The metalness texture or null\r\n     */\r\n    public get baseMetalnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.baseMetalnessTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets whether to use roughness from the metallic texture's green channel.\r\n     * @param value True to use green channel for roughness\r\n     */\r\n    public set useRoughnessFromMetallicTextureGreen(value: boolean) {\r\n        this._material._useRoughnessFromMetallicTextureGreen = value;\r\n    }\r\n\r\n    /**\r\n     * Sets whether to use metalness from the metallic texture's blue channel.\r\n     * @param value True to use blue channel for metalness\r\n     */\r\n    public set useMetallicFromMetallicTextureBlue(value: boolean) {\r\n        this._material._useMetallicFromMetallicTextureBlue = value;\r\n    }\r\n\r\n    // ========================================\r\n    // SPECULAR PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures specular properties for OpenPBR material.\r\n     * @param _enableEdgeColor Whether to enable edge color support (ignored for OpenPBR)\r\n     */\r\n    public enableSpecularEdgeColor(_enableEdgeColor: boolean = false): void {\r\n        // OpenPBR already supports edge color natively, no configuration needed\r\n    }\r\n\r\n    public configureSpecularGlossiness(): void {\r\n        this._specWorkflow = true;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular weight of the OpenPBR material.\r\n     * @param value The specular weight value (0-1)\r\n     */\r\n    public set specularWeight(value: number) {\r\n        this._material.specularWeight = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular weight of the OpenPBR material.\r\n     * @returns The specular weight value (0-1)\r\n     */\r\n    public get specularWeight(): number {\r\n        return this._material.specularWeight;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular weight texture of the OpenPBR material.\r\n     * If the same texture is used for specular color, optimizes by using alpha channel for weight.\r\n     * @param value The specular weight texture or null\r\n     */\r\n    public set specularWeightTexture(value: Nullable<BaseTexture>) {\r\n        if (this._material.specularColorTexture === value) {\r\n            this._material.specularWeightTexture = null;\r\n            this._material._useSpecularWeightFromSpecularColorTexture = true;\r\n            this._material._useSpecularWeightFromAlpha = true;\r\n        } else {\r\n            this._material.specularWeightTexture = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the specular weight texture of the OpenPBR material.\r\n     * @returns The specular weight texture or null\r\n     */\r\n    public get specularWeightTexture(): Nullable<BaseTexture> {\r\n        return this._material.specularWeightTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular color of the OpenPBR material.\r\n     * @param value The specular color as a Color3\r\n     */\r\n    public set specularColor(value: Color3) {\r\n        this._material.specularColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular color of the OpenPBR material.\r\n     * @returns The specular color as a Color3\r\n     */\r\n    public get specularColor(): Color3 {\r\n        return this._material.specularColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular color texture of the OpenPBR material.\r\n     * If the same texture is used for specular weight, optimizes by using alpha channel for weight.\r\n     * @param value The specular color texture or null\r\n     */\r\n    public set specularColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.specularColorTexture = value;\r\n        if (this._material.specularWeightTexture === this._material.specularColorTexture) {\r\n            this._material.specularWeightTexture = null;\r\n            this._material._useSpecularWeightFromSpecularColorTexture = true;\r\n            this._material._useSpecularWeightFromAlpha = true;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the specular color texture of the OpenPBR material.\r\n     * @returns The specular color texture or null\r\n     */\r\n    public get specularColorTexture(): Nullable<BaseTexture> {\r\n        return this._material.specularColorTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular roughness of the OpenPBR material.\r\n     * @param value The roughness value (0-1)\r\n     */\r\n    public set specularRoughness(value: number) {\r\n        this._material.specularRoughness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular roughness of the OpenPBR material.\r\n     * @returns The roughness value (0-1)\r\n     */\r\n    public get specularRoughness(): number {\r\n        return this._material.specularRoughness;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular roughness texture of the OpenPBR material.\r\n     * @param value The roughness texture or null\r\n     */\r\n    public set specularRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.specularRoughnessTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular roughness texture of the OpenPBR material.\r\n     * @returns The roughness texture or null\r\n     */\r\n    public get specularRoughnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.specularRoughnessTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular index of refraction (IOR) of the OpenPBR material.\r\n     * @param value The IOR value\r\n     */\r\n    public set specularIor(value: number) {\r\n        this._material.specularIor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular index of refraction (IOR) of the OpenPBR material.\r\n     * @returns The IOR value\r\n     */\r\n    public get specularIor(): number {\r\n        return this._material.specularIor;\r\n    }\r\n\r\n    /**\r\n     * Sets the glossiness (inverted roughness) of the OpenPBR material.\r\n     */\r\n    public set glossiness(value: number) {\r\n        this._material.specularRoughness = Math.max(1.0 - value, 0.0);\r\n    }\r\n\r\n    public get glossiness(): number {\r\n        return 1.0 - this._material.specularRoughness;\r\n    }\r\n\r\n    // ========================================\r\n    // EMISSION PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the emission color of the OpenPBR material.\r\n     * @param value The emission color as a Color3\r\n     */\r\n    public set emissionColor(value: Color3) {\r\n        this._material.emissionColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the emission color of the OpenPBR material.\r\n     * @returns The emission color as a Color3\r\n     */\r\n    public get emissionColor(): Color3 {\r\n        return this._material.emissionColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the emission luminance of the OpenPBR material.\r\n     * @param value The emission luminance value\r\n     */\r\n    public set emissionLuminance(value: number) {\r\n        this._material.emissionLuminance = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the emission luminance of the OpenPBR material.\r\n     * @returns The emission luminance value\r\n     */\r\n    public get emissionLuminance(): number {\r\n        return this._material.emissionLuminance;\r\n    }\r\n\r\n    /**\r\n     * Sets the emission color texture of the OpenPBR material.\r\n     * @param value The emission texture or null\r\n     */\r\n    public set emissionColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.emissionColorTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the emission color texture of the OpenPBR material.\r\n     * @returns The emission texture or null\r\n     */\r\n    public get emissionColorTexture(): Nullable<BaseTexture> {\r\n        return this._material.emissionColorTexture;\r\n    }\r\n\r\n    // ========================================\r\n    // AMBIENT OCCLUSION\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the ambient occlusion texture of the OpenPBR material.\r\n     * @param value The ambient occlusion texture or null\r\n     */\r\n    public set ambientOcclusionTexture(value: Nullable<BaseTexture>) {\r\n        this._material.ambientOcclusionTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the ambient occlusion texture of the OpenPBR material.\r\n     * @returns The ambient occlusion texture or null\r\n     */\r\n    public get ambientOcclusionTexture(): Nullable<BaseTexture> {\r\n        return this._material.ambientOcclusionTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the ambient occlusion texture strength by modifying the texture's level.\r\n     * @param value The strength value (typically 0-1)\r\n     */\r\n    public set ambientOcclusionTextureStrength(value: number) {\r\n        const texture = this._material.ambientOcclusionTexture;\r\n        if (texture) {\r\n            texture.level = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the ambient occlusion texture strength from the texture's level property.\r\n     * @returns The strength value, defaults to 1.0 if no texture or level is set\r\n     */\r\n    public get ambientOcclusionTextureStrength(): number {\r\n        const texture = this._material.ambientOcclusionTexture;\r\n        return texture?.level ?? 1.0;\r\n    }\r\n\r\n    // ========================================\r\n    // COAT PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures coat parameters for OpenPBR material.\r\n     * OpenPBR coat is already built-in, so no configuration is needed.\r\n     */\r\n    public configureCoat(): void {\r\n        // OpenPBR coat is already built-in, no configuration needed\r\n    }\r\n\r\n    /**\r\n     * Sets the coat weight of the OpenPBR material.\r\n     * @param value The coat weight value (0-1)\r\n     */\r\n    public set coatWeight(value: number) {\r\n        this._material.coatWeight = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat weight of the OpenPBR material.\r\n     * @returns The coat weight value (0-1)\r\n     */\r\n    public get coatWeight(): number {\r\n        return this._material.coatWeight;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat weight texture of the OpenPBR material.\r\n     * @param value The coat weight texture or null\r\n     */\r\n    public set coatWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.coatWeightTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat weight texture of the OpenPBR material.\r\n     * @returns The coat weight texture or null\r\n     */\r\n    public get coatWeightTexture(): Nullable<BaseTexture> {\r\n        return this._material.coatWeightTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat color of the OpenPBR material.\r\n     * @param value The coat color as a Color3\r\n     */\r\n    public set coatColor(value: Color3) {\r\n        this._material.coatColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat color of the OpenPBR material.\r\n     */\r\n    public get coatColor(): Color3 {\r\n        return this._material.coatColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat color texture of the OpenPBR material.\r\n     * @param value The coat color texture or null\r\n     */\r\n    public set coatColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.coatColorTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat roughness of the OpenPBR material.\r\n     * @param value The coat roughness value (0-1)\r\n     */\r\n    public set coatRoughness(value: number) {\r\n        this._material.coatRoughness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat roughness of the OpenPBR material.\r\n     * @returns The coat roughness value (0-1)\r\n     */\r\n    public get coatRoughness(): number {\r\n        return this._material.coatRoughness;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat roughness texture of the OpenPBR material.\r\n     * @param value The coat roughness texture or null\r\n     */\r\n    public set coatRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.coatRoughnessTexture = value;\r\n        if (value) {\r\n            this._material._useCoatRoughnessFromGreenChannel = true;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the coat roughness texture of the OpenPBR material.\r\n     * @returns The coat roughness texture or null\r\n     */\r\n    public get coatRoughnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.coatRoughnessTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat index of refraction (IOR) of the OpenPBR material.\r\n     */\r\n    public set coatIor(value: number) {\r\n        this._material.coatIor = value;\r\n    }\r\n\r\n    public get coatIor(): number {\r\n        return this._material.coatIor;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat darkening value of the OpenPBR material.\r\n     * @param value The coat darkening value\r\n     */\r\n    public set coatDarkening(value: number) {\r\n        this._material.coatDarkening = value;\r\n    }\r\n\r\n    public get coatDarkening(): number {\r\n        return this._material.coatDarkening;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat darkening texture (OpenPBR: coatDarkeningTexture, no PBR equivalent)\r\n     */\r\n    public set coatDarkeningTexture(value: Nullable<BaseTexture>) {\r\n        this._material.coatDarkeningTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat roughness anisotropy.\r\n     * TODO: Implementation pending OpenPBR coat anisotropy feature availability.\r\n     * @param value The coat anisotropy intensity value\r\n     */\r\n    public set coatRoughnessAnisotropy(value: number) {\r\n        this._material.coatRoughnessAnisotropy = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat roughness anisotropy.\r\n     * TODO: Implementation pending OpenPBR coat anisotropy feature availability.\r\n     * @returns Currently returns 0 as coat anisotropy is not yet available\r\n     */\r\n    public get coatRoughnessAnisotropy(): number {\r\n        return this._material.coatRoughnessAnisotropy;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat tangent angle for anisotropy.\r\n     * TODO: Implementation pending OpenPBR coat anisotropy feature availability.\r\n     * @param value The coat anisotropy rotation angle in radians\r\n     */\r\n    public set geometryCoatTangentAngle(value: number) {\r\n        this._material.geometryCoatTangentAngle = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat tangent texture for anisotropy.\r\n     * TODO: Implementation pending OpenPBR coat anisotropy feature availability.\r\n     * @param value The coat anisotropy texture or null\r\n     */\r\n    public set geometryCoatTangentTexture(value: Nullable<BaseTexture>) {\r\n        this._material.geometryCoatTangentTexture = value;\r\n        if (value) {\r\n            this._material._useCoatRoughnessAnisotropyFromTangentTexture = true;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the coat tangent texture for anisotropy.\r\n     * TODO: Implementation pending OpenPBR coat anisotropy feature availability.\r\n     * @returns Currently returns null as coat anisotropy is not yet available\r\n     */\r\n    public get geometryCoatTangentTexture(): Nullable<BaseTexture> {\r\n        return this._material.geometryCoatTangentTexture;\r\n    }\r\n\r\n    // ========================================\r\n    // TRANSMISSION LAYER\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures transmission for OpenPBR material.\r\n     */\r\n    public configureTransmission(): void {\r\n        // Material is thin-walled until otherwise specified by the glTF volume extension.\r\n        this._material.geometryThinWalled = 1.0;\r\n        this._material.transmissionDepth = 0.0;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission weight.\r\n     * @param value The transmission weight value (0-1)\r\n     */\r\n    public set transmissionWeight(value: number) {\r\n        this._material.transmissionWeight = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission weight texture.\r\n     * @param value The transmission weight texture or null\r\n     */\r\n    public set transmissionWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.transmissionWeightTexture = value;\r\n    }\r\n\r\n    public get transmissionWeightTexture(): Nullable<BaseTexture> {\r\n        return this._material.transmissionWeightTexture;\r\n    }\r\n\r\n    /**\r\n     * Gets the transmission weight.\r\n     * @returns Currently returns 0 as transmission is not yet available\r\n     */\r\n    public get transmissionWeight(): number {\r\n        return this._material.transmissionWeight;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission scatter coefficient.\r\n     * @param value The scatter coefficient as a Vector3\r\n     */\r\n    public set transmissionScatter(value: Color3) {\r\n        this._material.transmissionScatter = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the transmission scatter coefficient.\r\n     * @returns The scatter coefficient as a Vector3\r\n     */\r\n    public get transmissionScatter(): Color3 {\r\n        return this._material.transmissionScatter;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission scatter texture.\r\n     * @param value The transmission scatter texture or null\r\n     */\r\n    public set transmissionScatterTexture(value: Nullable<BaseTexture>) {\r\n        this._material.transmissionScatterTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the transmission scatter texture.\r\n     * @returns The transmission scatter texture or null\r\n     */\r\n    public get transmissionScatterTexture(): Nullable<BaseTexture> {\r\n        return this._material.transmissionScatterTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission scattering anisotropy.\r\n     * @param value The anisotropy intensity value (-1 to 1)\r\n     */\r\n    public set transmissionScatterAnisotropy(value: number) {\r\n        this._material.transmissionScatterAnisotropy = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission dispersion Abbe number.\r\n     * @param value The Abbe number value\r\n     */\r\n    public set transmissionDispersionAbbeNumber(value: number) {\r\n        this._material.transmissionDispersionAbbeNumber = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission dispersion scale.\r\n     * @param value The dispersion scale value\r\n     */\r\n    public set transmissionDispersionScale(value: number) {\r\n        this._material.transmissionDispersionScale = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the attenuation distance.\r\n     * @param value The attenuation distance value\r\n     */\r\n    public set transmissionDepth(value: number) {\r\n        // If the value is being set to the default max value, and the current transmission depth is 0,\r\n        // we assume that attenuation color isn't used and keep it at 0 to allow\r\n        // us to use constant transmission color to handle glTF's surface tint from base color.\r\n        if (value !== Number.MAX_VALUE || this._material.transmissionDepth !== 0) {\r\n            this._material.transmissionDepth = value;\r\n        } else {\r\n            this._material.transmissionDepth = 0;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the attenuation distance.\r\n     */\r\n    public get transmissionDepth(): number {\r\n        return this._material.transmissionDepth;\r\n    }\r\n\r\n    /**\r\n     * Sets the attenuation color.\r\n     * @param value The attenuation color as a Color3\r\n     */\r\n    public set transmissionColor(value: Color3) {\r\n        // Only set the transmission color if it's not white (default)\r\n        // This allows us to retain the base color as the transmission color,\r\n        // if that was previously set.\r\n        if (!value.equals(Color3.White())) {\r\n            this._material.transmissionColor = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the attenuation color.\r\n     */\r\n    public get transmissionColor(): Color3 {\r\n        return this._material.transmissionColor;\r\n    }\r\n\r\n    /**\r\n     * Gets the refraction background texture\r\n     * @returns The refraction background texture or null\r\n     */\r\n    public get refractionBackgroundTexture(): Nullable<BaseTexture> {\r\n        return this._material.backgroundRefractionTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the refraction background texture\r\n     * @param value The refraction background texture or null\r\n     */\r\n    public set refractionBackgroundTexture(value: Nullable<BaseTexture>) {\r\n        this._material.backgroundRefractionTexture = value;\r\n    }\r\n\r\n    // ========================================\r\n    // VOLUME PROPERTIES\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures volume properties for OpenPBR material.\r\n     */\r\n    public configureVolume(): void {\r\n        // If we're configuring volume, we assume the material is not thin-walled (i.e. it's volumetric).\r\n        this._material.geometryThinWalled = 0.0;\r\n    }\r\n\r\n    /**\r\n     * Sets whether the material is thin-walled (i.e. non-volumetric) or not.\r\n     */\r\n    public set geometryThinWalled(value: boolean) {\r\n        this._material.geometryThinWalled = value ? 1.0 : 0.0;\r\n    }\r\n\r\n    /**\r\n     * Gets whether the material is thin-walled (i.e. non-volumetric) or not.\r\n     */\r\n    public get geometryThinWalled(): boolean {\r\n        return this._material.geometryThinWalled ? true : false;\r\n    }\r\n\r\n    /**\r\n     * Sets the thickness texture.\r\n     * @param value The thickness texture or null\r\n     */\r\n    public set volumeThicknessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.geometryThicknessTexture = value;\r\n        this._material._useGeometryThicknessFromGreenChannel = true;\r\n    }\r\n\r\n    /**\r\n     * Sets the thickness factor.\r\n     * @param value The thickness value\r\n     */\r\n    public set volumeThickness(value: number) {\r\n        this._material.geometryThickness = value;\r\n    }\r\n\r\n    // ========================================\r\n    // SUBSURFACE PROPERTIES (Subsurface Scattering)\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures subsurface properties for PBR material\r\n     */\r\n    public configureSubsurface(): void {\r\n        // glTF diffuse transmission is thin-walled (before volume extension is applied) will map to the subsurface slab and, without a\r\n        this._material.geometryThinWalled = 1.0;\r\n        this._material.subsurfaceScatterAnisotropy = 1.0;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface weight\r\n     */\r\n    public set subsurfaceWeight(value: number) {\r\n        this._material.subsurfaceWeight = value;\r\n    }\r\n\r\n    public get subsurfaceWeight(): number {\r\n        return this._material.subsurfaceWeight;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface weight texture\r\n     */\r\n    public set subsurfaceWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subsurfaceWeightTexture = value;\r\n        this._material._useSubsurfaceWeightFromTextureAlpha = true;\r\n    }\r\n\r\n    public get subsurfaceWeightTexture(): Nullable<BaseTexture> {\r\n        return this._material.subsurfaceWeightTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface color.\r\n     * @param value The subsurface tint color as a Color3\r\n     */\r\n    public set subsurfaceColor(value: Color3) {\r\n        this._material.subsurfaceColor = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface color texture.\r\n     * @param value The subsurface tint texture or null\r\n     */\r\n    public set subsurfaceColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subsurfaceColorTexture = value;\r\n    }\r\n\r\n    private _diffuseTransmissionTint: Color3 = Color3.White();\r\n    private _diffuseTransmissionTintTexture: Nullable<BaseTexture> = null;\r\n\r\n    /**\r\n     * Sets the diffuse transmission tint of the material\r\n     */\r\n    public set diffuseTransmissionTint(value: Color3) {\r\n        this._diffuseTransmissionTint = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the diffuse transmission tint of the material\r\n     */\r\n    public get diffuseTransmissionTint(): Color3 {\r\n        return this._diffuseTransmissionTint;\r\n    }\r\n\r\n    /**\r\n     * Sets the diffuse transmission tint texture of the material\r\n     */\r\n    public set diffuseTransmissionTintTexture(value: Nullable<BaseTexture>) {\r\n        this._diffuseTransmissionTintTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the subsurface radius for subsurface scattering.\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     */\r\n    public get subsurfaceRadius(): number {\r\n        return this._material.subsurfaceRadius;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface radius for subsurface scattering.\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     * @param value The subsurface radius value\r\n     */\r\n    public set subsurfaceRadius(value: number) {\r\n        this._material.subsurfaceRadius = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the subsurface radius scale for subsurface scattering.\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     */\r\n    public get subsurfaceRadiusScale(): Color3 {\r\n        return this._material.subsurfaceRadiusScale;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface radius scale for subsurface scattering.\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     * @param value The subsurface radius scale as a Color3\r\n     */\r\n    public set subsurfaceRadiusScale(value: Color3) {\r\n        this._material.subsurfaceRadiusScale = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface scattering anisotropy.\r\n     * @param value The anisotropy intensity value\r\n     */\r\n    public set subsurfaceScatterAnisotropy(value: number) {\r\n        this._material.subsurfaceScatterAnisotropy = value;\r\n    }\r\n\r\n    /**\r\n     * Does this material have a translucent surface (i.e. either transmission or subsurface)?\r\n     * @returns True if the material is translucent, false otherwise\r\n     */\r\n    public isTranslucent(): boolean {\r\n        return this.transmissionWeight > 0 || this.subsurfaceWeight > 0;\r\n    }\r\n\r\n    // ========================================\r\n    // FUZZ LAYER (Sheen)\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures fuzz for OpenPBR.\r\n     * Enables fuzz and sets up proper configuration.\r\n     */\r\n    public configureFuzz(): void {\r\n        // Currently no setup to do for OpenPBR\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz weight.\r\n     * @param value The fuzz weight value\r\n     */\r\n    public set fuzzWeight(value: number) {\r\n        this._material.fuzzWeight = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz weight texture.\r\n     * @param value The fuzz weight texture or null\r\n     */\r\n    public set fuzzWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.fuzzWeightTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz color.\r\n     * @param value The fuzz color as a Color3\r\n     */\r\n    public set fuzzColor(value: Color3) {\r\n        this._material.fuzzColor = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz color texture.\r\n     * @param value The fuzz color texture or null\r\n     */\r\n    public set fuzzColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.fuzzColorTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz roughness.\r\n     * @param value The fuzz roughness value (0-1)\r\n     */\r\n    public set fuzzRoughness(value: number) {\r\n        this._material.fuzzRoughness = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz roughness texture.\r\n     * @param value The fuzz roughness texture or null\r\n     */\r\n    public set fuzzRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.fuzzRoughnessTexture = value;\r\n        this._material._useFuzzRoughnessFromTextureAlpha = true;\r\n    }\r\n\r\n    // ========================================\r\n    // ANISOTROPY\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the specular roughness anisotropy of the OpenPBR material.\r\n     * @param value The anisotropy intensity value\r\n     */\r\n    public set specularRoughnessAnisotropy(value: number) {\r\n        this._material.specularRoughnessAnisotropy = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular roughness anisotropy of the OpenPBR material.\r\n     * @returns The anisotropy intensity value\r\n     */\r\n    public get specularRoughnessAnisotropy(): number {\r\n        return this._material.specularRoughnessAnisotropy;\r\n    }\r\n\r\n    /**\r\n     * Sets the anisotropy rotation angle.\r\n     * @param value The anisotropy rotation angle in radians\r\n     */\r\n    public set geometryTangentAngle(value: number) {\r\n        this._material.geometryTangentAngle = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry tangent texture for anisotropy.\r\n     * Automatically enables using anisotropy from the tangent texture.\r\n     * @param value The anisotropy texture or null\r\n     */\r\n    public set geometryTangentTexture(value: Nullable<BaseTexture>) {\r\n        this._material.geometryTangentTexture = value;\r\n        this._material._useSpecularRoughnessAnisotropyFromTangentTexture = true;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry tangent texture for anisotropy.\r\n     * @returns The anisotropy texture or null\r\n     */\r\n    public get geometryTangentTexture(): Nullable<BaseTexture> {\r\n        return this._material.geometryTangentTexture;\r\n    }\r\n\r\n    /**\r\n     * Configures glTF-style anisotropy for the OpenPBR material.\r\n     * @param useGltfStyle Whether to use glTF-style anisotropy\r\n     */\r\n    public configureGltfStyleAnisotropy(useGltfStyle: boolean = true): void {\r\n        this._material._useGltfStyleAnisotropy = useGltfStyle;\r\n    }\r\n\r\n    // ========================================\r\n    // THIN FILM IRIDESCENCE\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the thin film weight.\r\n     * @param value The thin film weight value\r\n     */\r\n    public set thinFilmWeight(value: number) {\r\n        this._material.thinFilmWeight = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the thin film IOR.\r\n     * @param value The thin film IOR value\r\n     */\r\n    public set thinFilmIor(value: number) {\r\n        this._material.thinFilmIor = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the thin film thickness minimum.\r\n     * @param value The minimum thickness value in nanometers\r\n     */\r\n    public set thinFilmThicknessMinimum(value: number) {\r\n        this._material.thinFilmThicknessMin = value / 1000.0; // Convert to micrometers for OpenPBR\r\n    }\r\n\r\n    /**\r\n     * Sets the thin film thickness maximum.\r\n     * @param value The maximum thickness value in nanometers\r\n     */\r\n    public set thinFilmThicknessMaximum(value: number) {\r\n        this._material.thinFilmThickness = value / 1000.0; // Convert to micrometers for OpenPBR\r\n    }\r\n\r\n    /**\r\n     * Sets the thin film weight texture.\r\n     * @param value The thin film weight texture or null\r\n     */\r\n    public set thinFilmWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.thinFilmWeightTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the thin film thickness texture.\r\n     * @param value The thin film thickness texture or null\r\n     */\r\n    public set thinFilmThicknessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.thinFilmThicknessTexture = value;\r\n        this._material._useThinFilmThicknessFromTextureGreen = true;\r\n    }\r\n\r\n    // ========================================\r\n    // UNLIT MATERIALS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets whether the OpenPBR material is unlit.\r\n     * @param value True to make the material unlit\r\n     */\r\n    public set unlit(value: boolean) {\r\n        this._material.unlit = value;\r\n    }\r\n\r\n    // ========================================\r\n    // GEOMETRY PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the geometry opacity of the OpenPBR material.\r\n     * @param value The opacity value (0-1)\r\n     */\r\n    public set geometryOpacity(value: number) {\r\n        this._material.geometryOpacity = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry opacity of the OpenPBR material.\r\n     * @returns The opacity value (0-1)\r\n     */\r\n    public get geometryOpacity(): number {\r\n        return this._material.geometryOpacity;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry normal texture of the OpenPBR material.\r\n     * @param value The normal texture or null\r\n     */\r\n    public set geometryNormalTexture(value: Nullable<BaseTexture>) {\r\n        this._material.geometryNormalTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry normal texture of the OpenPBR material.\r\n     * @returns The normal texture or null\r\n     */\r\n    public get geometryNormalTexture(): Nullable<BaseTexture> {\r\n        return this._material.geometryNormalTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the normal map inversions for the OpenPBR material.\r\n     * Note: OpenPBR may handle normal map inversions differently or may not need them.\r\n     * @param invertX Whether to invert the normal map on the X axis (may be ignored)\r\n     * @param invertY Whether to invert the normal map on the Y axis (may be ignored)\r\n     */\r\n    public setNormalMapInversions(invertX: boolean, invertY: boolean): void {\r\n        // OpenPBR handles normal map inversions differently or may not need them\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry coat normal texture of the OpenPBR material.\r\n     * @param value The coat normal texture or null\r\n     */\r\n    public set geometryCoatNormalTexture(value: Nullable<BaseTexture>) {\r\n        this._material.geometryCoatNormalTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry coat normal texture of the OpenPBR material.\r\n     * @returns The coat normal texture or null\r\n     */\r\n    public get geometryCoatNormalTexture(): Nullable<BaseTexture> {\r\n        return this._material.geometryCoatNormalTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry coat normal texture scale.\r\n     * @param value The scale value for the coat normal texture\r\n     */\r\n    public set geometryCoatNormalTextureScale(value: number) {\r\n        if (this._material.geometryCoatNormalTexture) {\r\n            this._material.geometryCoatNormalTexture.level = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Finalizes material properties after all loading is complete.\r\n     * @param loader The glTF loader; `loader._disposed` is polled between texture passes to bail early on dispose.\r\n     */\r\n    public async finalizeAsync(loader: GLTFLoader): Promise<void> {\r\n        // Do final configuration for the material to handle any interactions/dependencies between properties that we had to defer until all properties were loaded.\r\n\r\n        // If the material is volumetric, we may need to create a coat layer to handle the surface tint.\r\n        if ((this._diffuseTransmissionTint && !this._diffuseTransmissionTint.equals(Color3.White())) || this._diffuseTransmissionTintTexture) {\r\n            if (this._material.geometryThinWalled) {\r\n                // Use the subsurface slab for surface tinting.\r\n                this.subsurfaceColor = this._diffuseTransmissionTint;\r\n                this.subsurfaceColorTexture = this._diffuseTransmissionTintTexture;\r\n            } else {\r\n                // Otherwise, we have volumetric attenuation so we need to use the coat layer to preserve the base color tinting of glTF.\r\n                await this.copySurfaceToCoatAsync(\r\n                    loader,\r\n                    this.subsurfaceWeight,\r\n                    this.subsurfaceWeightTexture,\r\n                    TextureChannel.A,\r\n                    this._diffuseTransmissionTint,\r\n                    this._diffuseTransmissionTintTexture,\r\n                    true\r\n                );\r\n                if (loader._disposed) {\r\n                    return;\r\n                }\r\n            }\r\n        }\r\n        // If the material has transmission, we need to use the base color to tint the transmission.\r\n        if (this.transmissionWeight > 0) {\r\n            if (this._material.geometryThinWalled || this._material.transmissionDepth === 0) {\r\n                // If the material is thin-walled or has no attenuation depth, we can use the base color as the transmission color directly.\r\n                this._material.transmissionColor = this._material.baseColor;\r\n                this._material.transmissionColorTexture = this._material.baseColorTexture;\r\n            } else if (!this.baseColor.equals(Color3.White()) || this.baseColorTexture !== null) {\r\n                // Otherwise, we have volumetric attenuation so we need to use the coat layer to preserve the base color tinting of glTF.\r\n                await this.copySurfaceToCoatAsync(loader, this.transmissionWeight, this.transmissionWeightTexture, TextureChannel.R, this.baseColor, this.baseColorTexture, false);\r\n                if (loader._disposed) {\r\n                    return;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (this._specWorkflow) {\r\n            // To convert from spec-gloss to OpenPBR, we'll grab the specular color's alpha channel (which contains glossiness) and\r\n            // invert it to get roughness.\r\n            const newRoughnessTexture = await InvertTextureAsync(\r\n                \"newRoughnessTexture (\" + this._material.name + \")\",\r\n                await ExtractChannelAsync(\r\n                    \"glossiness (\" + this._material.name + \")\",\r\n                    CreateTextureWithFactorOperand(\r\n                        this.specularColorTexture,\r\n                        new Color4(this.specularColor.r, this.specularColor.g, this.specularColor.b, this.glossiness),\r\n                        TextureChannel.A,\r\n                        TextureColorSpace.Linear\r\n                    ),\r\n                    TextureChannel.A,\r\n                    this._material.getScene(),\r\n                    TextureColorSpace.Linear,\r\n                    ChannelMask.R\r\n                ),\r\n                this._material.getScene(),\r\n                ChannelMask.R,\r\n                TextureColorSpace.Linear,\r\n                ChannelMask.R\r\n            );\r\n            if (loader._disposed) {\r\n                newRoughnessTexture.texture?.dispose();\r\n                return;\r\n            }\r\n            this.specularRoughnessTexture = newRoughnessTexture.texture;\r\n            this.specularRoughness = newRoughnessTexture.factor ? newRoughnessTexture.factor.r : 1.0;\r\n\r\n            // Metallic = max(linearize(specular).rgb). The specular texture is sRGB so we must\r\n            // linearize it first (TextureColorSpace.SRGB). The factor is already linear per convention.\r\n            // We store metallic as linear (no outputColorSpace) because it is a data/scalar value;\r\n            // encoding it as sRGB would corrupt it when it is used as the lerp t below.\r\n            const newMetallic = await ExtractMaxChannelAsync(\r\n                \"metallicTexture (\" + this._material.name + \")\",\r\n                CreateTextureWithFactorOperand(this.specularColorTexture, this.specularColor.toColor4(), TextureChannel.RGBA, TextureColorSpace.Linear),\r\n                this._material.getScene(),\r\n                false,\r\n                TextureColorSpace.SRGB,\r\n                ChannelMask.RGB\r\n            );\r\n            if (loader._disposed) {\r\n                newMetallic.texture?.dispose();\r\n                return;\r\n            }\r\n            this.baseMetalnessTexture = newMetallic.texture;\r\n            this.baseMetalness = newMetallic.factor ? newMetallic.factor.r : 1.0;\r\n\r\n            // base_color = lerp(diffuse, specular, metallic).\r\n            // Strip dispose before passing newMetallic as t — its texture is already owned by the\r\n            // material (baseMetalnessTexture) and must not be released after the lerp pass.\r\n            const newBaseColor = await LerpTexturesAsync(\r\n                \"newBaseColor (\" + this._material.name + \")\",\r\n                CreateTextureWithFactorOperand(this.baseColorTexture, this.baseColor.toColor4(), TextureChannel.RGBA, TextureColorSpace.Linear),\r\n                CreateTextureWithFactorOperand(this.specularColorTexture, this.specularColor.toColor4(), TextureChannel.RGBA, TextureColorSpace.Linear),\r\n                { ...newMetallic, dispose: undefined, colorSpace: TextureColorSpace.Linear },\r\n                this._material.getScene(),\r\n                TextureColorSpace.SRGB,\r\n                ChannelMask.RGB\r\n            );\r\n            if (loader._disposed) {\r\n                newBaseColor.texture?.dispose();\r\n                return;\r\n            }\r\n            const oldBaseColorTexture = this.baseColorTexture;\r\n            oldBaseColorTexture?.dispose();\r\n            this.baseColorTexture = newBaseColor.texture;\r\n            this.baseColor = newBaseColor.factor ? new Color3(newBaseColor.factor.r, newBaseColor.factor.g, newBaseColor.factor.b) : Color3.White();\r\n\r\n            const oldSpecularColorTexture = this.specularColorTexture;\r\n            oldSpecularColorTexture?.dispose();\r\n            this.specularColorTexture = null;\r\n        }\r\n    }\r\n\r\n    private async copySurfaceToCoatAsync(\r\n        loader: GLTFLoader,\r\n        weight: number,\r\n        weightTexture: Nullable<BaseTexture>,\r\n        weightTextureChannel: TextureChannel,\r\n        color: Color3,\r\n        colorTexture: Nullable<BaseTexture>,\r\n        diffuseTransmission: boolean = false\r\n    ): Promise<void> {\r\n        // Blend coat properties using:\r\n        // New coat will cover all areas that previously had coat or transmission.\r\n        //   new_coat_weight = max(weight, existing_coat_weight)\r\n        // New coat color is the multiplication of the base color tint and the existing coat tint, each blended by their respective weights:\r\n        //   new_coat_color  = lerp(white, existing_coat_color, existing_coat_weight)\r\n        //                   * lerp(white, color, weight)\r\n        // Snapshot the original coat properties before mutating them, so both lerps\r\n        // use the pre-merge values (the first lerp blends the *existing* coat color\r\n        // by the *existing* coat weight; we must not use the merged weight here).\r\n        const origCoatWeight = this._material.coatWeight;\r\n        const origCoatWeightTexture = this._material.coatWeightTexture;\r\n        const origCoatColor = this._material.coatColor.clone();\r\n        const origCoatColorTexture = this._material.coatColorTexture;\r\n        const origCoatNormalTexture = this._material.geometryCoatNormalTexture;\r\n\r\n        const origCoatWeightCol4 = new Color4(origCoatWeight, origCoatWeight, origCoatWeight, origCoatWeight);\r\n        const weightCol4 = new Color4(weight, weight, weight, weight);\r\n\r\n        this.coatWeightTexture = null;\r\n        this.coatWeight = 1.0;\r\n\r\n        const results = await Promise.allSettled([\r\n            LerpTexturesAsync(\r\n                \"lerpExistingCoat\",\r\n                CreateTextureWithFactorOperand(null, new Color4(1, 1, 1, 1)),\r\n                CreateTextureWithFactorOperand(origCoatColorTexture, origCoatColor.toColor4(), TextureChannel.RGBA, TextureColorSpace.SRGB),\r\n                CreateTextureWithFactorOperand(origCoatWeightTexture, origCoatWeightCol4, TextureChannel.R),\r\n                this._material.getScene(),\r\n                TextureColorSpace.SRGB\r\n            ),\r\n            LerpTexturesAsync(\r\n                \"lerpSurfaceColor\",\r\n                CreateTextureWithFactorOperand(null, new Color4(1, 1, 1, 1)),\r\n                CreateTextureWithFactorOperand(colorTexture, color.toColor4(), TextureChannel.RGBA, TextureColorSpace.SRGB),\r\n                CreateTextureWithFactorOperand(weightTexture, weightCol4, weightTextureChannel),\r\n                this._material.getScene(),\r\n                TextureColorSpace.SRGB\r\n            ),\r\n        ]);\r\n        const rejected = results.find((r) => r.status === \"rejected\") as PromiseRejectedResult | undefined;\r\n        if (rejected) {\r\n            for (const r of results) {\r\n                if (r.status === \"fulfilled\") {\r\n                    r.value.texture?.dispose();\r\n                }\r\n            }\r\n            throw rejected.reason;\r\n        }\r\n        const [lerpCoatColor, lerpSurfaceColor] = results.map(\r\n            (r) => (r as PromiseFulfilledResult<(typeof results)[number] extends PromiseSettledResult<infer T> ? T : never>).value\r\n        );\r\n        if (loader._disposed) {\r\n            lerpCoatColor.texture?.dispose();\r\n            lerpSurfaceColor.texture?.dispose();\r\n            return;\r\n        }\r\n\r\n        const newCoatColor = await MultiplyTexturesAsync(\r\n            \"newCoatColor (\" + this._material.name + \")\",\r\n            lerpCoatColor,\r\n            lerpSurfaceColor,\r\n            this._material.getScene(),\r\n            TextureColorSpace.SRGB\r\n        );\r\n        if (loader._disposed) {\r\n            newCoatColor.texture?.dispose();\r\n            return;\r\n        }\r\n\r\n        if (newCoatColor.texture) {\r\n            this.coatColorTexture = newCoatColor.texture;\r\n            this.coatColor = Color3.White();\r\n        } else if (newCoatColor.factor) {\r\n            this.coatColorTexture = null;\r\n            this.coatColor.fromArray([newCoatColor.factor.r, newCoatColor.factor.g, newCoatColor.factor.b]);\r\n        }\r\n\r\n        const newCoatIor = await LerpTexturesAsync(\r\n            \"newCoatIor (\" + this._material.name + \")\",\r\n            CreateTextureWithFactorOperand(null, new Color4(this._material.specularIor, this._material.specularIor, this._material.specularIor, 1.0), TextureChannel.R),\r\n            CreateTextureWithFactorOperand(null, new Color4(this.coatIor, this.coatIor, this.coatIor, 1.0), TextureChannel.R),\r\n            CreateTextureWithFactorOperand(origCoatWeightTexture, origCoatWeightCol4, TextureChannel.R),\r\n            this._material.getScene()\r\n        );\r\n        if (loader._disposed) {\r\n            newCoatIor.texture?.dispose();\r\n            return;\r\n        }\r\n        this.coatIor = newCoatIor.factor ? newCoatIor.factor.r : this.coatIor;\r\n\r\n        const newCoatRoughness = await LerpTexturesAsync(\r\n            \"newCoatRoughness (\" + this._material.name + \")\",\r\n            CreateTextureWithFactorOperand(\r\n                this.specularRoughnessTexture,\r\n                new Color4(this.specularRoughness, this.specularRoughness, this.specularRoughness, 1.0),\r\n                TextureChannel.G\r\n            ),\r\n            CreateTextureWithFactorOperand(this.coatRoughnessTexture, new Color4(this.coatRoughness, this.coatRoughness, this.coatRoughness, 1.0), TextureChannel.G),\r\n            CreateTextureWithFactorOperand(origCoatWeightTexture, origCoatWeightCol4, TextureChannel.R),\r\n            this._material.getScene()\r\n        );\r\n        if (loader._disposed) {\r\n            newCoatRoughness.texture?.dispose();\r\n            return;\r\n        }\r\n        this.coatRoughness = newCoatRoughness.factor ? newCoatRoughness.factor.r : 1.0;\r\n        this.coatRoughnessTexture = newCoatRoughness.texture;\r\n\r\n        const newCoatDarkening = await LerpTexturesAsync(\r\n            \"newCoatDarkening (\" + this._material.name + \")\",\r\n            CreateTextureWithFactorOperand(null, new Color4(0, 0, 0, 1.0), TextureChannel.R),\r\n            CreateTextureWithFactorOperand(null, new Color4(this.coatDarkening, this.coatDarkening, this.coatDarkening, 1.0), TextureChannel.R),\r\n            CreateTextureWithFactorOperand(origCoatWeightTexture, origCoatWeightCol4, TextureChannel.R),\r\n            this._material.getScene()\r\n        );\r\n        if (loader._disposed) {\r\n            newCoatDarkening.texture?.dispose();\r\n            return;\r\n        }\r\n        this.coatDarkening = newCoatDarkening.factor ? newCoatDarkening.factor.r : this.coatDarkening;\r\n\r\n        if (diffuseTransmission) {\r\n            const newSpecularRoughness = await LerpTexturesAsync(\r\n                \"newSpecularRoughness (\" + this._material.name + \")\",\r\n                CreateTextureWithFactorOperand(\r\n                    this.specularRoughnessTexture,\r\n                    new Color4(this._material.specularRoughness, this._material.specularRoughness, this._material.specularRoughness, 1.0),\r\n                    TextureChannel.G\r\n                ),\r\n                CreateTextureWithFactorOperand(null, new Color4(1, 1, 1, 1.0), TextureChannel.R),\r\n                CreateTextureWithFactorOperand(weightTexture, weightCol4, weightTextureChannel),\r\n                this._material.getScene()\r\n            );\r\n            if (loader._disposed) {\r\n                newSpecularRoughness.texture?.dispose();\r\n                return;\r\n            }\r\n            this.specularRoughness = newSpecularRoughness.factor ? newSpecularRoughness.factor.r : 1.0;\r\n            this.specularRoughnessTexture = newSpecularRoughness.texture;\r\n        }\r\n\r\n        if (origCoatNormalTexture || this.geometryNormalTexture) {\r\n            const newCoatNormal = await LerpTexturesAsync(\r\n                \"newCoatNormal (\" + this._material.name + \")\",\r\n                CreateTextureWithFactorOperand(\r\n                    this.geometryNormalTexture,\r\n                    this.geometryNormalTexture ? new Color4(1, 1, 1, 1) : new Color4(0.5, 0.5, 1.0, 1.0),\r\n                    TextureChannel.RGBA\r\n                ),\r\n                CreateTextureWithFactorOperand(origCoatNormalTexture, origCoatNormalTexture ? new Color4(1, 1, 1, 1) : new Color4(0.5, 0.5, 1.0, 1.0), TextureChannel.RGBA),\r\n                CreateTextureWithFactorOperand(origCoatWeightTexture, origCoatWeightCol4, TextureChannel.R),\r\n                this._material.getScene()\r\n            );\r\n            if (loader._disposed) {\r\n                newCoatNormal.texture?.dispose();\r\n                return;\r\n            }\r\n            if (newCoatNormal.texture) {\r\n                this.geometryCoatNormalTexture = newCoatNormal.texture;\r\n            }\r\n        }\r\n    }\r\n}\r\n","import { type PBRMaterial } from \"core/Materials/PBR/pbrMaterial\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { type IMaterialLoadingAdapter } from \"./materialLoadingAdapter\";\r\nimport { type GLTFLoader } from \"./glTFLoader\";\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\n\r\n/**\r\n * Material Loading Adapter for PBR materials that provides a unified OpenPBR-like interface.\r\n */\r\nexport class PBRMaterialLoadingAdapter implements IMaterialLoadingAdapter {\r\n    private _material: PBRMaterial;\r\n    private _specWorkflow: boolean = false;\r\n    /**\r\n     * Creates a new instance of the PBRMaterialLoadingAdapter.\r\n     * @param material - The PBR material to adapt.\r\n     */\r\n    constructor(material: Material) {\r\n        this._material = material as PBRMaterial;\r\n        this._material.enableSpecularAntiAliasing = true;\r\n    }\r\n\r\n    /**\r\n     * Gets the underlying material\r\n     */\r\n    public get material(): PBRMaterial {\r\n        return this._material;\r\n    }\r\n\r\n    /**\r\n     * No-op: PBRMaterial has no deferred finalization.\r\n     * @param _loader Unused.\r\n     */\r\n    public async finalizeAsync(_loader: GLTFLoader): Promise<void> {}\r\n\r\n    /**\r\n     * Whether the material should be treated as unlit\r\n     */\r\n    public get isUnlit(): boolean {\r\n        return this._material.unlit;\r\n    }\r\n\r\n    /**\r\n     * Sets whether the material should be treated as unlit\r\n     */\r\n    public set isUnlit(value: boolean) {\r\n        this._material.unlit = value;\r\n    }\r\n\r\n    // ========================================\r\n    // CULLING PROPERTIES\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets whether back face culling is enabled.\r\n     * @param value True to enable back face culling\r\n     */\r\n    public set backFaceCulling(value: boolean) {\r\n        this._material.backFaceCulling = value;\r\n    }\r\n\r\n    /**\r\n     * Gets whether back face culling is enabled.\r\n     * @returns True if back face culling is enabled\r\n     */\r\n    public get backFaceCulling(): boolean {\r\n        return this._material.backFaceCulling;\r\n    }\r\n\r\n    /**\r\n     * Sets whether two-sided lighting is enabled.\r\n     * @param value True to enable two-sided lighting\r\n     */\r\n    public set twoSidedLighting(value: boolean) {\r\n        this._material.twoSidedLighting = value;\r\n    }\r\n\r\n    /**\r\n     * Gets whether two-sided lighting is enabled.\r\n     * @returns True if two-sided lighting is enabled\r\n     */\r\n    public get twoSidedLighting(): boolean {\r\n        return this._material.twoSidedLighting;\r\n    }\r\n\r\n    // ========================================\r\n    // ALPHA PROPERTIES\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the alpha cutoff value for alpha testing.\r\n     * @param value The alpha cutoff threshold (0-1)\r\n     */\r\n    public set alphaCutOff(value: number) {\r\n        this._material.alphaCutOff = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the alpha cutoff value.\r\n     * @returns The alpha cutoff threshold (0-1)\r\n     */\r\n    public get alphaCutOff(): number {\r\n        return this._material.alphaCutOff;\r\n    }\r\n\r\n    /**\r\n     * Sets whether to use alpha from the albedo texture.\r\n     * @param value True to use alpha from albedo texture\r\n     */\r\n    public set useAlphaFromBaseColorTexture(value: boolean) {\r\n        this._material.useAlphaFromAlbedoTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets whether alpha is used from the albedo texture.\r\n     * @returns True if using alpha from albedo texture\r\n     */\r\n    public get useAlphaFromBaseColorTexture(): boolean {\r\n        return this._material.useAlphaFromAlbedoTexture;\r\n    }\r\n\r\n    /**\r\n     * Gets whether the transparency is treated as alpha coverage.\r\n     */\r\n    public get transparencyAsAlphaCoverage(): boolean {\r\n        return this._material.useRadianceOverAlpha || this._material.useSpecularOverAlpha;\r\n    }\r\n\r\n    /**\r\n     * Sets/Gets whether the transparency is treated as alpha coverage\r\n     */\r\n    public set transparencyAsAlphaCoverage(value: boolean) {\r\n        this._material.useRadianceOverAlpha = !value;\r\n        this._material.useSpecularOverAlpha = !value;\r\n    }\r\n\r\n    // ========================================\r\n    // BASE PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the base color of the material (mapped to PBR albedoColor).\r\n     * @param value The base color as a Color3\r\n     */\r\n    public set baseColor(value: Color3) {\r\n        this._material.albedoColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base color of the material.\r\n     * @returns The base color as a Color3\r\n     */\r\n    public get baseColor(): Color3 {\r\n        return this._material.albedoColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the base color texture of the material (mapped to PBR albedoTexture).\r\n     * @param value The base color texture or null\r\n     */\r\n    public set baseColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.albedoTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base color texture of the material.\r\n     * @returns The base color texture or null\r\n     */\r\n    public get baseColorTexture(): Nullable<BaseTexture> {\r\n        return this._material.albedoTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the base diffuse roughness of the material.\r\n     * @param value The diffuse roughness value (0-1)\r\n     */\r\n    public set baseDiffuseRoughness(value: number) {\r\n        this._material.baseDiffuseRoughness = value;\r\n        if (value > 0) {\r\n            this._material.brdf.baseDiffuseModel = Constants.MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the base diffuse roughness of the material.\r\n     * @returns The diffuse roughness value (0-1), defaults to 0 if not set\r\n     */\r\n    public get baseDiffuseRoughness(): number {\r\n        return this._material.baseDiffuseRoughness ?? 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the base diffuse roughness texture of the material.\r\n     * @param value The diffuse roughness texture or null\r\n     */\r\n    public set baseDiffuseRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.baseDiffuseRoughnessTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base diffuse roughness texture of the material.\r\n     * @returns The diffuse roughness texture or null\r\n     */\r\n    public get baseDiffuseRoughnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.baseDiffuseRoughnessTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the base metalness value of the material (mapped to PBR metallic).\r\n     * @param value The metalness value (0-1)\r\n     */\r\n    public set baseMetalness(value: number) {\r\n        this._material.metallic = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base metalness value of the material.\r\n     * @returns The metalness value (0-1), defaults to 1 if not set\r\n     */\r\n    public get baseMetalness(): number {\r\n        return this._material.metallic ?? 1;\r\n    }\r\n\r\n    /**\r\n     * Sets the base metalness texture of the material (mapped to PBR metallicTexture).\r\n     * @param value The metalness texture or null\r\n     */\r\n    public set baseMetalnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.metallicTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the base metalness texture of the material.\r\n     * @returns The metalness texture or null\r\n     */\r\n    public get baseMetalnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.metallicTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets whether to use roughness from the metallic texture's green channel.\r\n     * Also disables using roughness from the alpha channel when enabled.\r\n     * @param value True to use green channel for roughness\r\n     */\r\n    public set useRoughnessFromMetallicTextureGreen(value: boolean) {\r\n        this._material.useRoughnessFromMetallicTextureGreen = value;\r\n        this._material.useRoughnessFromMetallicTextureAlpha = !value;\r\n    }\r\n\r\n    /**\r\n     * Sets whether to use metalness from the metallic texture's blue channel.\r\n     * @param value True to use blue channel for metalness\r\n     */\r\n    public set useMetallicFromMetallicTextureBlue(value: boolean) {\r\n        this._material.useMetallnessFromMetallicTextureBlue = value;\r\n    }\r\n\r\n    // ========================================\r\n    // SPECULAR PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures specular properties and optionally enables OpenPBR BRDF model for edge color support.\r\n     * @param enableEdgeColor Whether to enable OpenPBR BRDF models for edge color support\r\n     */\r\n    public enableSpecularEdgeColor(enableEdgeColor: boolean = false): void {\r\n        if (enableEdgeColor) {\r\n            this._material.brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR;\r\n            this._material.brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Enable the specular/glossiness workflow and disable metallic/roughness.\r\n     */\r\n    public configureSpecularGlossiness(): void {\r\n        this._specWorkflow = true;\r\n        this._material.metallic = null;\r\n        this._material.roughness = null;\r\n        this._material.useMicroSurfaceFromReflectivityMapAlpha = true;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular weight (mapped to PBR metallicF0Factor).\r\n     * @param value The specular weight value\r\n     */\r\n    public set specularWeight(value: number) {\r\n        this._material.metallicF0Factor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular weight.\r\n     * @returns The specular weight value, defaults to 1 if not set\r\n     */\r\n    public get specularWeight(): number {\r\n        return this._material.metallicF0Factor ?? 1;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular weight texture (mapped to PBR metallicReflectanceTexture).\r\n     * Configures the material to use only metalness from this texture when set.\r\n     * @param value The specular weight texture or null\r\n     */\r\n    public set specularWeightTexture(value: Nullable<BaseTexture>) {\r\n        if (value) {\r\n            this._material.metallicReflectanceTexture = value;\r\n            this._material.useOnlyMetallicFromMetallicReflectanceTexture = true;\r\n        } else {\r\n            this._material.metallicReflectanceTexture = null;\r\n            this._material.useOnlyMetallicFromMetallicReflectanceTexture = false;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the specular weight texture.\r\n     * @returns The specular weight texture or null\r\n     */\r\n    public get specularWeightTexture(): Nullable<BaseTexture> {\r\n        return this._material.metallicReflectanceTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular color (mapped to PBR metallicReflectanceColor).\r\n     * @param value The specular color as a Color3\r\n     */\r\n    public set specularColor(value: Color3) {\r\n        if (this._specWorkflow) {\r\n            this._material.reflectivityColor = value;\r\n        } else {\r\n            this._material.metallicReflectanceColor = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the specular color.\r\n     * @returns The specular color as a Color3\r\n     */\r\n    public get specularColor(): Color3 {\r\n        if (this._specWorkflow) {\r\n            return this._material.reflectivityColor;\r\n        } else {\r\n            return this._material.metallicReflectanceColor;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Sets the specular color texture (mapped to PBR reflectanceTexture).\r\n     * @param value The specular color texture or null\r\n     */\r\n    public set specularColorTexture(value: Nullable<BaseTexture>) {\r\n        if (this._specWorkflow) {\r\n            this._material.reflectivityTexture = value;\r\n            if (this._material.reflectivityTexture) {\r\n                this._material.reflectivityTexture.hasAlpha = true;\r\n            }\r\n        } else {\r\n            this._material.reflectanceTexture = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the specular color texture.\r\n     * @returns The specular color texture or null\r\n     */\r\n    public get specularColorTexture(): Nullable<BaseTexture> {\r\n        if (this._specWorkflow) {\r\n            return this._material.reflectivityTexture;\r\n        } else {\r\n            return this._material.reflectanceTexture;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Sets the specular roughness (mapped to PBR roughness).\r\n     * @param value The roughness value (0-1)\r\n     */\r\n    public set specularRoughness(value: number) {\r\n        this._material.roughness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular roughness.\r\n     * @returns The roughness value (0-1), defaults to 1 if not set\r\n     */\r\n    public get specularRoughness(): number {\r\n        return this._material.roughness ?? 1;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular roughness texture.\r\n     * Note: PBR uses the same texture for both metallic and roughness,\r\n     * so this only sets the texture if no base metalness texture exists.\r\n     * @param value The roughness texture or null\r\n     */\r\n    public set specularRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        // PBR uses the same texture for both metallic and roughness\r\n        if (!this.baseMetalnessTexture) {\r\n            this._material.metallicTexture = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the specular roughness texture.\r\n     * @returns The roughness texture (same as metallic texture for PBR) or null\r\n     */\r\n    public get specularRoughnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.metallicTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the specular index of refraction (mapped to PBR indexOfRefraction).\r\n     * @param value The IOR value\r\n     */\r\n    public set specularIor(value: number) {\r\n        this._material.indexOfRefraction = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular index of refraction.\r\n     * @returns The IOR value\r\n     */\r\n    public get specularIor(): number {\r\n        return this._material.indexOfRefraction;\r\n    }\r\n\r\n    /**\r\n     * Sets/gets the glossiness (inverted roughness)\r\n     * ONLY used for specular/glossiness workflow; has no effect when metallic/roughness workflow is active\r\n     */\r\n    public get glossiness(): number {\r\n        return this._material.microSurface ?? 1;\r\n    }\r\n\r\n    /**\r\n     * Sets/gets the glossiness (inverted roughness)\r\n     * ONLY used for specular/glossiness workflow; has no effect when metallic/roughness workflow is active\r\n     */\r\n    public set glossiness(value: number) {\r\n        this._material.microSurface = value;\r\n    }\r\n\r\n    // ========================================\r\n    // EMISSION PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the emission color (mapped to PBR emissiveColor).\r\n     * @param value The emission color as a Color3\r\n     */\r\n    public set emissionColor(value: Color3) {\r\n        this._material.emissiveColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the emission color.\r\n     * @returns The emission color as a Color3\r\n     */\r\n    public get emissionColor(): Color3 {\r\n        return this._material.emissiveColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the emission luminance/intensity (mapped to PBR emissiveIntensity).\r\n     * @param value The emission intensity value\r\n     */\r\n    public set emissionLuminance(value: number) {\r\n        this._material.emissiveIntensity = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the emission luminance/intensity.\r\n     * @returns The emission intensity value\r\n     */\r\n    public get emissionLuminance(): number {\r\n        return this._material.emissiveIntensity;\r\n    }\r\n\r\n    /**\r\n     * Sets the emission color texture (mapped to PBR emissiveTexture).\r\n     * @param value The emission texture or null\r\n     */\r\n    public set emissionColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.emissiveTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the emission color texture.\r\n     * @returns The emission texture or null\r\n     */\r\n    public get emissionColorTexture(): Nullable<BaseTexture> {\r\n        return this._material.emissiveTexture;\r\n    }\r\n\r\n    // ========================================\r\n    // AMBIENT OCCLUSION\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the ambient occlusion texture (mapped to PBR ambientTexture).\r\n     * Automatically enables grayscale mode when set.\r\n     * @param value The ambient occlusion texture or null\r\n     */\r\n    public set ambientOcclusionTexture(value: Nullable<BaseTexture>) {\r\n        this._material.ambientTexture = value;\r\n        if (value) {\r\n            this._material.useAmbientInGrayScale = true;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the ambient occlusion texture.\r\n     * @returns The ambient occlusion texture or null\r\n     */\r\n    public get ambientOcclusionTexture(): Nullable<BaseTexture> {\r\n        return this._material.ambientTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the ambient occlusion texture strength.\r\n     * @param value The strength value (typically 0-1)\r\n     */\r\n    public set ambientOcclusionTextureStrength(value: number) {\r\n        this._material.ambientTextureStrength = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the ambient occlusion texture strength.\r\n     * @returns The strength value, defaults to 1.0 if not set\r\n     */\r\n    public get ambientOcclusionTextureStrength(): number {\r\n        return this._material.ambientTextureStrength ?? 1.0;\r\n    }\r\n\r\n    // ========================================\r\n    // COAT PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures clear coat for PBR material.\r\n     * Enables clear coat and sets up proper configuration.\r\n     */\r\n    public configureCoat(): void {\r\n        this._material.clearCoat.isEnabled = true;\r\n        this._material.clearCoat.useRoughnessFromMainTexture = false;\r\n        this._material.clearCoat.remapF0OnInterfaceChange = false;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat weight (mapped to PBR clearCoat.intensity).\r\n     * Automatically enables clear coat.\r\n     * @param value The coat weight value (0-1)\r\n     */\r\n    public set coatWeight(value: number) {\r\n        this._material.clearCoat.isEnabled = true;\r\n        this._material.clearCoat.intensity = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat weight.\r\n     * @returns The coat weight value\r\n     */\r\n    public get coatWeight(): number {\r\n        return this._material.clearCoat.intensity;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat weight texture (mapped to PBR clearCoat.texture).\r\n     * Automatically enables clear coat.\r\n     * @param value The coat weight texture or null\r\n     */\r\n    public set coatWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.clearCoat.isEnabled = true;\r\n        this._material.clearCoat.texture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat weight texture.\r\n     * @returns The coat weight texture or null\r\n     */\r\n    public get coatWeightTexture(): Nullable<BaseTexture> {\r\n        return this._material.clearCoat.texture;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat color (mapped to PBR clearCoat.tintColor).\r\n     * @param value The coat tint color as a Color3\r\n     */\r\n    public set coatColor(value: Color3) {\r\n        this._material.clearCoat.isTintEnabled = value != Color3.White();\r\n        this._material.clearCoat.tintColor = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat color texture (mapped to PBR clearCoat.tintTexture).\r\n     * @param value The coat color texture or null\r\n     */\r\n    public set coatColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.clearCoat.tintTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat roughness (mapped to PBR clearCoat.roughness).\r\n     * Automatically enables clear coat.\r\n     * @param value The coat roughness value (0-1)\r\n     */\r\n    public set coatRoughness(value: number) {\r\n        this._material.clearCoat.isEnabled = true;\r\n        this._material.clearCoat.roughness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat roughness.\r\n     * @returns The coat roughness value, defaults to 0 if not set\r\n     */\r\n    public get coatRoughness(): number {\r\n        return this._material.clearCoat.roughness ?? 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat roughness texture (mapped to PBR clearCoat.textureRoughness).\r\n     * Automatically enables clear coat and disables using roughness from main texture.\r\n     * @param value The coat roughness texture or null\r\n     */\r\n    public set coatRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.clearCoat.isEnabled = true;\r\n        this._material.clearCoat.useRoughnessFromMainTexture = false;\r\n        this._material.clearCoat.textureRoughness = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat roughness texture.\r\n     * @returns The coat roughness texture or null\r\n     */\r\n    public get coatRoughnessTexture(): Nullable<BaseTexture> {\r\n        return this._material.clearCoat.textureRoughness;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat index of refraction (IOR).\r\n     */\r\n    public set coatIor(value: number) {\r\n        this._material.clearCoat.indexOfRefraction = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat darkening value.\r\n     * Note: PBR doesn't have a direct coat darkening property, so this is a no-op.\r\n     * @param value The coat darkening value (ignored for PBR)\r\n     */\r\n    public set coatDarkening(value: number) {\r\n        // PBR doesn't have a coat darkening property\r\n    }\r\n\r\n    /**\r\n     * Sets the coat darkening texture\r\n     * @param value The coat darkening texture or null\r\n     */\r\n    public set coatDarkeningTexture(value: Nullable<BaseTexture>) {\r\n        // PBR doesn't have a coat darkening property\r\n    }\r\n\r\n    /**\r\n     * Sets the coat roughness anisotropy.\r\n     * Note: PBR clearCoat doesn't support anisotropy yet, so this is a placeholder.\r\n     * @param value The coat anisotropy intensity value (currently ignored)\r\n     */\r\n    public set coatRoughnessAnisotropy(value: number) {\r\n        // TODO: Implement when PBR clearCoat anisotropy becomes available\r\n        // this._material.clearCoat.anisotropy = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat roughness anisotropy.\r\n     * Note: PBR clearCoat doesn't support anisotropy yet, so this returns 0.\r\n     * @returns Currently returns 0 as clearCoat anisotropy is not yet available\r\n     */\r\n    public get coatRoughnessAnisotropy(): number {\r\n        // TODO: Implement when PBR clearCoat anisotropy becomes available\r\n        // return this._material.clearCoat.anisotropy ?? 0;\r\n        return 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat tangent angle for anisotropy.\r\n     * Note: PBR clearCoat doesn't support anisotropy yet, so this is a placeholder.\r\n     * @param value The coat anisotropy rotation angle in radians (currently ignored)\r\n     */\r\n    public set geometryCoatTangentAngle(value: number) {\r\n        // TODO: Implement when PBR clearCoat anisotropy becomes available\r\n        // this._material.clearCoat.anisotropyAngle = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the coat tangent texture for anisotropy.\r\n     * Note: PBR clearCoat doesn't support anisotropy textures yet, so this is a placeholder.\r\n     * @param value The coat anisotropy texture (currently ignored)\r\n     */\r\n    public set geometryCoatTangentTexture(value: Nullable<BaseTexture>) {\r\n        // TODO: Implement when PBR clearCoat anisotropy becomes available\r\n        // this._material.clearCoat.anisotropyTangentTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the coat tangent texture for anisotropy.\r\n     * Note: PBR clearCoat doesn't support anisotropy textures yet, so this returns null.\r\n     * @returns Currently returns null as clearCoat anisotropy is not yet available\r\n     */\r\n    public get geometryCoatTangentTexture(): Nullable<BaseTexture> {\r\n        // TODO: Implement when PBR clearCoat anisotropy becomes available\r\n        // return this._material.clearCoat.anisotropyTangentTexture;\r\n        return null;\r\n    }\r\n\r\n    // ========================================\r\n    // TRANSMISSION LAYER\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the transmission weight (mapped to PBR subSurface.refractionIntensity).\r\n     * Enables refraction when value \\> 0.\r\n     * @param value The transmission weight value (0-1)\r\n     */\r\n    public set transmissionWeight(value: number) {\r\n        this._material.subSurface.isRefractionEnabled = value > 0;\r\n        this._material.subSurface.refractionIntensity = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the transmission weight.\r\n     * @returns The transmission weight value\r\n     */\r\n    public get transmissionWeight(): number {\r\n        return this._material.subSurface.isRefractionEnabled ? this._material.subSurface.refractionIntensity : 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission weight texture (mapped to PBR subSurface.refractionIntensityTexture).\r\n     * Automatically enables refraction and glTF-style textures.\r\n     * @param value The transmission weight texture or null\r\n     */\r\n    public set transmissionWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subSurface.isRefractionEnabled = true;\r\n        this._material.subSurface.refractionIntensityTexture = value;\r\n        this._material.subSurface.useGltfStyleTextures = true;\r\n    }\r\n\r\n    /**\r\n     * Sets the attenuation distance for volume.\r\n     * @param value The attenuation distance value\r\n     */\r\n    public set transmissionDepth(value: number) {\r\n        if (this.transmissionWeight > 0) {\r\n            this._material.subSurface.tintColorAtDistance = value;\r\n        } else if (this.subsurfaceWeight > 0) {\r\n            this._material.subSurface.diffusionDistance.multiplyInPlace(new Color3(value, value, value));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the attenuation distance for volume.\r\n     * @returns The attenuation distance value\r\n     */\r\n    public get transmissionDepth(): number {\r\n        if (this.transmissionWeight > 0) {\r\n            return this._material.subSurface.tintColorAtDistance;\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the attenuation color (mapped to PBR subSurface.tintColor).\r\n     * @param value The attenuation color as a Color3\r\n     */\r\n    public set transmissionColor(value: Color3) {\r\n        if (this.transmissionWeight > 0) {\r\n            this._material.subSurface.tintColor = value;\r\n        } else if (this.subsurfaceWeight > 0) {\r\n            this._material.subSurface.diffusionDistance.multiplyInPlace(value);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Sets the attenuation color (mapped to PBR subSurface.tintColor).\r\n     * @returns The attenuation color as a Color3\r\n     */\r\n    public get transmissionColor(): Color3 {\r\n        if (this.transmissionWeight > 0) {\r\n            return this._material.subSurface.tintColor;\r\n        } else if (this.subsurfaceWeight > 0) {\r\n            return this._material.subSurface.diffusionDistance;\r\n        }\r\n        return new Color3(0, 0, 0);\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission scatter coefficient.\r\n     * @param value The scatter coefficient as a Color3\r\n     */\r\n    public set transmissionScatter(value: Color3) {\r\n        // TODO convert from scatter coefficient to diffusion distance\r\n        this._material.subSurface.diffusionDistance = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission scatter coefficient.\r\n     * @returns The scatter coefficient as a Color3\r\n     */\r\n    public get transmissionScatter(): Color3 {\r\n        // TODO convert from diffusion distance to scatter coefficient\r\n        return this._material.subSurface.diffusionDistance;\r\n    }\r\n\r\n    public set transmissionScatterTexture(value: Nullable<BaseTexture>) {}\r\n\r\n    /**\r\n     * Sets the transmission scattering anisotropy.\r\n     * @param value The anisotropy intensity value (-1 to 1)\r\n     */\r\n    public set transmissionScatterAnisotropy(value: number) {\r\n        // No direct mapping in PBRMaterial\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission dispersion Abbe number.\r\n     * @param value The Abbe number value\r\n     */\r\n    public set transmissionDispersionAbbeNumber(value: number) {\r\n        // PBRMaterial assumes a fixed Abbe number of 20.0 for dispersion calculations.\r\n    }\r\n\r\n    /**\r\n     * Sets the transmission dispersion scale.\r\n     * @param value The dispersion scale value\r\n     */\r\n    public set transmissionDispersionScale(value: number) {\r\n        if (value > 0) {\r\n            this._material.subSurface.isDispersionEnabled = true;\r\n            this._material.subSurface.dispersion = 20.0 / value;\r\n        } else {\r\n            this._material.subSurface.isDispersionEnabled = false;\r\n            this._material.subSurface.dispersion = 0;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets the refraction background texture\r\n     * @returns The refraction background texture or null\r\n     */\r\n    public get refractionBackgroundTexture(): Nullable<BaseTexture> {\r\n        return this._material.subSurface.refractionTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the refraction background texture\r\n     * @param value The refraction background texture or null\r\n     */\r\n    public set refractionBackgroundTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subSurface.refractionTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Configures transmission for thin-surface transmission (KHR_materials_transmission).\r\n     * Sets up the material for proper thin-surface transmission behavior.\r\n     */\r\n    public configureTransmission(): void {\r\n        // Since this extension models thin-surface transmission only, we must make IOR = 1.0\r\n        this._material.subSurface.volumeIndexOfRefraction = 1.0;\r\n        // Albedo colour will tint transmission.\r\n        this._material.subSurface.useAlbedoToTintRefraction = true;\r\n        this._material.subSurface.minimumThickness = 0.0;\r\n        this._material.subSurface.maximumThickness = 0.0;\r\n    }\r\n\r\n    // ========================================\r\n    // VOLUME PROPERTIES\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures volume properties for PBR material. Nothing to do for PBRMaterial.\r\n     */\r\n    public configureVolume(): void {}\r\n\r\n    /**\r\n     * Sets whether the material is thin-walled (i.e. non-volumetric) or not.\r\n     */\r\n    public set geometryThinWalled(value: boolean) {}\r\n\r\n    /**\r\n     * Gets whether the material is thin-walled (i.e. non-volumetric) or not.\r\n     */\r\n    public get geometryThinWalled(): boolean {\r\n        return this._material.subSurface.maximumThickness === 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the thickness texture (mapped to PBR subSurface.thicknessTexture).\r\n     * Automatically enables refraction.\r\n     * @param value The thickness texture or null\r\n     */\r\n    public set volumeThicknessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subSurface.thicknessTexture = value;\r\n        this._material.subSurface.useGltfStyleTextures = true;\r\n    }\r\n\r\n    /**\r\n     * Sets the thickness factor (mapped to PBR subSurface.maximumThickness).\r\n     * Automatically enables refraction.\r\n     * @param value The thickness value\r\n     */\r\n    public set volumeThickness(value: number) {\r\n        this._material.subSurface.minimumThickness = 0.0;\r\n        this._material.subSurface.maximumThickness = value;\r\n        this._material.subSurface.useThicknessAsDepth = true;\r\n        if (value > 0) {\r\n            this._material.subSurface.volumeIndexOfRefraction = this._material.indexOfRefraction;\r\n        }\r\n    }\r\n\r\n    // ========================================\r\n    // SUBSURFACE PROPERTIES (Subsurface Scattering)\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures subsurface properties for PBR material\r\n     */\r\n    public configureSubsurface(): void {\r\n        this._material.subSurface.useGltfStyleTextures = true;\r\n\r\n        // Since this extension models thin-surface transmission only, we must make the\r\n        // internal IOR == 1.0 and set the thickness to 0.\r\n        this._material.subSurface.volumeIndexOfRefraction = 1.0;\r\n        this._material.subSurface.minimumThickness = 0.0;\r\n        this._material.subSurface.maximumThickness = 0.0;\r\n\r\n        // Tint color will be used for transmission.\r\n        this._material.subSurface.useAlbedoToTintTranslucency = false;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface weight\r\n     */\r\n    public set subsurfaceWeight(value: number) {\r\n        this._material.subSurface.isTranslucencyEnabled = value > 0;\r\n        this._material.subSurface.translucencyIntensity = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the subsurface weight\r\n     * @returns The subsurface weight value\r\n     */\r\n    public get subsurfaceWeight(): number {\r\n        return this._material.subSurface.isTranslucencyEnabled ? this._material.subSurface.translucencyIntensity : 0;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface weight texture\r\n     */\r\n    public set subsurfaceWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subSurface.translucencyIntensityTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface color.\r\n     * @param value The subsurface tint color as a Color3\r\n     */\r\n    public set subsurfaceColor(value: Color3) {\r\n        // PBRMaterial does not have a direct equivalent for subsurface color,\r\n        // We could set the base color to this value, wherever subsurfaceWeight > 0\r\n        // When scatterAnisotropy is 1, I believe we can approximate the subsurface effect quite well with\r\n        // Translucency and a diffusion distance\r\n        const extinctionCoefficient = new Vector3(-Math.log(this.transmissionColor.r), -Math.log(this.transmissionColor.g), -Math.log(this.transmissionColor.b));\r\n        extinctionCoefficient.scaleInPlace(1 / Math.max(this.transmissionDepth, 0.001));\r\n        const absorptionCoeff = extinctionCoefficient;\r\n        const maxChannel = Math.max(absorptionCoeff.x, Math.max(absorptionCoeff.y, absorptionCoeff.z));\r\n        const attenuationDistance = maxChannel > 0 ? 1.0 / maxChannel : 1;\r\n        this._material.subSurface.diffusionDistance = new Color3(\r\n            Math.exp(-absorptionCoeff.x * attenuationDistance),\r\n            Math.exp(-absorptionCoeff.y * attenuationDistance),\r\n            Math.exp(-absorptionCoeff.z * attenuationDistance)\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface color texture.\r\n     * @param value The subsurface tint texture or null\r\n     */\r\n    public set subsurfaceColorTexture(value: Nullable<BaseTexture>) {\r\n        // PBRMaterial does not have a direct equivalent for subsurface color texture,\r\n    }\r\n\r\n    /**\r\n     * Sets the surface tint of the material (when using subsurface scattering)\r\n     */\r\n    public set diffuseTransmissionTint(value: Color3) {\r\n        this._material.subSurface.tintColor = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the subsurface constant tint (when using subsurface scattering)\r\n     * @returns The subsurface constant tint as a Color3\r\n     */\r\n    public get diffuseTransmissionTint(): Color3 {\r\n        return this._material.subSurface.tintColor;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface constant tint texture (when using subsurface scattering)\r\n     * @param value The subsurface constant tint texture or null\r\n     */\r\n    public set diffuseTransmissionTintTexture(value: Nullable<BaseTexture>) {\r\n        this._material.subSurface.translucencyColorTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the subsurface radius (used for subsurface scattering)\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     * @returns The subsurface radius as a Color3\r\n     */\r\n    public get subsurfaceRadius(): number {\r\n        return 1.0;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface radius (used for subsurface scattering)\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     * @param value The subsurface radius as a number\r\n     */\r\n    public set subsurfaceRadius(value: number) {\r\n        //\r\n    }\r\n\r\n    /**\r\n     * Gets the subsurface radius scale (used for subsurface scattering)\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     * @returns The subsurface radius scale as a Color3\r\n     */\r\n    public get subsurfaceRadiusScale(): Color3 {\r\n        return this._material.subSurface.scatteringDiffusionProfile ?? Color3.White();\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface radius scale (used for subsurface scattering)\r\n     * subsurfaceRadiusScale * subsurfaceRadius gives the mean free path per color channel.\r\n     * @param value The subsurface radius scale as a Color3\r\n     */\r\n    public set subsurfaceRadiusScale(value: Color3) {\r\n        this._material.subSurface.scatteringDiffusionProfile = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the subsurface scattering anisotropy.\r\n     * Note: PBRMaterial does not have a direct equivalent, so this is a no-op.\r\n     * @param value The anisotropy intensity value (ignored for PBR)\r\n     */\r\n    public set subsurfaceScatterAnisotropy(value: number) {\r\n        // No equivalent in PBRMaterial\r\n    }\r\n\r\n    /**\r\n     * Does this material have a translucent surface (i.e. either transmission or subsurface)?\r\n     * @returns True if the material is translucent, false otherwise\r\n     */\r\n    public isTranslucent(): boolean {\r\n        return this.transmissionWeight > 0 || this.subsurfaceWeight > 0;\r\n    }\r\n\r\n    // ========================================\r\n    // FUZZ LAYER (Sheen)\r\n    // ========================================\r\n\r\n    /**\r\n     * Configures sheen for PBR material.\r\n     * Enables sheen and sets up proper configuration.\r\n     */\r\n    public configureFuzz(): void {\r\n        this._material.sheen.isEnabled = true;\r\n        this._material.sheen.useRoughnessFromMainTexture = false;\r\n        this._material.sheen.albedoScaling = true;\r\n    }\r\n\r\n    /**\r\n     * Sets the sheen weight (mapped to PBR sheen.intensity).\r\n     * Automatically enables sheen.\r\n     * @param value The sheen weight value\r\n     */\r\n    public set fuzzWeight(value: number) {\r\n        this._material.sheen.isEnabled = true;\r\n        this._material.sheen.intensity = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the fuzz weight texture.\r\n     * @param value The fuzz weight texture or null\r\n     */\r\n    public set fuzzWeightTexture(value: Nullable<BaseTexture>) {\r\n        // PBRMaterial sheen supports glTF-style sheen which doesn't\r\n        // use a separate texture for intensity. So we'll only set the\r\n        // weight texture if none is already assigned. If one's already\r\n        // assigned, we assume it contains the sheen color data.\r\n        if (!this._material.sheen.texture) {\r\n            this._material.sheen.texture = value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Sets the sheen color (mapped to PBR sheen.color).\r\n     * Automatically enables sheen.\r\n     * @param value The sheen color as a Color3\r\n     */\r\n    public set fuzzColor(value: Color3) {\r\n        this._material.sheen.isEnabled = true;\r\n        this._material.sheen.color = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the sheen color texture (mapped to PBR sheen.texture).\r\n     * Automatically enables sheen.\r\n     * @param value The sheen color texture or null\r\n     */\r\n    public set fuzzColorTexture(value: Nullable<BaseTexture>) {\r\n        this._material.sheen.texture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the sheen roughness (mapped to PBR sheen.roughness).\r\n     * Automatically enables sheen.\r\n     * @param value The sheen roughness value (0-1)\r\n     */\r\n    public set fuzzRoughness(value: number) {\r\n        this._material.sheen.isEnabled = true;\r\n        this._material.sheen.roughness = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the sheen roughness texture (mapped to PBR sheen.textureRoughness).\r\n     * Automatically enables sheen.\r\n     * @param value The sheen roughness texture or null\r\n     */\r\n    public set fuzzRoughnessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.sheen.isEnabled = true;\r\n        this._material.sheen.textureRoughness = value;\r\n    }\r\n\r\n    // ========================================\r\n    // ANISOTROPY\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the specular roughness anisotropy (mapped to PBR anisotropy.intensity).\r\n     * Automatically enables anisotropy.\r\n     * @param value The anisotropy intensity value\r\n     */\r\n    public set specularRoughnessAnisotropy(value: number) {\r\n        this._material.anisotropy.isEnabled = true;\r\n        this._material.anisotropy.intensity = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the specular roughness anisotropy.\r\n     * @returns The anisotropy intensity value\r\n     */\r\n    public get specularRoughnessAnisotropy(): number {\r\n        return this._material.anisotropy.intensity;\r\n    }\r\n\r\n    /**\r\n     * Sets the anisotropy rotation (mapped to PBR anisotropy.angle).\r\n     * Automatically enables anisotropy.\r\n     * @param value The anisotropy rotation angle in radians\r\n     */\r\n    public set geometryTangentAngle(value: number) {\r\n        this._material.anisotropy.isEnabled = true;\r\n        this._material.anisotropy.angle = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry tangent texture (mapped to PBR anisotropy.texture).\r\n     * Automatically enables anisotropy.\r\n     * @param value The anisotropy texture or null\r\n     */\r\n    public set geometryTangentTexture(value: Nullable<BaseTexture>) {\r\n        this._material.anisotropy.isEnabled = true;\r\n        this._material.anisotropy.texture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry tangent texture.\r\n     * @returns The anisotropy texture or null\r\n     */\r\n    public get geometryTangentTexture(): Nullable<BaseTexture> {\r\n        return this._material.anisotropy.texture;\r\n    }\r\n\r\n    /**\r\n     * Configures glTF-style anisotropy for the material.\r\n     * Note: PBR materials don't need this configuration, so this is a no-op.\r\n     * @param useGltfStyle Whether to use glTF-style anisotropy (ignored for PBR)\r\n     */\r\n    public configureGltfStyleAnisotropy(useGltfStyle: boolean = true): void {\r\n        // PBR materials don't need this configuration\r\n    }\r\n\r\n    // ========================================\r\n    // THIN FILM IRIDESCENCE\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the iridescence weight (mapped to PBR iridescence.intensity).\r\n     * Automatically enables iridescence.\r\n     * @param value The iridescence intensity value\r\n     */\r\n    public set thinFilmWeight(value: number) {\r\n        this._material.iridescence.isEnabled = value > 0;\r\n        this._material.iridescence.intensity = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the iridescence IOR (mapped to PBR iridescence.indexOfRefraction).\r\n     * @param value The iridescence IOR value\r\n     */\r\n    public set thinFilmIor(value: number) {\r\n        this._material.iridescence.indexOfRefraction = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the iridescence thickness minimum (mapped to PBR iridescence.minimumThickness).\r\n     * @param value The minimum thickness value in nanometers\r\n     */\r\n    public set thinFilmThicknessMinimum(value: number) {\r\n        this._material.iridescence.minimumThickness = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the iridescence thickness maximum (mapped to PBR iridescence.maximumThickness).\r\n     * @param value The maximum thickness value in nanometers\r\n     */\r\n    public set thinFilmThicknessMaximum(value: number) {\r\n        this._material.iridescence.maximumThickness = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the thin film weight texture (mapped to PBR iridescence.texture).\r\n     * @param value The thin film weight texture or null\r\n     */\r\n    public set thinFilmWeightTexture(value: Nullable<BaseTexture>) {\r\n        this._material.iridescence.texture = value;\r\n    }\r\n\r\n    /**\r\n     * Sets the iridescence thickness texture (mapped to PBR iridescence.thicknessTexture).\r\n     * @param value The iridescence thickness texture or null\r\n     */\r\n    public set thinFilmThicknessTexture(value: Nullable<BaseTexture>) {\r\n        this._material.iridescence.thicknessTexture = value;\r\n    }\r\n\r\n    // ========================================\r\n    // UNLIT MATERIALS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets whether the material is unlit.\r\n     * @param value True to make the material unlit\r\n     */\r\n    public set unlit(value: boolean) {\r\n        this._material.unlit = value;\r\n    }\r\n\r\n    // ========================================\r\n    // GEOMETRY PARAMETERS\r\n    // ========================================\r\n\r\n    /**\r\n     * Sets the geometry opacity (mapped to PBR alpha).\r\n     * @param value The opacity value (0-1)\r\n     */\r\n    public set geometryOpacity(value: number) {\r\n        this._material.alpha = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry opacity.\r\n     * @returns The opacity value (0-1)\r\n     */\r\n    public get geometryOpacity(): number {\r\n        return this._material.alpha;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry normal texture (mapped to PBR bumpTexture).\r\n     * Also forces irradiance computation in fragment shader for better lighting.\r\n     * @param value The normal texture or null\r\n     */\r\n    public set geometryNormalTexture(value: Nullable<BaseTexture>) {\r\n        this._material.bumpTexture = value;\r\n        this._material.forceIrradianceInFragment = true;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry normal texture.\r\n     * @returns The normal texture or null\r\n     */\r\n    public get geometryNormalTexture(): Nullable<BaseTexture> {\r\n        return this._material.bumpTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the normal map inversions for the material.\r\n     * @param invertX Whether to invert the normal map on the X axis\r\n     * @param invertY Whether to invert the normal map on the Y axis\r\n     */\r\n    public setNormalMapInversions(invertX: boolean, invertY: boolean): void {\r\n        this._material.invertNormalMapX = invertX;\r\n        this._material.invertNormalMapY = invertY;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry coat normal texture (mapped to PBR clearCoat.bumpTexture).\r\n     * Automatically enables clear coat.\r\n     * @param value The coat normal texture or null\r\n     */\r\n    public set geometryCoatNormalTexture(value: Nullable<BaseTexture>) {\r\n        this._material.clearCoat.isEnabled = true;\r\n        this._material.clearCoat.bumpTexture = value;\r\n    }\r\n\r\n    /**\r\n     * Gets the geometry coat normal texture.\r\n     * @returns The coat normal texture or null\r\n     */\r\n    public get geometryCoatNormalTexture(): Nullable<BaseTexture> {\r\n        return this._material.clearCoat.bumpTexture;\r\n    }\r\n\r\n    /**\r\n     * Sets the geometry coat normal texture scale.\r\n     * @param value The scale value for the coat normal texture\r\n     */\r\n    public set geometryCoatNormalTextureScale(value: number) {\r\n        if (this._material.clearCoat.bumpTexture) {\r\n            this._material.clearCoat.bumpTexture.level = value;\r\n        }\r\n    }\r\n}\r\n","import { type Nullable } from \"core/types\";\r\nimport { SphericalHarmonics, SphericalPolynomial } from \"core/Maths/sphericalPolynomial\";\r\nimport { Quaternion, Matrix } from \"core/Maths/math.vector.pure\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { RawCubeTexture } from \"core/Materials/Textures/rawCubeTexture\";\r\n\r\nimport { type IEXTLightsImageBased_LightReferenceImageBased, type IEXTLightsImageBased_LightImageBased, type IEXTLightsImageBased } from \"babylonjs-gltf2interface\";\r\nimport { type IScene } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"EXT_lights_image_based\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_lights_image_based/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_lights_image_based implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n    private _lights?: IEXTLightsImageBased_LightImageBased[];\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        delete this._lights;\r\n    }\r\n\r\n    /** @internal */\r\n    public onLoading(): void {\r\n        const extensions = this._loader.gltf.extensions;\r\n        if (extensions && extensions[this.name]) {\r\n            const extension = extensions[this.name] as IEXTLightsImageBased;\r\n            this._lights = extension.lights;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadSceneAsync(context: string, scene: IScene): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTLightsImageBased_LightReferenceImageBased>(context, scene, this.name, async (extensionContext, extension) => {\r\n            this._loader._allMaterialsDirtyRequired = true;\r\n\r\n            const promises = new Array<Promise<any>>();\r\n\r\n            promises.push(this._loader.loadSceneAsync(context, scene));\r\n\r\n            this._loader.logOpen(`${extensionContext}`);\r\n\r\n            const light = ArrayItem.Get(`${extensionContext}/light`, this._lights, extension.light);\r\n            promises.push(\r\n                // eslint-disable-next-line github/no-then\r\n                this._loadLightAsync(`/extensions/${this.name}/lights/${extension.light}`, light).then((texture) => {\r\n                    this._loader.babylonScene.environmentTexture = texture;\r\n                })\r\n            );\r\n\r\n            this._loader.logClose();\r\n\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadLightAsync(context: string, light: IEXTLightsImageBased_LightImageBased): Promise<BaseTexture> {\r\n        if (!light._loaded) {\r\n            const promises = new Array<Promise<any>>();\r\n\r\n            this._loader.logOpen(`${context}`);\r\n\r\n            const imageData = new Array<Array<ArrayBufferView>>(light.specularImages.length);\r\n            for (let mipmap = 0; mipmap < light.specularImages.length; mipmap++) {\r\n                const faces = light.specularImages[mipmap];\r\n                imageData[mipmap] = new Array<ArrayBufferView>(faces.length);\r\n                for (let face = 0; face < faces.length; face++) {\r\n                    const specularImageContext = `${context}/specularImages/${mipmap}/${face}`;\r\n                    this._loader.logOpen(`${specularImageContext}`);\r\n\r\n                    const index = faces[face];\r\n                    const image = ArrayItem.Get(specularImageContext, this._loader.gltf.images, index);\r\n                    promises.push(\r\n                        // eslint-disable-next-line github/no-then\r\n                        this._loader.loadImageAsync(`/images/${index}`, image).then((data) => {\r\n                            imageData[mipmap][face] = data;\r\n                        })\r\n                    );\r\n\r\n                    this._loader.logClose();\r\n                }\r\n            }\r\n\r\n            this._loader.logClose();\r\n\r\n            // eslint-disable-next-line github/no-then\r\n            light._loaded = Promise.all(promises).then(async () => {\r\n                const babylonTexture = new RawCubeTexture(this._loader.babylonScene, null, light.specularImageSize);\r\n                babylonTexture.name = light.name || \"environment\";\r\n                light._babylonTexture = babylonTexture;\r\n\r\n                if (light.intensity != undefined) {\r\n                    babylonTexture.level = light.intensity;\r\n                }\r\n\r\n                if (light.rotation) {\r\n                    let rotation = Quaternion.FromArray(light.rotation);\r\n\r\n                    // Invert the rotation so that positive rotation is counter-clockwise.\r\n                    if (!this._loader.babylonScene.useRightHandedSystem) {\r\n                        rotation = Quaternion.Inverse(rotation);\r\n                    }\r\n\r\n                    Matrix.FromQuaternionToRef(rotation, babylonTexture.getReflectionTextureMatrix());\r\n                }\r\n\r\n                if (!light.irradianceCoefficients) {\r\n                    throw new Error(`${context}: Irradiance coefficients are missing`);\r\n                }\r\n\r\n                const sphericalHarmonics = SphericalHarmonics.FromArray(light.irradianceCoefficients);\r\n                sphericalHarmonics.scaleInPlace(light.intensity);\r\n\r\n                sphericalHarmonics.convertIrradianceToLambertianRadiance();\r\n                const sphericalPolynomial = SphericalPolynomial.FromHarmonics(sphericalHarmonics);\r\n\r\n                // Compute the lod generation scale to fit exactly to the number of levels available.\r\n                const lodGenerationScale = (imageData.length - 1) / Math.log2(light.specularImageSize);\r\n                return await babylonTexture.updateRGBDAsync(imageData, sphericalPolynomial, lodGenerationScale);\r\n            });\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return light._loaded.then(() => {\r\n            return light._babylonTexture!;\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_lights_image_based glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_lights_image_based(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_lights_image_based(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_lights_image_based.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_lights_image_based.types\";\r\nexport * from \"./EXT_lights_image_based.pure\";\r\n\r\nimport { RegisterEXT_lights_image_based } from \"./EXT_lights_image_based.pure\";\r\nRegisterEXT_lights_image_based();\r\n","import { Vector3, Quaternion, Matrix, TmpVectors } from \"core/Maths/math.vector.pure\";\r\nimport { type Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { type INode } from \"../glTFLoaderInterfaces\";\r\nimport { type IEXTMeshGpuInstancing } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"EXT_mesh_gpu_instancing\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing/README.md)\r\n * [Playground Sample](https://playground.babylonjs.com/#QFIGLW#9)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_mesh_gpu_instancing implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTMeshGpuInstancing, TransformNode>(context, node, this.name, async (extensionContext, extension) => {\r\n            this._loader._disableInstancedMesh++;\r\n\r\n            const promise = this._loader.loadNodeAsync(`/nodes/${node.index}`, node, assign);\r\n\r\n            this._loader._disableInstancedMesh--;\r\n\r\n            if (!node._primitiveBabylonMeshes) {\r\n                return await promise;\r\n            }\r\n\r\n            const promises = new Array<Promise<Nullable<Float32Array>>>();\r\n            let instanceCount = 0;\r\n\r\n            const loadAttribute = (attribute: string) => {\r\n                if (extension.attributes[attribute] == undefined) {\r\n                    promises.push(Promise.resolve(null));\r\n                    return;\r\n                }\r\n\r\n                const accessor = ArrayItem.Get(`${extensionContext}/attributes/${attribute}`, this._loader.gltf.accessors, extension.attributes[attribute]);\r\n                promises.push(this._loader._loadFloatAccessorAsync(`/accessors/${accessor.bufferView}`, accessor));\r\n\r\n                if (instanceCount === 0) {\r\n                    instanceCount = accessor.count;\r\n                } else if (instanceCount !== accessor.count) {\r\n                    throw new Error(`${extensionContext}/attributes: Instance buffer accessors do not have the same count.`);\r\n                }\r\n            };\r\n\r\n            loadAttribute(\"TRANSLATION\");\r\n            loadAttribute(\"ROTATION\");\r\n            loadAttribute(\"SCALE\");\r\n            loadAttribute(\"_COLOR_0\");\r\n\r\n            // eslint-disable-next-line github/no-then\r\n            return await promise.then(async (babylonTransformNode) => {\r\n                const [translationBuffer, rotationBuffer, scaleBuffer, colorBuffer] = await Promise.all(promises);\r\n                const matrices = new Float32Array(instanceCount * 16);\r\n                TmpVectors.Vector3[0].copyFromFloats(0, 0, 0); // translation\r\n                TmpVectors.Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation\r\n                TmpVectors.Vector3[1].copyFromFloats(1, 1, 1); // scale\r\n                for (let i = 0; i < instanceCount; ++i) {\r\n                    translationBuffer && Vector3.FromArrayToRef(translationBuffer, i * 3, TmpVectors.Vector3[0]);\r\n                    rotationBuffer && Quaternion.FromArrayToRef(rotationBuffer, i * 4, TmpVectors.Quaternion[0]);\r\n                    scaleBuffer && Vector3.FromArrayToRef(scaleBuffer, i * 3, TmpVectors.Vector3[1]);\r\n\r\n                    Matrix.ComposeToRef(TmpVectors.Vector3[1], TmpVectors.Quaternion[0], TmpVectors.Vector3[0], TmpVectors.Matrix[0]);\r\n\r\n                    TmpVectors.Matrix[0].copyToArray(matrices, i * 16);\r\n                }\r\n                for (const babylonMesh of node._primitiveBabylonMeshes!) {\r\n                    (babylonMesh as Mesh).thinInstanceSetBuffer(\"matrix\", matrices, 16, true);\r\n                    if (colorBuffer) {\r\n                        if (colorBuffer.length === instanceCount * 3) {\r\n                            (babylonMesh as Mesh).thinInstanceSetBuffer(\"color\", colorBuffer, 3, true);\r\n                        } else if (colorBuffer.length === instanceCount * 4) {\r\n                            (babylonMesh as Mesh).thinInstanceSetBuffer(\"color\", colorBuffer, 4, true);\r\n                        } else {\r\n                            Logger.Warn(\"Unexpected size of _COLOR_0 attribute for mesh \" + babylonMesh.name);\r\n                        }\r\n                    }\r\n                }\r\n                return babylonTransformNode;\r\n            });\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_mesh_gpu_instancing glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_mesh_gpu_instancing(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_mesh_gpu_instancing(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_mesh_gpu_instancing.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_mesh_gpu_instancing.types\";\r\nexport * from \"./EXT_mesh_gpu_instancing.pure\";\r\n\r\nimport \"core/Meshes/thinInstanceMesh\";\r\n\r\nimport { RegisterEXT_mesh_gpu_instancing } from \"./EXT_mesh_gpu_instancing.pure\";\r\nRegisterEXT_mesh_gpu_instancing();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { ArrayItem, GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IBufferView } from \"../glTFLoaderInterfaces\";\r\nimport { type IEXTMeshoptCompression } from \"babylonjs-gltf2interface\";\r\nimport { MeshoptCompression } from \"core/Meshes/Compression/meshoptCompression\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"EXT_meshopt_compression\";\r\n\r\ninterface IBufferViewMeshopt extends IBufferView {\r\n    _meshOptData?: Promise<ArrayBufferView>;\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_meshopt_compression/README.md)\r\n *\r\n * This extension uses a WebAssembly decoder module from https://github.com/zeux/meshoptimizer/tree/master/js\r\n * @since 5.0.0\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_meshopt_compression implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n        this._loader = loader;\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadBufferViewAsync(context: string, bufferView: IBufferView): Nullable<Promise<ArrayBufferView>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTMeshoptCompression, ArrayBufferView>(context, bufferView, this.name, async (extensionContext, extension) => {\r\n            const bufferViewMeshopt = bufferView as IBufferViewMeshopt;\r\n            if (bufferViewMeshopt._meshOptData) {\r\n                return await bufferViewMeshopt._meshOptData;\r\n            }\r\n\r\n            const buffer = ArrayItem.Get(`${context}/buffer`, this._loader.gltf.buffers, extension.buffer);\r\n            bufferViewMeshopt._meshOptData = this._loader\r\n                .loadBufferAsync(`/buffers/${buffer.index}`, buffer, extension.byteOffset || 0, extension.byteLength)\r\n                // eslint-disable-next-line github/no-then\r\n                .then(async (buffer) => {\r\n                    return await MeshoptCompression.Default.decodeGltfBufferAsync(buffer as Uint8Array, extension.count, extension.byteStride, extension.mode, extension.filter);\r\n                });\r\n\r\n            return await bufferViewMeshopt._meshOptData;\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_meshopt_compression glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_meshopt_compression(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_meshopt_compression(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_meshopt_compression.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_meshopt_compression.types\";\r\nexport * from \"./EXT_meshopt_compression.pure\";\r\n\r\nimport { RegisterEXT_meshopt_compression } from \"./EXT_meshopt_compression.pure\";\r\nRegisterEXT_meshopt_compression();\r\n","import { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { type ITexture } from \"../glTFLoaderInterfaces\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type IEXTTextureWebP } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"EXT_texture_webp\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_texture_webp/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_texture_webp implements IGLTFLoaderExtension {\r\n    /** The name of this extension. */\r\n    public readonly name = NAME;\r\n\r\n    /** Defines whether this extension is enabled. */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTTextureWebP, BaseTexture>(context, texture, this.name, async (extensionContext, extension) => {\r\n            const sampler = texture.sampler == undefined ? GLTFLoader.DefaultSampler : ArrayItem.Get(`${context}/sampler`, this._loader.gltf.samplers, texture.sampler);\r\n            const image = ArrayItem.Get(`${extensionContext}/source`, this._loader.gltf.images, extension.source);\r\n            return await this._loader._createTextureAsync(\r\n                context,\r\n                sampler,\r\n                image,\r\n                (babylonTexture) => {\r\n                    assign(babylonTexture);\r\n                },\r\n                undefined,\r\n                !texture._textureInfo.nonColorData,\r\n                texture\r\n            );\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_texture_webp glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_texture_webp(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_texture_webp(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_texture_webp.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_texture_webp.types\";\r\nexport * from \"./EXT_texture_webp.pure\";\r\n\r\nimport { RegisterEXT_texture_webp } from \"./EXT_texture_webp.pure\";\r\nRegisterEXT_texture_webp();\r\n","import { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { type ITexture } from \"../glTFLoaderInterfaces\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type IEXTTextureAVIF } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"EXT_texture_avif\";\r\n\r\n/**\r\n * [glTF PR](https://github.com/KhronosGroup/glTF/pull/2235)\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_texture_avif/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_texture_avif implements IGLTFLoaderExtension {\r\n    /** The name of this extension. */\r\n    public readonly name = NAME;\r\n\r\n    /** Defines whether this extension is enabled. */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTTextureAVIF, BaseTexture>(context, texture, this.name, async (extensionContext, extension) => {\r\n            const sampler = texture.sampler == undefined ? GLTFLoader.DefaultSampler : ArrayItem.Get(`${context}/sampler`, this._loader.gltf.samplers, texture.sampler);\r\n            const image = ArrayItem.Get(`${extensionContext}/source`, this._loader.gltf.images, extension.source);\r\n            return await this._loader._createTextureAsync(\r\n                context,\r\n                sampler,\r\n                image,\r\n                (babylonTexture) => {\r\n                    assign(babylonTexture);\r\n                },\r\n                undefined,\r\n                !texture._textureInfo.nonColorData,\r\n                texture\r\n            );\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_texture_avif glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_texture_avif(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_texture_avif(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_texture_avif.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_texture_avif.types\";\r\nexport * from \"./EXT_texture_avif.pure\";\r\n\r\nimport { RegisterEXT_texture_avif } from \"./EXT_texture_avif.pure\";\r\nRegisterEXT_texture_avif();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { SpotLight } from \"core/Lights/spotLight.pure\";\r\nimport { Light } from \"core/Lights/light\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\n\r\nimport { type IEXTLightsIES_LightReference } from \"babylonjs-gltf2interface\";\r\nimport { type IEXTLightsIES_Light, type INode } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { Texture } from \"core/Materials/Textures/texture.pure\";\r\n\r\nconst NAME = \"EXT_lights_ies\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Vendor/EXT_lights_ies)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_lights_ies implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /** hidden */\r\n    private _loader: GLTFLoader;\r\n    private _lights?: IEXTLightsIES_Light[];\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        delete this._lights;\r\n    }\r\n\r\n    /** @internal */\r\n    public onLoading(): void {\r\n        const extensions = this._loader.gltf.extensions;\r\n        if (extensions && extensions[this.name]) {\r\n            const extension = extensions[this.name];\r\n            this._lights = extension.lights;\r\n            ArrayItem.Assign(this._lights);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTLightsIES_LightReference, TransformNode>(context, node, this.name, async (extensionContext, extension) => {\r\n            this._loader._allMaterialsDirtyRequired = true;\r\n\r\n            let babylonSpotLight: SpotLight;\r\n            let light: IEXTLightsIES_Light;\r\n\r\n            const transformNode = await this._loader.loadNodeAsync(context, node, (babylonMesh) => {\r\n                light = ArrayItem.Get(extensionContext, this._lights, extension.light);\r\n                const name = light.name || babylonMesh.name;\r\n\r\n                this._loader.babylonScene._blockEntityCollection = !!this._loader._assetContainer;\r\n\r\n                babylonSpotLight = new SpotLight(name, Vector3.Zero(), Vector3.Backward(), 0, 1, this._loader.babylonScene);\r\n                babylonSpotLight.angle = Math.PI / 2;\r\n                babylonSpotLight.innerAngle = 0;\r\n\r\n                babylonSpotLight._parentContainer = this._loader._assetContainer;\r\n                this._loader.babylonScene._blockEntityCollection = false;\r\n                light._babylonLight = babylonSpotLight;\r\n\r\n                babylonSpotLight.falloffType = Light.FALLOFF_GLTF;\r\n                babylonSpotLight.diffuse = extension.color ? Color3.FromArray(extension.color) : Color3.White();\r\n                babylonSpotLight.intensity = extension.multiplier || 1;\r\n                babylonSpotLight.range = Number.MAX_VALUE;\r\n                babylonSpotLight.parent = babylonMesh;\r\n\r\n                this._loader._babylonLights.push(babylonSpotLight);\r\n\r\n                GLTFLoader.AddPointerMetadata(babylonSpotLight, extensionContext);\r\n\r\n                assign(babylonMesh);\r\n            });\r\n\r\n            // Load the profile\r\n            let bufferData: ArrayBufferView;\r\n            if (light!.uri) {\r\n                bufferData = await this._loader.loadUriAsync(context, light!, light!.uri);\r\n            } else {\r\n                const bufferView = ArrayItem.Get(`${context}/bufferView`, this._loader.gltf.bufferViews, light!.bufferView);\r\n                bufferData = await this._loader.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView);\r\n            }\r\n            babylonSpotLight!.iesProfileTexture = new Texture(\r\n                babylonSpotLight!.name + \"_iesProfile\",\r\n                this._loader.babylonScene,\r\n                true,\r\n                false,\r\n                undefined,\r\n                null,\r\n                null,\r\n                bufferData,\r\n                true,\r\n                undefined,\r\n                undefined,\r\n                undefined,\r\n                undefined,\r\n                \".ies\"\r\n            );\r\n\r\n            return transformNode;\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_lights_ies glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_lights_ies(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_lights_ies(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_lights_ies.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_lights_ies.types\";\r\nexport * from \"./EXT_lights_ies.pure\";\r\n\r\nimport { RegisterEXT_lights_ies } from \"./EXT_lights_ies.pure\";\r\nRegisterEXT_lights_ies();\r\n","/* eslint-disable github/no-then */\r\nimport { DracoDecoder } from \"core/Meshes/Compression/dracoDecoder\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer.pure\";\r\nimport { type Geometry } from \"core/Meshes/geometry\";\r\nimport { type Mesh } from \"core/Meshes/mesh.pure\";\r\n\r\nimport { MeshPrimitiveMode, type IKHRDracoMeshCompression } from \"babylonjs-gltf2interface\";\r\nimport { type IMeshPrimitive, type IBufferView } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem, LoadBoundingInfoFromPositionAccessor } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_draco_mesh_compression\";\r\n\r\ninterface IBufferViewDraco extends IBufferView {\r\n    _dracoBabylonGeometry?: Promise<Geometry>;\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_draco_mesh_compression implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * The draco decoder used to decode vertex data or DracoDecoder.Default if not defined\r\n     */\r\n    public dracoDecoder?: DracoDecoder;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines whether to use the normalized flag from the glTF accessor instead of the Draco data. Defaults to true.\r\n     */\r\n    public useNormalizedFlagFromAccessor = true;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = DracoDecoder.DefaultAvailable && this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose(): void {\r\n        delete this.dracoDecoder;\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadVertexDataAsync(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRDracoMeshCompression, Geometry>(context, primitive, this.name, async (extensionContext, extension) => {\r\n            if (primitive.mode != undefined) {\r\n                if (primitive.mode !== MeshPrimitiveMode.TRIANGLES && primitive.mode !== MeshPrimitiveMode.TRIANGLE_STRIP) {\r\n                    throw new Error(`${context}: Unsupported mode ${primitive.mode}`);\r\n                }\r\n            }\r\n\r\n            const attributes: { [kind: string]: number } = {};\r\n            const normalized: { [kind: string]: boolean } = {};\r\n            const loadAttribute = (name: string, kind: string) => {\r\n                const uniqueId = extension.attributes[name];\r\n                if (uniqueId == undefined) {\r\n                    return;\r\n                }\r\n\r\n                babylonMesh._delayInfo = babylonMesh._delayInfo || [];\r\n                if (babylonMesh._delayInfo.indexOf(kind) === -1) {\r\n                    babylonMesh._delayInfo.push(kind);\r\n                }\r\n\r\n                attributes[kind] = uniqueId;\r\n\r\n                if (this.useNormalizedFlagFromAccessor) {\r\n                    const accessor = ArrayItem.TryGet(this._loader.gltf.accessors, primitive.attributes[name]);\r\n                    if (accessor) {\r\n                        normalized[kind] = accessor.normalized || false;\r\n                    }\r\n                }\r\n            };\r\n\r\n            loadAttribute(\"POSITION\", VertexBuffer.PositionKind);\r\n            loadAttribute(\"NORMAL\", VertexBuffer.NormalKind);\r\n            loadAttribute(\"TANGENT\", VertexBuffer.TangentKind);\r\n            loadAttribute(\"TEXCOORD_0\", VertexBuffer.UVKind);\r\n            loadAttribute(\"TEXCOORD_1\", VertexBuffer.UV2Kind);\r\n            loadAttribute(\"TEXCOORD_2\", VertexBuffer.UV3Kind);\r\n            loadAttribute(\"TEXCOORD_3\", VertexBuffer.UV4Kind);\r\n            loadAttribute(\"TEXCOORD_4\", VertexBuffer.UV5Kind);\r\n            loadAttribute(\"TEXCOORD_5\", VertexBuffer.UV6Kind);\r\n            loadAttribute(\"JOINTS_0\", VertexBuffer.MatricesIndicesKind);\r\n            loadAttribute(\"WEIGHTS_0\", VertexBuffer.MatricesWeightsKind);\r\n            loadAttribute(\"COLOR_0\", VertexBuffer.ColorKind);\r\n\r\n            const bufferView = ArrayItem.Get(extensionContext, this._loader.gltf.bufferViews, extension.bufferView) as IBufferViewDraco;\r\n            if (!bufferView._dracoBabylonGeometry) {\r\n                bufferView._dracoBabylonGeometry = this._loader.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then(async (data) => {\r\n                    const dracoDecoder = this.dracoDecoder || DracoDecoder.Default;\r\n                    const positionAccessor = ArrayItem.TryGet(this._loader.gltf.accessors, primitive.attributes[\"POSITION\"]);\r\n                    const babylonBoundingInfo =\r\n                        !this._loader.parent.alwaysComputeBoundingBox && !babylonMesh.skeleton && positionAccessor ? LoadBoundingInfoFromPositionAccessor(positionAccessor) : null;\r\n                    return await dracoDecoder\r\n                        ._decodeMeshToGeometryForGltfAsync(babylonMesh.name, this._loader.babylonScene, data, attributes, normalized, babylonBoundingInfo)\r\n                        .catch((error) => {\r\n                            throw new Error(`${context}: ${error.message}`);\r\n                        });\r\n                });\r\n            }\r\n\r\n            return await bufferView._dracoBabylonGeometry;\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_draco_mesh_compression glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_draco_mesh_compression(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_draco_mesh_compression(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_draco_mesh_compression.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_draco_mesh_compression.types\";\r\nexport * from \"./KHR_draco_mesh_compression.pure\";\r\n\r\nimport { RegisterKHR_draco_mesh_compression } from \"./KHR_draco_mesh_compression.pure\";\r\nRegisterKHR_draco_mesh_compression();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh.pure\";\r\nimport { GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh.pure\";\r\nimport { AllocateShBuffers } from \"core/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure\";\r\n\r\nimport { MeshPrimitiveMode, type IKHRGaussianSplatting } from \"babylonjs-gltf2interface\";\r\nimport { type IMeshPrimitive, type INode, type IMesh, type IAccessor } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_gaussian_splatting\";\r\n\r\n// Zeroth-order spherical harmonics coefficient used to reconstruct a base color from the SH DC term.\r\nconst ShC0 = 0.28209479177387814;\r\n\r\n// Attribute semantics defined by the KHR_gaussian_splatting ellipse kernel.\r\nconst RotationAttribute = \"KHR_gaussian_splatting:ROTATION\";\r\nconst ScaleAttribute = \"KHR_gaussian_splatting:SCALE\";\r\nconst OpacityAttribute = \"KHR_gaussian_splatting:OPACITY\";\r\nconst ShDegree0Attribute = \"KHR_gaussian_splatting:SH_DEGREE_0_COEF_0\";\r\n\r\n// Number of spherical harmonics coefficients (VEC3) for each degree beyond the DC term.\r\nconst ShCoefficientCountPerDegree = [0, 3, 5, 7];\r\n\r\nfunction Clamp255(value: number): number {\r\n    return value <= 0 ? 0 : value >= 255 ? 255 : (value + 0.5) | 0;\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_gaussian_splatting/README.md)\r\n * Loads a mesh primitive tagged with KHR_gaussian_splatting as a {@link GaussianSplattingMesh}.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_gaussian_splatting implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose(): void {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadMeshPrimitiveAsync(\r\n        context: string,\r\n        name: string,\r\n        node: INode,\r\n        mesh: IMesh,\r\n        primitive: IMeshPrimitive,\r\n        assign: (babylonMesh: AbstractMesh) => void\r\n    ): Nullable<Promise<AbstractMesh>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRGaussianSplatting, AbstractMesh>(context, primitive, this.name, async (extensionContext) => {\r\n            if (primitive.mode != undefined && primitive.mode !== MeshPrimitiveMode.POINTS) {\r\n                throw new Error(`${extensionContext}: Gaussian splatting primitives must use POINTS mode`);\r\n            }\r\n\r\n            const loader = this._loader;\r\n\r\n            const loadAttribute = (attributeName: string): Nullable<Promise<Float32Array>> => {\r\n                const accessorIndex = primitive.attributes[attributeName];\r\n                if (accessorIndex == undefined) {\r\n                    return null;\r\n                }\r\n                const accessor = ArrayItem.Get(`${context}/attributes/${attributeName}`, loader.gltf.accessors, accessorIndex) as IAccessor;\r\n                return loader._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor);\r\n            };\r\n\r\n            const positionsPromise = loadAttribute(\"POSITION\");\r\n            if (!positionsPromise) {\r\n                throw new Error(`${extensionContext}: Gaussian splatting primitive is missing the POSITION attribute`);\r\n            }\r\n\r\n            // Determine which spherical harmonics degrees are present (all lower degrees must exist per spec).\r\n            let shDegree = 0;\r\n            const shAttributeNames: string[] = [];\r\n            for (let degree = 1; degree <= 3; degree++) {\r\n                if (primitive.attributes[`KHR_gaussian_splatting:SH_DEGREE_${degree}_COEF_0`] == undefined) {\r\n                    break;\r\n                }\r\n                shDegree = degree;\r\n                for (let coef = 0; coef < ShCoefficientCountPerDegree[degree]; coef++) {\r\n                    shAttributeNames.push(`KHR_gaussian_splatting:SH_DEGREE_${degree}_COEF_${coef}`);\r\n                }\r\n            }\r\n\r\n            // Create the Gaussian Splatting mesh and assign it to the node synchronously (before awaiting the\r\n            // attribute data). The base loader wires the node's transform node from this assign call\r\n            // synchronously, so it must happen before the first await. The splat data is uploaded afterwards.\r\n            const scene = loader.babylonScene;\r\n            scene._blockEntityCollection = !!loader._assetContainer;\r\n            const gaussianSplattingMesh = new GaussianSplattingMesh(name, null, scene);\r\n            gaussianSplattingMesh._parentContainer = loader._assetContainer;\r\n            scene._blockEntityCollection = false;\r\n\r\n            GLTFLoader.AddPointerMetadata(gaussianSplattingMesh, context);\r\n            loader.parent.onMeshLoadedObservable.notifyObservers(gaussianSplattingMesh);\r\n            assign(gaussianSplattingMesh);\r\n\r\n            const engineCaps = scene.getEngine().getCaps();\r\n\r\n            const [positions, rotations, scales, opacities, shDegree0, colors, ...shHigherDegrees] = await Promise.all([\r\n                positionsPromise,\r\n                loadAttribute(RotationAttribute),\r\n                loadAttribute(ScaleAttribute),\r\n                loadAttribute(OpacityAttribute),\r\n                loadAttribute(ShDegree0Attribute),\r\n                loadAttribute(\"COLOR_0\"),\r\n                ...shAttributeNames.map((attributeName): Nullable<Promise<Float32Array>> => loadAttribute(attributeName)),\r\n            ]);\r\n\r\n            const splatCount = positions.length / 3;\r\n            const colorStride = colors ? colors.length / splatCount : 0;\r\n\r\n            const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32 bytes: position(12) scale(12) color RGBA(4) quaternion wxyz(4)\r\n            const buffer = new ArrayBuffer(rowOutputLength * splatCount);\r\n            const floatView = new Float32Array(buffer);\r\n            const byteView = new Uint8Array(buffer);\r\n\r\n            // Build spherical harmonics texture buffers for degrees above 0.\r\n            let shBuffers: Nullable<Uint8Array[]> = null;\r\n            if (shDegree > 0) {\r\n                const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\r\n                const shComponentCount = shVectorCount * 3;\r\n                const textureCount = Math.ceil(shComponentCount / 16);\r\n                const width = engineCaps.maxTextureSize;\r\n                const height = Math.ceil(splatCount / width);\r\n                shBuffers = AllocateShBuffers(textureCount, height * width * 4 * 4);\r\n            }\r\n\r\n            for (let i = 0; i < splatCount; i++) {\r\n                const floatBase = i * 8;\r\n                const byteBase = i * 32;\r\n                const p = i * 3;\r\n\r\n                // Position (float32 x3, bytes 0-11)\r\n                floatView[floatBase + 0] = positions[p + 0];\r\n                floatView[floatBase + 1] = positions[p + 1];\r\n                floatView[floatBase + 2] = positions[p + 2];\r\n\r\n                // Scale (float32 x3, bytes 12-23) — glTF stores linear scale directly.\r\n                floatView[floatBase + 3] = scales ? scales[p + 0] : 1;\r\n                floatView[floatBase + 4] = scales ? scales[p + 1] : 1;\r\n                floatView[floatBase + 5] = scales ? scales[p + 2] : 1;\r\n\r\n                // Color RGB (uint8 x3, bytes 24-26) — reconstructed from the SH DC term, or COLOR_0 as a fallback.\r\n                if (shDegree0) {\r\n                    byteView[byteBase + 24] = Clamp255((0.5 + ShC0 * shDegree0[p + 0]) * 255);\r\n                    byteView[byteBase + 25] = Clamp255((0.5 + ShC0 * shDegree0[p + 1]) * 255);\r\n                    byteView[byteBase + 26] = Clamp255((0.5 + ShC0 * shDegree0[p + 2]) * 255);\r\n                } else if (colors) {\r\n                    const c = i * colorStride;\r\n                    byteView[byteBase + 24] = Clamp255(colors[c + 0] * 255);\r\n                    byteView[byteBase + 25] = Clamp255(colors[c + 1] * 255);\r\n                    byteView[byteBase + 26] = Clamp255(colors[c + 2] * 255);\r\n                } else {\r\n                    byteView[byteBase + 24] = 255;\r\n                    byteView[byteBase + 25] = 255;\r\n                    byteView[byteBase + 26] = 255;\r\n                }\r\n\r\n                // Alpha (uint8, byte 27) — opacity is a normalized linear value per spec.\r\n                if (opacities) {\r\n                    byteView[byteBase + 27] = Clamp255(opacities[i] * 255);\r\n                } else if (colors && colorStride >= 4) {\r\n                    byteView[byteBase + 27] = Clamp255(colors[i * colorStride + 3] * 255);\r\n                } else {\r\n                    byteView[byteBase + 27] = 255;\r\n                }\r\n\r\n                // Quaternion (uint8 x4, bytes 28-31) stored as wxyz encoded as q * 127.5 + 127.5. glTF stores xyzw.\r\n                const r = i * 4;\r\n                const qx = rotations ? rotations[r + 0] : 0;\r\n                const qy = rotations ? rotations[r + 1] : 0;\r\n                const qz = rotations ? rotations[r + 2] : 0;\r\n                const qw = rotations ? rotations[r + 3] : 1;\r\n                byteView[byteBase + 28] = Clamp255(qw * 127.5 + 127.5);\r\n                byteView[byteBase + 29] = Clamp255(qx * 127.5 + 127.5);\r\n                byteView[byteBase + 30] = Clamp255(qy * 127.5 + 127.5);\r\n                byteView[byteBase + 31] = Clamp255(qz * 127.5 + 127.5);\r\n\r\n                // Spherical harmonics (coefficient-major, channel-minor) encoded as coeff * 128 + 128.\r\n                if (shBuffers) {\r\n                    const offsetPerSplat = i * 16;\r\n                    for (let coef = 0; coef < shHigherDegrees.length; coef++) {\r\n                        const coefData = shHigherDegrees[coef];\r\n                        if (!coefData) {\r\n                            continue;\r\n                        }\r\n                        for (let channel = 0; channel < 3; channel++) {\r\n                            const flatIndex = coef * 3 + channel;\r\n                            const textureIndex = flatIndex >> 4; // Math.floor(flatIndex / 16)\r\n                            const byteIndexInTexture = flatIndex & 15; // flatIndex % 16\r\n                            shBuffers[textureIndex][offsetPerSplat + byteIndexInTexture] = Clamp255(coefData[p + channel] * 128 + 128);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n            await gaussianSplattingMesh.updateDataAsync(buffer, shBuffers ?? undefined, undefined, shDegree || undefined);\r\n\r\n            return gaussianSplattingMesh;\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_gaussian_splatting glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_gaussian_splatting(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_gaussian_splatting(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_gaussian_splatting.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_gaussian_splatting.types\";\r\nexport * from \"./KHR_gaussian_splatting.pure\";\r\n\r\nimport { RegisterKHR_gaussian_splatting } from \"./KHR_gaussian_splatting.pure\";\r\nRegisterKHR_gaussian_splatting();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { DirectionalLight } from \"core/Lights/directionalLight.pure\";\r\nimport { PointLight } from \"core/Lights/pointLight.pure\";\r\nimport { SpotLight } from \"core/Lights/spotLight.pure\";\r\nimport { Light } from \"core/Lights/light\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\n\r\nimport { type IKHRLightsPunctual_LightReference, KHRLightsPunctual_LightType } from \"babylonjs-gltf2interface\";\r\nimport { type INode, type IKHRLightsPunctual_Light } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_lights_punctual\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_lights implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /** hidden */\r\n    private _loader: GLTFLoader;\r\n    private _lights?: IKHRLightsPunctual_Light[];\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        delete this._lights;\r\n    }\r\n\r\n    /** @internal */\r\n    public onLoading(): void {\r\n        const extensions = this._loader.gltf.extensions;\r\n        if (extensions && extensions[this.name]) {\r\n            const extension = extensions[this.name];\r\n            this._lights = extension.lights;\r\n            ArrayItem.Assign(this._lights);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRLightsPunctual_LightReference, TransformNode>(context, node, this.name, async (extensionContext, extension) => {\r\n            this._loader._allMaterialsDirtyRequired = true;\r\n\r\n            return await this._loader.loadNodeAsync(context, node, (babylonMesh) => {\r\n                let babylonLight: Light;\r\n\r\n                const light = ArrayItem.Get(extensionContext, this._lights, extension.light);\r\n                const name = light.name || babylonMesh.name;\r\n\r\n                this._loader.babylonScene._blockEntityCollection = !!this._loader._assetContainer;\r\n\r\n                switch (light.type) {\r\n                    case KHRLightsPunctual_LightType.DIRECTIONAL: {\r\n                        const babylonDirectionalLight = new DirectionalLight(name, Vector3.Backward(), this._loader.babylonScene);\r\n                        babylonDirectionalLight.position.setAll(0);\r\n                        babylonLight = babylonDirectionalLight;\r\n                        break;\r\n                    }\r\n                    case KHRLightsPunctual_LightType.POINT: {\r\n                        babylonLight = new PointLight(name, Vector3.Zero(), this._loader.babylonScene);\r\n                        break;\r\n                    }\r\n                    case KHRLightsPunctual_LightType.SPOT: {\r\n                        const babylonSpotLight = new SpotLight(name, Vector3.Zero(), Vector3.Backward(), 0, 1, this._loader.babylonScene);\r\n                        babylonSpotLight.angle = ((light.spot && light.spot.outerConeAngle) || Math.PI / 4) * 2;\r\n                        babylonSpotLight.innerAngle = ((light.spot && light.spot.innerConeAngle) || 0) * 2;\r\n                        babylonLight = babylonSpotLight;\r\n                        break;\r\n                    }\r\n                    default: {\r\n                        this._loader.babylonScene._blockEntityCollection = false;\r\n                        throw new Error(`${extensionContext}: Invalid light type (${light.type})`);\r\n                    }\r\n                }\r\n\r\n                babylonLight._parentContainer = this._loader._assetContainer;\r\n                this._loader.babylonScene._blockEntityCollection = false;\r\n                light._babylonLight = babylonLight;\r\n\r\n                babylonLight.falloffType = Light.FALLOFF_GLTF;\r\n                babylonLight.diffuse = light.color ? Color3.FromArray(light.color) : Color3.White();\r\n                babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;\r\n                babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;\r\n                babylonLight.parent = babylonMesh;\r\n\r\n                this._loader._babylonLights.push(babylonLight);\r\n\r\n                GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);\r\n\r\n                assign(babylonMesh);\r\n            });\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_lights glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_lights(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_lights(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_lights_punctual.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_lights_punctual.types\";\r\nexport * from \"./KHR_lights_punctual.pure\";\r\n\r\nimport { RegisterKHR_lights } from \"./KHR_lights_punctual.pure\";\r\nRegisterKHR_lights();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { Vector3, Quaternion } from \"core/Maths/math.vector.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { Light } from \"core/Lights/light\";\r\nimport { RectAreaLight } from \"core/Lights/rectAreaLight.pure\";\r\nimport { type TransformNode, TransformNode as BabylonTransformNode } from \"core/Meshes/transformNode.pure\";\r\n\r\nimport { type IEXTLightsArea_LightReference, EXTLightsArea_LightType } from \"babylonjs-gltf2interface\";\r\nimport { type INode, type IEXTLightsArea_Light } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"EXT_lights_area\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_lights_area/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class EXT_lights_area implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /** hidden */\r\n    private _loader: GLTFLoader;\r\n    private _lights?: IEXTLightsArea_Light[];\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        delete this._lights;\r\n    }\r\n\r\n    /** @internal */\r\n    public onLoading(): void {\r\n        const extensions = this._loader.gltf.extensions;\r\n        if (extensions && extensions[this.name]) {\r\n            const extension = extensions[this.name];\r\n            this._lights = extension.lights;\r\n            ArrayItem.Assign(this._lights);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return GLTFLoader.LoadExtensionAsync<IEXTLightsArea_LightReference, TransformNode>(context, node, this.name, async (extensionContext, extension) => {\r\n            this._loader._allMaterialsDirtyRequired = true;\r\n\r\n            return await this._loader.loadNodeAsync(context, node, (babylonMesh) => {\r\n                let babylonLight: Light;\r\n\r\n                const light = ArrayItem.Get(extensionContext, this._lights, extension.light);\r\n                const name = light.name || babylonMesh.name;\r\n\r\n                this._loader.babylonScene._blockEntityCollection = !!this._loader._assetContainer;\r\n                const size = light.size !== undefined ? light.size : 1.0;\r\n\r\n                switch (light.type) {\r\n                    case EXTLightsArea_LightType.RECT: {\r\n                        const width = light.rect?.aspect !== undefined ? light.rect.aspect * size : size;\r\n                        const height = size;\r\n                        const babylonRectAreaLight = new RectAreaLight(name, Vector3.Zero(), width, height, this._loader.babylonScene);\r\n                        babylonLight = babylonRectAreaLight;\r\n                        break;\r\n                    }\r\n                    case EXTLightsArea_LightType.DISK: {\r\n                        // For disk lights, we'll use a rectangle light with the same area to approximate the disk light\r\n                        // In the future, this could be extended to support actual disk area lights\r\n                        const newSize = Math.sqrt(size * size * 0.25 * Math.PI); // Area of the disk\r\n                        const babylonRectAreaLight = new RectAreaLight(name, Vector3.Zero(), newSize, newSize, this._loader.babylonScene);\r\n                        babylonLight = babylonRectAreaLight;\r\n                        break;\r\n                    }\r\n                    default: {\r\n                        this._loader.babylonScene._blockEntityCollection = false;\r\n                        throw new Error(`${extensionContext}: Invalid area light type (${light.type})`);\r\n                    }\r\n                }\r\n\r\n                babylonLight._parentContainer = this._loader._assetContainer;\r\n                this._loader.babylonScene._blockEntityCollection = false;\r\n                light._babylonLight = babylonLight;\r\n\r\n                babylonLight.falloffType = Light.FALLOFF_GLTF;\r\n                babylonLight.diffuse = light.color ? Color3.FromArray(light.color) : Color3.White();\r\n                babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;\r\n\r\n                // glTF EXT_lights_area specifies lights face down -Z, but Babylon.js area lights face down +Z\r\n                // Create a parent transform node with 180-degree rotation around Y axis to flip the direction\r\n                const lightParentNode = new BabylonTransformNode(`${name}_orientation`, this._loader.babylonScene);\r\n                lightParentNode.rotationQuaternion = Quaternion.RotationAxis(Vector3.Up(), Math.PI);\r\n                lightParentNode.parent = babylonMesh;\r\n                babylonLight.parent = lightParentNode;\r\n\r\n                this._loader._babylonLights.push(babylonLight);\r\n\r\n                GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);\r\n\r\n                assign(babylonMesh);\r\n            });\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the EXT_lights_area glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterEXT_lights_area(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new EXT_lights_area(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./EXT_lights_area.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./EXT_lights_area.types\";\r\nexport * from \"./EXT_lights_area.pure\";\r\n\r\nimport { RegisterEXT_lights_area } from \"./EXT_lights_area.pure\";\r\nRegisterEXT_lights_area();\r\n","import { type Nullable } from \"core/types\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { type Material } from \"core/Materials/material\";\r\n\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsPbrSpecularGlossiness } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_pbrSpecularGlossiness\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 200;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            this._loader.loadMaterialAlphaProperties(context, material, babylonMaterial);\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadSpecularGlossinessPropertiesAsync(context: string, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        adapter.configureSpecularGlossiness();\r\n\r\n        if (properties.diffuseFactor) {\r\n            adapter.baseColor = Color3.FromArray(properties.diffuseFactor);\r\n            babylonMaterial.alpha = properties.diffuseFactor[3];\r\n        } else {\r\n            adapter.baseColor = Color3.White();\r\n        }\r\n\r\n        adapter.specularColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : Color3.White();\r\n        adapter.glossiness = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;\r\n\r\n        if (properties.diffuseTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/diffuseTexture`, properties.diffuseTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Diffuse)`;\r\n                    adapter.baseColorTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.specularGlossinessTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/specularGlossinessTexture`, properties.specularGlossinessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Specular Glossiness)`;\r\n                    adapter.specularColorTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_pbrSpecularGlossiness glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_pbrSpecularGlossiness(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_pbrSpecularGlossiness(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_pbrSpecularGlossiness.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_pbrSpecularGlossiness.types\";\r\nexport * from \"./KHR_materials_pbrSpecularGlossiness.pure\";\r\n\r\nimport { RegisterKHR_materials_pbrSpecularGlossiness } from \"./KHR_materials_pbrSpecularGlossiness.pure\";\r\nRegisterKHR_materials_pbrSpecularGlossiness();\r\n","import { type Nullable } from \"core/types\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { type Material } from \"core/Materials/material\";\r\n\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_unlit\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_unlit/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_unlit implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 210;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync(context, material, this.name, async () => {\r\n            return await this._loadUnlitPropertiesAsync(context, material, babylonMaterial);\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadUnlitPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial)!;\r\n\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        const properties = material.pbrMetallicRoughness;\r\n        if (properties) {\r\n            if (properties.baseColorFactor) {\r\n                adapter.baseColor = Color3.FromArray(properties.baseColorFactor);\r\n                adapter.geometryOpacity = properties.baseColorFactor[3];\r\n            }\r\n\r\n            if (properties.baseColorTexture) {\r\n                promises.push(\r\n                    this._loader.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => {\r\n                        texture.name = `${babylonMaterial.name} (Base Color)`;\r\n                        adapter.baseColorTexture = texture;\r\n                    })\r\n                );\r\n            }\r\n        }\r\n        adapter.isUnlit = true;\r\n        if (material.doubleSided) {\r\n            adapter.backFaceCulling = false;\r\n            adapter.twoSidedLighting = true;\r\n        }\r\n\r\n        this._loader.loadMaterialAlphaProperties(context, material, babylonMaterial);\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_unlit glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_unlit(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_unlit(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_unlit.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_unlit.types\";\r\nexport * from \"./KHR_materials_unlit.pure\";\r\n\r\nimport { RegisterKHR_materials_unlit } from \"./KHR_materials_unlit.pure\";\r\nRegisterKHR_materials_unlit();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsClearcoat } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_clearcoat\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md)\r\n * [Playground Sample](https://www.babylonjs-playground.com/frame.html#7F7PN6#8)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_clearcoat implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 190;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsClearcoat>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            await Promise.all(promises);\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        // Set non-texture properties immediately\r\n        adapter.configureCoat();\r\n        adapter.coatWeight = properties.clearcoatFactor !== undefined ? properties.clearcoatFactor : 0;\r\n        adapter.coatRoughness = properties.clearcoatRoughnessFactor !== undefined ? properties.clearcoatRoughnessFactor : 0;\r\n\r\n        // Load textures\r\n        if (properties.clearcoatTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/clearcoatTexture`, properties.clearcoatTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (ClearCoat)`;\r\n                    adapter.coatWeightTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.clearcoatRoughnessTexture) {\r\n            (properties.clearcoatRoughnessTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/clearcoatRoughnessTexture`, properties.clearcoatRoughnessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (ClearCoat Roughness)`;\r\n                    adapter.coatRoughnessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.clearcoatNormalTexture) {\r\n            (properties.clearcoatNormalTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/clearcoatNormalTexture`, properties.clearcoatNormalTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (ClearCoat Normal)`;\r\n                    adapter.geometryCoatNormalTexture = texture;\r\n                    if (properties.clearcoatNormalTexture?.scale != undefined) {\r\n                        adapter.geometryCoatNormalTextureScale = properties.clearcoatNormalTexture.scale;\r\n                    }\r\n                })\r\n            );\r\n            adapter.setNormalMapInversions(!babylonMaterial.getScene().useRightHandedSystem, babylonMaterial.getScene().useRightHandedSystem);\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_clearcoat glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_clearcoat(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_clearcoat(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_clearcoat.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_clearcoat.types\";\r\nexport * from \"./KHR_materials_clearcoat.pure\";\r\n\r\nimport { RegisterKHR_materials_clearcoat } from \"./KHR_materials_clearcoat.pure\";\r\nRegisterKHR_materials_clearcoat();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsCoat } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\n\r\nconst NAME = \"KHR_materials_coat\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/6cb2cb84b504c245c49cf2e9a8ae16d26f72ac97/extensions/2.0/Khronos/KHR_materials_coat/README.md)\r\n * @experimental\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_coat implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 191;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * Defines whether the KHR_materials_openpbr extension is used, indicating that\r\n     * the material should be interpreted as OpenPBR (for coat, this might be necessary\r\n     * to interpret anisotropy correctly).\r\n     */\r\n    private useOpenPBR: boolean = false;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsCoat>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            if (material.extensions && material.extensions[\"KHR_materials_openpbr\"]) {\r\n                this.useOpenPBR = true;\r\n            }\r\n            promises.push(this._loadCoatPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            await Promise.all(promises);\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadCoatPropertiesAsync(context: string, properties: IKHRMaterialsCoat, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        // Set non-texture properties immediately\r\n        adapter.configureCoat();\r\n        adapter.coatWeight = properties.coatFactor !== undefined ? properties.coatFactor : 0;\r\n        adapter.coatRoughness = properties.coatRoughnessFactor !== undefined ? properties.coatRoughnessFactor : 0;\r\n\r\n        // Load textures\r\n        if (properties.coatTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/coatTexture`, properties.coatTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Coat)`;\r\n                    adapter.coatWeightTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.coatRoughnessTexture) {\r\n            (properties.coatRoughnessTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/coatRoughnessTexture`, properties.coatRoughnessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Coat Roughness)`;\r\n                    adapter.coatRoughnessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.coatNormalTexture) {\r\n            (properties.coatNormalTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/coatNormalTexture`, properties.coatNormalTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Coat Normal)`;\r\n                    adapter.geometryCoatNormalTexture = texture;\r\n                    if (properties.coatNormalTexture?.scale != undefined) {\r\n                        adapter.geometryCoatNormalTextureScale = properties.coatNormalTexture.scale;\r\n                    }\r\n                })\r\n            );\r\n            adapter.setNormalMapInversions(!babylonMaterial.getScene().useRightHandedSystem, babylonMaterial.getScene().useRightHandedSystem);\r\n        }\r\n\r\n        adapter.coatDarkening = properties.coatDarkeningFactor !== undefined ? properties.coatDarkeningFactor : 1;\r\n        adapter.coatIor = properties.coatIor !== undefined ? properties.coatIor : 1.5;\r\n\r\n        const colorFactor = Color3.White();\r\n        if (properties.coatColorFactor !== undefined) {\r\n            colorFactor.fromArray(properties.coatColorFactor);\r\n        }\r\n\r\n        adapter.coatColor = colorFactor;\r\n\r\n        if (properties.coatColorTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/coatColorTexture`, properties.coatColorTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Coat Color)`;\r\n                    adapter.coatColorTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // Set non-texture properties immediately\r\n        const coatAnisotropyWeight = properties.coatAnisotropyStrength ?? 0;\r\n        const coatAnisotropyAngle = properties.coatAnisotropyRotation ?? 0;\r\n\r\n        adapter.coatRoughnessAnisotropy = coatAnisotropyWeight;\r\n        adapter.geometryCoatTangentAngle = coatAnisotropyAngle;\r\n\r\n        // Check if this is glTF-style anisotropy\r\n        if (!this.useOpenPBR) {\r\n            adapter.configureGltfStyleAnisotropy(true);\r\n        }\r\n\r\n        // Load texture if present\r\n        if (properties.coatAnisotropyTexture) {\r\n            (properties.coatAnisotropyTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/coatAnisotropyTexture`, properties.coatAnisotropyTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Coat Anisotropy)`;\r\n                    adapter.geometryCoatTangentTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_coat glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_coat(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_coat(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_coat.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_coat.types\";\r\nexport * from \"./KHR_materials_coat.pure\";\r\n\r\nimport { RegisterKHR_materials_coat } from \"./KHR_materials_coat.pure\";\r\nRegisterKHR_materials_coat();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsIridescence } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_iridescence\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_iridescence/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_iridescence implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 195;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsIridescence>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        // Set non-texture properties immediately\r\n        adapter.thinFilmWeight = properties.iridescenceFactor ?? 0;\r\n        adapter.thinFilmIor = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3;\r\n        adapter.thinFilmThicknessMinimum = properties.iridescenceThicknessMinimum ?? 100;\r\n        adapter.thinFilmThicknessMaximum = properties.iridescenceThicknessMaximum ?? 400;\r\n\r\n        // Load textures\r\n        if (properties.iridescenceTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/iridescenceTexture`, properties.iridescenceTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Iridescence)`;\r\n                    adapter.thinFilmWeightTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.iridescenceThicknessTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/iridescenceThicknessTexture`, properties.iridescenceThicknessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Iridescence Thickness)`;\r\n                    adapter.thinFilmThicknessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_iridescence glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_iridescence(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_iridescence(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_iridescence.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_iridescence.types\";\r\nexport * from \"./KHR_materials_iridescence.pure\";\r\n\r\nimport { RegisterKHR_materials_iridescence } from \"./KHR_materials_iridescence.pure\";\r\nRegisterKHR_materials_iridescence();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsAnisotropy } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_anisotropy\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_anisotropy)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_anisotropy implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 195;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsAnisotropy>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadAnisotropyPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            await Promise.all(promises);\r\n        });\r\n    }\r\n\r\n    private async _loadAnisotropyPropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        // Set non-texture properties immediately\r\n        const anisotropyWeight = properties.anisotropyStrength ?? 0;\r\n        const anisotropyAngle = properties.anisotropyRotation ?? 0;\r\n\r\n        adapter.specularRoughnessAnisotropy = anisotropyWeight;\r\n        adapter.geometryTangentAngle = anisotropyAngle;\r\n\r\n        // Check if this is glTF-style anisotropy\r\n        const extensions = properties.extensions ?? {};\r\n        if (!extensions.EXT_materials_anisotropy_openpbr || !extensions.EXT_materials_anisotropy_openpbr.openPbrAnisotropyEnabled) {\r\n            adapter.configureGltfStyleAnisotropy(true);\r\n        }\r\n\r\n        // Load texture if present\r\n        if (properties.anisotropyTexture) {\r\n            (properties.anisotropyTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/anisotropyTexture`, properties.anisotropyTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Anisotropy Intensity)`;\r\n                    adapter.geometryTangentTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        await Promise.all(promises);\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_anisotropy glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_anisotropy(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_anisotropy(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_anisotropy.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_anisotropy.types\";\r\nexport * from \"./KHR_materials_anisotropy.pure\";\r\n\r\nimport { RegisterKHR_materials_anisotropy } from \"./KHR_materials_anisotropy.pure\";\r\nRegisterKHR_materials_anisotropy();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\n\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsEmissiveStrength } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_emissive_strength\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_emissive_strength implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 170;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsEmissiveStrength>(context, material, this.name, async (extensionContext, extension) => {\r\n            await this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial);\r\n            this._loadEmissiveProperties(extensionContext, extension, babylonMaterial);\r\n            return await Promise.resolve();\r\n        });\r\n    }\r\n\r\n    private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void {\r\n        if (properties.emissiveStrength !== undefined) {\r\n            const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n            adapter.emissionLuminance = properties.emissiveStrength;\r\n        }\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_emissive_strength glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_emissive_strength(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_emissive_strength(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_emissive_strength.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_emissive_strength.types\";\r\nexport * from \"./KHR_materials_emissive_strength.pure\";\r\n\r\nimport { RegisterKHR_materials_emissive_strength } from \"./KHR_materials_emissive_strength.pure\";\r\nRegisterKHR_materials_emissive_strength();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { type IKHRMaterialsSheen } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_sheen\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_sheen/README.md)\r\n * [Playground Sample](https://www.babylonjs-playground.com/frame.html#BNIZX6#4)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_sheen implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 190;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsSheen>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        adapter.configureFuzz();\r\n\r\n        // Set non-texture properties immediately\r\n        const sheenColor = properties.sheenColorFactor !== undefined ? Color3.FromArray(properties.sheenColorFactor) : Color3.Black();\r\n        const sheenRoughness = properties.sheenRoughnessFactor !== undefined ? properties.sheenRoughnessFactor : 0.0;\r\n\r\n        adapter.fuzzWeight = 1; // KHR_materials_sheen assumes intensity of 1\r\n        adapter.fuzzColor = sheenColor;\r\n        adapter.fuzzRoughness = sheenRoughness;\r\n\r\n        // Load textures\r\n        if (properties.sheenColorTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/sheenColorTexture`, properties.sheenColorTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Sheen Color)`;\r\n                    adapter.fuzzColorTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.sheenRoughnessTexture) {\r\n            (properties.sheenRoughnessTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/sheenRoughnessTexture`, properties.sheenRoughnessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Sheen Roughness)`;\r\n                    adapter.fuzzRoughnessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_sheen glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_sheen(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_sheen(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_sheen.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_sheen.types\";\r\nexport * from \"./KHR_materials_sheen.pure\";\r\n\r\nimport { RegisterKHR_materials_sheen } from \"./KHR_materials_sheen.pure\";\r\nRegisterKHR_materials_sheen();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { type IKHRMaterialsFuzz } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_fuzz\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/9734e44accd0dfb986ec5f376117aa00192745fe/extensions/2.0/Khronos/KHR_materials_fuzz/README.md)\r\n * @experimental\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_fuzz implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 190;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsFuzz>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadFuzzPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadFuzzPropertiesAsync(context: string, properties: IKHRMaterialsFuzz, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        adapter.configureFuzz();\r\n\r\n        // Set non-texture properties immediately\r\n        adapter.fuzzWeight = properties.fuzzFactor !== undefined ? properties.fuzzFactor : 0.0;\r\n        adapter.fuzzColor = properties.fuzzColorFactor !== undefined ? Color3.FromArray(properties.fuzzColorFactor) : Color3.White();\r\n        adapter.fuzzRoughness = properties.fuzzRoughnessFactor !== undefined ? properties.fuzzRoughnessFactor : 0.5;\r\n\r\n        // Load textures\r\n        if (properties.fuzzTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/fuzzTexture`, properties.fuzzTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Fuzz)`;\r\n                    adapter.fuzzWeightTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.fuzzColorTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/fuzzColorTexture`, properties.fuzzColorTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Fuzz Color)`;\r\n                    adapter.fuzzColorTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.fuzzRoughnessTexture) {\r\n            (properties.fuzzRoughnessTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/fuzzRoughnessTexture`, properties.fuzzRoughnessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Fuzz Roughness)`;\r\n                    adapter.fuzzRoughnessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_fuzz glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_fuzz(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_fuzz(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_fuzz.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_fuzz.types\";\r\nexport * from \"./KHR_materials_fuzz.pure\";\r\n\r\nimport { RegisterKHR_materials_fuzz } from \"./KHR_materials_fuzz.pure\";\r\nRegisterKHR_materials_fuzz();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { type IEXTMaterialsSpecularEdgeColor, type IKHRMaterialsSpecular } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_specular\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_specular implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 190;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsSpecular>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            // Handle the EXT_materials_specular_edge_color sub-extension\r\n            // https://github.com/KhronosGroup/glTF/blob/2a1111b88f052cbd3e2d82abb9faee56e7494904/extensions/2.0/Vendor/EXT_materials_specular_edge_color/README.md\r\n            const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n            if (extension.extensions && extension.extensions.EXT_materials_specular_edge_color) {\r\n                const specularEdgeColorExtension = extension.extensions.EXT_materials_specular_edge_color as IEXTMaterialsSpecularEdgeColor;\r\n                if (specularEdgeColorExtension.specularEdgeColorEnabled) {\r\n                    adapter.enableSpecularEdgeColor(true);\r\n                }\r\n            }\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        // Set non-texture properties immediately\r\n        adapter.specularWeight = properties.specularFactor ?? 1.0;\r\n        adapter.specularColor = properties.specularColorFactor !== undefined ? Color3.FromArray(properties.specularColorFactor) : new Color3(1, 1, 1);\r\n\r\n        if (properties.specularTexture) {\r\n            (properties.specularTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Specular)`;\r\n                    adapter.specularWeightTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (properties.specularColorTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/specularColorTexture`, properties.specularColorTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Specular Color)`;\r\n                    adapter.specularColorTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_specular glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_specular(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_specular(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_specular.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_specular.types\";\r\nexport * from \"./KHR_materials_specular.pure\";\r\n\r\nimport { RegisterKHR_materials_specular } from \"./KHR_materials_specular.pure\";\r\nRegisterKHR_materials_specular();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\n\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsIor } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_ior\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_ior/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_ior implements IGLTFLoaderExtension {\r\n    /**\r\n     * Default ior Value from the spec.\r\n     */\r\n    private static readonly _DEFAULT_IOR = 1.5;\r\n\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 180;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsIor>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const indexOfRefraction = properties.ior !== undefined ? properties.ior : KHR_materials_ior._DEFAULT_IOR;\r\n        adapter.specularIor = indexOfRefraction;\r\n\r\n        return Promise.resolve();\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_ior glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_ior(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_ior(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_ior.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_ior.types\";\r\nexport * from \"./KHR_materials_ior.pure\";\r\n\r\nimport { RegisterKHR_materials_ior } from \"./KHR_materials_ior.pure\";\r\nRegisterKHR_materials_ior();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\n\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { type Node } from \"core/node\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { type INode, type IMeshPrimitive, type IMesh } from \"../glTFLoaderInterfaces\";\r\nimport { type IKHRMaterialVariants_Mapping, type IKHRMaterialVariants_Variant, type IKHRMaterialVariants_Variants } from \"babylonjs-gltf2interface\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_variants\";\r\n\r\n// eslint-disable-next-line @typescript-eslint/naming-convention, jsdoc/require-jsdoc\r\nexport type MaterialVariantsController = {\r\n    /**\r\n     * The list of available variant names for this asset.\r\n     */\r\n    readonly variants: readonly string[];\r\n\r\n    /**\r\n     * Gets or sets the selected variant.\r\n     */\r\n    selectedVariant: string;\r\n};\r\n\r\ninterface IVariantsMap {\r\n    [key: string]: Array<{ mesh: AbstractMesh; material: Nullable<Material> }>;\r\n}\r\n\r\ninterface IExtensionMetadata {\r\n    lastSelected: Nullable<string | Array<string>>;\r\n    original: Array<{ mesh: AbstractMesh; material: Nullable<Material> }>;\r\n    variants: IVariantsMap;\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_variants/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_variants implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    private _variants?: Array<IKHRMaterialVariants_Variant>;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME) && !this._loader.parent.skipMaterials;\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * Gets the list of available variant names for this asset.\r\n     * @param rootNode The glTF root node\r\n     * @returns the list of all the variant names for this model\r\n     */\r\n    public static GetAvailableVariants(rootNode: TransformNode): string[] {\r\n        const extensionMetadata = this._GetExtensionMetadata(rootNode);\r\n        if (!extensionMetadata) {\r\n            return [];\r\n        }\r\n\r\n        return Object.keys(extensionMetadata.variants);\r\n    }\r\n\r\n    /**\r\n     * Gets the list of available variant names for this asset.\r\n     * @param rootNode The glTF root node\r\n     * @returns the list of all the variant names for this model\r\n     */\r\n    public getAvailableVariants(rootNode: TransformNode): string[] {\r\n        return KHR_materials_variants.GetAvailableVariants(rootNode);\r\n    }\r\n\r\n    /**\r\n     * Select a variant given a variant name or a list of variant names.\r\n     * @param rootNode The glTF root node\r\n     * @param variantName The variant name(s) to select.\r\n     */\r\n    public static SelectVariant(rootNode: TransformNode, variantName: string | string[]): void {\r\n        const extensionMetadata = this._GetExtensionMetadata(rootNode);\r\n        if (!extensionMetadata) {\r\n            throw new Error(`Cannot select variant on a glTF mesh that does not have the ${NAME} extension`);\r\n        }\r\n\r\n        const select = (variantName: string): void => {\r\n            const entries = extensionMetadata.variants[variantName];\r\n            if (entries) {\r\n                for (const entry of entries) {\r\n                    entry.mesh.material = entry.material;\r\n                }\r\n            }\r\n        };\r\n\r\n        if (variantName instanceof Array) {\r\n            for (const name of variantName) {\r\n                select(name);\r\n            }\r\n        } else {\r\n            select(variantName);\r\n        }\r\n\r\n        extensionMetadata.lastSelected = variantName;\r\n    }\r\n\r\n    /**\r\n     * Select a variant given a variant name or a list of variant names.\r\n     * @param rootNode The glTF root node\r\n     * @param variantName The variant name(s) to select.\r\n     */\r\n    public selectVariant(rootNode: TransformNode, variantName: string | string[]): void {\r\n        KHR_materials_variants.SelectVariant(rootNode, variantName);\r\n    }\r\n\r\n    /**\r\n     * Reset back to the original before selecting a variant.\r\n     * @param rootNode The glTF root node\r\n     */\r\n    public static Reset(rootNode: TransformNode): void {\r\n        const extensionMetadata = this._GetExtensionMetadata(rootNode);\r\n        if (!extensionMetadata) {\r\n            throw new Error(`Cannot reset on a glTF mesh that does not have the ${NAME} extension`);\r\n        }\r\n\r\n        for (const entry of extensionMetadata.original) {\r\n            entry.mesh.material = entry.material;\r\n        }\r\n\r\n        extensionMetadata.lastSelected = null;\r\n    }\r\n\r\n    /**\r\n     * Reset back to the original before selecting a variant.\r\n     * @param rootNode The glTF root node\r\n     */\r\n    public reset(rootNode: TransformNode): void {\r\n        KHR_materials_variants.Reset(rootNode);\r\n    }\r\n\r\n    /**\r\n     * Gets the last selected variant name(s) or null if original.\r\n     * @param rootNode The glTF root node\r\n     * @returns The selected variant name(s).\r\n     */\r\n    public static GetLastSelectedVariant(rootNode: TransformNode): Nullable<string | string[]> {\r\n        const extensionMetadata = this._GetExtensionMetadata(rootNode);\r\n        if (!extensionMetadata) {\r\n            throw new Error(`Cannot get the last selected variant on a glTF mesh that does not have the ${NAME} extension`);\r\n        }\r\n\r\n        return extensionMetadata.lastSelected;\r\n    }\r\n\r\n    /**\r\n     * Gets the last selected variant name(s) or null if original.\r\n     * @param rootNode The glTF root node\r\n     * @returns The selected variant name(s).\r\n     */\r\n    public getLastSelectedVariant(rootNode: TransformNode): Nullable<string | string[]> {\r\n        return KHR_materials_variants.GetLastSelectedVariant(rootNode);\r\n    }\r\n\r\n    private static _GetExtensionMetadata(rootNode: Nullable<TransformNode>): Nullable<IExtensionMetadata> {\r\n        return rootNode?._internalMetadata?.gltf?.[NAME] || null;\r\n    }\r\n\r\n    /** @internal */\r\n    public onLoading(): void {\r\n        const extensions = this._loader.gltf.extensions;\r\n        if (extensions && extensions[this.name]) {\r\n            const extension = extensions[this.name] as IKHRMaterialVariants_Variants;\r\n            this._variants = extension.variants;\r\n        }\r\n    }\r\n\r\n    /** @internal */\r\n    public onReady(): void {\r\n        const rootNode = this._loader.rootBabylonMesh;\r\n        if (rootNode) {\r\n            const options = this._loader.parent.extensionOptions[NAME];\r\n            if (options?.defaultVariant) {\r\n                KHR_materials_variants.SelectVariant(rootNode, options.defaultVariant);\r\n            }\r\n\r\n            options?.onLoaded?.({\r\n                get variants() {\r\n                    return KHR_materials_variants.GetAvailableVariants(rootNode);\r\n                },\r\n                get selectedVariant(): string {\r\n                    const lastSelectedVariant = KHR_materials_variants.GetLastSelectedVariant(rootNode);\r\n                    if (!lastSelectedVariant) {\r\n                        return KHR_materials_variants.GetAvailableVariants(rootNode)[0];\r\n                    }\r\n                    if (Array.isArray(lastSelectedVariant)) {\r\n                        return lastSelectedVariant[0];\r\n                    }\r\n                    return lastSelectedVariant;\r\n                },\r\n                set selectedVariant(variantName) {\r\n                    KHR_materials_variants.SelectVariant(rootNode, variantName);\r\n                },\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadMeshPrimitiveAsync(\r\n        context: string,\r\n        name: string,\r\n        node: INode,\r\n        mesh: IMesh,\r\n        primitive: IMeshPrimitive,\r\n        assign: (babylonMesh: AbstractMesh) => void\r\n    ): Nullable<Promise<AbstractMesh>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialVariants_Mapping, AbstractMesh>(context, primitive, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(\r\n                this._loader._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, (babylonMesh) => {\r\n                    assign(babylonMesh);\r\n\r\n                    if (babylonMesh instanceof Mesh) {\r\n                        const babylonDrawMode = GLTFLoader._GetDrawMode(context, primitive.mode);\r\n\r\n                        const root = this._loader.rootBabylonMesh;\r\n                        const metadata = root ? (root._internalMetadata = root._internalMetadata || {}) : {};\r\n                        const gltf = (metadata.gltf = metadata.gltf || {});\r\n                        const extensionMetadata: IExtensionMetadata = (gltf[NAME] = gltf[NAME] || { lastSelected: null, original: [], variants: {} });\r\n\r\n                        // Store the original material.\r\n                        extensionMetadata.original.push({ mesh: babylonMesh, material: babylonMesh.material });\r\n\r\n                        // For each mapping, look at the variants and make a new entry for them.\r\n                        for (let mappingIndex = 0; mappingIndex < extension.mappings.length; ++mappingIndex) {\r\n                            const mapping = extension.mappings[mappingIndex];\r\n                            const material = ArrayItem.Get(`${extensionContext}/mappings/${mappingIndex}/material`, this._loader.gltf.materials, mapping.material);\r\n                            promises.push(\r\n                                this._loader._loadMaterialAsync(`#/materials/${mapping.material}`, material, babylonMesh, babylonDrawMode, (babylonMaterial) => {\r\n                                    for (let mappingVariantIndex = 0; mappingVariantIndex < mapping.variants.length; ++mappingVariantIndex) {\r\n                                        const variantIndex = mapping.variants[mappingVariantIndex];\r\n                                        const variant = ArrayItem.Get(`/extensions/${NAME}/variants/${variantIndex}`, this._variants, variantIndex);\r\n                                        extensionMetadata.variants[variant.name] = extensionMetadata.variants[variant.name] || [];\r\n                                        extensionMetadata.variants[variant.name].push({\r\n                                            mesh: babylonMesh,\r\n                                            material: babylonMaterial,\r\n                                        });\r\n\r\n                                        // Replace the target when original mesh is cloned\r\n                                        babylonMesh.onClonedObservable.add((newOne: Node) => {\r\n                                            const newMesh = newOne as Mesh;\r\n                                            let metadata: Nullable<IExtensionMetadata>;\r\n                                            let newRoot: Nullable<Node> = newMesh;\r\n\r\n                                            // Find root to get medata\r\n                                            do {\r\n                                                newRoot = newRoot.parent;\r\n                                                if (!newRoot) {\r\n                                                    return;\r\n                                                }\r\n                                                metadata = KHR_materials_variants._GetExtensionMetadata(newRoot as Mesh);\r\n                                            } while (metadata === null);\r\n\r\n                                            // Need to clone the metadata on the root (first time only)\r\n                                            if (root && metadata === KHR_materials_variants._GetExtensionMetadata(root)) {\r\n                                                // Copy main metadata\r\n                                                newRoot._internalMetadata = {};\r\n                                                for (const key in root._internalMetadata) {\r\n                                                    newRoot._internalMetadata[key] = root._internalMetadata[key];\r\n                                                }\r\n\r\n                                                // Copy the gltf metadata\r\n                                                newRoot._internalMetadata.gltf = [];\r\n                                                for (const key in root._internalMetadata.gltf) {\r\n                                                    newRoot._internalMetadata.gltf[key] = root._internalMetadata.gltf[key];\r\n                                                }\r\n\r\n                                                // Duplicate the extension specific metadata\r\n                                                newRoot._internalMetadata.gltf[NAME] = { lastSelected: null, original: [], variants: {} };\r\n                                                for (const original of metadata.original) {\r\n                                                    newRoot._internalMetadata.gltf[NAME].original.push({\r\n                                                        mesh: original.mesh,\r\n                                                        material: original.material,\r\n                                                    });\r\n                                                }\r\n                                                for (const key in metadata.variants) {\r\n                                                    if (Object.prototype.hasOwnProperty.call(metadata.variants, key)) {\r\n                                                        newRoot._internalMetadata.gltf[NAME].variants[key] = [];\r\n                                                        for (const variantEntry of metadata.variants[key]) {\r\n                                                            newRoot._internalMetadata.gltf[NAME].variants[key].push({\r\n                                                                mesh: variantEntry.mesh,\r\n                                                                material: variantEntry.material,\r\n                                                            });\r\n                                                        }\r\n                                                    }\r\n                                                }\r\n\r\n                                                metadata = newRoot._internalMetadata.gltf[NAME];\r\n                                            }\r\n\r\n                                            // Relocate\r\n                                            for (const target of metadata!.original) {\r\n                                                if (target.mesh === babylonMesh) {\r\n                                                    target.mesh = newMesh;\r\n                                                }\r\n                                            }\r\n                                            for (const target of metadata!.variants[variant.name]) {\r\n                                                if (target.mesh === babylonMesh) {\r\n                                                    target.mesh = newMesh;\r\n                                                }\r\n                                            }\r\n                                        });\r\n                                    }\r\n                                })\r\n                            );\r\n                        }\r\n                    }\r\n                })\r\n            );\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(([babylonMesh]) => {\r\n                return babylonMesh;\r\n            });\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_variants glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_variants(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_variants(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_variants.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_variants.types\";\r\nexport * from \"./KHR_materials_variants.pure\";\r\n\r\nimport { RegisterKHR_materials_variants } from \"./KHR_materials_variants.pure\";\r\nRegisterKHR_materials_variants();\r\n","import { type Nullable } from \"core/types\";\nimport { type Material } from \"core/Materials/material\";\nimport { MultiMaterial } from \"core/Materials/multiMaterial\";\nimport { type Scene } from \"core/scene\";\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\nimport { type SubMesh } from \"core/Meshes/subMesh\";\nimport { type Texture } from \"core/Materials/Textures/texture\";\nimport { RenderTargetTexture } from \"core/Materials/Textures/renderTargetTexture\";\nimport { type Observer, Observable } from \"core/Misc/observable\";\nimport { Constants } from \"core/Engines/constants\";\nimport { Tools } from \"core/Misc/tools\";\nimport { type Color4 } from \"core/Maths/math.color\";\nimport { type IMaterialLoadingAdapter } from \"../materialLoadingAdapter\";\nimport { type GLTFLoader } from \"../glTFLoader\";\n\n/**\n * Describes a material class and its corresponding loading adapter.\n * Passed to TransmissionHelper so it can classify and interact with materials\n * independently of any specific loader instance.\n */\nexport interface ITransmissionHelperMaterialImpl {\n    /** The material class constructor */\n    materialClass: typeof Material;\n    /** The adapter class constructor */\n    adapterClass: new (material: Material) => IMaterialLoadingAdapter;\n}\n\n/**\n * @internal\n */\nexport interface ITransmissionHelperHolder {\n    /** The transmission helper instance, if created on the scene */\n    _transmissionHelper: TransmissionHelper | undefined;\n}\n\n/**\n * Options for the TransmissionHelper.\n */\nexport interface ITransmissionHelperOptions {\n    /**\n     * The size of the render buffers (default: 1024)\n     */\n    renderSize: number;\n\n    /**\n     * The number of samples to use when generating the render target texture for opaque meshes (default: 4)\n     */\n    samples: number;\n\n    /**\n     * Scale to apply when selecting the LOD level to sample the refraction texture (default: 1)\n     */\n    lodGenerationScale: number;\n\n    /**\n     * Offset to apply when selecting the LOD level to sample the refraction texture (default: -4)\n     */\n    lodGenerationOffset: number;\n\n    /**\n     * Type of the refraction render target texture (default: TEXTURETYPE_HALF_FLOAT)\n     */\n    renderTargetTextureType: number;\n\n    /**\n     * Defines if the mipmaps for the refraction render target texture must be generated (default: true)\n     */\n    generateMipmaps: boolean;\n\n    /**\n     * Clear color of the opaque texture. If not provided, use the scene clear color (which will be converted to linear space).\n     * If provided, should be in linear space\n     */\n    clearColor?: Color4;\n}\n\n/**\n * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects.\n * @internal\n */\nexport class TransmissionHelper {\n    /**\n     * Creates the default options for the helper.\n     * @returns the default options\n     */\n    private static _GetDefaultOptions(): ITransmissionHelperOptions {\n        return {\n            renderSize: 1024,\n            samples: 4,\n            lodGenerationScale: 1,\n            lodGenerationOffset: -4,\n            renderTargetTextureType: Constants.TEXTURETYPE_HALF_FLOAT,\n            generateMipmaps: true,\n        };\n    }\n\n    private readonly _scene: Scene & ITransmissionHelperHolder;\n\n    private _options: ITransmissionHelperOptions;\n\n    private _opaqueRenderTarget: Nullable<RenderTargetTexture> = null;\n    private _opaqueMeshesCache: AbstractMesh[] = [];\n    private _transparentMeshesCache: AbstractMesh[] = [];\n    private _materialObservers: { [id: string]: Nullable<Observer<AbstractMesh>> } = {};\n    private _newMeshObserver: Nullable<Observer<AbstractMesh>> = null;\n    private _removedMeshObserver: Nullable<Observer<AbstractMesh>> = null;\n    private _disposed = false;\n\n    // Material implementations registered by loaders. Each entry maps a material class\n    // to its adapter class so the helper can classify and interact with materials\n    // independently of whichever loader originally created them.\n    private readonly _materialImpls: ITransmissionHelperMaterialImpl[] = [];\n    private readonly _adapterCache: WeakMap<Material, IMaterialLoadingAdapter> = new WeakMap();\n\n    /**\n     * This observable will be notified with any error during the creation of the environment,\n     * mainly texture creation errors.\n     */\n    public onErrorObservable: Observable<{ message?: string; exception?: any }>;\n\n    // For MultiMaterial meshes with mixed opaque/translucent sub-materials:\n    // maps mesh → set of materialIndex values that are translucent.\n    private _translucentMaterialIndices: Map<AbstractMesh, Set<number>> = new Map();\n    // Precomputed opaque-only submesh arrays for mixed meshes, swapped in\n    // during the opaque RT render to avoid per-frame allocations.\n    private _opaqueOnlySubMeshes: Map<AbstractMesh, SubMesh[]> = new Map();\n    private _savedSubMeshes: Map<AbstractMesh, SubMesh[]> = new Map();\n\n    /**\n     * constructor\n     * @param options Defines the options we want to customize the helper\n     * @param scene The scene to add the material to\n     */\n    constructor(options: Partial<ITransmissionHelperOptions>, scene: Scene) {\n        this._options = {\n            ...TransmissionHelper._GetDefaultOptions(),\n            ...options,\n        };\n        this._scene = scene as any;\n        this._scene._transmissionHelper = this;\n\n        this.onErrorObservable = new Observable();\n        this._scene.onDisposeObservable.addOnce(() => {\n            this.dispose();\n        });\n\n        this._parseScene();\n        this._setupRenderTargets();\n    }\n\n    /**\n     * Registers a material implementation with the helper so it can classify and create\n     * adapters for materials of that type. Safe to call multiple times with the same\n     * implementation — duplicates are ignored.\n     * @param impl The material implementation to register\n     */\n    public addMaterialImpl(impl: ITransmissionHelperMaterialImpl): void {\n        if (!this._materialImpls.some((i) => i.materialClass === impl.materialClass)) {\n            this._materialImpls.push(impl);\n        }\n    }\n\n    /**\n     * Updates the helper options.\n     * @param options the options to update\n     */\n    public updateOptions(options: Partial<ITransmissionHelperOptions>) {\n        // First check if any options are actually being changed. If not, exit.\n        const newValues = Object.keys(options).filter((key: string) => (this._options as any)[key] !== (options as any)[key]);\n        if (!newValues.length) {\n            return;\n        }\n\n        const newOptions = {\n            ...this._options,\n            ...options,\n        };\n\n        const oldOptions = this._options;\n        this._options = newOptions;\n\n        // If size changes, recreate everything\n        if (\n            newOptions.renderSize !== oldOptions.renderSize ||\n            newOptions.renderTargetTextureType !== oldOptions.renderTargetTextureType ||\n            newOptions.generateMipmaps !== oldOptions.generateMipmaps ||\n            !this._opaqueRenderTarget\n        ) {\n            this._setupRenderTargets();\n        } else {\n            this._opaqueRenderTarget.samples = newOptions.samples;\n            this._opaqueRenderTarget.lodGenerationScale = newOptions.lodGenerationScale;\n            this._opaqueRenderTarget.lodGenerationOffset = newOptions.lodGenerationOffset;\n        }\n    }\n\n    /**\n     * @returns the opaque render target texture or null if not available.\n     */\n    public getOpaqueTarget(): Nullable<Texture> {\n        return this._opaqueRenderTarget;\n    }\n\n    private _getOrCreateAdapter(material: Material): IMaterialLoadingAdapter | undefined {\n        let adapter = this._adapterCache.get(material);\n        if (!adapter) {\n            for (const impl of this._materialImpls) {\n                if (material instanceof impl.materialClass) {\n                    adapter = new impl.adapterClass(material);\n                    this._adapterCache.set(material, adapter);\n                    break;\n                }\n            }\n        }\n        return adapter;\n    }\n\n    /**\n     * Classify a mesh's materials as transparent, opaque, or mixed.\n     * Sets the refraction background texture on any translucent materials found.\n     * For mixed MultiMaterial meshes, populates _translucentMaterialIndices so\n     * their translucent submeshes can be excluded from the opaque render target.\n     * @param mesh - The mesh to classify\n     * @returns 'transparent' if all materials are translucent, 'opaque' if none are, 'mixed' if both\n     */\n    private _classifyMeshMaterials(mesh: AbstractMesh): \"transparent\" | \"opaque\" | \"mixed\" {\n        const material = mesh.material;\n        if (!material) {\n            return \"opaque\";\n        }\n\n        // Single material case\n        if (!(material instanceof MultiMaterial)) {\n            const adapter = this._getOrCreateAdapter(material);\n            if (!adapter) {\n                return \"opaque\";\n            }\n            if (adapter.isTranslucent()) {\n                adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\n                return \"transparent\";\n            }\n            return \"opaque\";\n        }\n\n        // MultiMaterial case: check each sub-material individually\n        let hasTranslucent = false;\n        let hasOpaque = false;\n        const translucentIndices = new Set<number>();\n\n        for (let i = 0; i < material.subMaterials.length; i++) {\n            const subMat = material.subMaterials[i];\n            if (!subMat) {\n                hasOpaque = true;\n                continue;\n            }\n            const adapter = this._getOrCreateAdapter(subMat);\n            if (adapter) {\n                if (adapter.isTranslucent()) {\n                    adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\n                    hasTranslucent = true;\n                    translucentIndices.add(i);\n                } else {\n                    hasOpaque = true;\n                }\n            } else {\n                hasOpaque = true;\n            }\n        }\n\n        if (hasTranslucent && hasOpaque) {\n            this._translucentMaterialIndices.set(mesh, translucentIndices);\n            this._rebuildOpaqueOnlySubMeshes(mesh, translucentIndices);\n            return \"mixed\";\n        }\n        this._translucentMaterialIndices.delete(mesh);\n        this._opaqueOnlySubMeshes.delete(mesh);\n        return hasTranslucent ? \"transparent\" : \"opaque\";\n    }\n\n    /**\n     * Rebuild the cached opaque-only submesh array for a mixed mesh.\n     * Called when classification changes so the per-frame swap is allocation-free.\n     * @param mesh - The mesh to rebuild for\n     * @param translucentIndices - Set of materialIndex values that are translucent\n     */\n    private _rebuildOpaqueOnlySubMeshes(mesh: AbstractMesh, translucentIndices: Set<number>): void {\n        if (mesh.subMeshes) {\n            this._opaqueOnlySubMeshes.set(\n                mesh,\n                mesh.subMeshes.filter((sm: SubMesh) => !translucentIndices.has(sm.materialIndex))\n            );\n        }\n    }\n\n    private _addMesh(mesh: AbstractMesh): void {\n        this._materialObservers[mesh.uniqueId] = mesh.onMaterialChangedObservable.add(this._onMeshMaterialChanged.bind(this));\n\n        // we need to defer the processing because _addMesh may be called as part as an instance mesh creation, in which case some\n        // internal properties are not setup yet, like _sourceMesh (needed when doing mesh.material below)\n        Tools.SetImmediate(() => {\n            // Guard: skip if the helper was disposed before this deferred callback fires.\n            // Without this, a disposed helper with a null _opaqueRenderTarget would stamp\n            // null onto transmission materials, overriding any texture already assigned by\n            // an active frame graph or other external code.\n            if (this._disposed) {\n                return;\n            }\n            if (mesh.material) {\n                const classification = this._classifyMeshMaterials(mesh);\n                if (classification === \"transparent\") {\n                    if (this._transparentMeshesCache.indexOf(mesh) === -1) {\n                        this._transparentMeshesCache.push(mesh);\n                    }\n                } else {\n                    // Both 'opaque' and 'mixed' go in the opaque cache.\n                    // For 'mixed', the translucent submeshes are temporarily\n                    // excluded during the opaque render target render.\n                    if (this._opaqueMeshesCache.indexOf(mesh) === -1) {\n                        this._opaqueMeshesCache.push(mesh);\n                    }\n                }\n            }\n        });\n    }\n\n    private _removeMesh(mesh: AbstractMesh): void {\n        mesh.onMaterialChangedObservable.remove(this._materialObservers[mesh.uniqueId]);\n        delete this._materialObservers[mesh.uniqueId];\n        let idx = this._transparentMeshesCache.indexOf(mesh);\n        if (idx !== -1) {\n            this._transparentMeshesCache.splice(idx, 1);\n        }\n        idx = this._opaqueMeshesCache.indexOf(mesh);\n        if (idx !== -1) {\n            this._opaqueMeshesCache.splice(idx, 1);\n        }\n        this._translucentMaterialIndices.delete(mesh);\n        this._opaqueOnlySubMeshes.delete(mesh);\n    }\n\n    private _parseScene(): void {\n        this._scene.meshes.forEach(this._addMesh.bind(this));\n        // Listen for when a mesh is added to the scene and add it to our cache lists.\n        this._newMeshObserver = this._scene.onNewMeshAddedObservable.add(this._addMesh.bind(this));\n        // Listen for when a mesh is removed from to the scene and remove it from our cache lists.\n        this._removedMeshObserver = this._scene.onMeshRemovedObservable.add(this._removeMesh.bind(this));\n    }\n\n    // When one of the meshes in the scene has its material changed, make sure that it's in the correct cache list.\n    private _onMeshMaterialChanged(mesh: AbstractMesh) {\n        const transparentIdx = this._transparentMeshesCache.indexOf(mesh);\n        const opaqueIdx = this._opaqueMeshesCache.indexOf(mesh);\n\n        const classification = this._classifyMeshMaterials(mesh);\n\n        if (classification === \"transparent\") {\n            // Fully translucent: move to transparent cache\n            if (opaqueIdx !== -1) {\n                this._opaqueMeshesCache.splice(opaqueIdx, 1);\n                this._transparentMeshesCache.push(mesh);\n            } else if (transparentIdx === -1) {\n                this._transparentMeshesCache.push(mesh);\n            }\n        } else {\n            // Opaque or mixed: move to opaque cache (mixed meshes have their\n            // translucent submeshes excluded during opaque RT render)\n            if (transparentIdx !== -1) {\n                this._transparentMeshesCache.splice(transparentIdx, 1);\n                this._opaqueMeshesCache.push(mesh);\n            } else if (opaqueIdx === -1) {\n                this._opaqueMeshesCache.push(mesh);\n            }\n        }\n    }\n\n    /**\n     * @internal\n     * Check if the opaque render target has not been disposed and can still be used.\n     * @returns\n     */\n    public _isRenderTargetValid() {\n        return this._opaqueRenderTarget?.getInternalTexture() !== null;\n    }\n\n    /**\n     * @internal\n     * Setup the render targets according to the specified options.\n     */\n    public _setupRenderTargets(): void {\n        if (this._opaqueRenderTarget) {\n            this._opaqueRenderTarget.dispose();\n        }\n        this._opaqueRenderTarget = new RenderTargetTexture(\n            \"opaqueSceneTexture\",\n            this._options.renderSize,\n            this._scene,\n            this._options.generateMipmaps,\n            undefined,\n            this._options.renderTargetTextureType\n        );\n        this._opaqueRenderTarget.ignoreCameraViewport = true;\n        this._opaqueRenderTarget.renderList = this._opaqueMeshesCache;\n        // The opaque cache holds every opaque mesh of the scene, regardless of the camera currently rendering.\n        // Providing a renderList normally disables the layerMask check, which would make meshes hidden from the\n        // active camera show up in the refraction texture, so force the check back on.\n        this._opaqueRenderTarget.forceLayerMaskCheck = true;\n        this._opaqueRenderTarget.clearColor = this._options.clearColor?.clone() ?? this._scene.clearColor.clone();\n        this._opaqueRenderTarget.clearColor.a = 0.0;\n        this._opaqueRenderTarget.gammaSpace = false;\n        this._opaqueRenderTarget.lodGenerationScale = this._options.lodGenerationScale;\n        this._opaqueRenderTarget.lodGenerationOffset = this._options.lodGenerationOffset;\n        this._opaqueRenderTarget.samples = this._options.samples;\n        this._opaqueRenderTarget.renderSprites = true;\n        this._opaqueRenderTarget.renderParticles = true;\n        this._opaqueRenderTarget.disableImageProcessing = true;\n\n        let saveSceneEnvIntensity: number;\n        this._opaqueRenderTarget.onBeforeBindObservable.add((opaqueRenderTarget) => {\n            saveSceneEnvIntensity = this._scene.environmentIntensity;\n            this._scene.environmentIntensity = 1.0;\n            if (!this._options.clearColor) {\n                this._scene.clearColor.toLinearSpaceToRef(opaqueRenderTarget.clearColor, this._scene.getEngine().useExactSrgbConversions);\n            } else {\n                opaqueRenderTarget.clearColor.copyFrom(this._options.clearColor);\n            }\n            opaqueRenderTarget.clearColor.a = 0.0;\n\n            // For mixed MultiMaterial meshes, swap in the precomputed opaque-only\n            // submesh array so translucent submeshes don't render into the opaque texture.\n            const tlEntries = this._opaqueOnlySubMeshes.entries();\n            for (let tlEntry = tlEntries.next(); !tlEntry.done; tlEntry = tlEntries.next()) {\n                const mesh = tlEntry.value[0];\n                const opaqueOnly = tlEntry.value[1];\n                if (mesh.subMeshes) {\n                    this._savedSubMeshes.set(mesh, mesh.subMeshes);\n                    mesh.subMeshes = opaqueOnly;\n                }\n            }\n        });\n        this._opaqueRenderTarget.onAfterUnbindObservable.add(() => {\n            this._scene.environmentIntensity = saveSceneEnvIntensity;\n\n            // Restore the full submesh list after the opaque RT render\n            const savedEntries = this._savedSubMeshes.entries();\n            for (let savedEntry = savedEntries.next(); !savedEntry.done; savedEntry = savedEntries.next()) {\n                savedEntry.value[0].subMeshes = savedEntry.value[1];\n            }\n            this._savedSubMeshes.clear();\n        });\n\n        // Update refraction textures on transparent and mixed meshes\n        for (const mesh of this._transparentMeshesCache) {\n            if (mesh.material) {\n                this._classifyMeshMaterials(mesh);\n            }\n        }\n        const mixedEntries = this._translucentMaterialIndices.entries();\n        for (let mixedEntry = mixedEntries.next(); !mixedEntry.done; mixedEntry = mixedEntries.next()) {\n            const mesh = mixedEntry.value[0];\n            if (mesh.material) {\n                this._classifyMeshMaterials(mesh);\n            }\n        }\n    }\n\n    /**\n     * Dispose all the elements created by the Helper.\n     */\n    public dispose(): void {\n        // Set the disposed flag first so any pending SetImmediate callbacks (from _addMesh)\n        // are no-ops. Without this guard a deferred _classifyMeshMaterials call would stamp\n        // a null _opaqueRenderTarget onto transmission materials after disposal.\n        this._disposed = true;\n\n        // Unregister scene-level observers so this helper stops reacting to mesh changes.\n        this._newMeshObserver?.remove();\n        this._removedMeshObserver?.remove();\n        this._newMeshObserver = null;\n        this._removedMeshObserver = null;\n\n        // Remove per-mesh material-change observers for all tracked meshes.\n        const allTracked = [...this._transparentMeshesCache, ...this._opaqueMeshesCache];\n        for (const mesh of allTracked) {\n            const observer = this._materialObservers[mesh.uniqueId];\n            if (observer) {\n                observer.remove();\n                delete this._materialObservers[mesh.uniqueId];\n            }\n        }\n\n        // Also remove any remaining observers that were registered before deferred\n        // classification added their meshes to the caches.\n        for (const mesh of this._scene.meshes) {\n            const observer = this._materialObservers[mesh.uniqueId];\n            if (observer) {\n                observer.remove();\n                delete this._materialObservers[mesh.uniqueId];\n            }\n        }\n\n        this._materialObservers = {};\n\n        this._scene._transmissionHelper = undefined;\n        if (this._opaqueRenderTarget) {\n            this._opaqueRenderTarget.dispose();\n            this._opaqueRenderTarget = null;\n        }\n        this._transparentMeshesCache = [];\n        this._opaqueMeshesCache = [];\n        this._translucentMaterialIndices.clear();\n        this._opaqueOnlySubMeshes.clear();\n        this._savedSubMeshes.clear();\n    }\n}\n\n/**\n * Ensures a TransmissionHelper exists on the scene and has all of the loader's material\n * implementations registered with it. Creates the helper if one does not yet exist on the\n * scene, and recreates its render target if it has been disposed. Does nothing when the\n * loader's parent has `dontUseTransmissionHelper` set.\n * @param loader The glTF loader whose material implementations should be registered\n * @param babylonMaterial A material belonging to the scene where the helper should live\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ensureTransmissionHelper(loader: GLTFLoader, babylonMaterial: Material): void {\n    if (loader.parent.dontUseTransmissionHelper) {\n        return;\n    }\n    const scene = babylonMaterial.getScene() as unknown as ITransmissionHelperHolder;\n    const existingHelper = scene._transmissionHelper;\n    const helper = existingHelper ?? new TransmissionHelper({}, babylonMaterial.getScene());\n    for (const impl of Array.from(loader._pbrMaterialImpls.values())) {\n        helper.addMaterialImpl(impl);\n    }\n    if (existingHelper && !existingHelper._isRenderTargetValid()) {\n        existingHelper._setupRenderTargets();\n    }\n}\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsTransmission } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { ensureTransmissionHelper } from \"./transmissionHelper\";\r\n\r\nconst NAME = \"KHR_materials_transmission\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_transmission/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_transmission implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 175;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n        if (this.enabled) {\r\n            loader.parent.transparencyAsCoverage = true;\r\n        }\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsTransmission>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async\r\n    private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const transmissionWeight = extension.transmissionFactor !== undefined ? extension.transmissionFactor : 0.0;\r\n\r\n        if (transmissionWeight === 0 || !adapter) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        // Set transmission properties immediately via adapter\r\n        adapter.configureTransmission();\r\n        adapter.transmissionWeight = transmissionWeight;\r\n\r\n        if (transmissionWeight > 0) {\r\n            ensureTransmissionHelper(this._loader, babylonMaterial);\r\n        }\r\n\r\n        // Load texture if present\r\n        let texturePromise: Promise<Nullable<BaseTexture>> = Promise.resolve(null);\r\n        if (extension.transmissionTexture) {\r\n            (extension.transmissionTexture as ITextureInfo).nonColorData = true;\r\n            texturePromise = this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => {\r\n                texture.name = `${babylonMaterial.name} (Transmission)`;\r\n                adapter.transmissionWeightTexture = texture;\r\n            });\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return texturePromise.then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_transmission glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_transmission(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_transmission(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_transmission.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_transmission.types\";\r\nexport * from \"./KHR_materials_transmission.pure\";\r\n\r\nimport { RegisterKHR_materials_transmission } from \"./KHR_materials_transmission.pure\";\r\nRegisterKHR_materials_transmission();\r\n","/* eslint-disable github/no-then */\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsDiffuseTransmission } from \"babylonjs-gltf2interface\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { ensureTransmissionHelper } from \"./transmissionHelper\";\r\n\r\nconst NAME = \"KHR_materials_diffuse_transmission\";\r\n\r\n/**\r\n * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)\r\n * !!! Experimental Extension Subject to Changes !!!\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 174;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n        if (this.enabled) {\r\n            loader.parent.transparencyAsCoverage = true;\r\n        }\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsDiffuseTransmission>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async\r\n    private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        adapter.configureSubsurface();\r\n        adapter.subsurfaceWeight = extension.diffuseTransmissionFactor ?? 0;\r\n\r\n        if (adapter.subsurfaceWeight > 0) {\r\n            ensureTransmissionHelper(this._loader, babylonMaterial);\r\n        }\r\n\r\n        adapter.diffuseTransmissionTint = extension.diffuseTransmissionColorFactor !== undefined ? Color3.FromArray(extension.diffuseTransmissionColorFactor) : Color3.White();\r\n\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        if (extension.diffuseTransmissionTexture) {\r\n            (extension.diffuseTransmissionTexture as ITextureInfo).nonColorData = true;\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionTexture`, extension.diffuseTransmissionTexture).then((texture: BaseTexture) => {\r\n                    texture.name = `${babylonMaterial.name} (Diffuse Transmission)`;\r\n                    adapter.subsurfaceWeightTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        if (extension.diffuseTransmissionColorTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionColorTexture`, extension.diffuseTransmissionColorTexture).then((texture: BaseTexture) => {\r\n                    texture.name = `${babylonMaterial.name} (Diffuse Transmission Color)`;\r\n                    adapter.diffuseTransmissionTintTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_diffuse_transmission glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_diffuse_transmission(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_diffuse_transmission(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_diffuse_transmission.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_diffuse_transmission.types\";\r\nexport * from \"./KHR_materials_diffuse_transmission.pure\";\r\n\r\nimport { RegisterKHR_materials_diffuse_transmission } from \"./KHR_materials_diffuse_transmission.pure\";\r\nRegisterKHR_materials_diffuse_transmission();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsVolume } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_volume\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md)\r\n * @since 5.0.0\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_volume implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 173;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n        if (this.enabled) {\r\n            // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh\r\n            this._loader._disableInstancedMesh++;\r\n        }\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        if (this.enabled) {\r\n            this._loader._disableInstancedMesh--;\r\n        }\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsVolume>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n        // If transparency isn't enabled already, this extension shouldn't do anything.\r\n        // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions.\r\n        if ((adapter.transmissionWeight === 0 && adapter.subsurfaceWeight === 0) || !extension.thicknessFactor) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        adapter.geometryThinWalled = false;\r\n        const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE;\r\n        const attenuationColor = extension.attenuationColor !== undefined && extension.attenuationColor.length == 3 ? Color3.FromArray(extension.attenuationColor) : Color3.White();\r\n        adapter.configureVolume();\r\n        adapter.transmissionColor = attenuationColor;\r\n        adapter.transmissionDepth = attenuationDistance;\r\n\r\n        adapter.volumeThickness = extension.thicknessFactor ?? 0;\r\n\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        if (extension.thicknessTexture) {\r\n            (extension.thicknessTexture as ITextureInfo).nonColorData = true;\r\n            // eslint-disable-next-line github/no-then\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture, (texture: BaseTexture) => {\r\n                    texture.name = `${babylonMaterial.name} (Thickness)`;\r\n                    adapter.volumeThicknessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_volume glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_volume(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_volume(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_volume.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_volume.types\";\r\nexport * from \"./KHR_materials_volume.pure\";\r\n\r\nimport { RegisterKHR_materials_volume } from \"./KHR_materials_volume.pure\";\r\nRegisterKHR_materials_volume();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsVolumeScatter } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_volume_scatter\";\r\n\r\nfunction multiScatterToSingleScatterAlbedo(multiScatter: Color3): Vector3 {\r\n    const multiScatterAlbedo = new Vector3(multiScatter.r, multiScatter.g, multiScatter.b);\r\n    const s: Vector3 = new Vector3(4.09712, 4.09712, 4.09712);\r\n    s.addInPlace(new Vector3(4.20863, 4.20863, 4.20863).multiplyInPlace(multiScatterAlbedo));\r\n\r\n    const p: Vector3 = new Vector3(9.59217, 9.59217, 9.59217);\r\n    p.addInPlace(new Vector3(41.6808, 41.6808, 41.6808).multiplyInPlace(multiScatterAlbedo));\r\n    p.addInPlace(new Vector3(17.7126, 17.7126, 17.7126).multiplyInPlace(multiScatterAlbedo.multiply(multiScatterAlbedo)));\r\n    s.subtractInPlace(new Vector3(Math.sqrt(p.x), Math.sqrt(p.y), Math.sqrt(p.z)));\r\n    return new Vector3(1.0, 1.0, 1.0).subtract(s.multiply(s));\r\n}\r\n\r\n/**\r\n * TODO: In-progress specification\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/7ea427ed55d44427e83c0a6d1c87068b1a4151c5/extensions/2.0/Khronos/KHR_materials_volume_scatter/README.md)\r\n * @experimental\r\n * @since 9.0.0\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_volume_scatter implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 172;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n        if (this.enabled) {\r\n            // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh\r\n            this._loader._disableInstancedMesh++;\r\n        }\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        if (this.enabled) {\r\n            this._loader._disableInstancedMesh--;\r\n        }\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsVolumeScatter>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolumeScatter): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n        // If transparency isn't enabled already, this extension shouldn't do anything.\r\n        // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions.\r\n        // Additionally, this already needs to be a volumetric material to apply this extension.\r\n        if ((adapter.transmissionWeight === 0 && adapter.subsurfaceWeight === 0) || adapter.geometryThinWalled) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        const scatterColor =\r\n            extension.multiscatterColorFactor !== undefined && extension.multiscatterColorFactor.length == 3 ? Color3.FromArray(extension.multiscatterColorFactor) : Color3.Black();\r\n        const scatterAnisotropy = extension.scatterAnisotropy !== undefined ? extension.scatterAnisotropy : 0;\r\n\r\n        // If diffuse_transmission, apply props to subsurface\r\n        // If transmission, apply props to transmission\r\n        // Load texture if present\r\n        let texturePromise: Promise<Nullable<BaseTexture>> = Promise.resolve(null);\r\n        if (extension.multiscatterColorTexture) {\r\n            (extension.multiscatterColorTexture as ITextureInfo).nonColorData = true;\r\n            texturePromise = this._loader.loadTextureInfoAsync(`${context}/multiscatterColorTexture`, extension.multiscatterColorTexture, (texture: BaseTexture) => {\r\n                texture.name = `${babylonMaterial.name} (Scatter Color)`;\r\n                if (adapter.transmissionWeight > 0) {\r\n                    adapter.transmissionScatterTexture = texture;\r\n                }\r\n                if (adapter.subsurfaceWeight > 0) {\r\n                    adapter.subsurfaceColorTexture = texture;\r\n                }\r\n            });\r\n        }\r\n\r\n        const extinctionCoefficient = new Vector3(-Math.log(adapter.transmissionColor.r), -Math.log(adapter.transmissionColor.g), -Math.log(adapter.transmissionColor.b));\r\n        extinctionCoefficient.scaleInPlace(1 / Math.max(adapter.transmissionDepth, 0.000001));\r\n\r\n        // In glTF, both the translucency volume and subsurface volume use the same input parameters.\r\n        // We'll apply them to both, as appropriate.\r\n        if (adapter.transmissionWeight > 0) {\r\n            const singleScatterAlbedo = multiScatterToSingleScatterAlbedo(scatterColor);\r\n            const scatteringCoefficient = extinctionCoefficient.multiply(singleScatterAlbedo);\r\n\r\n            // The scattering coefficient in OpenPBR is defined as per unit distance, so we need to scale it back up by the depth.\r\n            scatteringCoefficient.scaleInPlace(adapter.transmissionDepth);\r\n            adapter.transmissionScatter.set(scatteringCoefficient.x, scatteringCoefficient.y, scatteringCoefficient.z);\r\n\r\n            adapter.transmissionScatterAnisotropy = scatterAnisotropy;\r\n        }\r\n        // Subsurface volume\r\n        if (adapter.subsurfaceWeight > 0) {\r\n            adapter.subsurfaceScatterAnisotropy = scatterAnisotropy;\r\n            adapter.subsurfaceColor = scatterColor;\r\n\r\n            const mfp = new Vector3(\r\n                extinctionCoefficient.x !== 0 ? 1.0 / extinctionCoefficient.x : 1.0,\r\n                extinctionCoefficient.y !== 0 ? 1.0 / extinctionCoefficient.y : 1.0,\r\n                extinctionCoefficient.z !== 0 ? 1.0 / extinctionCoefficient.z : 1.0\r\n            );\r\n\r\n            adapter.subsurfaceRadius = Math.max(mfp.x, mfp.y, mfp.z);\r\n            adapter.subsurfaceRadiusScale = new Color3(mfp.x / adapter.subsurfaceRadius, mfp.y / adapter.subsurfaceRadius, mfp.z / adapter.subsurfaceRadius);\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return texturePromise.then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_volume_scatter glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_volume_scatter(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_volume_scatter(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_volume_scatter.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_volume_scatter.types\";\r\nexport * from \"./KHR_materials_volume_scatter.pure\";\r\n\r\nimport { RegisterKHR_materials_volume_scatter } from \"./KHR_materials_volume_scatter.pure\";\r\nRegisterKHR_materials_volume_scatter();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsDispersion } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_dispersion\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/87bd64a7f5e23c84b6aef2e6082069583ed0ddb4/extensions/2.0/Khronos/KHR_materials_dispersion/README.md)\r\n * @experimental\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_dispersion implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 174;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsDispersion>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n        // If transparency isn't enabled already, this extension shouldn't do anything.\r\n        // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions.\r\n        if (adapter.transmissionWeight == 0 || !extension.dispersion) {\r\n            return Promise.resolve();\r\n        }\r\n\r\n        adapter.transmissionDispersionAbbeNumber = 20.0;\r\n        adapter.transmissionDispersionScale = extension.dispersion;\r\n\r\n        return Promise.resolve();\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_dispersion glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_dispersion(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_dispersion(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_dispersion.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_dispersion.types\";\r\nexport * from \"./KHR_materials_dispersion.pure\";\r\n\r\nimport { RegisterKHR_materials_dispersion } from \"./KHR_materials_dispersion.pure\";\r\nRegisterKHR_materials_dispersion();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\n\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRMaterialsDiffuseRoughness } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_diffuse_roughness\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/b102d2d2b40d44a8776800bb2bf85e218853c17d/extensions/2.0/Khronos/KHR_materials_diffuse_roughness/README.md)\r\n * @experimental\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_diffuse_roughness implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 190;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsDiffuseRoughness>(context, material, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n            promises.push(this._loadDiffuseRoughnessPropertiesAsync(extensionContext, extension, babylonMaterial));\r\n            // eslint-disable-next-line github/no-then\r\n            return await Promise.all(promises).then(() => {});\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadDiffuseRoughnessPropertiesAsync(context: string, properties: IKHRMaterialsDiffuseRoughness, babylonMaterial: Material): Promise<void> {\r\n        const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n        const promises = new Array<Promise<any>>();\r\n\r\n        adapter.baseDiffuseRoughness = properties.diffuseRoughnessFactor ?? 0;\r\n\r\n        if (properties.diffuseRoughnessTexture) {\r\n            promises.push(\r\n                this._loader.loadTextureInfoAsync(`${context}/diffuseRoughnessTexture`, properties.diffuseRoughnessTexture, (texture) => {\r\n                    texture.name = `${babylonMaterial.name} (Diffuse Roughness)`;\r\n                    adapter.baseDiffuseRoughnessTexture = texture;\r\n                })\r\n            );\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(promises).then(() => {});\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_materials_diffuse_roughness glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_materials_diffuse_roughness(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_materials_diffuse_roughness(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_materials_diffuse_roughness.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_materials_diffuse_roughness.types\";\r\nexport * from \"./KHR_materials_diffuse_roughness.pure\";\r\n\r\nimport { RegisterKHR_materials_diffuse_roughness } from \"./KHR_materials_diffuse_roughness.pure\";\r\nRegisterKHR_materials_diffuse_roughness();\r\n","import { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_mesh_quantization\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_mesh_quantization/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_mesh_quantization implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {}\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_mesh_quantization glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_mesh_quantization(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_mesh_quantization(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_mesh_quantization.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_mesh_quantization.types\";\r\nexport * from \"./KHR_mesh_quantization.pure\";\r\n\r\nimport { RegisterKHR_mesh_quantization } from \"./KHR_mesh_quantization.pure\";\r\nRegisterKHR_mesh_quantization();\r\n","import { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { type ITexture } from \"../glTFLoaderInterfaces\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type IKHRTextureBasisU } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_texture_basisu\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_basisu/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_texture_basisu implements IGLTFLoaderExtension {\r\n    /** The name of this extension. */\r\n    public readonly name = NAME;\r\n\r\n    /** Defines whether this extension is enabled. */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRTextureBasisU, BaseTexture>(context, texture, this.name, async (extensionContext, extension) => {\r\n            const sampler = texture.sampler == undefined ? GLTFLoader.DefaultSampler : ArrayItem.Get(`${context}/sampler`, this._loader.gltf.samplers, texture.sampler);\r\n            const image = ArrayItem.Get(`${extensionContext}/source`, this._loader.gltf.images, extension.source);\r\n            return await this._loader._createTextureAsync(\r\n                context,\r\n                sampler,\r\n                image,\r\n                (babylonTexture) => {\r\n                    assign(babylonTexture);\r\n                },\r\n                texture._textureInfo.nonColorData ? { useRGBAIfASTCBC7NotAvailableWhenUASTC: true } : undefined,\r\n                !texture._textureInfo.nonColorData,\r\n                texture\r\n            );\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_texture_basisu glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_texture_basisu(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_texture_basisu(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_texture_basisu.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_texture_basisu.types\";\r\nexport * from \"./KHR_texture_basisu.pure\";\r\n\r\nimport { RegisterKHR_texture_basisu } from \"./KHR_texture_basisu.pure\";\r\nRegisterKHR_texture_basisu();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { Texture } from \"core/Materials/Textures/texture.pure\";\r\n\r\nimport { type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRTextureTransform } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_texture_transform\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_transform/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_texture_transform implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {\r\n        return GLTFLoader.LoadExtensionAsync<IKHRTextureTransform, BaseTexture>(context, textureInfo, this.name, async (extensionContext, extension) => {\r\n            return await this._loader.loadTextureInfoAsync(context, textureInfo, (babylonTexture) => {\r\n                if (!(babylonTexture instanceof Texture)) {\r\n                    throw new Error(`${extensionContext}: Texture type not supported`);\r\n                }\r\n\r\n                if (extension.offset) {\r\n                    babylonTexture.uOffset = extension.offset[0];\r\n                    babylonTexture.vOffset = extension.offset[1];\r\n                }\r\n\r\n                // Always rotate around the origin.\r\n                babylonTexture.uRotationCenter = 0;\r\n                babylonTexture.vRotationCenter = 0;\r\n\r\n                if (extension.rotation) {\r\n                    babylonTexture.wAng = -extension.rotation;\r\n                }\r\n\r\n                if (extension.scale) {\r\n                    babylonTexture.uScale = extension.scale[0];\r\n                    babylonTexture.vScale = extension.scale[1];\r\n                }\r\n\r\n                if (extension.texCoord != undefined) {\r\n                    babylonTexture.coordinatesIndex = extension.texCoord;\r\n                }\r\n\r\n                assign(babylonTexture);\r\n            });\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_texture_transform glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_texture_transform(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_texture_transform(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_texture_transform.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_texture_transform.types\";\r\nexport * from \"./KHR_texture_transform.pure\";\r\n\r\nimport { RegisterKHR_texture_transform } from \"./KHR_texture_transform.pure\";\r\nRegisterKHR_texture_transform();\r\n","import { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IKHRXmpJsonLd_Gltf, type IKHRXmpJsonLd_Node } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_xmp_json_ld\";\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_xmp_json_ld/README.md)\r\n * @since 5.0.0\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_xmp_json_ld implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 100;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * Called after the loader state changes to LOADING.\r\n     */\r\n    public onLoading(): void {\r\n        if (this._loader.rootBabylonMesh === null) {\r\n            return;\r\n        }\r\n\r\n        const xmpGltf = this._loader.gltf.extensions?.KHR_xmp_json_ld as IKHRXmpJsonLd_Gltf;\r\n        const xmpNode = this._loader.gltf.asset?.extensions?.KHR_xmp_json_ld as IKHRXmpJsonLd_Node;\r\n        if (xmpGltf && xmpNode) {\r\n            const packet = +xmpNode.packet;\r\n            if (xmpGltf.packets && packet < xmpGltf.packets.length) {\r\n                this._loader.rootBabylonMesh.metadata = this._loader.rootBabylonMesh.metadata || {};\r\n                this._loader.rootBabylonMesh.metadata.xmp = xmpGltf.packets[packet];\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_xmp_json_ld glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_xmp_json_ld(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_xmp_json_ld(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_xmp_json_ld.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_xmp_json_ld.types\";\r\nexport * from \"./KHR_xmp_json_ld.pure\";\r\n\r\nimport { RegisterKHR_xmp_json_ld } from \"./KHR_xmp_json_ld.pure\";\r\nRegisterKHR_xmp_json_ld();\r\n","import { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Animation } from \"core/Animations/animation.pure\";\r\nimport { type IAnimatable } from \"core/Animations/animatable.interface\";\r\nimport { type IAnimation, type IAnimationChannel } from \"../glTFLoaderInterfaces\";\r\nimport { type IKHRAnimationPointer, AnimationChannelTargetPath } from \"babylonjs-gltf2interface\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { type GLTFPathToObjectConverter } from \"./gltfPathToObjectConverter\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { GetPathToObjectConverter } from \"./objectModelMapping\";\r\n\r\nconst NAME = \"KHR_animation_pointer\";\r\n\r\n/**\r\n * [Specification PR](https://github.com/KhronosGroup/glTF/pull/2147)\r\n * !!! Experimental Extension Subject to Changes !!!\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_animation_pointer implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    private _loader: GLTFLoader;\r\n    private _pathToObjectConverter?: GLTFPathToObjectConverter<any, any, any>;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this._pathToObjectConverter = GetPathToObjectConverter(this._loader.gltf);\r\n    }\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public get enabled(): boolean {\r\n        return this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        delete this._pathToObjectConverter; // GC\r\n    }\r\n\r\n    /**\r\n     * Loads a glTF animation channel.\r\n     * @param context The context when loading the asset\r\n     * @param animationContext The context of the animation when loading the asset\r\n     * @param animation The glTF animation property\r\n     * @param channel The glTF animation channel property\r\n     * @param onLoad Called for each animation loaded\r\n     * @returns A void promise that resolves when the load is complete or null if not handled\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadAnimationChannelAsync(\r\n        context: string,\r\n        animationContext: string,\r\n        animation: IAnimation,\r\n        channel: IAnimationChannel,\r\n        onLoad: (babylonAnimatable: IAnimatable, babylonAnimation: Animation) => void\r\n    ): Nullable<Promise<void>> {\r\n        const extension = channel.target.extensions?.KHR_animation_pointer as IKHRAnimationPointer;\r\n        if (!extension || !this._pathToObjectConverter) {\r\n            return null;\r\n        }\r\n\r\n        if (channel.target.path !== AnimationChannelTargetPath.POINTER) {\r\n            Logger.Warn(`${context}/target/path: Value (${channel.target.path}) must be (${AnimationChannelTargetPath.POINTER}) when using the ${this.name} extension`);\r\n        }\r\n\r\n        if (channel.target.node != undefined) {\r\n            Logger.Warn(`${context}/target/node: Value (${channel.target.node}) must not be present when using the ${this.name} extension`);\r\n        }\r\n\r\n        const extensionContext = `${context}/extensions/${this.name}`;\r\n\r\n        const pointer = extension.pointer;\r\n        if (!pointer) {\r\n            throw new Error(`${extensionContext}: Pointer is missing`);\r\n        }\r\n\r\n        try {\r\n            const obj = this._pathToObjectConverter.convert(pointer);\r\n            if (!obj.info.interpolation) {\r\n                throw new Error(`${extensionContext}/pointer: Interpolation is missing`);\r\n            }\r\n            return this._loader._loadAnimationChannelFromTargetInfoAsync(\r\n                context,\r\n                animationContext,\r\n                animation,\r\n                channel,\r\n                {\r\n                    object: obj.object,\r\n                    info: obj.info.interpolation,\r\n                },\r\n                onLoad\r\n            );\r\n        } catch (e) {\r\n            Logger.Warn(`${extensionContext}/pointer: Invalid pointer (${pointer}) skipped`);\r\n            return null;\r\n        }\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_animation_pointer glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_animation_pointer(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_animation_pointer(loader));\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\n\r\n/** This file must only contain pure code and pure imports */\r\n\r\nimport { Animation } from \"core/Animations/animation.pure\";\r\nimport { type ICamera, type IKHRLightsPunctual_Light, type IMaterial, type INode } from \"../glTFLoaderInterfaces\";\r\nimport { type IAnimatable } from \"core/Animations/animatable.interface\";\r\nimport { AnimationPropertyInfo, RegisterGLTFLoaderAnimation } from \"../glTFLoaderAnimation.pure\";\r\nimport { Color3 } from \"core/Maths/math.color.pure\";\r\nimport { SetInterpolationForKey } from \"./objectModelMapping\";\r\n\r\nfunction getColor3(_target: any, source: Float32Array, offset: number, scale: number): Color3 {\r\n    return Color3.FromArray(source, offset).scale(scale);\r\n}\r\n\r\nfunction getAlpha(_target: any, source: Float32Array, offset: number, scale: number): number {\r\n    return source[offset + 3] * scale;\r\n}\r\n\r\nfunction getFloat(_target: any, source: Float32Array, offset: number, scale: number): number {\r\n    return source[offset] * scale;\r\n}\r\n\r\nfunction getMinusFloat(_target: any, source: Float32Array, offset: number, scale: number): number {\r\n    return -source[offset] * scale;\r\n}\r\n\r\nfunction getNextFloat(_target: any, source: Float32Array, offset: number, scale: number): number {\r\n    return source[offset + 1] * scale;\r\n}\r\n\r\nfunction getFloatBy2(_target: any, source: Float32Array, offset: number, scale: number): number {\r\n    return source[offset] * scale * 2;\r\n}\r\n\r\nfunction getTextureTransformTree(textureName: string) {\r\n    return {\r\n        scale: [\r\n            new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, `${textureName}.uScale`, getFloat, () => 2),\r\n            new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, `${textureName}.vScale`, getNextFloat, () => 2),\r\n        ],\r\n        offset: [\r\n            new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, `${textureName}.uOffset`, getFloat, () => 2),\r\n            new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, `${textureName}.vOffset`, getNextFloat, () => 2),\r\n        ],\r\n        rotation: [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, `${textureName}.wAng`, getMinusFloat, () => 1)],\r\n    };\r\n}\r\n\r\nclass CameraAnimationPropertyInfo extends AnimationPropertyInfo {\r\n    /** @internal */\r\n    public buildAnimations(target: ICamera, name: string, fps: number, keys: any[]) {\r\n        return [{ babylonAnimatable: target._babylonCamera!, babylonAnimation: this._buildAnimation(name, fps, keys) }];\r\n    }\r\n}\r\n\r\nclass MaterialAnimationPropertyInfo extends AnimationPropertyInfo {\r\n    /** @internal */\r\n    public buildAnimations(target: IMaterial, name: string, fps: number, keys: any[]) {\r\n        const babylonAnimations: { babylonAnimatable: IAnimatable; babylonAnimation: Animation }[] = [];\r\n        for (const fillMode in target._data!) {\r\n            babylonAnimations.push({\r\n                babylonAnimatable: target._data[fillMode].babylonMaterial,\r\n                babylonAnimation: this._buildAnimation(name, fps, keys),\r\n            });\r\n        }\r\n        return babylonAnimations;\r\n    }\r\n}\r\n\r\nclass LightAnimationPropertyInfo extends AnimationPropertyInfo {\r\n    /** @internal */\r\n    public buildAnimations(target: IKHRLightsPunctual_Light, name: string, fps: number, keys: any[]) {\r\n        return [{ babylonAnimatable: target._babylonLight!, babylonAnimation: this._buildAnimation(name, fps, keys) }];\r\n    }\r\n}\r\n\r\nclass MeshAnimationPropertyInfo extends AnimationPropertyInfo {\r\n    /** @internal */\r\n    public buildAnimations(target: INode, name: string, fps: number, keys: any[]) {\r\n        return target._primitiveBabylonMeshes\r\n            ? target._primitiveBabylonMeshes.map((mesh) => ({ babylonAnimatable: mesh, babylonAnimation: this._buildAnimation(name, fps, keys) }))\r\n            : [];\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n\r\n/**\r\n * Registers the KHR_animation_pointer interpolation mappings.\r\n * @internal\r\n */\r\nexport function _RegisterKHRAnimationPointerData(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    RegisterGLTFLoaderAnimation();\r\n\r\n    SetInterpolationForKey(\"/cameras/{}/orthographic/xmag\", [\r\n        new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"orthoLeft\", getMinusFloat, () => 1),\r\n        new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"orthoRight\", getNextFloat, () => 1),\r\n    ]);\r\n\r\n    SetInterpolationForKey(\"/cameras/{}/orthographic/ymag\", [\r\n        new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"orthoBottom\", getMinusFloat, () => 1),\r\n        new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"orthoTop\", getNextFloat, () => 1),\r\n    ]);\r\n\r\n    SetInterpolationForKey(\"/cameras/{}/orthographic/zfar\", [new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"maxZ\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/cameras/{}/orthographic/znear\", [new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"minZ\", getFloat, () => 1)]);\r\n\r\n    SetInterpolationForKey(\"/cameras/{}/perspective/yfov\", [new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"fov\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/cameras/{}/perspective/zfar\", [new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"maxZ\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/cameras/{}/perspective/znear\", [new CameraAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"minZ\", getFloat, () => 1)]);\r\n\r\n    // add interpolation to the materials mapping\r\n    SetInterpolationForKey(\"/materials/{}/pbrMetallicRoughness/baseColorFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"albedoColor\", getColor3, () => 4),\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"alpha\", getAlpha, () => 4),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/pbrMetallicRoughness/metallicFactor\", [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"metallic\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/materials/{}/pbrMetallicRoughness/metallicFactor\", [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"roughness\", getFloat, () => 1)]);\r\n    const baseColorTextureInterpolation = getTextureTransformTree(\"albedoTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/pbrMetallicRoughness/baseColorTexture/extensions/KHR_texture_transform/scale\", baseColorTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/pbrMetallicRoughness/baseColorTexture/extensions/KHR_texture_transform/offset\", baseColorTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/pbrMetallicRoughness/baseColorTexture/extensions/KHR_texture_transform/rotation\", baseColorTextureInterpolation.rotation);\r\n\r\n    const metallicRoughnessTextureInterpolation = getTextureTransformTree(\"metallicTexture\");\r\n    SetInterpolationForKey(\"//materials/{}/pbrMetallicRoughness/metallicRoughnessTexture/scale\", metallicRoughnessTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"//materials/{}/pbrMetallicRoughness/metallicRoughnessTexture/offset\", metallicRoughnessTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"//materials/{}/pbrMetallicRoughness/metallicRoughnessTexture/rotation\", metallicRoughnessTextureInterpolation.rotation);\r\n\r\n    SetInterpolationForKey(\"/materials/{}/emissiveFactor\", [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"emissiveColor\", getColor3, () => 3)]);\r\n    const normalTextureInterpolation = getTextureTransformTree(\"bumpTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/normalTexture/scale\", [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"bumpTexture.level\", getFloat, () => 1)]);\r\n\r\n    SetInterpolationForKey(\"/materials/{}/normalTexture/extensions/KHR_texture_transform/scale\", normalTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/normalTexture/extensions/KHR_texture_transform/offset\", normalTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/normalTexture/extensions/KHR_texture_transform/rotation\", normalTextureInterpolation.rotation);\r\n\r\n    SetInterpolationForKey(\"/materials/{}/occlusionTexture/strength\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"ambientTextureStrength\", getFloat, () => 1),\r\n    ]);\r\n\r\n    const occlusionTextureInterpolation = getTextureTransformTree(\"ambientTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/occlusionTexture/extensions/KHR_texture_transform/scale\", occlusionTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/occlusionTexture/extensions/KHR_texture_transform/offset\", occlusionTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/occlusionTexture/extensions/KHR_texture_transform/rotation\", occlusionTextureInterpolation.rotation);\r\n    const emissiveTextureInterpolation = getTextureTransformTree(\"emissiveTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/emissiveTexture/extensions/KHR_texture_transform/scale\", emissiveTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/emissiveTexture/extensions/KHR_texture_transform/offset\", emissiveTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/emissiveTexture/extensions/KHR_texture_transform/rotation\", emissiveTextureInterpolation.rotation);\r\n\r\n    // materials extensions\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_anisotropy/anisotropyStrength\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"anisotropy.intensity\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_anisotropy/anisotropyRotation\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"anisotropy.angle\", getFloat, () => 1),\r\n    ]);\r\n    const anisotropyTextureInterpolation = getTextureTransformTree(\"anisotropy.texture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_anisotropy/anisotropyTexture/extensions/KHR_texture_transform/scale\", anisotropyTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_anisotropy/anisotropyTexture/extensions/KHR_texture_transform/offset\", anisotropyTextureInterpolation.offset);\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_anisotropy/anisotropyTexture/extensions/KHR_texture_transform/rotation\",\r\n        anisotropyTextureInterpolation.rotation\r\n    );\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"clearCoat.intensity\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatRoughnessFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"clearCoat.roughness\", getFloat, () => 1),\r\n    ]);\r\n    const clearcoatTextureInterpolation = getTextureTransformTree(\"clearCoat.texture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatTexture/extensions/KHR_texture_transform/scale\", clearcoatTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatTexture/extensions/KHR_texture_transform/offset\", clearcoatTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatTexture/extensions/KHR_texture_transform/rotation\", clearcoatTextureInterpolation.rotation);\r\n    const clearcoatNormalTextureInterpolation = getTextureTransformTree(\"clearCoat.bumpTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatNormalTexture/scale\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"clearCoat.bumpTexture.level\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatNormalTexture/extensions/KHR_texture_transform/scale\",\r\n        clearcoatNormalTextureInterpolation.scale\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatNormalTexture/extensions/KHR_texture_transform/offset\",\r\n        clearcoatNormalTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatNormalTexture/extensions/KHR_texture_transform/rotation\",\r\n        clearcoatNormalTextureInterpolation.rotation\r\n    );\r\n    const clearcoatRoughnessTextureInterpolation = getTextureTransformTree(\"clearCoat.textureRoughness\");\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatRoughnessTexture/extensions/KHR_texture_transform/scale\",\r\n        clearcoatRoughnessTextureInterpolation.scale\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatRoughnessTexture/extensions/KHR_texture_transform/offset\",\r\n        clearcoatRoughnessTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_clearcoat/clearcoatRoughnessTexture/extensions/KHR_texture_transform/rotation\",\r\n        clearcoatRoughnessTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_dispersion/dispersionFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"subSurface.dispersion\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_emissive_strength/emissiveStrength\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"emissiveIntensity\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_ior/ior\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"indexOfRefraction\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_iridescence/iridescenceFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"iridescence.intensity\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_iridescence/iridescenceIor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"iridescence.indexOfRefraction\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_iridescence/iridescenceThicknessMinimum\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"iridescence.minimumThickness\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_iridescence/iridescenceThicknessMaximum\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"iridescence.maximumThickness\", getFloat, () => 1),\r\n    ]);\r\n\r\n    const iridescenceTextureInterpolation = getTextureTransformTree(\"iridescence.texture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_iridescence/iridescenceTexture/extensions/KHR_texture_transform/scale\", iridescenceTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_iridescence/iridescenceTexture/extensions/KHR_texture_transform/offset\", iridescenceTextureInterpolation.offset);\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_iridescence/iridescenceTexture/extensions/KHR_texture_transform/rotation\",\r\n        iridescenceTextureInterpolation.rotation\r\n    );\r\n\r\n    const iridescenceThicknessTextureInterpolation = getTextureTransformTree(\"iridescence.thicknessTexture\");\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_iridescence/iridescenceThicknessTexture/extensions/KHR_texture_transform/scale\",\r\n        iridescenceThicknessTextureInterpolation.scale\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_iridescence/iridescenceThicknessTexture/extensions/KHR_texture_transform/offset\",\r\n        iridescenceThicknessTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_iridescence/iridescenceThicknessTexture/extensions/KHR_texture_transform/rotation\",\r\n        iridescenceThicknessTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenColorFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"sheen.color\", getColor3, () => 3),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenRoughnessFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"sheen.roughness\", getFloat, () => 1),\r\n    ]);\r\n\r\n    const sheenTextureInterpolation = getTextureTransformTree(\"sheen.texture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenColorTexture/extensions/KHR_texture_transform/scale\", sheenTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenColorTexture/extensions/KHR_texture_transform/offset\", sheenTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenColorTexture/extensions/KHR_texture_transform/rotation\", sheenTextureInterpolation.rotation);\r\n\r\n    const sheenRoughnessTextureInterpolation = getTextureTransformTree(\"sheen.textureRoughness\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenRoughnessTexture/extensions/KHR_texture_transform/scale\", sheenRoughnessTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_sheen/sheenRoughnessTexture/extensions/KHR_texture_transform/offset\", sheenRoughnessTextureInterpolation.offset);\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_sheen/sheenRoughnessTexture/extensions/KHR_texture_transform/rotation\",\r\n        sheenRoughnessTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_specular/specularFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"metallicF0Factor\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_specular/specularColorFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"metallicReflectanceColor\", getColor3, () => 3),\r\n    ]);\r\n\r\n    const specularTextureInterpolation = getTextureTransformTree(\"metallicReflectanceTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_specular/specularTexture/extensions/KHR_texture_transform/scale\", specularTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_specular/specularTexture/extensions/KHR_texture_transform/offset\", specularTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_specular/specularTexture/extensions/KHR_texture_transform/rotation\", specularTextureInterpolation.rotation);\r\n    const specularColorTextureInterpolation = getTextureTransformTree(\"reflectanceTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_specular/specularColorTexture/extensions/KHR_texture_transform/scale\", specularColorTextureInterpolation.scale);\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_specular/specularColorTexture/extensions/KHR_texture_transform/offset\",\r\n        specularColorTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_specular/specularColorTexture/extensions/KHR_texture_transform/rotation\",\r\n        specularColorTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_transmission/transmissionFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"subSurface.refractionIntensity\", getFloat, () => 1),\r\n    ]);\r\n    const transmissionTextureInterpolation = getTextureTransformTree(\"subSurface.refractionIntensityTexture\");\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_transmission/transmissionTexture/extensions/KHR_texture_transform/scale\",\r\n        transmissionTextureInterpolation.scale\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_transmission/transmissionTexture/extensions/KHR_texture_transform/offset\",\r\n        transmissionTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"/materials/{}/extensions/KHR_materials_transmission/transmissionTexture/extensions/KHR_texture_transform/rotation\",\r\n        transmissionTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_volume/attenuationColor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"subSurface.tintColor\", getColor3, () => 3),\r\n    ]);\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_volume/attenuationDistance\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"subSurface.tintColorAtDistance\", getFloat, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_volume/thicknessFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"subSurface.maximumThickness\", getFloat, () => 1),\r\n    ]);\r\n\r\n    const thicknessTextureInterpolation = getTextureTransformTree(\"subSurface.thicknessTexture\");\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_volume/thicknessTexture/extensions/KHR_texture_transform/scale\", thicknessTextureInterpolation.scale);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_volume/thicknessTexture/extensions/KHR_texture_transform/offset\", thicknessTextureInterpolation.offset);\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_volume/thicknessTexture/extensions/KHR_texture_transform/rotation\", thicknessTextureInterpolation.rotation);\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"subSurface.translucencyIntensity\", getFloat, () => 1),\r\n    ]);\r\n\r\n    const diffuseTransmissionTextureInterpolation = getTextureTransformTree(\"subSurface.translucencyIntensityTexture\");\r\n    SetInterpolationForKey(\r\n        \"materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionTexture/extensions/KHR_texture_transform/scale\",\r\n        diffuseTransmissionTextureInterpolation.scale\r\n    );\r\n    SetInterpolationForKey(\r\n        \"materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionTexture/extensions/KHR_texture_transform/offset\",\r\n        diffuseTransmissionTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionTexture/extensions/KHR_texture_transform/rotation\",\r\n        diffuseTransmissionTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionColorFactor\", [\r\n        new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"subSurface.translucencyColor\", getColor3, () => 3),\r\n    ]);\r\n\r\n    const diffuseTransmissionColorTextureInterpolation = getTextureTransformTree(\"subSurface.translucencyColorTexture\");\r\n    SetInterpolationForKey(\r\n        \"materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionColorTexture/extensions/KHR_texture_transform/scale\",\r\n        diffuseTransmissionColorTextureInterpolation.scale\r\n    );\r\n    SetInterpolationForKey(\r\n        \"materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionColorTexture/extensions/KHR_texture_transform/offset\",\r\n        diffuseTransmissionColorTextureInterpolation.offset\r\n    );\r\n    SetInterpolationForKey(\r\n        \"materials/{}/extensions/KHR_materials_diffuse_transmission/diffuseTransmissionColorTexture/extensions/KHR_texture_transform/rotation\",\r\n        diffuseTransmissionColorTextureInterpolation.rotation\r\n    );\r\n\r\n    SetInterpolationForKey(\"/extensions/KHR_lights_punctual/lights/{}/color\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"diffuse\", getColor3, () => 3)]);\r\n    SetInterpolationForKey(\"/extensions/KHR_lights_punctual/lights/{}/intensity\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"intensity\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/extensions/KHR_lights_punctual/lights/{}/range\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"range\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/extensions/KHR_lights_punctual/lights/{}/spot/innerConeAngle\", [\r\n        new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"innerAngle\", getFloatBy2, () => 1),\r\n    ]);\r\n    SetInterpolationForKey(\"/extensions/KHR_lights_punctual/lights/{}/spot/outerConeAngle\", [\r\n        new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"angle\", getFloatBy2, () => 1),\r\n    ]);\r\n\r\n    SetInterpolationForKey(\"/extensions/EXT_lights_area/lights/{}/color\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"diffuse\", getColor3, () => 3)]);\r\n    SetInterpolationForKey(\"/extensions/EXT_lights_area/lights/{}/intensity\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"intensity\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/extensions/EXT_lights_area/lights/{}/size\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"radius\", getFloat, () => 1)]);\r\n    SetInterpolationForKey(\"/extensions/EXT_lights_area/lights/{}/rect/aspect\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"radius\", getFloat, () => 1)]);\r\n\r\n    SetInterpolationForKey(\"/nodes/{}/extensions/EXT_lights_ies/color\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_COLOR3, \"diffuse\", getColor3, () => 3)]);\r\n    SetInterpolationForKey(\"/nodes/{}/extensions/EXT_lights_ies/multiplier\", [new LightAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"intensity\", getFloat, () => 1)]);\r\n\r\n    SetInterpolationForKey(\"/nodes/{}/extensions/KHR_node_visibility/visible\", [new MeshAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, \"isVisible\", getFloat, () => 1)]);\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_animation_pointer.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_animation_pointer.types\";\r\nexport * from \"./KHR_animation_pointer.pure\";\r\n\r\nimport { _RegisterKHRAnimationPointerData } from \"./KHR_animation_pointer.data.pure\";\r\nimport { RegisterKHR_animation_pointer } from \"./KHR_animation_pointer.pure\";\r\n_RegisterKHRAnimationPointerData();\r\nRegisterKHR_animation_pointer();\r\n","import { type Nullable } from \"core/types\";\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { type AnimationGroup } from \"core/Animations/animationGroup.pure\";\r\nimport { AnimationEvent } from \"core/Animations/animationEvent\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { Sound } from \"core/Audio/sound.pure\";\r\nimport { WeightedSound } from \"core/Audio/weightedsound\";\r\n\r\nimport { type IArrayItem, type IScene, type INode, type IAnimation } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport {\r\n    type IMSFTAudioEmitter_Clip,\r\n    type IMSFTAudioEmitter_Emitter,\r\n    type IMSFTAudioEmitter_EmittersReference,\r\n    type IMSFTAudioEmitter_AnimationEvent,\r\n    IMSFTAudioEmitter_AnimationEventAction,\r\n} from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nimport { GetBlobBufferSource } from \"core/Buffers/bufferUtils\";\r\n\r\nconst NAME = \"MSFT_audio_emitter\";\r\n\r\ninterface ILoaderClip extends IMSFTAudioEmitter_Clip, IArrayItem {\r\n    _objectURL?: Promise<string>;\r\n}\r\n\r\ninterface ILoaderEmitter extends IMSFTAudioEmitter_Emitter, IArrayItem {\r\n    _babylonData?: {\r\n        sound?: WeightedSound;\r\n        loaded: Promise<void>;\r\n    };\r\n    _babylonSounds: Sound[];\r\n}\r\n\r\ninterface IMSFTAudioEmitter {\r\n    clips: ILoaderClip[];\r\n    emitters: ILoaderEmitter[];\r\n}\r\n\r\ninterface ILoaderAnimationEvent extends IMSFTAudioEmitter_AnimationEvent, IArrayItem {}\r\n\r\ninterface ILoaderAnimationEvents {\r\n    events: ILoaderAnimationEvent[];\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/najadojo/glTF/blob/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter/README.md)\r\n * !!! Experimental Extension Subject to Changes !!!\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class MSFT_audio_emitter implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n    private _clips: Array<ILoaderClip>;\r\n    private _emitters: Array<ILoaderEmitter>;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        (this._clips as any) = null;\r\n        (this._emitters as any) = null;\r\n    }\r\n\r\n    /** @internal */\r\n    public onLoading(): void {\r\n        const extensions = this._loader.gltf.extensions;\r\n        if (extensions && extensions[this.name]) {\r\n            const extension = extensions[this.name] as IMSFTAudioEmitter;\r\n\r\n            this._clips = extension.clips;\r\n            this._emitters = extension.emitters;\r\n\r\n            ArrayItem.Assign(this._clips);\r\n            ArrayItem.Assign(this._emitters);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadSceneAsync(context: string, scene: IScene): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtensionAsync<IMSFTAudioEmitter_EmittersReference>(context, scene, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n\r\n            promises.push(this._loader.loadSceneAsync(context, scene));\r\n\r\n            for (const emitterIndex of extension.emitters) {\r\n                const emitter = ArrayItem.Get(`${extensionContext}/emitters`, this._emitters, emitterIndex);\r\n                if (\r\n                    emitter.refDistance != undefined ||\r\n                    emitter.maxDistance != undefined ||\r\n                    emitter.rolloffFactor != undefined ||\r\n                    emitter.distanceModel != undefined ||\r\n                    emitter.innerAngle != undefined ||\r\n                    emitter.outerAngle != undefined\r\n                ) {\r\n                    throw new Error(`${extensionContext}: Direction or Distance properties are not allowed on emitters attached to a scene`);\r\n                }\r\n\r\n                promises.push(this._loadEmitterAsync(`${extensionContext}/emitters/${emitter.index}`, emitter));\r\n            }\r\n\r\n            await Promise.all(promises);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return GLTFLoader.LoadExtensionAsync<IMSFTAudioEmitter_EmittersReference, TransformNode>(context, node, this.name, async (extensionContext, extension) => {\r\n            const promises = new Array<Promise<any>>();\r\n\r\n            const babylonMesh = await this._loader.loadNodeAsync(extensionContext, node, (babylonMesh) => {\r\n                for (const emitterIndex of extension.emitters) {\r\n                    const emitter = ArrayItem.Get(`${extensionContext}/emitters`, this._emitters, emitterIndex);\r\n                    promises.push(\r\n                        // eslint-disable-next-line github/no-then\r\n                        this._loadEmitterAsync(`${extensionContext}/emitters/${emitter.index}`, emitter).then(() => {\r\n                            for (const sound of emitter._babylonSounds) {\r\n                                sound.attachToMesh(babylonMesh);\r\n                                if (emitter.innerAngle != undefined || emitter.outerAngle != undefined) {\r\n                                    sound.setLocalDirectionToMesh(Vector3.Forward());\r\n                                    sound.setDirectionalCone(\r\n                                        2 * Tools.ToDegrees(emitter.innerAngle == undefined ? Math.PI : emitter.innerAngle),\r\n                                        2 * Tools.ToDegrees(emitter.outerAngle == undefined ? Math.PI : emitter.outerAngle),\r\n                                        0\r\n                                    );\r\n                                }\r\n                            }\r\n                        })\r\n                    );\r\n                }\r\n\r\n                assign(babylonMesh);\r\n            });\r\n            await Promise.all(promises);\r\n            return babylonMesh;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadAnimationAsync(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>> {\r\n        return GLTFLoader.LoadExtensionAsync<ILoaderAnimationEvents, AnimationGroup>(context, animation, this.name, async (extensionContext, extension) => {\r\n            const babylonAnimationGroup = await this._loader.loadAnimationAsync(context, animation);\r\n            const promises = new Array<Promise<any>>();\r\n            ArrayItem.Assign(extension.events);\r\n            for (const event of extension.events) {\r\n                promises.push(this._loadAnimationEventAsync(`${extensionContext}/events/${event.index}`, context, animation, event, babylonAnimationGroup));\r\n            }\r\n            await Promise.all(promises);\r\n            return babylonAnimationGroup;\r\n        });\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadClipAsync(context: string, clip: ILoaderClip): Promise<string> {\r\n        if (clip._objectURL) {\r\n            return clip._objectURL;\r\n        }\r\n\r\n        let promise: Promise<ArrayBufferView>;\r\n        if (clip.uri) {\r\n            promise = this._loader.loadUriAsync(context, clip, clip.uri);\r\n        } else {\r\n            const bufferView = ArrayItem.Get(`${context}/bufferView`, this._loader.gltf.bufferViews, clip.bufferView);\r\n            promise = this._loader.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView);\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        clip._objectURL = promise.then((data) => {\r\n            const buffer = GetBlobBufferSource(data);\r\n            return URL.createObjectURL(new Blob([buffer], { type: clip.mimeType }));\r\n        });\r\n\r\n        return clip._objectURL;\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadEmitterAsync(context: string, emitter: ILoaderEmitter): Promise<void> {\r\n        emitter._babylonSounds = emitter._babylonSounds || [];\r\n        if (!emitter._babylonData) {\r\n            const clipPromises = new Array<Promise<any>>();\r\n            const name = emitter.name || `emitter${emitter.index}`;\r\n            const options = {\r\n                loop: false,\r\n                autoplay: false,\r\n                volume: emitter.volume == undefined ? 1 : emitter.volume,\r\n            };\r\n\r\n            for (let i = 0; i < emitter.clips.length; i++) {\r\n                const clipContext = `/extensions/${this.name}/clips`;\r\n                const clip = ArrayItem.Get(clipContext, this._clips, emitter.clips[i].clip);\r\n                clipPromises.push(\r\n                    // eslint-disable-next-line github/no-then\r\n                    this._loadClipAsync(`${clipContext}/${emitter.clips[i].clip}`, clip).then((objectURL: string) => {\r\n                        const sound = (emitter._babylonSounds[i] = new Sound(name, objectURL, this._loader.babylonScene, null, options));\r\n                        sound.refDistance = emitter.refDistance || 1;\r\n                        sound.maxDistance = emitter.maxDistance || 256;\r\n                        sound.rolloffFactor = emitter.rolloffFactor || 1;\r\n                        sound.distanceModel = emitter.distanceModel || \"exponential\";\r\n                    })\r\n                );\r\n            }\r\n\r\n            // eslint-disable-next-line github/no-then\r\n            const promise = Promise.all(clipPromises).then(() => {\r\n                const weights = emitter.clips.map((clip) => {\r\n                    return clip.weight || 1;\r\n                });\r\n                const weightedSound = new WeightedSound(emitter.loop || false, emitter._babylonSounds, weights);\r\n                if (emitter.innerAngle) {\r\n                    weightedSound.directionalConeInnerAngle = 2 * Tools.ToDegrees(emitter.innerAngle);\r\n                }\r\n                if (emitter.outerAngle) {\r\n                    weightedSound.directionalConeOuterAngle = 2 * Tools.ToDegrees(emitter.outerAngle);\r\n                }\r\n                if (emitter.volume) {\r\n                    weightedSound.volume = emitter.volume;\r\n                }\r\n                emitter._babylonData!.sound = weightedSound;\r\n            });\r\n\r\n            emitter._babylonData = {\r\n                loaded: promise,\r\n            };\r\n        }\r\n\r\n        return emitter._babylonData.loaded;\r\n    }\r\n\r\n    private _getEventAction(\r\n        context: string,\r\n        sound: WeightedSound,\r\n        action: IMSFTAudioEmitter_AnimationEventAction,\r\n        time: number,\r\n        startOffset?: number\r\n    ): (currentFrame: number) => void {\r\n        switch (action) {\r\n            case IMSFTAudioEmitter_AnimationEventAction.play: {\r\n                return (currentFrame: number) => {\r\n                    const frameOffset = (startOffset || 0) + (currentFrame - time);\r\n                    sound.play(frameOffset);\r\n                };\r\n            }\r\n            case IMSFTAudioEmitter_AnimationEventAction.stop: {\r\n                return () => {\r\n                    sound.stop();\r\n                };\r\n            }\r\n            case IMSFTAudioEmitter_AnimationEventAction.pause: {\r\n                return () => {\r\n                    sound.pause();\r\n                };\r\n            }\r\n            default: {\r\n                throw new Error(`${context}: Unsupported action ${action}`);\r\n            }\r\n        }\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _loadAnimationEventAsync(\r\n        context: string,\r\n        animationContext: string,\r\n        animation: IAnimation,\r\n        event: ILoaderAnimationEvent,\r\n        babylonAnimationGroup: AnimationGroup\r\n    ): Promise<void> {\r\n        if (babylonAnimationGroup.targetedAnimations.length == 0) {\r\n            return Promise.resolve();\r\n        }\r\n        const babylonAnimation = babylonAnimationGroup.targetedAnimations[0];\r\n        const emitterIndex = event.emitter;\r\n        const emitter = ArrayItem.Get(`/extensions/${this.name}/emitters`, this._emitters, emitterIndex);\r\n        // eslint-disable-next-line github/no-then\r\n        return this._loadEmitterAsync(context, emitter).then(() => {\r\n            const sound = emitter._babylonData!.sound;\r\n            if (sound) {\r\n                const babylonAnimationEvent = new AnimationEvent(event.time, this._getEventAction(context, sound, event.action, event.time, event.startOffset));\r\n                babylonAnimation.animation.addEvent(babylonAnimationEvent);\r\n                // Make sure all started audio stops when this animation is terminated.\r\n                babylonAnimationGroup.onAnimationGroupEndObservable.add(() => {\r\n                    sound.stop();\r\n                });\r\n                babylonAnimationGroup.onAnimationGroupPauseObservable.add(() => {\r\n                    sound.pause();\r\n                });\r\n            }\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the MSFT_audio_emitter glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterMSFT_audio_emitter(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new MSFT_audio_emitter(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./MSFT_audio_emitter.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./MSFT_audio_emitter.types\";\r\nexport * from \"./MSFT_audio_emitter.pure\";\r\n\r\nimport \"core/Audio/audioSceneComponent\";\r\n\r\nimport { RegisterMSFT_audio_emitter } from \"./MSFT_audio_emitter.pure\";\r\nRegisterMSFT_audio_emitter();\r\n","/* eslint-disable github/no-then */\r\nimport { type Nullable } from \"core/types\";\r\nimport { Observable } from \"core/Misc/observable\";\r\nimport { Deferred } from \"core/Misc/deferred\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { type Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type INode, type IMaterial, type IBuffer, type IScene } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader, ArrayItem } from \"../glTFLoader.pure\";\r\nimport { type IProperty, type IMSFTLOD } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"MSFT_lod\";\r\n\r\ninterface IBufferInfo {\r\n    start: number;\r\n    end: number;\r\n    loaded: Deferred<ArrayBufferView>;\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/MSFT_lod/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class MSFT_lod implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    /**\r\n     * Defines a number that determines the order the extensions are applied.\r\n     */\r\n    public order = 100;\r\n\r\n    /**\r\n     * Maximum number of LODs to load, starting from the lowest LOD.\r\n     */\r\n    public maxLODsToLoad = 10;\r\n\r\n    /**\r\n     * Observable raised when all node LODs of one level are loaded.\r\n     * The event data is the index of the loaded LOD starting from zero.\r\n     * Dispose the loader to cancel the loading of the next level of LODs.\r\n     */\r\n    public onNodeLODsLoadedObservable = new Observable<number>();\r\n\r\n    /**\r\n     * Observable raised when all material LODs of one level are loaded.\r\n     * The event data is the index of the loaded LOD starting from zero.\r\n     * Dispose the loader to cancel the loading of the next level of LODs.\r\n     */\r\n    public onMaterialLODsLoadedObservable = new Observable<number>();\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    private _bufferLODs = new Array<IBufferInfo>();\r\n\r\n    private _nodeIndexLOD: Nullable<number> = null;\r\n    private _nodeSignalLODs = new Array<Deferred<void>>();\r\n    private _nodePromiseLODs = new Array<Array<Promise<any>>>();\r\n    private _nodeBufferLODs = new Array<IBufferInfo>();\r\n\r\n    private _materialIndexLOD: Nullable<number> = null;\r\n    private _materialSignalLODs = new Array<Deferred<void>>();\r\n    private _materialPromiseLODs = new Array<Array<Promise<any>>>();\r\n    private _materialBufferLODs = new Array<IBufferInfo>();\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        // Options takes precedence. The maxLODsToLoad extension property is retained for back compat.\r\n        // For new extensions, they should only use options.\r\n        this.maxLODsToLoad = this._loader.parent.extensionOptions[NAME]?.maxLODsToLoad ?? this.maxLODsToLoad;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n\r\n        this._nodeIndexLOD = null;\r\n        this._nodeSignalLODs.length = 0;\r\n        this._nodePromiseLODs.length = 0;\r\n        this._nodeBufferLODs.length = 0;\r\n\r\n        this._materialIndexLOD = null;\r\n        this._materialSignalLODs.length = 0;\r\n        this._materialPromiseLODs.length = 0;\r\n        this._materialBufferLODs.length = 0;\r\n\r\n        this.onMaterialLODsLoadedObservable.clear();\r\n        this.onNodeLODsLoadedObservable.clear();\r\n    }\r\n\r\n    /** @internal */\r\n    public onReady(): void {\r\n        for (let indexLOD = 0; indexLOD < this._nodePromiseLODs.length; indexLOD++) {\r\n            const promise = Promise.all(this._nodePromiseLODs[indexLOD]).then(() => {\r\n                if (indexLOD !== 0) {\r\n                    this._loader.endPerformanceCounter(`Node LOD ${indexLOD}`);\r\n                    this._loader.log(`Loaded node LOD ${indexLOD}`);\r\n                }\r\n\r\n                this.onNodeLODsLoadedObservable.notifyObservers(indexLOD);\r\n\r\n                if (indexLOD !== this._nodePromiseLODs.length - 1) {\r\n                    this._loader.startPerformanceCounter(`Node LOD ${indexLOD + 1}`);\r\n                    this._loadBufferLOD(this._nodeBufferLODs, indexLOD + 1);\r\n                    if (this._nodeSignalLODs[indexLOD]) {\r\n                        this._nodeSignalLODs[indexLOD].resolve();\r\n                    }\r\n                }\r\n            });\r\n\r\n            this._loader._completePromises.push(promise);\r\n        }\r\n\r\n        for (let indexLOD = 0; indexLOD < this._materialPromiseLODs.length; indexLOD++) {\r\n            const promise = Promise.all(this._materialPromiseLODs[indexLOD]).then(() => {\r\n                if (indexLOD !== 0) {\r\n                    this._loader.endPerformanceCounter(`Material LOD ${indexLOD}`);\r\n                    this._loader.log(`Loaded material LOD ${indexLOD}`);\r\n                }\r\n\r\n                this.onMaterialLODsLoadedObservable.notifyObservers(indexLOD);\r\n\r\n                if (indexLOD !== this._materialPromiseLODs.length - 1) {\r\n                    this._loader.startPerformanceCounter(`Material LOD ${indexLOD + 1}`);\r\n                    this._loadBufferLOD(this._materialBufferLODs, indexLOD + 1);\r\n                    if (this._materialSignalLODs[indexLOD]) {\r\n                        this._materialSignalLODs[indexLOD].resolve();\r\n                    }\r\n                }\r\n            });\r\n\r\n            this._loader._completePromises.push(promise);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadSceneAsync(context: string, scene: IScene): Nullable<Promise<void>> {\r\n        const promise = this._loader.loadSceneAsync(context, scene);\r\n        this._loadBufferLOD(this._bufferLODs, 0);\r\n        return promise;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return GLTFLoader.LoadExtensionAsync<IMSFTLOD, TransformNode>(context, node, this.name, async (extensionContext, extension) => {\r\n            let firstPromise: Promise<TransformNode>;\r\n\r\n            const nodeLODs = this._getLODs(extensionContext, node, this._loader.gltf.nodes, extension.ids);\r\n            this._loader.logOpen(`${extensionContext}`);\r\n\r\n            for (let indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) {\r\n                const nodeLOD = nodeLODs[indexLOD];\r\n\r\n                if (indexLOD !== 0) {\r\n                    this._nodeIndexLOD = indexLOD;\r\n                    this._nodeSignalLODs[indexLOD] = this._nodeSignalLODs[indexLOD] || new Deferred();\r\n                }\r\n\r\n                const assignWrap = (babylonTransformNode: TransformNode) => {\r\n                    assign(babylonTransformNode);\r\n                    babylonTransformNode.setEnabled(false);\r\n                };\r\n\r\n                const promise = this._loader.loadNodeAsync(`/nodes/${nodeLOD.index}`, nodeLOD, assignWrap).then((babylonMesh) => {\r\n                    if (indexLOD !== 0) {\r\n                        // TODO: should not rely on _babylonTransformNode\r\n                        const previousNodeLOD = nodeLODs[indexLOD - 1];\r\n                        if (previousNodeLOD._babylonTransformNode) {\r\n                            this._disposeTransformNode(previousNodeLOD._babylonTransformNode);\r\n                            delete previousNodeLOD._babylonTransformNode;\r\n                        }\r\n                    }\r\n\r\n                    babylonMesh.setEnabled(true);\r\n                    return babylonMesh;\r\n                });\r\n\r\n                this._nodePromiseLODs[indexLOD] = this._nodePromiseLODs[indexLOD] || [];\r\n\r\n                if (indexLOD === 0) {\r\n                    firstPromise = promise;\r\n                } else {\r\n                    this._nodeIndexLOD = null;\r\n                    this._nodePromiseLODs[indexLOD].push(promise);\r\n                }\r\n            }\r\n\r\n            this._loader.logClose();\r\n            return await firstPromise!;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadMaterialAsync(\r\n        context: string,\r\n        material: IMaterial,\r\n        babylonMesh: Nullable<Mesh>,\r\n        babylonDrawMode: number,\r\n        assign: (babylonMaterial: Material) => void\r\n    ): Nullable<Promise<Material>> {\r\n        // Don't load material LODs if already loading a node LOD.\r\n        if (this._nodeIndexLOD) {\r\n            return null;\r\n        }\r\n\r\n        return GLTFLoader.LoadExtensionAsync<IMSFTLOD, Material>(context, material, this.name, async (extensionContext, extension) => {\r\n            let firstPromise: Promise<Material>;\r\n\r\n            const materialLODs = this._getLODs(extensionContext, material, this._loader.gltf.materials, extension.ids);\r\n            this._loader.logOpen(`${extensionContext}`);\r\n\r\n            for (let indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) {\r\n                const materialLOD = materialLODs[indexLOD];\r\n\r\n                if (indexLOD !== 0) {\r\n                    this._materialIndexLOD = indexLOD;\r\n                }\r\n\r\n                const promise = this._loader\r\n                    ._loadMaterialAsync(`/materials/${materialLOD.index}`, materialLOD, babylonMesh, babylonDrawMode, (babylonMaterial) => {\r\n                        if (indexLOD === 0) {\r\n                            assign(babylonMaterial);\r\n                        }\r\n                    })\r\n                    .then((babylonMaterial) => {\r\n                        if (indexLOD !== 0) {\r\n                            assign(babylonMaterial);\r\n\r\n                            // TODO: should not rely on _data\r\n                            const previousDataLOD = materialLODs[indexLOD - 1]._data!;\r\n                            if (previousDataLOD[babylonDrawMode]) {\r\n                                this._disposeMaterials([previousDataLOD[babylonDrawMode].babylonMaterial]);\r\n                                delete previousDataLOD[babylonDrawMode];\r\n                            }\r\n                        }\r\n\r\n                        return babylonMaterial;\r\n                    });\r\n\r\n                this._materialPromiseLODs[indexLOD] = this._materialPromiseLODs[indexLOD] || [];\r\n\r\n                if (indexLOD === 0) {\r\n                    firstPromise = promise;\r\n                } else {\r\n                    this._materialIndexLOD = null;\r\n                    this._materialPromiseLODs[indexLOD].push(promise);\r\n                }\r\n            }\r\n\r\n            this._loader.logClose();\r\n            return await firstPromise!;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public _loadUriAsync(context: string, property: IProperty, uri: string): Nullable<Promise<ArrayBufferView>> {\r\n        // Defer the loading of uris if loading a node or material LOD.\r\n        if (this._nodeIndexLOD !== null) {\r\n            this._loader.log(`deferred`);\r\n            const previousIndexLOD = this._nodeIndexLOD - 1;\r\n            this._nodeSignalLODs[previousIndexLOD] = this._nodeSignalLODs[previousIndexLOD] || new Deferred<void>();\r\n            return this._nodeSignalLODs[this._nodeIndexLOD - 1].promise.then(async () => {\r\n                return await this._loader.loadUriAsync(context, property, uri);\r\n            });\r\n        } else if (this._materialIndexLOD !== null) {\r\n            this._loader.log(`deferred`);\r\n            const previousIndexLOD = this._materialIndexLOD - 1;\r\n            this._materialSignalLODs[previousIndexLOD] = this._materialSignalLODs[previousIndexLOD] || new Deferred<void>();\r\n            return this._materialSignalLODs[previousIndexLOD].promise.then(async () => {\r\n                return await this._loader.loadUriAsync(context, property, uri);\r\n            });\r\n        }\r\n\r\n        return null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadBufferAsync(context: string, buffer: IBuffer, byteOffset: number, byteLength: number): Nullable<Promise<ArrayBufferView>> {\r\n        if (this._loader.parent.useRangeRequests && !buffer.uri) {\r\n            if (!this._loader.bin) {\r\n                throw new Error(`${context}: Uri is missing or the binary glTF is missing its binary chunk`);\r\n            }\r\n\r\n            const loadAsync = async (bufferLODs: Array<IBufferInfo>, indexLOD: number) => {\r\n                const start = byteOffset;\r\n                const end = start + byteLength - 1;\r\n                let bufferLOD = bufferLODs[indexLOD];\r\n                if (bufferLOD) {\r\n                    bufferLOD.start = Math.min(bufferLOD.start, start);\r\n                    bufferLOD.end = Math.max(bufferLOD.end, end);\r\n                } else {\r\n                    bufferLOD = { start: start, end: end, loaded: new Deferred() };\r\n                    bufferLODs[indexLOD] = bufferLOD;\r\n                }\r\n\r\n                return await bufferLOD.loaded.promise.then((data) => {\r\n                    return new Uint8Array(data.buffer, data.byteOffset + byteOffset - bufferLOD.start, byteLength);\r\n                });\r\n            };\r\n\r\n            this._loader.log(`deferred`);\r\n\r\n            if (this._nodeIndexLOD !== null) {\r\n                return loadAsync(this._nodeBufferLODs, this._nodeIndexLOD);\r\n            } else if (this._materialIndexLOD !== null) {\r\n                return loadAsync(this._materialBufferLODs, this._materialIndexLOD);\r\n            } else {\r\n                return loadAsync(this._bufferLODs, 0);\r\n            }\r\n        }\r\n\r\n        return null;\r\n    }\r\n\r\n    private _loadBufferLOD(bufferLODs: Array<IBufferInfo>, indexLOD: number): void {\r\n        const bufferLOD = bufferLODs[indexLOD];\r\n        if (bufferLOD) {\r\n            this._loader.log(`Loading buffer range [${bufferLOD.start}-${bufferLOD.end}]`);\r\n            this._loader.bin!.readAsync(bufferLOD.start, bufferLOD.end - bufferLOD.start + 1).then(\r\n                (data) => {\r\n                    bufferLOD.loaded.resolve(data);\r\n                },\r\n                (error) => {\r\n                    bufferLOD.loaded.reject(error);\r\n                }\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @returns an array of LOD properties from lowest to highest.\r\n     * @param context\r\n     * @param property\r\n     * @param array\r\n     * @param ids\r\n     */\r\n    private _getLODs<T>(context: string, property: T, array: ArrayLike<T> | undefined, ids: number[]): T[] {\r\n        if (this.maxLODsToLoad <= 0) {\r\n            throw new Error(\"maxLODsToLoad must be greater than zero\");\r\n        }\r\n\r\n        const properties: T[] = [];\r\n\r\n        for (let i = ids.length - 1; i >= 0; i--) {\r\n            properties.push(ArrayItem.Get(`${context}/ids/${ids[i]}`, array, ids[i]));\r\n            if (properties.length === this.maxLODsToLoad) {\r\n                return properties;\r\n            }\r\n        }\r\n\r\n        properties.push(property);\r\n        return properties;\r\n    }\r\n\r\n    private _disposeTransformNode(babylonTransformNode: TransformNode): void {\r\n        const babylonMaterials: Material[] = [];\r\n        const babylonMaterial = (babylonTransformNode as Mesh).material;\r\n        if (babylonMaterial) {\r\n            babylonMaterials.push(babylonMaterial);\r\n        }\r\n        for (const babylonMesh of babylonTransformNode.getChildMeshes()) {\r\n            if (babylonMesh.material) {\r\n                babylonMaterials.push(babylonMesh.material);\r\n            }\r\n        }\r\n\r\n        babylonTransformNode.dispose();\r\n\r\n        const babylonMaterialsToDispose = babylonMaterials.filter((babylonMaterial) => this._loader.babylonScene.meshes.every((mesh) => mesh.material != babylonMaterial));\r\n        this._disposeMaterials(babylonMaterialsToDispose);\r\n    }\r\n\r\n    private _disposeMaterials(babylonMaterials: Material[]): void {\r\n        const babylonTextures: { [uniqueId: number]: BaseTexture } = {};\r\n\r\n        for (const babylonMaterial of babylonMaterials) {\r\n            for (const babylonTexture of babylonMaterial.getActiveTextures()) {\r\n                babylonTextures[babylonTexture.uniqueId] = babylonTexture;\r\n            }\r\n\r\n            babylonMaterial.dispose();\r\n        }\r\n\r\n        for (const uniqueId in babylonTextures) {\r\n            for (const babylonMaterial of this._loader.babylonScene.materials) {\r\n                if (babylonMaterial.hasTexture(babylonTextures[uniqueId])) {\r\n                    delete babylonTextures[uniqueId];\r\n                }\r\n            }\r\n        }\r\n\r\n        for (const uniqueId in babylonTextures) {\r\n            babylonTextures[uniqueId].dispose();\r\n        }\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the MSFT_lod glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterMSFT_lod(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new MSFT_lod(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./MSFT_lod.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./MSFT_lod.types\";\r\nexport * from \"./MSFT_lod.pure\";\r\n\r\nimport { RegisterMSFT_lod } from \"./MSFT_lod.pure\";\r\nRegisterMSFT_lod();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type PBRMaterial } from \"core/Materials/PBR/pbrMaterial\";\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"MSFT_minecraftMesh\";\r\n\r\n/** @internal */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class MSFT_minecraftMesh implements IGLTFLoaderExtension {\r\n    /** @internal */\r\n    public readonly name = NAME;\r\n\r\n    /** @internal */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /** @internal */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /** @internal */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtraAsync<boolean>(context, material, this.name, async (extraContext, extra) => {\r\n            if (extra) {\r\n                const impl = this._loader._pbrMaterialImpls.get(\"pbr\");\r\n                if (!impl) {\r\n                    throw new Error(`${extraContext}: Material type not supported`);\r\n                }\r\n\r\n                const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial);\r\n\r\n                if (babylonMaterial.needAlphaBlending()) {\r\n                    babylonMaterial.forceDepthWrite = true;\r\n                    babylonMaterial.separateCullingPass = true;\r\n                }\r\n\r\n                babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite;\r\n                (babylonMaterial as PBRMaterial).twoSidedLighting = true;\r\n\r\n                return await promise;\r\n            }\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the MSFT_minecraftMesh glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterMSFT_minecraftMesh(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new MSFT_minecraftMesh(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./MSFT_minecraftMesh.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./MSFT_minecraftMesh.types\";\r\nexport * from \"./MSFT_minecraftMesh.pure\";\r\n\r\nimport { RegisterMSFT_minecraftMesh } from \"./MSFT_minecraftMesh.pure\";\r\nRegisterMSFT_minecraftMesh();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type IMaterial } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"MSFT_sRGBFactors\";\r\n\r\n/** @internal */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class MSFT_sRGBFactors implements IGLTFLoaderExtension {\r\n    /** @internal */\r\n    public readonly name = NAME;\r\n\r\n    /** @internal */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /** @internal */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /** @internal*/\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n        return GLTFLoader.LoadExtraAsync<boolean>(context, material, this.name, async (extraContext, extra) => {\r\n            if (extra) {\r\n                const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial)!;\r\n                const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial);\r\n\r\n                const useExactSrgbConversions = babylonMaterial.getScene().getEngine().useExactSrgbConversions;\r\n                if (!adapter.baseColorTexture) {\r\n                    adapter.baseColor.toLinearSpaceToRef(adapter.baseColor, useExactSrgbConversions);\r\n                }\r\n                if (!adapter.specularColorTexture) {\r\n                    adapter.specularColor.toLinearSpaceToRef(adapter.specularColor, useExactSrgbConversions);\r\n                }\r\n\r\n                return await promise;\r\n            }\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the MSFT_sRGBFactors glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterMSFT_sRGBFactors(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new MSFT_sRGBFactors(loader));\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport { type IKHRInteractivity_Declaration, type IKHRInteractivity_Graph, type IKHRInteractivity_Node } from \"babylonjs-gltf2interface\";\nimport { FlowGraphBlockNames } from \"core/FlowGraph/Blocks/flowGraphBlockNames\";\nimport { Logger } from \"core/Misc/logger\";\nimport { type ISerializedFlowGraphBlock, type ISerializedFlowGraphContext } from \"core/FlowGraph/typeDefinitions\";\nimport { type InteractivityEvent, type InteractivityGraphToFlowGraphParser } from \"./interactivityGraphParser\";\nimport { type IGLTF } from \"../../glTFLoaderInterfaces\";\nimport { FlowGraphTypes, getAnimationTypeByFlowGraphType } from \"core/FlowGraph/flowGraphRichTypes\";\n\n// Per-block runaway-loop guard for KHR_interactivity for-loops. Interactivity assets may run large\n// finite loops (e.g. the math/random Monte Carlo conformance asset iterates 10k times), so this is\n// set above the FlowGraphForLoopBlock process-wide default while staying low enough that the guard is\n// still meaningful — every iteration runs a full synchronous sub-graph, so a much larger value (and\n// especially nested loops) could lock the main thread before the guard trips. Applied per for-loop\n// block via the flow/for extraProcessor rather than by mutating the shared static.\nconst InteractivityForLoopMaxIterations = 20000;\n\n/**\n * Describes how one KHR_interactivity configuration or socket property maps to FlowGraph.\n *\n * The same contract is used for fixed sockets, wildcard sockets, configuration validation,\n * defaulting, and multi-block routing during strict graph lowering.\n */\nexport interface IGLTFToFlowGraphMappingObject {\n    /**\n     * The name of the property in the FlowGraph block.\n     */\n    name: string;\n\n    /**\n     * Whether this socket mapping exists only for pre-ratification compatibility input.\n     */\n    compatibilityOnly?: boolean;\n\n    /**\n     * The type of the property in the glTF specs.\n     * If not provided will be inferred.\n     */\n    gltfType?: string;\n\n    /**\n     * The type of the property in the FlowGraph block.\n     * If not defined it equals the glTF type.\n     */\n    flowGraphType?: string;\n\n    /**\n     * A function that transforms the data from the glTF to the FlowGraph block.\n     */\n    dataTransformer?: (data: any, parser: InteractivityGraphToFlowGraphParser) => any;\n\n    /**\n     * If the property can contain multiple values.\n     */\n    isArray?: boolean;\n\n    /**\n     * If the property is in the options passed to the constructor of the block.\n     */\n    inOptions?: boolean;\n\n    /**\n     * If the property is an index to a value.\n     * if defined this will be the name of the array to find the object in.\n     */\n    isVariable?: boolean;\n\n    /**\n     * the name of the class type this value will be mapped to.\n     * This is used if we generate more than one block for a single glTF node.\n     * Defaults to the first block in the mapping.\n     */\n    toBlock?: FlowGraphBlockNames | string;\n\n    /**\n     * Used in configuration values. If defined, this will be the default value, if no value is provided.\n     */\n    defaultValue?: any;\n\n    /**\n     * When the input value comes from a connection (an upstream node output) rather than a literal,\n     * the parse-time {@link dataTransformer} cannot run. If this is `true`, the importer inserts a\n     * runtime multiply block that scales the connected value by the animation target fps, converting\n     * a KHR animation time (seconds) into Babylon animation frames. Literal values keep using the\n     * {@link dataTransformer}. Used by `animation/start` / `animation/stopAt` time inputs, which may\n     * be fed by a `pointer/get` (e.g. the read-only `maxTime` animation pointer).\n     */\n    convertConnectedTimeToFrames?: boolean;\n\n    /**\n     * KHR configuration value type used by canonical validation.\n     */\n    configurationType?: \"bool\" | \"int\" | \"int[]\" | \"string\";\n\n    /**\n     * Whether this configuration entry exists only for canonical validation.\n     */\n    validationOnly?: boolean;\n\n    /**\n     * Whether an operation without a complete default configuration requires this property.\n     */\n    required?: boolean;\n\n    /**\n     * Graph array referenced by an integer configuration value.\n     */\n    indexSource?: \"types\" | \"variables\" | \"events\" | \"nodes\" | \"assetNodes\";\n\n    /**\n     * Minimum number of values required for an array configuration.\n     */\n    minItems?: number;\n\n    /**\n     * Whether the configured indices generate required input value sockets.\n     */\n    generatesInputValueSockets?: boolean;\n\n    /**\n     * Whether integer case values generate required input value sockets.\n     */\n    generatesCaseInputValueSockets?: boolean;\n\n    /**\n     * Whether this string configuration generates JSON Pointer Template sockets.\n     */\n    pointerTemplate?: boolean;\n\n    /**\n     * Whether an invalid value falls back to the operation's default configuration.\n     */\n    invalidUsesDefault?: boolean;\n\n    /**\n     * Allowed KHR type signatures for a type-index configuration.\n     */\n    allowedSignatures?: readonly (\"bool\" | \"float\" | \"float2\" | \"float3\" | \"float4\" | \"float2x2\" | \"float3x3\" | \"float4x4\" | \"int\" | \"ref\" | \"custom\")[];\n\n    /** Allowed literal values for this configuration property. */\n    allowedValues?: readonly (boolean | number | string)[];\n\n    /**\n     * Input socket whose effective type determines this output socket type.\n     */\n    typeSourceInput?: string;\n\n    /** Inclusive minimum for an integer configuration value. */\n    minimum?: number;\n\n    /** Inclusive maximum for an integer configuration value. */\n    maximum?: number;\n\n    /**\n     * Whether this configuration value generates numbered input flow sockets.\n     */\n    generatesInputFlowSockets?: boolean;\n\n    /**\n     * Whether this configuration array generates output flow sockets.\n     */\n    generatesOutputFlowSockets?: boolean;\n\n    /**\n     * Properties in the same group fall back to their defaults together when any member is\n     * missing or invalid.\n     */\n    configurationGroup?: string;\n\n    /**\n     * Whether duplicate array values are removed from the effective configuration.\n     */\n    uniqueValues?: boolean;\n\n    /**\n     * Whether a string configuration value is a `debug/log` message template.\n     */\n    debugLogTemplate?: boolean;\n}\n\n/**\n * Description of how a KHR_interactivity declaration (op such as\n * `pointer/get`, `event/onSelect`, `math/add`) maps to one or more\n * FlowGraph blocks. Used by {@link InteractivityGraphToFlowGraphParser}\n * to translate the source glTF graph into the serialized FlowGraph form.\n */\nexport interface IGLTFToFlowGraphMapping {\n    /**\n     * The type of the FlowGraph block(s).\n     * Typically will be a single element in an array.\n     * When adding blocks defined in this module use the KHR_interactivity prefix.\n     */\n    blocks: (FlowGraphBlockNames | string)[];\n\n    /**\n     * Exact value socket contract for an operation supplied by another extension.\n     */\n    declarationSchema?: {\n        inputValueSockets: Record<string, \"bool\" | \"float\" | \"float2\" | \"float3\" | \"float4\" | \"float2x2\" | \"float3x3\" | \"float4x4\" | \"int\" | \"ref\" | \"custom\">;\n        outputValueSockets: Record<string, \"bool\" | \"float\" | \"float2\" | \"float3\" | \"float4\" | \"float2x2\" | \"float3x3\" | \"float4x4\" | \"int\" | \"ref\" | \"custom\">;\n    };\n    /**\n     * The inputs of the glTF node mapped to the FlowGraph block.\n     */\n    inputs?: {\n        /**\n         * The value inputs of the glTF node mapped to the FlowGraph block.\n         */\n        values?: { [originName: string]: IGLTFToFlowGraphMappingObject };\n        /**\n         * The flow inputs of the glTF node mapped to the FlowGraph block.\n         */\n        flows?: { [originName: string]: IGLTFToFlowGraphMappingObject };\n    };\n    /**\n     * The outputs of the glTF node mapped to the FlowGraph block.\n     */\n    outputs?: {\n        /**\n         * The value outputs of the glTF node mapped to the FlowGraph block.\n         */\n        values?: { [originName: string]: IGLTFToFlowGraphMappingObject };\n        /**\n         * The flow outputs of the glTF node mapped to the FlowGraph block.\n         */\n        flows?: { [originName: string]: IGLTFToFlowGraphMappingObject };\n    };\n    /**\n     * The configuration of the glTF node mapped to the FlowGraph block.\n     * This information is usually passed to the constructor of the block.\n     */\n    configuration?: { [originName: string]: IGLTFToFlowGraphMappingObject };\n\n    /**\n     * If we generate more than one block for a single glTF node, this mapping will be used to map\n     * between the flowGraph classes.\n     */\n    typeToTypeMapping?: { [originName: string]: IGLTFToFlowGraphMappingObject };\n\n    /**\n     * The connections between two or more blocks.\n     * This is used to connect the blocks in the graph\n     */\n    interBlockConnectors?: {\n        /**\n         * The name of the input connection in the first block.\n         */\n        input: string;\n        /**\n         * The name of the output connection in the second block.\n         */\n        output: string;\n\n        /**\n         * The index of the block in the array of blocks that corresponds to the input.\n         */\n        inputBlockIndex: number;\n        /**\n         * The index of the block in the array of blocks that corresponds to the output.\n         */\n        outputBlockIndex: number;\n        /**\n         * If the connection is a variable connection or a flow connection.\n         */\n        isVariable?: boolean;\n    }[];\n\n    /**\n     * This optional function will allow to validate the node, according to the glTF specs.\n     * For example, if a node has a configuration object, it must be present and correct.\n     * This is a basic node-based validation.\n     * This function is expected to return false and log the error if the node is not valid.\n     * Note that this function can also modify the node, if needed.\n     *\n     * @param gltfBlock the glTF node to validate\n     * @param interactivityGraph the interactivity graph\n     * @param glTFObject the glTF object\n     * @returns true if validated, false if not.\n     */\n    validation?: (gltfBlock: IKHRInteractivity_Node, interactivityGraph: IKHRInteractivity_Graph, glTFObject?: IGLTF) => { valid: boolean; error?: string };\n\n    /**\n     * This is used if we need extra information for the constructor/options that is not provided directly by the glTF node.\n     * This function can return more than one node, if extra nodes are needed for this block to function correctly.\n     * Returning more than one block will usually happen when a json pointer was provided.\n     *\n     * @param gltfBlock the glTF node\n     * @param declaration the declaration object\n     * @param mapping the mapping object\n     * @param parser the interactivity graph parser\n     * @param serializedObjects the serialized objects\n     * @param context the serialized flow graph context\n     * @param globalGLTF the global gltf object\n     * @returns an array of serialized nodes that will be added to the graph.\n     */\n    extraProcessor?: (\n        gltfBlock: IKHRInteractivity_Node,\n        declaration: IKHRInteractivity_Declaration,\n        mapping: IGLTFToFlowGraphMapping,\n        parser: InteractivityGraphToFlowGraphParser,\n        serializedObjects: ISerializedFlowGraphBlock[],\n        context: ISerializedFlowGraphContext,\n        globalGLTF?: IGLTF\n    ) => ISerializedFlowGraphBlock[];\n}\n\nexport function getMappingForFullOperationName(fullOperationName: string) {\n    const [op, extension] = fullOperationName.split(\":\");\n    return getMappingForDeclaration({ op, extension });\n}\n\n/**\n * Returns whether a KHR operation accepts the conventional `in` flow socket when the registry\n * does not need a renamed or dynamic input mapping.\n * @param operation full KHR operation name\n * @returns true when the operation accepts the conventional input flow\n */\nexport function HasDefaultInteractivityFlowInput(operation: string): boolean {\n    if (operation === \"flow/waitAll\") {\n        return false;\n    }\n    return (\n        operation.startsWith(\"flow/\") ||\n        operation.startsWith(\"animation/\") ||\n        operation === \"pointer/set\" ||\n        operation === \"pointer/interpolate\" ||\n        operation === \"variable/set\" ||\n        operation === \"variable/interpolate\" ||\n        operation === \"event/send\" ||\n        operation === \"event/stopPropagation\" ||\n        operation === \"flow/log:BABYLON\"\n    );\n}\n\n/**\n * Normalizes serialized or runtime FlowGraph custom-event configuration for inverse comparison.\n * @param value serialized event-data entries or the runtime event-data dictionary\n * @returns stable event-data entries sorted by socket id\n */\nexport function NormalizeInteractivityEventDataConfiguration(value: unknown): unknown {\n    const normalizeValue = (entry: unknown): unknown => {\n        if (Array.isArray(entry)) {\n            return entry.slice();\n        }\n        if (entry !== null && typeof entry === \"object\") {\n            if (typeof (entry as { asArray?: () => ArrayLike<unknown> }).asArray === \"function\") {\n                return Array.from((entry as { asArray: () => ArrayLike<unknown> }).asArray());\n            }\n            if (Object.prototype.hasOwnProperty.call(entry, \"value\")) {\n                const nested = (entry as { value: unknown }).value;\n                return Array.isArray(nested) ? nested.slice() : [nested];\n            }\n        }\n        return [entry];\n    };\n    if (Array.isArray(value)) {\n        return value\n            .filter((entry): entry is { id: string; type: string; value?: unknown } => entry !== null && typeof entry === \"object\" && typeof entry.id === \"string\")\n            .map((entry) => ({\n                id: entry.id,\n                type: entry.type,\n                ...(entry.value === undefined ? {} : { value: normalizeValue(entry.value) }),\n            }))\n            .sort((left, right) => left.id.localeCompare(right.id));\n    }\n    if (value !== null && typeof value === \"object\") {\n        return Object.entries(value as Record<string, unknown>)\n            .map(([id, entry]) => {\n                if (entry === null || typeof entry !== \"object\") {\n                    return { id, malformed: true };\n                }\n                const definition = entry as { type?: { typeName?: string } | string; value?: unknown };\n                return {\n                    id,\n                    type: typeof definition.type === \"string\" ? definition.type : definition.type?.typeName,\n                    ...(definition.value === undefined ? {} : { value: normalizeValue(definition.value) }),\n                };\n            })\n            .sort((left, right) => left.id.localeCompare(right.id));\n    }\n    return value;\n}\n\nexport function getMappingForDeclaration(declaration: IKHRInteractivity_Declaration, returnNoOpIfNotAvailable: boolean = true): IGLTFToFlowGraphMapping | undefined {\n    const extensionMappings = declaration.extension ? _GetOwnRegistryValue(gltfExtensionsToFlowGraphMapping, declaration.extension) : undefined;\n    const mapping = declaration.extension ? _GetOwnRegistryValue(extensionMappings, declaration.op) : _GetOwnRegistryValue(gltfToFlowGraphMapping, declaration.op);\n    if (!mapping) {\n        if (returnNoOpIfNotAvailable) {\n            Logger.Warn(`No mapping found for operation ${declaration.op} and extension ${declaration.extension || \"KHR_interactivity\"}`);\n            return getNoOpMappingForDeclaration(declaration);\n        }\n    }\n    return mapping;\n}\n\n/**\n * Creates the typed no-op mapping required for an unsupported extension declaration.\n * @param declaration unsupported extension declaration\n * @returns a mapping that preserves the declared value sockets\n */\nexport function getNoOpMappingForDeclaration(declaration: IKHRInteractivity_Declaration): IGLTFToFlowGraphMapping {\n    const inputs: IGLTFToFlowGraphMapping[\"inputs\"] = {};\n    const outputs: IGLTFToFlowGraphMapping[\"outputs\"] = {\n        flows: {},\n    };\n    if (declaration.inputValueSockets) {\n        inputs.values = Object.create(null);\n        for (const key in declaration.inputValueSockets) {\n            if (Object.prototype.hasOwnProperty.call(declaration.inputValueSockets, key)) {\n                Object.defineProperty(inputs.values, key, {\n                    configurable: true,\n                    enumerable: true,\n                    value: { name: key },\n                    writable: true,\n                });\n            }\n        }\n    }\n    if (declaration.outputValueSockets) {\n        outputs.values = Object.create(null);\n        Object.keys(declaration.outputValueSockets).forEach((key) => {\n            Object.defineProperty(outputs.values!, key, {\n                configurable: true,\n                enumerable: true,\n                value: { name: key },\n                writable: true,\n            });\n        });\n    }\n    return {\n        blocks: [],\n        inputs,\n        outputs,\n    };\n}\n\n/**\n * This function will add new mapping to glTF interactivity.\n * Other extensions can define new types of blocks, this is the way to let interactivity know how to parse them.\n * @param key the type of node, i.e. \"variable/get\"\n * @param extension the extension of the interactivity operation, i.e. \"KHR_selectability\"\n * @param mapping The mapping object. See documentation or examples below.\n */\nexport function addNewInteractivityFlowGraphMapping(key: string, extension: string, mapping: IGLTFToFlowGraphMapping) {\n    let extensionMappings = _GetOwnRegistryValue(gltfExtensionsToFlowGraphMapping, extension);\n    if (!extensionMappings) {\n        extensionMappings = Object.create(null);\n        Object.defineProperty(gltfExtensionsToFlowGraphMapping, extension, {\n            configurable: true,\n            enumerable: true,\n            value: extensionMappings,\n            writable: true,\n        });\n    }\n    Object.defineProperty(extensionMappings, key, {\n        configurable: true,\n        enumerable: true,\n        value: mapping,\n        writable: true,\n    });\n}\n\nfunction _GetOwnRegistryValue<T>(registry: Record<string, T> | undefined, key: string): T | undefined {\n    return registry && Object.prototype.hasOwnProperty.call(registry, key) ? registry[key] : undefined;\n}\n\n/**\n * One operation entry in the shared KHR_interactivity-to-FlowGraph registry.\n */\nexport interface IKHRInteractivityOperationRegistryEntry {\n    /** Ratified operation identifier. */\n    op: string;\n    /** Extension defining the operation, when it is not a KHR_interactivity core operation. */\n    extension?: string;\n    /** Bidirectional structural mapping used by import and export. */\n    mapping: IGLTFToFlowGraphMapping;\n}\n\n/**\n * Gets a deterministic snapshot of the registered KHR_interactivity operation mappings.\n * Export analysis uses this same registry as import lowering so the two directions cannot\n * independently drift.\n * @returns registered mappings sorted by extension and operation\n */\nexport function GetInteractivityOperationRegistry(): readonly IKHRInteractivityOperationRegistryEntry[] {\n    const entries: IKHRInteractivityOperationRegistryEntry[] = Object.keys(gltfToFlowGraphMapping).map((op) => ({\n        op,\n        mapping: gltfToFlowGraphMapping[op],\n    }));\n    for (const extension of Object.keys(gltfExtensionsToFlowGraphMapping).sort()) {\n        for (const op of Object.keys(gltfExtensionsToFlowGraphMapping[extension]).sort()) {\n            entries.push({\n                op,\n                extension,\n                mapping: gltfExtensionsToFlowGraphMapping[extension][op],\n            });\n        }\n    }\n    return entries.sort((left, right) => `${left.extension ?? \"\"}:${left.op}`.localeCompare(`${right.extension ?? \"\"}:${right.op}`));\n}\n\nconst gltfExtensionsToFlowGraphMapping: { [extension: string]: { [key: string]: IGLTFToFlowGraphMapping } } = {\n    /**\n     * This is the BABYLON extension for glTF interactivity.\n     * It defines babylon-specific blocks and operations.\n     */\n    BABYLON: {\n        /**\n         * flow/log is a flow node that logs input to the console.\n         * It has \"in\" and \"out\" flows, and takes a message as input.\n         * The message can be any type of value.\n         * The message is logged to the console when the \"in\" flow is triggered.\n         * The \"out\" flow is triggered when the message is logged.\n         */\n        \"flow/log\": {\n            blocks: [FlowGraphBlockNames.ConsoleLog],\n            inputs: {\n                values: {\n                    message: { name: \"message\" },\n                    \"[segment]\": { name: \"$1\", compatibilityOnly: true },\n                },\n            },\n            outputs: {\n                flows: {\n                    out: { name: \"out\", compatibilityOnly: true },\n                },\n            },\n        },\n    },\n};\n\n// this mapper is just a way to convert the glTF nodes to FlowGraph nodes in terms of input/output connection names and values.\nconst gltfToFlowGraphMapping: { [key: string]: IGLTFToFlowGraphMapping } = {\n    \"event/onStart\": {\n        blocks: [FlowGraphBlockNames.SceneReadyEvent],\n        outputs: {\n            values: {\n                // KHR_interactivity `ref event` output (the event reference).\n                event: { name: \"event\" },\n            },\n            flows: {\n                out: { name: \"done\" },\n            },\n        },\n    },\n    \"event/onTick\": {\n        blocks: [FlowGraphBlockNames.SceneTickEvent],\n        inputs: {},\n        outputs: {\n            values: {\n                timeSinceStart: { name: \"timeSinceStart\", gltfType: \"number\" },\n                timeSinceLastTick: { name: \"deltaTime\", gltfType: \"number\" /*, dataTransformer: (time: number) => time / 1000*/ },\n                // KHR_interactivity `ref event` output (the event reference).\n                event: { name: \"event\" },\n            },\n            flows: {\n                out: { name: \"done\" },\n            },\n        },\n    },\n    \"event/send\": {\n        blocks: [FlowGraphBlockNames.SendCustomEvent],\n        configuration: {\n            event: {\n                name: \"eventId\",\n                configurationType: \"int\",\n                required: true,\n                indexSource: \"events\",\n                validationOnly: true,\n            },\n        },\n        inputs: {\n            values: {\n                \"[segment]\": { name: \"$1\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n            },\n        },\n        extraProcessor(gltfBlock, declaration, _mapping, parser, serializedObjects) {\n            // set eventId and eventData. The configuration object of the glTF should have a single object.\n            // validate that we are running it on the right block.\n            if (declaration.op !== \"event/send\" || !gltfBlock.configuration?.event) {\n                throw new Error(\"Send event should have a single configuration object, the event itself\");\n            }\n            const eventConfiguration = gltfBlock.configuration[\"event\"];\n            const eventId = eventConfiguration.value?.[0];\n            if (typeof eventId !== \"number\") {\n                throw new Error(\"Event id should be a number\");\n            }\n            const event: InteractivityEvent = parser.arrays.events[eventId];\n            const serializedObject = serializedObjects[0];\n            serializedObject.config ||= {};\n            serializedObject.config.eventId = event.eventId;\n            serializedObject.config.eventData = event.eventData;\n            return serializedObjects;\n        },\n    },\n    \"event/receive\": {\n        blocks: [FlowGraphBlockNames.ReceiveCustomEvent],\n        configuration: {\n            event: {\n                name: \"eventId\",\n                configurationType: \"int\",\n                required: true,\n                indexSource: \"events\",\n                validationOnly: true,\n            },\n        },\n        outputs: {\n            values: {\n                // KHR_interactivity `ref event` output (the event reference).\n                event: { name: \"event\" },\n                \"[segment]\": { name: \"$1\" },\n            },\n            flows: {\n                out: { name: \"done\" },\n            },\n        },\n        validation(gltfBlock, interactivityGraph) {\n            if (!gltfBlock.configuration) {\n                Logger.Error(\"Receive event should have a configuration object\");\n                return { valid: false, error: \"Receive event should have a configuration object\" };\n            }\n            const eventConfiguration = gltfBlock.configuration[\"event\"];\n            if (!eventConfiguration) {\n                Logger.Error(\"Receive event should have a single configuration object, the event itself\");\n                return { valid: false, error: \"Receive event should have a single configuration object, the event itself\" };\n            }\n            const eventId = eventConfiguration.value?.[0];\n            if (typeof eventId !== \"number\") {\n                Logger.Error(\"Event id should be a number\");\n                return { valid: false, error: \"Event id should be a number\" };\n            }\n            const event = interactivityGraph.events?.[eventId];\n            if (!event) {\n                Logger.Error(`Event with id ${eventId} not found`);\n                return { valid: false, error: `Event with id ${eventId} not found` };\n            }\n            return { valid: true };\n        },\n        extraProcessor(gltfBlock, declaration, _mapping, parser, serializedObjects) {\n            // set eventId and eventData. The configuration object of the glTF should have a single object.\n            // validate that we are running it on the right block.\n            if (declaration.op !== \"event/receive\" || !gltfBlock.configuration?.event) {\n                throw new Error(\"Receive event should have a single configuration object, the event itself\");\n            }\n            const eventConfiguration = gltfBlock.configuration[\"event\"];\n            const eventId = eventConfiguration.value?.[0];\n            if (typeof eventId !== \"number\") {\n                throw new Error(\"Event id should be a number\");\n            }\n            const event: InteractivityEvent = parser.arrays.events[eventId];\n            const serializedObject = serializedObjects[0];\n            serializedObject.config ||= {};\n            serializedObject.config.eventId = event.eventId;\n            serializedObject.config.eventData = event.eventData;\n            return serializedObjects;\n        },\n    },\n    \"event/stopPropagation\": {\n        blocks: [FlowGraphBlockNames.StopEventPropagation],\n        inputs: {\n            values: {\n                event: { name: \"event\" },\n                stopImmediate: { name: \"stopImmediate\" },\n            },\n            flows: {\n                in: { name: \"in\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n            },\n        },\n    },\n    \"math/E\": getSimpleInputMapping(FlowGraphBlockNames.E, []),\n    \"math/Pi\": getSimpleInputMapping(FlowGraphBlockNames.PI, []),\n    \"math/Tau\": getSimpleInputMapping(FlowGraphBlockNames.Tau, []),\n    \"math/Inf\": getSimpleInputMapping(FlowGraphBlockNames.Inf, []),\n    \"math/NaN\": getSimpleInputMapping(FlowGraphBlockNames.NaN, []),\n    \"math/abs\": getSimpleInputMapping(FlowGraphBlockNames.Abs),\n    \"math/sign\": getSimpleInputMapping(FlowGraphBlockNames.Sign),\n    \"math/trunc\": getSimpleInputMapping(FlowGraphBlockNames.Trunc),\n    \"math/floor\": getSimpleInputMapping(FlowGraphBlockNames.Floor),\n    \"math/ceil\": getSimpleInputMapping(FlowGraphBlockNames.Ceil),\n    \"math/round\": {\n        blocks: [FlowGraphBlockNames.Round],\n        configuration: {},\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n        extraProcessor(gltfBlock, declaration, _mapping, parser, serializedObjects) {\n            // configure it to work the way glTF specifies\n            serializedObjects[0].config ||= {};\n            serializedObjects[0].config.roundHalfAwayFromZero = true;\n            return serializedObjects;\n        },\n    },\n    \"math/fract\": getSimpleInputMapping(FlowGraphBlockNames.Fraction),\n    \"math/neg\": getSimpleInputMapping(FlowGraphBlockNames.Negation),\n    \"math/add\": getSimpleInputMapping(FlowGraphBlockNames.Add, [\"a\", \"b\"], true),\n    \"math/sub\": getSimpleInputMapping(FlowGraphBlockNames.Subtract, [\"a\", \"b\"], true),\n    \"math/mul\": {\n        blocks: [FlowGraphBlockNames.Multiply],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                b: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) {\n            // configure it to work the way glTF specifies\n            serializedObjects[0].config ||= {};\n            serializedObjects[0].config.useMatrixPerComponent = true;\n            serializedObjects[0].config.preventIntegerFloatArithmetic = true;\n            // try to infer the type or fallback to Integer\n            // check the gltf block for the inputs, see if they have a type\n            let type = -1;\n            Object.keys(_gltfBlock.values || {}).find((value) => {\n                if (_gltfBlock.values?.[value].type !== undefined) {\n                    type = _gltfBlock.values[value].type;\n                    return true;\n                }\n                return false;\n            });\n            if (type !== -1) {\n                serializedObjects[0].config.type = _parser.arrays.types[type].flowGraphType;\n            }\n            return serializedObjects;\n        },\n        validation(gltfBlock) {\n            if (gltfBlock.values) {\n                // make sure types are the same\n                return ValidateTypes(gltfBlock);\n            }\n            return { valid: true };\n        },\n    },\n    \"math/div\": getSimpleInputMapping(FlowGraphBlockNames.Divide, [\"a\", \"b\"], true),\n    \"math/rem\": getSimpleInputMapping(FlowGraphBlockNames.Modulo, [\"a\", \"b\"]),\n    \"math/min\": getSimpleInputMapping(FlowGraphBlockNames.Min, [\"a\", \"b\"]),\n    \"math/max\": getSimpleInputMapping(FlowGraphBlockNames.Max, [\"a\", \"b\"]),\n    \"math/clamp\": getSimpleInputMapping(FlowGraphBlockNames.Clamp, [\"a\", \"b\", \"c\"]),\n    \"math/saturate\": getSimpleInputMapping(FlowGraphBlockNames.Saturate),\n    \"math/mix\": getSimpleInputMapping(FlowGraphBlockNames.MathInterpolation, [\"a\", \"b\", \"c\"]),\n    // Smooth-step (Hermite interpolation): edges a/b and value c.\n    \"math/smoothStep\": getSimpleInputMapping(FlowGraphBlockNames.SmoothStep, [\"a\", \"b\", \"c\"]),\n    // Linear sRGB <-> OkLCh (Oklab polar form). Scalar r/g/b inputs map to l/c/h\n    // outputs (hue in radians) and vice-versa.\n    \"math/rgbToOkLCh\": {\n        blocks: [FlowGraphBlockNames.RGBToOkLCh],\n        inputs: {\n            values: {\n                r: { name: \"r\", gltfType: \"number\" },\n                g: { name: \"g\", gltfType: \"number\" },\n                b: { name: \"b\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                l: { name: \"l\" },\n                c: { name: \"c\" },\n                h: { name: \"h\" },\n            },\n        },\n    },\n    \"math/rgbFromOkLCh\": {\n        blocks: [FlowGraphBlockNames.RGBFromOkLCh],\n        inputs: {\n            values: {\n                l: { name: \"l\", gltfType: \"number\" },\n                c: { name: \"c\", gltfType: \"number\" },\n                h: { name: \"h\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                r: { name: \"r\" },\n                g: { name: \"g\" },\n                b: { name: \"b\" },\n            },\n        },\n    },\n    // Quaternion spherical-linear interpolation. Inputs are two unit\n    // quaternions and an unclamped float coefficient.\n    \"math/quatSlerp\": getSimpleInputMapping(FlowGraphBlockNames.MathSlerp, [\"a\", \"b\", \"c\"]),\n    // Vector spherical-linear interpolation (float2/float3). Inputs are two\n    // vectors and an unclamped float coefficient.\n    \"math/slerp\": getSimpleInputMapping(FlowGraphBlockNames.VectorSlerp, [\"a\", \"b\", \"c\"]),\n    \"math/eq\": getSimpleInputMapping(FlowGraphBlockNames.Equality, [\"a\", \"b\"]),\n    // Reference equality. The spec defines `ref/eq` as: true if both refs are\n    // null, true if both refer to the same object (regardless of whether it\n    // exists), false otherwise. FlowGraphEqualityBlock falls through to a\n    // strict `===` comparison for non-vector/matrix/numeric types, which\n    // already produces the spec-defined behaviour for Babylon object refs.\n    \"ref/eq\": getSimpleInputMapping(FlowGraphBlockNames.Equality, [\"a\", \"b\"]),\n    \"math/lt\": getSimpleInputMapping(FlowGraphBlockNames.LessThan, [\"a\", \"b\"]),\n    \"math/le\": getSimpleInputMapping(FlowGraphBlockNames.LessThanOrEqual, [\"a\", \"b\"]),\n    \"math/gt\": getSimpleInputMapping(FlowGraphBlockNames.GreaterThan, [\"a\", \"b\"]),\n    \"math/ge\": getSimpleInputMapping(FlowGraphBlockNames.GreaterThanOrEqual, [\"a\", \"b\"]),\n    \"math/isNaN\": getSimpleInputMapping(FlowGraphBlockNames.IsNaN),\n    \"math/isInf\": getSimpleInputMapping(FlowGraphBlockNames.IsInfinity),\n    \"math/select\": {\n        blocks: [FlowGraphBlockNames.Conditional],\n        inputs: {\n            values: {\n                condition: { name: \"condition\" },\n                // Should we validate those have the same type here, or assume it is already validated?\n                a: { name: \"onTrue\" },\n                b: { name: \"onFalse\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"output\", typeSourceInput: \"a\" },\n            },\n        },\n    },\n    \"math/random\": {\n        blocks: [FlowGraphBlockNames.Random],\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float\" },\n            },\n        },\n    },\n    \"math/sin\": getSimpleInputMapping(FlowGraphBlockNames.Sin),\n    \"math/cos\": getSimpleInputMapping(FlowGraphBlockNames.Cos),\n    \"math/tan\": getSimpleInputMapping(FlowGraphBlockNames.Tan),\n    \"math/asin\": getSimpleInputMapping(FlowGraphBlockNames.Asin),\n    \"math/acos\": getSimpleInputMapping(FlowGraphBlockNames.Acos),\n    \"math/atan\": getSimpleInputMapping(FlowGraphBlockNames.Atan),\n    \"math/atan2\": getSimpleInputMapping(FlowGraphBlockNames.Atan2, [\"a\", \"b\"]),\n    \"math/sinh\": getSimpleInputMapping(FlowGraphBlockNames.Sinh),\n    \"math/cosh\": getSimpleInputMapping(FlowGraphBlockNames.Cosh),\n    \"math/tanh\": getSimpleInputMapping(FlowGraphBlockNames.Tanh),\n    \"math/asinh\": getSimpleInputMapping(FlowGraphBlockNames.Asinh),\n    \"math/acosh\": getSimpleInputMapping(FlowGraphBlockNames.Acosh),\n    \"math/atanh\": getSimpleInputMapping(FlowGraphBlockNames.Atanh),\n    \"math/exp\": getSimpleInputMapping(FlowGraphBlockNames.Exponential),\n    \"math/log\": getSimpleInputMapping(FlowGraphBlockNames.Log),\n    \"math/log2\": getSimpleInputMapping(FlowGraphBlockNames.Log2),\n    \"math/log10\": getSimpleInputMapping(FlowGraphBlockNames.Log10),\n    \"math/sqrt\": getSimpleInputMapping(FlowGraphBlockNames.SquareRoot),\n    \"math/cbrt\": getSimpleInputMapping(FlowGraphBlockNames.CubeRoot),\n    \"math/pow\": getSimpleInputMapping(FlowGraphBlockNames.Power, [\"a\", \"b\"]),\n    \"math/length\": getSimpleInputMapping(FlowGraphBlockNames.Length),\n    \"math/normalize\": {\n        ...getSimpleInputMapping(FlowGraphBlockNames.Normalize),\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n                isValid: { name: \"isValid\", gltfType: \"bool\" },\n            },\n        },\n    },\n    \"math/dot\": getSimpleInputMapping(FlowGraphBlockNames.Dot, [\"a\", \"b\"]),\n    \"math/cross\": getSimpleInputMapping(FlowGraphBlockNames.Cross, [\"a\", \"b\"]),\n    \"math/rotate2D\": {\n        blocks: [FlowGraphBlockNames.Rotate2D],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                angle: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n    },\n    \"math/rotate3D\": {\n        blocks: [FlowGraphBlockNames.Rotate3D],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                rotation: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n    },\n    \"math/transform\": {\n        // glTF transform is vectorN with matrixN\n        blocks: [FlowGraphBlockNames.TransformVector],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                b: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n    },\n    \"math/combine2\": {\n        blocks: [FlowGraphBlockNames.CombineVector2],\n        inputs: {\n            values: {\n                a: { name: \"input_0\", gltfType: \"number\" },\n                b: { name: \"input_1\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float2\" },\n            },\n        },\n    },\n    \"math/combine3\": {\n        blocks: [FlowGraphBlockNames.CombineVector3],\n        inputs: {\n            values: {\n                a: { name: \"input_0\", gltfType: \"number\" },\n                b: { name: \"input_1\", gltfType: \"number\" },\n                c: { name: \"input_2\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float3\" },\n            },\n        },\n    },\n    \"math/combine4\": {\n        blocks: [FlowGraphBlockNames.CombineVector4],\n        inputs: {\n            values: {\n                a: { name: \"input_0\", gltfType: \"number\" },\n                b: { name: \"input_1\", gltfType: \"number\" },\n                c: { name: \"input_2\", gltfType: \"number\" },\n                d: { name: \"input_3\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4\" },\n            },\n        },\n    },\n    // one input, N outputs! outputs named using numbers.\n    \"math/extract2\": {\n        blocks: [FlowGraphBlockNames.ExtractVector2],\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                \"0\": { name: \"output_0\" },\n                \"1\": { name: \"output_1\" },\n            },\n        },\n    },\n    \"math/extract3\": {\n        blocks: [FlowGraphBlockNames.ExtractVector3],\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                \"0\": { name: \"output_0\" },\n                \"1\": { name: \"output_1\" },\n                \"2\": { name: \"output_2\" },\n            },\n        },\n    },\n    \"math/extract4\": {\n        blocks: [FlowGraphBlockNames.ExtractVector4],\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                \"0\": { name: \"output_0\" },\n                \"1\": { name: \"output_1\" },\n                \"2\": { name: \"output_2\" },\n                \"3\": { name: \"output_3\" },\n            },\n        },\n    },\n    \"math/transpose\": getSimpleInputMapping(FlowGraphBlockNames.Transpose),\n    \"math/determinant\": getSimpleInputMapping(FlowGraphBlockNames.Determinant),\n    \"math/inverse\": {\n        ...getSimpleInputMapping(FlowGraphBlockNames.InvertMatrix),\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n                isValid: { name: \"isValid\", gltfType: \"bool\" },\n            },\n        },\n    },\n    \"math/matMul\": getSimpleInputMapping(FlowGraphBlockNames.MatrixMultiplication, [\"a\", \"b\"]),\n    \"math/matCompose\": {\n        blocks: [FlowGraphBlockNames.MatrixCompose],\n        inputs: {\n            values: {\n                translation: { name: \"position\", gltfType: \"float3\" },\n                rotation: { name: \"rotationQuaternion\", gltfType: \"float4\" },\n                scale: { name: \"scaling\", gltfType: \"float3\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4x4\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) {\n            // configure it to work the way glTF specifies\n            const d = serializedObjects[0].dataInputs.find((input) => input.name === \"rotationQuaternion\");\n            if (!d) {\n                throw new Error(\"Rotation quaternion input not found\");\n            }\n            // if value is defined, set the type to quaternion\n            if (context._connectionValues[d.uniqueId]) {\n                context._connectionValues[d.uniqueId].type = FlowGraphTypes.Quaternion;\n            }\n            return serializedObjects;\n        },\n    },\n    \"math/matDecompose\": {\n        blocks: [FlowGraphBlockNames.MatrixDecompose],\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                translation: { name: \"position\" },\n                rotation: { name: \"rotationQuaternion\" },\n                scale: { name: \"scaling\" },\n                scaling: { name: \"scaling\", compatibilityOnly: true },\n                isValid: { name: \"isValid\", compatibilityOnly: true },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) {\n            // KHR_interactivity step 4 of the matDecompose algorithm requires a non-decomposable matrix to still\n            // report the extracted translation and the raw column lengths, instead of the type defaults the\n            // FlowGraph block emits by default. The block has no `isValid` output in glTF, so the caller can only\n            // observe those values.\n            serializedObjects[0].config ||= {};\n            serializedObjects[0].config.keepDegenerateComponents = true;\n            return serializedObjects;\n        },\n    },\n    \"math/quatConjugate\": getSimpleInputMapping(FlowGraphBlockNames.Conjugate, [\"a\"]),\n    \"math/quatMul\": {\n        blocks: [FlowGraphBlockNames.Multiply],\n        inputs: {\n            values: {\n                a: { name: \"a\", gltfType: \"float4\" },\n                b: { name: \"b\", gltfType: \"float4\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) {\n            serializedObjects[0].config ||= {};\n            serializedObjects[0].config.type = FlowGraphTypes.Quaternion;\n            return serializedObjects;\n        },\n    },\n    \"math/quatAngleBetween\": getSimpleInputMapping(FlowGraphBlockNames.AngleBetween, [\"a\", \"b\"]),\n    \"math/quatFromAxisAngle\": {\n        blocks: [FlowGraphBlockNames.QuaternionFromAxisAngle],\n        inputs: {\n            values: {\n                axis: { name: \"a\", gltfType: \"float3\" },\n                angle: { name: \"b\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4\" },\n            },\n        },\n    },\n    \"math/quatToAxisAngle\": {\n        blocks: [FlowGraphBlockNames.AxisAngleFromQuaternion],\n        inputs: {\n            values: {\n                a: { name: \"a\", gltfType: \"float4\" },\n            },\n        },\n        outputs: {\n            values: {\n                axis: { name: \"axis\", gltfType: \"float3\" },\n                angle: { name: \"angle\", gltfType: \"float\" },\n            },\n        },\n    },\n    \"math/quatFromDirections\": {\n        ...getSimpleInputMapping(FlowGraphBlockNames.QuaternionFromDirections, [\"a\", \"b\"]),\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4\" },\n            },\n        },\n    },\n    \"math/quatFromUpForward\": {\n        blocks: [FlowGraphBlockNames.QuaternionFromUpForward],\n        inputs: {\n            values: {\n                up: { name: \"a\", gltfType: \"float3\" },\n                forward: { name: \"b\", gltfType: \"float3\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4\" },\n            },\n        },\n    },\n    // Tait–Bryan intrinsic Euler angles (x/y/z, in radians) to a rotation quaternion. The rotation\n    // order is selected by the `order` configuration string (default `yxz`).\n    \"math/quatFromAngles\": {\n        blocks: [FlowGraphBlockNames.QuaternionFromAngles],\n        configuration: {\n            order: {\n                name: \"order\",\n                defaultValue: [\"yxz\"],\n                configurationType: \"string\",\n                invalidUsesDefault: true,\n                allowedValues: [\"xyz\", \"xzy\", \"yxz\", \"yzx\", \"zxy\", \"zyx\"],\n            },\n        },\n        inputs: {\n            values: {\n                x: { name: \"a\", gltfType: \"number\" },\n                y: { name: \"b\", gltfType: \"number\" },\n                z: { name: \"c\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4\" },\n            },\n        },\n    },\n    \"math/combine2x2\": {\n        blocks: [FlowGraphBlockNames.CombineMatrix2D],\n        inputs: {\n            values: {\n                a: { name: \"input_0\", gltfType: \"number\" },\n                b: { name: \"input_1\", gltfType: \"number\" },\n                c: { name: \"input_2\", gltfType: \"number\" },\n                d: { name: \"input_3\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float2x2\" },\n            },\n        },\n    },\n    \"math/extract2x2\": {\n        blocks: [FlowGraphBlockNames.ExtractMatrix2D],\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"float2x2\" },\n            },\n        },\n        outputs: {\n            values: {\n                \"0\": { name: \"output_0\" },\n                \"1\": { name: \"output_1\" },\n                \"2\": { name: \"output_2\" },\n                \"3\": { name: \"output_3\" },\n            },\n        },\n    },\n    \"math/combine3x3\": {\n        blocks: [FlowGraphBlockNames.CombineMatrix3D],\n        inputs: {\n            values: {\n                a: { name: \"input_0\", gltfType: \"number\" },\n                b: { name: \"input_1\", gltfType: \"number\" },\n                c: { name: \"input_2\", gltfType: \"number\" },\n                d: { name: \"input_3\", gltfType: \"number\" },\n                e: { name: \"input_4\", gltfType: \"number\" },\n                f: { name: \"input_5\", gltfType: \"number\" },\n                g: { name: \"input_6\", gltfType: \"number\" },\n                h: { name: \"input_7\", gltfType: \"number\" },\n                i: { name: \"input_8\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float3x3\" },\n            },\n        },\n    },\n    \"math/extract3x3\": {\n        blocks: [FlowGraphBlockNames.ExtractMatrix3D],\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"float3x3\" },\n            },\n        },\n        outputs: {\n            values: {\n                \"0\": { name: \"output_0\" },\n                \"1\": { name: \"output_1\" },\n                \"2\": { name: \"output_2\" },\n                \"3\": { name: \"output_3\" },\n                \"4\": { name: \"output_4\" },\n                \"5\": { name: \"output_5\" },\n                \"6\": { name: \"output_6\" },\n                \"7\": { name: \"output_7\" },\n                \"8\": { name: \"output_8\" },\n            },\n        },\n    },\n    \"math/combine4x4\": {\n        blocks: [FlowGraphBlockNames.CombineMatrix],\n        inputs: {\n            values: {\n                a: { name: \"input_0\", gltfType: \"number\" },\n                b: { name: \"input_1\", gltfType: \"number\" },\n                c: { name: \"input_2\", gltfType: \"number\" },\n                d: { name: \"input_3\", gltfType: \"number\" },\n                e: { name: \"input_4\", gltfType: \"number\" },\n                f: { name: \"input_5\", gltfType: \"number\" },\n                g: { name: \"input_6\", gltfType: \"number\" },\n                h: { name: \"input_7\", gltfType: \"number\" },\n                i: { name: \"input_8\", gltfType: \"number\" },\n                j: { name: \"input_9\", gltfType: \"number\" },\n                k: { name: \"input_10\", gltfType: \"number\" },\n                l: { name: \"input_11\", gltfType: \"number\" },\n                m: { name: \"input_12\", gltfType: \"number\" },\n                n: { name: \"input_13\", gltfType: \"number\" },\n                o: { name: \"input_14\", gltfType: \"number\" },\n                p: { name: \"input_15\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", gltfType: \"float4x4\" },\n            },\n        },\n    },\n    \"math/extract4x4\": {\n        blocks: [FlowGraphBlockNames.ExtractMatrix],\n        configuration: {},\n        inputs: {\n            values: {\n                a: { name: \"input\", gltfType: \"number\" },\n            },\n        },\n        outputs: {\n            values: {\n                \"0\": { name: \"output_0\" },\n                \"1\": { name: \"output_1\" },\n                \"2\": { name: \"output_2\" },\n                \"3\": { name: \"output_3\" },\n                \"4\": { name: \"output_4\" },\n                \"5\": { name: \"output_5\" },\n                \"6\": { name: \"output_6\" },\n                \"7\": { name: \"output_7\" },\n                \"8\": { name: \"output_8\" },\n                \"9\": { name: \"output_9\" },\n                \"10\": { name: \"output_10\" },\n                \"11\": { name: \"output_11\" },\n                \"12\": { name: \"output_12\" },\n                \"13\": { name: \"output_13\" },\n                \"14\": { name: \"output_14\" },\n                \"15\": { name: \"output_15\" },\n            },\n        },\n    },\n    \"math/not\": {\n        blocks: [FlowGraphBlockNames.BitwiseNot],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) {\n            // configure it to work the way glTF specifies\n            serializedObjects[0].config ||= {};\n            // try to infer the type or fallback to Integer\n            const socketIn = serializedObjects[0].dataInputs[0];\n            serializedObjects[0].config.valueType = context._connectionValues[socketIn.uniqueId]?.type ?? FlowGraphTypes.Integer;\n            return serializedObjects;\n        },\n    },\n    \"math/and\": {\n        blocks: [FlowGraphBlockNames.BitwiseAnd],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                b: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) {\n            // configure it to work the way glTF specifies\n            serializedObjects[0].config ||= {};\n            // try to infer the type or fallback to Integer\n            const socketInA = serializedObjects[0].dataInputs[0];\n            const socketInB = serializedObjects[0].dataInputs[1];\n            serializedObjects[0].config.valueType =\n                context._connectionValues[socketInA.uniqueId]?.type ?? context._connectionValues[socketInB.uniqueId]?.type ?? FlowGraphTypes.Integer;\n            return serializedObjects;\n        },\n    },\n    \"math/or\": {\n        blocks: [FlowGraphBlockNames.BitwiseOr],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                b: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) {\n            // configure it to work the way glTF specifies\n            serializedObjects[0].config ||= {};\n            // try to infer the type or fallback to Integer\n            const socketInA = serializedObjects[0].dataInputs[0];\n            const socketInB = serializedObjects[0].dataInputs[1];\n            serializedObjects[0].config.valueType =\n                context._connectionValues[socketInA.uniqueId]?.type ?? context._connectionValues[socketInB.uniqueId]?.type ?? FlowGraphTypes.Integer;\n            return serializedObjects;\n        },\n    },\n    \"math/xor\": {\n        blocks: [FlowGraphBlockNames.BitwiseXor],\n        inputs: {\n            values: {\n                a: { name: \"a\" },\n                b: { name: \"b\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: \"a\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) {\n            // configure it to work the way glTF specifies\n            serializedObjects[0].config ||= {};\n            // try to infer the type or fallback to Integer\n            const socketInA = serializedObjects[0].dataInputs[0];\n            const socketInB = serializedObjects[0].dataInputs[1];\n            serializedObjects[0].config.valueType =\n                context._connectionValues[socketInA.uniqueId]?.type ?? context._connectionValues[socketInB.uniqueId]?.type ?? FlowGraphTypes.Integer;\n            return serializedObjects;\n        },\n    },\n    \"math/asr\": getSimpleInputMapping(FlowGraphBlockNames.BitwiseRightShift, [\"a\", \"b\"]),\n    \"math/lsl\": getSimpleInputMapping(FlowGraphBlockNames.BitwiseLeftShift, [\"a\", \"b\"]),\n    \"math/clz\": getSimpleInputMapping(FlowGraphBlockNames.LeadingZeros),\n    \"math/ctz\": getSimpleInputMapping(FlowGraphBlockNames.TrailingZeros),\n    \"math/popcnt\": getSimpleInputMapping(FlowGraphBlockNames.OneBitsCounter),\n    \"math/rad\": getSimpleInputMapping(FlowGraphBlockNames.DegToRad),\n    \"math/deg\": getSimpleInputMapping(FlowGraphBlockNames.RadToDeg),\n    \"type/boolToInt\": getSimpleInputMapping(FlowGraphBlockNames.BooleanToInt),\n    \"type/boolToFloat\": getSimpleInputMapping(FlowGraphBlockNames.BooleanToFloat),\n    \"type/intToBool\": getSimpleInputMapping(FlowGraphBlockNames.IntToBoolean),\n    \"type/intToFloat\": getSimpleInputMapping(FlowGraphBlockNames.IntToFloat),\n    \"type/floatToInt\": getSimpleInputMapping(FlowGraphBlockNames.FloatToInt),\n    \"type/floatToBool\": getSimpleInputMapping(FlowGraphBlockNames.FloatToBoolean),\n\n    // flows\n    \"flow/sequence\": {\n        blocks: [FlowGraphBlockNames.Sequence],\n        outputs: {\n            flows: {\n                \"[segment]\": { name: \"$1\" },\n            },\n        },\n        extraProcessor(gltfBlock, _declaration, _mapping, _arrays, serializedObjects) {\n            const serializedObject = serializedObjects[0];\n            serializedObject.config ||= {};\n            serializedObject.config.outputSignalCount = Object.keys(gltfBlock.flows || []).length;\n            serializedObject.signalOutputs.forEach((output, index) => {\n                output.name = \"out_\" + index;\n            });\n            return serializedObjects;\n        },\n    },\n    \"flow/branch\": {\n        blocks: [FlowGraphBlockNames.Branch],\n        inputs: {\n            values: {\n                condition: { name: \"condition\", gltfType: \"boolean\" },\n            },\n        },\n        outputs: {\n            flows: {\n                true: { name: \"onTrue\" },\n                false: { name: \"onFalse\" },\n            },\n        },\n    },\n    \"flow/switch\": {\n        blocks: [FlowGraphBlockNames.Switch],\n        configuration: {\n            cases: {\n                name: \"cases\",\n                isArray: true,\n                inOptions: true,\n                defaultValue: [],\n                configurationType: \"int[]\",\n                invalidUsesDefault: true,\n                generatesOutputFlowSockets: true,\n                uniqueValues: true,\n            },\n        },\n        inputs: {\n            values: {\n                selection: { name: \"case\" },\n                default: { name: \"default\" },\n            },\n        },\n        outputs: {\n            flows: {\n                default: { name: \"default\" },\n                \"[segment]\": { name: \"$1\" },\n            },\n        },\n        validation(gltfBlock) {\n            const cases = gltfBlock.configuration?.cases;\n            if (cases && cases.value) {\n                const onlyIntegers = cases.value.every(\n                    (caseValue) => typeof caseValue === \"number\" && Number.isInteger(caseValue) && caseValue >= -2147483648 && caseValue <= 2147483647\n                );\n                if (!onlyIntegers) {\n                    Logger.Warn(\"Switch cases should be integers. Using empty array instead.\");\n                    cases.value = [] as number[];\n                    return { valid: true };\n                }\n                // check for duplicates\n                const uniqueCases = new Set(cases.value);\n                cases.value = Array.from(uniqueCases) as number[];\n            }\n            return { valid: true };\n        },\n        extraProcessor(gltfBlock, declaration, _mapping, _arrays, serializedObjects) {\n            // convert all names of output flow to out_$1 apart from \"default\"\n            if (declaration.op !== \"flow/switch\" || !gltfBlock.flows || Object.keys(gltfBlock.flows).length === 0) {\n                throw new Error(\"Switch should have a single configuration object, the cases array\");\n            }\n            const serializedObject = serializedObjects[0];\n            serializedObject.signalOutputs.forEach((output) => {\n                if (output.name !== \"default\") {\n                    output.name = \"out_\" + output.name;\n                }\n            });\n            return serializedObjects;\n        },\n    },\n    \"flow/while\": {\n        blocks: [FlowGraphBlockNames.WhileLoop],\n        inputs: {\n            values: {\n                condition: { name: \"condition\", gltfType: \"boolean\" },\n            },\n        },\n        outputs: {\n            flows: {\n                loopBody: { name: \"executionFlow\" },\n                completed: { name: \"completed\" },\n            },\n        },\n    },\n    \"flow/for\": {\n        blocks: [FlowGraphBlockNames.ForLoop],\n        configuration: {\n            initialIndex: {\n                name: \"initialIndex\",\n                gltfType: \"int\",\n                inOptions: true,\n                defaultValue: 0,\n                configurationType: \"int\",\n                invalidUsesDefault: true,\n            },\n        },\n        inputs: {\n            values: {\n                startIndex: { name: \"startIndex\", gltfType: \"int\" },\n                endIndex: { name: \"endIndex\", gltfType: \"int\" },\n            },\n        },\n        outputs: {\n            values: {\n                index: { name: \"index\" },\n            },\n            flows: {\n                loopBody: { name: \"executionFlow\" },\n                completed: { name: \"completed\" },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects) {\n            const serializedObject = serializedObjects[0];\n            serializedObject.config ||= {};\n            serializedObject.config.incrementIndexWhenLoopDone = true;\n            // KHR_interactivity assets may run large finite loops (e.g. the math/random Monte Carlo\n            // conformance asset iterates 10k times), well above the block's conservative default guard.\n            // Raise the cap for interactivity for-loops only, per block, instead of mutating the\n            // process-wide FlowGraphForLoopBlock.MaxLoopIterations that every other FlowGraph relies on.\n            serializedObject.config.maxLoopIterations = InteractivityForLoopMaxIterations;\n            return serializedObjects;\n        },\n    },\n    \"flow/doN\": {\n        blocks: [FlowGraphBlockNames.DoN],\n        configuration: {},\n        inputs: {\n            values: {\n                n: { name: \"maxExecutions\", gltfType: \"int\" },\n            },\n            flows: {\n                reset: { name: \"reset\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n            },\n            values: {\n                currentCount: { name: \"executionCount\" },\n            },\n        },\n    },\n    \"flow/multiGate\": {\n        blocks: [FlowGraphBlockNames.MultiGate],\n        inputs: {\n            flows: {\n                reset: { name: \"reset\" },\n            },\n        },\n        configuration: {\n            isRandom: {\n                name: \"isRandom\",\n                gltfType: \"boolean\",\n                inOptions: true,\n                defaultValue: false,\n                configurationType: \"bool\",\n                invalidUsesDefault: true,\n                configurationGroup: \"multiGate\",\n            },\n            isLoop: {\n                name: \"isLoop\",\n                gltfType: \"boolean\",\n                inOptions: true,\n                defaultValue: false,\n                configurationType: \"bool\",\n                invalidUsesDefault: true,\n                configurationGroup: \"multiGate\",\n            },\n        },\n        outputs: {\n            flows: {\n                \"[segment]\": { name: \"$1\" },\n            },\n            values: {\n                lastIndex: { name: \"lastIndex\", gltfType: \"int\" },\n            },\n        },\n        extraProcessor(gltfBlock, declaration, _mapping, _arrays, serializedObjects) {\n            if (declaration.op !== \"flow/multiGate\") {\n                throw new Error(\"Invalid operation for MultiGate mapping\");\n            }\n            const serializedObject = serializedObjects[0];\n            serializedObject.config ||= {};\n            serializedObject.config.outputSignalCount = Object.keys(gltfBlock.flows ?? {}).length;\n            serializedObject.signalOutputs.forEach((output, index) => {\n                output.name = \"out_\" + index;\n            });\n            return serializedObjects;\n        },\n    },\n    \"flow/waitAll\": {\n        blocks: [FlowGraphBlockNames.WaitAll],\n        configuration: {\n            inputFlows: {\n                name: \"inputSignalCount\",\n                gltfType: \"number\",\n                inOptions: true,\n                defaultValue: [0],\n                configurationType: \"int\",\n                invalidUsesDefault: true,\n                minimum: 0,\n                maximum: 64,\n                generatesInputFlowSockets: true,\n            },\n        },\n        inputs: {\n            flows: {\n                reset: { name: \"reset\" },\n                \"[segment]\": { name: \"in_$1\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n                completed: { name: \"completed\" },\n            },\n            values: {\n                remainingInputs: { name: \"remainingInputs\", gltfType: \"int\" },\n            },\n        },\n        validation(gltfBlock) {\n            const inputFlowsConfiguration = gltfBlock.configuration?.inputFlows?.value;\n            const inputFlows = inputFlowsConfiguration?.[0];\n            if (inputFlowsConfiguration?.length !== 1 || typeof inputFlows !== \"number\" || !Number.isInteger(inputFlows) || inputFlows < 0 || inputFlows > 64) {\n                gltfBlock.configuration = gltfBlock.configuration || {\n                    inputFlows: { value: [0] },\n                };\n                gltfBlock.configuration.inputFlows.value = [0];\n            }\n            return { valid: true };\n        },\n    },\n    \"flow/throttle\": {\n        blocks: [FlowGraphBlockNames.Throttle],\n        inputs: {\n            values: {\n                duration: { name: \"duration\", gltfType: \"number\" },\n            },\n            flows: {\n                reset: { name: \"reset\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n                err: { name: \"error\" },\n            },\n            values: {\n                lastRemainingTime: { name: \"lastRemainingTime\", gltfType: \"number\" },\n            },\n        },\n    },\n    \"flow/setDelay\": {\n        blocks: [FlowGraphBlockNames.SetDelay],\n        inputs: {\n            values: {\n                duration: { name: \"duration\", gltfType: \"number\" },\n            },\n            flows: {\n                cancel: { name: \"cancel\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n                err: { name: \"error\" },\n                done: { name: \"done\" },\n            },\n            values: {\n                // New spec renames this output to `lastDelay` (ref). Internally we still produce a\n                // FlowGraphInteger; the index is unique per delay so it acts as the opaque handle.\n                lastDelay: { name: \"lastDelayIndex\" },\n                lastDelayIndex: { name: \"lastDelayIndex\", compatibilityOnly: true },\n            },\n        },\n    },\n    \"flow/cancelDelay\": {\n        blocks: [FlowGraphBlockNames.CancelDelay],\n        inputs: {\n            values: {\n                delay: { name: \"delayIndex\", gltfType: \"ref\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n            },\n        },\n    },\n    \"variable/get\": {\n        blocks: [FlowGraphBlockNames.GetVariable],\n        validation(gltfBlock) {\n            if (!gltfBlock.configuration?.variable?.value) {\n                Logger.Error(\"Variable get block should have a variable configuration\");\n                return { valid: false, error: \"Variable get block should have a variable configuration\" };\n            }\n            return { valid: true };\n        },\n        configuration: {\n            variable: {\n                name: \"variable\",\n                gltfType: \"number\",\n                configurationType: \"int\",\n                required: true,\n                indexSource: \"variables\",\n                flowGraphType: \"string\",\n                inOptions: true,\n                isVariable: true,\n                dataTransformer(index, parser) {\n                    return parser.getVariableName(index);\n                },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\" },\n            },\n        },\n    },\n    \"variable/set\": {\n        blocks: [FlowGraphBlockNames.SetVariable],\n        inputs: {\n            values: {\n                \"[segment]\": { name: \"$1\" },\n            },\n        },\n        configuration: {\n            variables: {\n                name: \"variables\",\n                gltfType: \"number\",\n                configurationType: \"int[]\",\n                required: true,\n                indexSource: \"variables\",\n                minItems: 1,\n                generatesInputValueSockets: true,\n                flowGraphType: \"string\",\n                inOptions: true,\n                isArray: true,\n                dataTransformer(index: number[], parser): string[] {\n                    return index.map((i) => parser.getVariableName(i));\n                },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\", compatibilityOnly: true },\n            },\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, parser, serializedObjects) {\n            // variable/get configuration\n            const serializedGetVariable = serializedObjects[0];\n            serializedGetVariable.dataInputs.forEach((input) => {\n                input.name = parser.getVariableName(+input.name);\n            });\n\n            return serializedObjects;\n        },\n    },\n    \"variable/interpolate\": {\n        blocks: [\n            FlowGraphBlockNames.ValueInterpolation,\n            FlowGraphBlockNames.Context,\n            FlowGraphBlockNames.PlayAnimation,\n            FlowGraphBlockNames.BezierCurveEasing,\n            FlowGraphBlockNames.GetVariable,\n        ],\n        configuration: {\n            variable: {\n                name: \"propertyName\",\n                configurationType: \"int\",\n                required: true,\n                indexSource: \"variables\",\n                inOptions: true,\n                isVariable: true,\n                dataTransformer(index, parser) {\n                    return parser.getVariableName(index);\n                },\n            },\n            useSlerp: {\n                name: \"animationType\",\n                configurationType: \"bool\",\n                required: true,\n                inOptions: true,\n                dataTransformer(value) {\n                    return value === true ? FlowGraphTypes.Quaternion : undefined;\n                },\n            },\n        },\n        inputs: {\n            values: {\n                value: { name: \"value_1\" },\n                duration: { name: \"duration_1\", gltfType: \"number\" },\n                p1: { name: \"controlPoint1\", toBlock: FlowGraphBlockNames.BezierCurveEasing },\n                p2: { name: \"controlPoint2\", toBlock: FlowGraphBlockNames.BezierCurveEasing },\n            },\n            flows: {\n                in: { name: \"in\", toBlock: FlowGraphBlockNames.PlayAnimation },\n            },\n        },\n        outputs: {\n            flows: {\n                err: { name: \"error\", toBlock: FlowGraphBlockNames.PlayAnimation },\n                out: { name: \"out\", toBlock: FlowGraphBlockNames.PlayAnimation },\n                done: { name: \"done\", toBlock: FlowGraphBlockNames.PlayAnimation },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"object\",\n                output: \"userVariables\",\n                inputBlockIndex: 2,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"animation\",\n                output: \"animation\",\n                inputBlockIndex: 2,\n                outputBlockIndex: 0,\n                isVariable: true,\n            },\n            {\n                input: \"easingFunction\",\n                output: \"easingFunction\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 3,\n                isVariable: true,\n            },\n            {\n                input: \"value_0\",\n                output: \"value\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 4,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(gltfBlock, _declaration, _mapping, parser, serializedObjects) {\n            // is useSlerp is used, animationType should be set to be quaternion!\n            const serializedValueInterpolation = serializedObjects[0];\n            const propertyIndex = gltfBlock.configuration?.variable.value?.[0];\n            if (typeof propertyIndex !== \"number\") {\n                Logger.Error(\"Variable index is not defined for variable interpolation block\");\n                throw new Error(\"Variable index is not defined for variable interpolation block\");\n            }\n            const variable = parser.arrays.staticVariables[propertyIndex];\n            // if not set by useSlerp\n            if (typeof serializedValueInterpolation.config?.animationType?.value === \"undefined\") {\n                serializedValueInterpolation.config ||= {};\n                serializedValueInterpolation.config.animationType ||= {};\n                serializedValueInterpolation.config.animationType.value = getAnimationTypeByFlowGraphType(variable.type);\n            }\n\n            // variable/get configuration\n            const serializedGetVariable = serializedObjects[4];\n            serializedGetVariable.config ||= {};\n            serializedGetVariable.config.variable ||= {};\n            serializedGetVariable.config.variable.value = parser.getVariableName(propertyIndex);\n\n            return serializedObjects;\n        },\n    },\n    \"pointer/get\": {\n        blocks: [FlowGraphBlockNames.GetProperty, FlowGraphBlockNames.JsonPointerParser],\n        validation: (node) => ValidateJsonPointerTemplate(node),\n        configuration: {\n            pointer: { name: \"jsonPointer\", toBlock: FlowGraphBlockNames.JsonPointerParser, configurationType: \"string\", required: true, pointerTemplate: true },\n            type: {\n                name: \"type\",\n                configurationType: \"int\",\n                required: true,\n                validationOnly: true,\n                indexSource: \"types\",\n            },\n        },\n        inputs: {\n            values: {\n                \"[segment]\": { name: \"$1\", toBlock: FlowGraphBlockNames.JsonPointerParser },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\" },\n                isValid: { name: \"isValid\", gltfType: \"bool\" },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"object\",\n                output: \"object\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"propertyName\",\n                output: \"propertyName\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"customGetFunction\",\n                output: \"getFunction\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(gltfBlock, _declaration, _mapping, parser, serializedObjects) {\n            serializedObjects.forEach((serializedObject) => {\n                // check if it is the json pointer block\n                if (serializedObject.className === FlowGraphBlockNames.JsonPointerParser) {\n                    serializedObject.config ||= {};\n                    serializedObject.config.outputValue = true;\n                }\n            });\n            return serializedObjects;\n        },\n    },\n    \"pointer/set\": {\n        blocks: [FlowGraphBlockNames.SetProperty, FlowGraphBlockNames.JsonPointerParser],\n        validation: (node) => ValidateJsonPointerTemplate(node, new Set([\"value\"])),\n        configuration: {\n            pointer: { name: \"jsonPointer\", toBlock: FlowGraphBlockNames.JsonPointerParser, configurationType: \"string\", required: true, pointerTemplate: true },\n            type: {\n                name: \"type\",\n                configurationType: \"int\",\n                required: true,\n                validationOnly: true,\n                indexSource: \"types\",\n            },\n        },\n        inputs: {\n            values: {\n                // must be defined due to the array taking over\n                value: { name: \"value\" },\n                \"[segment]\": { name: \"$1\", toBlock: FlowGraphBlockNames.JsonPointerParser },\n            },\n        },\n        outputs: {\n            flows: {\n                err: { name: \"error\" },\n                out: { name: \"out\", compatibilityOnly: true },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"object\",\n                output: \"object\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"propertyName\",\n                output: \"propertyName\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"customSetFunction\",\n                output: \"setFunction\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(gltfBlock, _declaration, _mapping, parser, serializedObjects) {\n            serializedObjects.forEach((serializedObject) => {\n                // check if it is the json pointer block\n                if (serializedObject.className === FlowGraphBlockNames.JsonPointerParser) {\n                    serializedObject.config ||= {};\n                    serializedObject.config.outputValue = true;\n                }\n            });\n            return serializedObjects;\n        },\n    },\n    \"pointer/interpolate\": {\n        // interpolate, parse the pointer and play the animation generated. 3 blocks!\n        blocks: [FlowGraphBlockNames.ValueInterpolation, FlowGraphBlockNames.JsonPointerParser, FlowGraphBlockNames.PlayAnimation, FlowGraphBlockNames.BezierCurveEasing],\n        validation: (node) => ValidateJsonPointerTemplate(node, new Set([\"value\", \"duration\", \"p1\", \"p2\"])),\n        configuration: {\n            pointer: { name: \"jsonPointer\", toBlock: FlowGraphBlockNames.JsonPointerParser, configurationType: \"string\", required: true, pointerTemplate: true },\n            type: {\n                name: \"type\",\n                configurationType: \"int\",\n                required: true,\n                validationOnly: true,\n                indexSource: \"types\",\n                allowedSignatures: [\"float\", \"float2\", \"float3\", \"float4\", \"float2x2\", \"float3x3\", \"float4x4\"],\n            },\n        },\n        inputs: {\n            values: {\n                value: { name: \"value_1\" },\n                \"[segment]\": { name: \"$1\", toBlock: FlowGraphBlockNames.JsonPointerParser },\n                duration: { name: \"duration_1\", gltfType: \"number\" /*, inOptions: true */ },\n                p1: { name: \"controlPoint1\", toBlock: FlowGraphBlockNames.BezierCurveEasing },\n                p2: { name: \"controlPoint2\", toBlock: FlowGraphBlockNames.BezierCurveEasing },\n            },\n            flows: {\n                in: { name: \"in\", toBlock: FlowGraphBlockNames.PlayAnimation },\n            },\n        },\n        outputs: {\n            flows: {\n                err: { name: \"error\", toBlock: FlowGraphBlockNames.PlayAnimation },\n                out: { name: \"out\", toBlock: FlowGraphBlockNames.PlayAnimation },\n                done: { name: \"done\", toBlock: FlowGraphBlockNames.PlayAnimation },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"object\",\n                output: \"object\",\n                inputBlockIndex: 2,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"propertyName\",\n                output: \"propertyName\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"customBuildAnimation\",\n                output: \"generateAnimationsFunction\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"animation\",\n                output: \"animation\",\n                inputBlockIndex: 2,\n                outputBlockIndex: 0,\n                isVariable: true,\n            },\n            {\n                input: \"easingFunction\",\n                output: \"easingFunction\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 3,\n                isVariable: true,\n            },\n            {\n                input: \"value_0\",\n                output: \"value\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(gltfBlock, _declaration, _mapping, parser, serializedObjects) {\n            serializedObjects.forEach((serializedObject) => {\n                // check if it is the json pointer block\n                if (serializedObject.className === FlowGraphBlockNames.JsonPointerParser) {\n                    serializedObject.config ||= {};\n                    serializedObject.config.outputValue = true;\n                } else if (serializedObject.className === FlowGraphBlockNames.ValueInterpolation) {\n                    serializedObject.config ||= {};\n                    Object.keys(gltfBlock.values || []).forEach((key) => {\n                        const value = gltfBlock.values?.[key];\n                        if (key === \"value\" && value) {\n                            // get the type of the value\n                            const type = value.type;\n                            if (type !== undefined) {\n                                serializedObject.config.animationType = parser.arrays.types[type].flowGraphType;\n                            }\n                        }\n                    });\n                }\n            });\n            return serializedObjects;\n        },\n    },\n    \"animation/start\": {\n        blocks: [FlowGraphBlockNames.PlayAnimation, FlowGraphBlockNames.ArrayIndex, \"KHR_interactivity/FlowGraphGLTFDataProvider\"],\n        inputs: {\n            values: {\n                animation: { name: \"index\", gltfType: \"ref\", toBlock: FlowGraphBlockNames.ArrayIndex },\n                speed: { name: \"speed\", gltfType: \"number\" },\n                startTime: {\n                    name: \"from\",\n                    gltfType: \"number\",\n                    convertConnectedTimeToFrames: true,\n                    dataTransformer: (time: number[], parser) => [time[0] * parser._animationTargetFps],\n                },\n                endTime: {\n                    name: \"to\",\n                    gltfType: \"number\",\n                    convertConnectedTimeToFrames: true,\n                    dataTransformer: (time: number[], parser) => [time[0] * parser._animationTargetFps],\n                },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n                err: { name: \"error\" },\n                done: { name: \"done\" },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"animationGroup\",\n                output: \"value\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"array\",\n                output: \"animationGroups\",\n                inputBlockIndex: 1,\n                outputBlockIndex: 2,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects, _context, globalGLTF) {\n            const playAnimationBlock = serializedObjects.find((block) => block.className === FlowGraphBlockNames.PlayAnimation);\n            if (playAnimationBlock) {\n                playAnimationBlock.config.useVirtualTimeline = true;\n            }\n            const arrayIndexBlock = serializedObjects.find((block) => block.className === FlowGraphBlockNames.ArrayIndex);\n            if (arrayIndexBlock) {\n                arrayIndexBlock.config.referenceCollection = \"animations\";\n            }\n            // add the glTF to the configuration of the last serialized object\n            const serializedObject = serializedObjects[serializedObjects.length - 1];\n            serializedObject.config ||= {};\n            serializedObject.config.glTF = globalGLTF;\n            return serializedObjects;\n        },\n    },\n    \"animation/stop\": {\n        blocks: [FlowGraphBlockNames.StopAnimation, FlowGraphBlockNames.ArrayIndex, \"KHR_interactivity/FlowGraphGLTFDataProvider\"],\n        inputs: {\n            values: {\n                animation: { name: \"index\", gltfType: \"ref\", toBlock: FlowGraphBlockNames.ArrayIndex },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n                err: { name: \"error\" },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"animationGroup\",\n                output: \"value\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"array\",\n                output: \"animationGroups\",\n                inputBlockIndex: 1,\n                outputBlockIndex: 2,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects, _context, globalGLTF) {\n            const stopAnimationBlock = serializedObjects.find((block) => block.className === FlowGraphBlockNames.StopAnimation);\n            if (stopAnimationBlock) {\n                stopAnimationBlock.config.skipOnAnimationEnd = true;\n            }\n            const arrayIndexBlock = serializedObjects.find((block) => block.className === FlowGraphBlockNames.ArrayIndex);\n            if (arrayIndexBlock) {\n                arrayIndexBlock.config.referenceCollection = \"animations\";\n            }\n            // add the glTF to the configuration of the last serialized object\n            const serializedObject = serializedObjects[serializedObjects.length - 1];\n            serializedObject.config ||= {};\n            serializedObject.config.glTF = globalGLTF;\n            return serializedObjects;\n        },\n    },\n    \"animation/stopAt\": {\n        blocks: [FlowGraphBlockNames.StopAnimation, FlowGraphBlockNames.ArrayIndex, \"KHR_interactivity/FlowGraphGLTFDataProvider\"],\n        configuration: {},\n        inputs: {\n            values: {\n                animation: { name: \"index\", gltfType: \"ref\", toBlock: FlowGraphBlockNames.ArrayIndex },\n                stopTime: {\n                    name: \"stopAtFrame\",\n                    gltfType: \"number\",\n                    convertConnectedTimeToFrames: true,\n                    dataTransformer: (time: number[], parser) => [time[0] * parser._animationTargetFps],\n                },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n                err: { name: \"error\" },\n                done: { name: \"done\" },\n            },\n        },\n        interBlockConnectors: [\n            {\n                input: \"animationGroup\",\n                output: \"value\",\n                inputBlockIndex: 0,\n                outputBlockIndex: 1,\n                isVariable: true,\n            },\n            {\n                input: \"array\",\n                output: \"animationGroups\",\n                inputBlockIndex: 1,\n                outputBlockIndex: 2,\n                isVariable: true,\n            },\n        ],\n        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects, _context, globalGLTF) {\n            const stopAnimationBlock = serializedObjects.find((block) => block.className === FlowGraphBlockNames.StopAnimation);\n            if (stopAnimationBlock) {\n                stopAnimationBlock.config.useVirtualStopAt = true;\n                stopAnimationBlock.config.skipOnAnimationEnd = true;\n            }\n            const arrayIndexBlock = serializedObjects.find((block) => block.className === FlowGraphBlockNames.ArrayIndex);\n            if (arrayIndexBlock) {\n                arrayIndexBlock.config.referenceCollection = \"animations\";\n            }\n            // add the glTF to the configuration of the last serialized object\n            const serializedObject = serializedObjects[serializedObjects.length - 1];\n            serializedObject.config ||= {};\n            serializedObject.config.glTF = globalGLTF;\n            return serializedObjects;\n        },\n    },\n    \"math/switch\": {\n        blocks: [FlowGraphBlockNames.DataSwitch],\n        configuration: {\n            cases: {\n                name: \"cases\",\n                isArray: true,\n                inOptions: true,\n                defaultValue: [],\n                configurationType: \"int[]\",\n                invalidUsesDefault: true,\n                generatesCaseInputValueSockets: true,\n                uniqueValues: true,\n            },\n        },\n        inputs: {\n            values: {\n                selection: { name: \"case\", gltfType: \"int\" },\n                default: { name: \"default\" },\n                \"[case]\": { name: \"$1\" },\n            },\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\" },\n            },\n        },\n        validation(gltfBlock) {\n            const cases = gltfBlock.configuration?.cases;\n            if (cases && cases.value) {\n                const onlyIntegers = cases.value.every((caseValue) => {\n                    // case value should be an integer. Since Number.isInteger(1.0) is true, we need to check if toString has only digits.\n                    return typeof caseValue === \"number\" && /^-?\\d+$/.test(caseValue.toString());\n                });\n                if (!onlyIntegers) {\n                    Logger.Warn(\"Switch cases should be integers. Using empty array instead.\");\n                    cases.value = [] as number[];\n                    return { valid: true };\n                }\n                // check for duplicates\n                const uniqueCases = new Set(cases.value);\n                cases.value = Array.from(uniqueCases) as number[];\n            }\n            return { valid: true };\n        },\n        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects) {\n            const serializedObject = serializedObjects[0];\n            serializedObject.dataInputs.forEach((input) => {\n                if (input.name !== \"default\" && input.name !== \"case\") {\n                    input.name = \"in_\" + input.name;\n                }\n            });\n            serializedObject.config ||= {};\n            serializedObject.config.treatCasesAsIntegers = true;\n            return serializedObjects;\n        },\n    },\n    \"debug/log\": {\n        blocks: [FlowGraphBlockNames.ConsoleLog],\n        inputs: {\n            flows: {\n                in: { name: \"in\" },\n            },\n            values: {\n                \"[parameter]\": { name: \"$1\" },\n            },\n        },\n        outputs: {\n            flows: {\n                out: { name: \"out\" },\n            },\n        },\n        configuration: {\n            severity: {\n                name: \"severity\",\n                configurationType: \"int\",\n                defaultValue: 0,\n                invalidUsesDefault: true,\n                validationOnly: true,\n                configurationGroup: \"debugLog\",\n            },\n            message: {\n                name: \"messageTemplate\",\n                configurationType: \"string\",\n                defaultValue: \"\",\n                invalidUsesDefault: true,\n                inOptions: true,\n                configurationGroup: \"debugLog\",\n                debugLogTemplate: true,\n            },\n        },\n    },\n};\n\nfunction getSimpleInputMapping(type: FlowGraphBlockNames, inputs: string[] = [\"a\"], inferType?: boolean): IGLTFToFlowGraphMapping {\n    return {\n        blocks: [type],\n        inputs: {\n            values: inputs.reduce(\n                (acc, input) => {\n                    acc[input] = { name: input };\n                    return acc;\n                },\n                {} as { [key: string]: { name: string } }\n            ),\n        },\n        outputs: {\n            values: {\n                value: { name: \"value\", typeSourceInput: inputs[0] },\n            },\n        },\n        extraProcessor(gltfBlock, _declaration, _mapping, _parser, serializedObjects) {\n            if (inferType) {\n                // configure it to work the way glTF specifies\n                serializedObjects[0].config ||= {};\n                serializedObjects[0].config.preventIntegerFloatArithmetic = true;\n                // try to infer the type or fallback to Integer\n                // check the gltf block for the inputs, see if they have a type\n                let type = -1;\n                Object.keys(gltfBlock.values || {}).find((value) => {\n                    if (gltfBlock.values?.[value].type !== undefined) {\n                        type = gltfBlock.values[value].type;\n                        return true;\n                    }\n                    return false;\n                });\n                if (type !== -1) {\n                    serializedObjects[0].config.type = _parser.arrays.types[type].flowGraphType;\n                }\n            }\n            return serializedObjects;\n        },\n        validation(gltfBlock) {\n            if (inferType) {\n                // make sure types are the same\n                return ValidateTypes(gltfBlock);\n            }\n            return { valid: true };\n        },\n    };\n}\n\nfunction ValidateTypes(gltfBlock: IKHRInteractivity_Node): { valid: boolean; error?: string } {\n    if (gltfBlock.values) {\n        const types = Object.keys(gltfBlock.values)\n            .map((key) => gltfBlock.values![key].type)\n            .filter((type) => type !== undefined);\n        const allSameType = types.every((type) => type === types[0]);\n        if (!allSameType) {\n            return { valid: false, error: \"All inputs must be of the same type\" };\n        }\n    }\n    return { valid: true };\n}\n\n/**\n * Returns whether a literal path segment has an odd number of consecutive occurrences of any bracket character.\n * Brackets used literally inside a path segment must be doubled, so an odd run means the segment is malformed.\n * @param segment the literal path segment\n * @returns true when the segment contains an odd run of brackets\n */\nfunction HasOddBracketRun(segment: string): boolean {\n    for (let index = 0; index < segment.length; index++) {\n        const character = segment[index];\n        if (\"[]{}\".indexOf(character) === -1) {\n            continue;\n        }\n\n        let runLength = 1;\n        while (segment[index + runLength] === character) {\n            runLength++;\n        }\n        if (runLength % 2 !== 0) {\n            return true;\n        }\n        index += runLength - 1;\n    }\n    return false;\n}\n\n/**\n * Result of parsing a ratified `debug/log` message template.\n */\nexport interface IDebugLogTemplateParseResult {\n    /** Whether all literal braces are doubled and every parameter is well formed. */\n    valid: boolean;\n    /** Unique parameter socket ids in first-occurrence order. */\n    sockets: string[];\n}\n\n/**\n * Parses a ratified `debug/log` message template.\n * Literal braces must be doubled; non-empty text inside a single brace pair defines a socket id.\n * @param message message template to parse\n * @returns template validity and its exact dynamic socket ids\n */\nexport function ParseDebugLogTemplate(message: string): IDebugLogTemplateParseResult {\n    let state = 0;\n    let parameterStart = -1;\n    const sockets: string[] = [];\n    const seen = new Set<string>();\n    for (let index = 0; index < message.length; index++) {\n        const character = message[index];\n        if (character === \"{\") {\n            if (state === 0) {\n                state = 1;\n            } else if (state === 1) {\n                state = 0;\n            } else {\n                return { valid: false, sockets: [] };\n            }\n        } else if (character === \"}\") {\n            if (state === 0) {\n                state = 3;\n            } else if (state === 3) {\n                state = 0;\n            } else if (state === 2) {\n                const socket = message.substring(parameterStart + 1, index);\n                if (!seen.has(socket)) {\n                    seen.add(socket);\n                    sockets.push(socket);\n                }\n                state = 0;\n            } else {\n                return { valid: false, sockets: [] };\n            }\n        } else if (state === 1) {\n            parameterStart = index - 1;\n            state = 2;\n        } else if (state === 3) {\n            return { valid: false, sockets: [] };\n        }\n    }\n    return { valid: state === 0, sockets: state === 0 ? sockets : [] };\n}\n\n/**\n * Validates the `pointer` configuration value of a `pointer/*` operation, following the JSON Pointer Template\n * Parsing steps of the KHR_interactivity specification. A template parameter must span an entire path segment, so\n * a template such as `/materials/{materialRef}pbrMetallicRoughness/...` is a syntax error, and the specification\n * requires the whole behavior graph to be rejected.\n * @param gltfBlock the glTF interactivity node\n * @param reservedSocketIds input ids owned by the operation rather than template parameters\n * @returns the validation result\n */\nfunction ValidateJsonPointerTemplate(gltfBlock: IKHRInteractivity_Node, reservedSocketIds: ReadonlySet<string> = new Set()): { valid: boolean; error?: string } {\n    const pointer = gltfBlock.configuration?.pointer?.value?.[0];\n    if (typeof pointer !== \"string\") {\n        return { valid: false, error: \"A pointer operation requires a string `pointer` configuration value\" };\n    }\n    // A JSON Pointer (RFC 6901) is either empty or a sequence of `/`-prefixed reference tokens.\n    if (pointer.length !== 0 && pointer[0] !== \"/\") {\n        return { valid: false, error: `The JSON Pointer Template \"${pointer}\" is not a syntactically valid JSON Pointer` };\n    }\n\n    const invalid = (reason: string) => ({ valid: false, error: `The JSON Pointer Template \"${pointer}\" is invalid: ${reason}` });\n    const socketIds = new Set<string>();\n    for (const segment of pointer.split(\"/\")) {\n        if (/~(?:[^01]|$)/.test(segment)) {\n            return invalid(`the path segment \"${segment}\" contains an invalid RFC 6901 escape`);\n        }\n        const isIntegerParameter = segment[0] === \"[\" && segment[1] !== \"[\";\n        const isReferenceParameter = segment[0] === \"{\" && segment[1] !== \"{\";\n        if (!isIntegerParameter && !isReferenceParameter) {\n            if (HasOddBracketRun(segment)) {\n                return invalid(`the path segment \"${segment}\" contains an odd number of consecutive brackets`);\n            }\n            continue;\n        }\n\n        const closingBracket = isIntegerParameter ? \"]\" : \"}\";\n        const body = segment.substring(1, segment.length - 1);\n        if (segment.length < 3 || segment[segment.length - 1] !== closingBracket || /[[{]/.test(body) || /[\\]}]/.test(body)) {\n            return invalid(`the template parameter path segment \"${segment}\" is malformed`);\n        }\n\n        const socketId = body.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n        if (reservedSocketIds.has(socketId)) {\n            return invalid(`the template parameter \"${socketId}\" uses a reserved input socket id`);\n        }\n        if (socketIds.has(socketId)) {\n            return invalid(`the template parameter \"${socketId}\" is used more than once`);\n        }\n        socketIds.add(socketId);\n    }\n\n    return { valid: true };\n}\n\nexport function getAllSupportedNativeNodeTypes(): string[] {\n    return Object.keys(gltfToFlowGraphMapping);\n}\n\n/**\n * \n * These are the nodes from the specs:\n\n### Math Nodes\n1. **Constants**\n   - E (`math/E`) FlowGraphBlockNames.E\n   - Pi (`math/Pi`) FlowGraphBlockNames.PI\n   - Infinity (`math/Inf`) FlowGraphBlockNames.Inf\n   - Not a Number (`math/NaN`) FlowGraphBlockNames.NaN\n2. **Arithmetic Nodes**\n   - Absolute Value (`math/abs`) FlowGraphBlockNames.Abs\n   - Sign (`math/sign`) FlowGraphBlockNames.Sign\n   - Truncate (`math/trunc`) FlowGraphBlockNames.Trunc\n   - Floor (`math/floor`) FlowGraphBlockNames.Floor\n   - Ceil (`math/ceil`) FlowGraphBlockNames.Ceil\n   - Round (`math/round`)  FlowGraphBlockNames.Round\n   - Fraction (`math/fract`) FlowGraphBlockNames.Fract\n   - Negation (`math/neg`) FlowGraphBlockNames.Negation\n   - Addition (`math/add`) FlowGraphBlockNames.Add\n   - Subtraction (`math/sub`) FlowGraphBlockNames.Subtract\n   - Multiplication (`math/mul`) FlowGraphBlockNames.Multiply\n   - Division (`math/div`) FlowGraphBlockNames.Divide\n   - Remainder (`math/rem`) FlowGraphBlockNames.Modulo\n   - Minimum (`math/min`) FlowGraphBlockNames.Min\n   - Maximum (`math/max`) FlowGraphBlockNames.Max\n   - Clamp (`math/clamp`) FlowGraphBlockNames.Clamp\n   - Saturate (`math/saturate`) FlowGraphBlockNames.Saturate\n   - Interpolate (`math/mix`) FlowGraphBlockNames.MathInterpolation\n3. **Comparison Nodes**\n   - Equality (`math/eq`) FlowGraphBlockNames.Equality\n   - Less Than (`math/lt`) FlowGraphBlockNames.LessThan\n   - Less Than Or Equal To (`math/le`) FlowGraphBlockNames.LessThanOrEqual\n   - Greater Than (`math/gt`) FlowGraphBlockNames.GreaterThan\n   - Greater Than Or Equal To (`math/ge`) FlowGraphBlockNames.GreaterThanOrEqual\n4. **Special Nodes**\n   - Is Not a Number (`math/isNaN`) FlowGraphBlockNames.IsNaN\n   - Is Infinity (`math/isInf`) FlowGraphBlockNames.IsInfinity\n   - Select (`math/select`) FlowGraphBlockNames.Conditional\n   - Switch (`math/switch`) FlowGraphBlockNames.DataSwitch\n   - Random (`math/random`) FlowGraphBlockNames.Random\n5. **Angle and Trigonometry Nodes**\n   - Degrees-To-Radians (`math/rad`) FlowGraphBlockNames.DegToRad\n   - Radians-To-Degrees (`math/deg`) FlowGraphBlockNames.RadToDeg\n   - Sine (`math/sin`)  FlowGraphBlockNames.Sin\n   - Cosine (`math/cos`) FlowGraphBlockNames.Cos\n   - Tangent (`math/tan`) FlowGraphBlockNames.Tan\n   - Arcsine (`math/asin`) FlowGraphBlockNames.Asin\n   - Arccosine (`math/acos`) FlowGraphBlockNames.Acos\n   - Arctangent (`math/atan`) FlowGraphBlockNames.Atan\n   - Arctangent 2 (`math/atan2`) FlowGraphBlockNames.Atan2\n6. **Hyperbolic Nodes**\n   - Hyperbolic Sine (`math/sinh`) FlowGraphBlockNames.Sinh\n   - Hyperbolic Cosine (`math/cosh`) FlowGraphBlockNames.Cosh\n   - Hyperbolic Tangent (`math/tanh`) FlowGraphBlockNames.Tanh\n   - Inverse Hyperbolic Sine (`math/asinh`) FlowGraphBlockNames.Asinh\n   - Inverse Hyperbolic Cosine (`math/acosh`) FlowGraphBlockNames.Acosh\n   - Inverse Hyperbolic Tangent (`math/atanh`) FlowGraphBlockNames.Atanh\n7. **Exponential Nodes**\n   - Exponent (`math/exp`) FlowGraphBlockNames.Exponential\n   - Natural Logarithm (`math/log`) FlowGraphBlockNames.Log\n   - Base-2 Logarithm (`math/log2`) FlowGraphBlockNames.Log2\n   - Base-10 Logarithm (`math/log10`) FlowGraphBlockNames.Log10\n   - Square Root (`math/sqrt`) FlowGraphBlockNames.SquareRoot\n   - Cube Root (`math/cbrt`) FlowGraphBlockNames.CubeRoot\n   - Power (`math/pow`) FlowGraphBlockNames.Power\n8. **Vector Nodes**\n   - Length (`math/length`) FlowGraphBlockNames.Length\n   - Normalize (`math/normalize`) FlowGraphBlockNames.Normalize\n   - Dot Product (`math/dot`) FlowGraphBlockNames.Dot\n   - Cross Product (`math/cross`) FlowGraphBlockNames.Cross\n   - Rotate 2D (`math/rotate2D`) FlowGraphBlockNames.Rotate2D\n   - Rotate 3D (`math/rotate3D`) FlowGraphBlockNames.Rotate3D\n   - Transform (`math/transform`) FlowGraphBlockNames.TransformVector\n9. **Matrix Nodes**\n   - Transpose (`math/transpose`) FlowGraphBlockNames.Transpose\n   - Determinant (`math/determinant`) FlowGraphBlockNames.Determinant\n   - Inverse (`math/inverse`) FlowGraphBlockNames.InvertMatrix\n   - Multiplication (`math/matMul`) FlowGraphBlockNames.MatrixMultiplication\n   - Compose (`math/matCompose`) FlowGraphBlockNames.MatrixCompose\n   - Decompose (`math/matDecompose`) FlowGraphBlockNames.MatrixDecompose\n10. **Quaternion Nodes**\n    - Conjugate (`math/quatConjugate`) FlowGraphBlockNames.Conjugate\n    - Multiplication (`math/quatMul`) FlowGraphBlockNames.Multiply\n    - Angle Between Quaternions (`math/quatAngleBetween`) FlowGraphBlockNames.AngleBetween\n    - Quaternion From Axis Angle (`math/quatFromAxisAngle`) FlowGraphBlockNames.QuaternionFromAxisAngle\n    - Quaternion To Axis Angle (`math/quatToAxisAngle`) FlowGraphBlockNames.QuaternionToAxisAngle\n    - Quaternion From Two Directional Vectors (`math/quatFromDirections`) FlowGraphBlockNames.QuaternionFromDirections\n11. **Swizzle Nodes**\n    - Combine (`math/combine2`, `math/combine3`, `math/combine4`, `math/combine2x2`, `math/combine3x3`, `math/combine4x4`)\n        FlowGraphBlockNames.CombineVector2, FlowGraphBlockNames.CombineVector3, FlowGraphBlockNames.CombineVector4\n        FlowGraphBlockNames.CombineMatrix2D, FlowGraphBlockNames.CombineMatrix3D, FlowGraphBlockNames.CombineMatrix\n    - Extract (`math/extract2`, `math/extract3`, `math/extract4`, `math/extract2x2`, `math/extract3x3`, `math/extract4x4`)\n        FlowGraphBlockNames.ExtractVector2, FlowGraphBlockNames.ExtractVector3, FlowGraphBlockNames.ExtractVector4\n        FlowGraphBlockNames.ExtractMatrix2D, FlowGraphBlockNames.ExtractMatrix3D, FlowGraphBlockNames.ExtractMatrix\n12. **Integer Arithmetic Nodes**\n    - Absolute Value (`math/abs`) FlowGraphBlockNames.Abs\n    - Sign (`math/sign`) FlowGraphBlockNames.Sign\n    - Negation (`math/neg`) FlowGraphBlockNames.Negation\n    - Addition (`math/add`) FlowGraphBlockNames.Add\n    - Subtraction (`math/sub`) FlowGraphBlockNames.Subtract\n    - Multiplication (`math/mul`) FlowGraphBlockNames.Multiply\n    - Division (`math/div`) FlowGraphBlockNames.Divide\n    - Remainder (`math/rem`) FlowGraphBlockNames.Modulo\n    - Minimum (`math/min`) FlowGraphBlockNames.Min\n    - Maximum (`math/max`) FlowGraphBlockNames.Max\n    - Clamp (`math/clamp`) FlowGraphBlockNames.Clamp\n13. **Integer Comparison Nodes**\n    - Equality (`math/eq`) FlowGraphBlockNames.Equality\n    - Less Than (`math/lt`) FlowGraphBlockNames.LessThan\n    - Less Than Or Equal To (`math/le`) FlowGraphBlockNames.LessThanOrEqual\n    - Greater Than (`math/gt`) FlowGraphBlockNames.GreaterThan\n    - Greater Than Or Equal To (`math/ge`) FlowGraphBlockNames.GreaterThanOrEqual\n14. **Integer Bitwise Nodes**\n    - Bitwise NOT (`math/not`) FlowGraphBlockNames.BitwiseNot\n    - Bitwise AND (`math/and`) FlowGraphBlockNames.BitwiseAnd\n    - Bitwise OR (`math/or`) FlowGraphBlockNames.BitwiseOr\n    - Bitwise XOR (`math/xor`) FlowGraphBlockNames.BitwiseXor\n    - Right Shift (`math/asr`) FlowGraphBlockNames.BitwiseRightShift\n    - Left Shift (`math/lsl`) FlowGraphBlockNames.BitwiseLeftShift\n    - Count Leading Zeros (`math/clz`) FlowGraphBlockNames.LeadingZeros\n    - Count Trailing Zeros (`math/ctz`) FlowGraphBlockNames.TrailingZeros\n    - Count One Bits (`math/popcnt`) FlowGraphBlockNames.OneBitsCounter\n15. **Boolean Arithmetic Nodes**\n    - Equality (`math/eq`) FlowGraphBlockNames.Equality\n    - Boolean NOT (`math/not`) FlowGraphBlockNames.BitwiseNot\n    - Boolean AND (`math/and`) FlowGraphBlockNames.BitwiseAnd\n    - Boolean OR (`math/or`) FlowGraphBlockNames.BitwiseOr\n    - Boolean XOR (`math/xor`) FlowGraphBlockNames.BitwiseXor\n\n### Type Conversion Nodes\n1. **Boolean Conversion Nodes**\n   - Boolean to Integer (`type/boolToInt`) FlowGraphBlockNames.BooleanToInt\n   - Boolean to Float (`type/boolToFloat`) FlowGraphBlockNames.BooleanToFloat\n2. **Integer Conversion Nodes**\n   - Integer to Boolean (`type/intToBool`) FlowGraphBlockNames.IntToBoolean\n   - Integer to Float (`type/intToFloat`) FlowGraphBlockNames.IntToFloat\n3. **Float Conversion Nodes**\n   - Float to Boolean (`type/floatToBool`) FlowGraphBlockNames.FloatToBoolean\n   - Float to Integer (`type/floatToInt`) FlowGraphBlockNames.FloatToInt\n\n### Control Flow Nodes\n1. **Sync Nodes**\n   - Sequence (`flow/sequence`) FlowGraphBlockNames.Sequence\n   - Branch (`flow/branch`) FlowGraphBlockNames.Branch\n   - Switch (`flow/switch`) FlowGraphBlockNames.Switch\n   - While Loop (`flow/while`) FlowGraphBlockNames.WhileLoop\n   - For Loop (`flow/for`) FlowGraphBlockNames.ForLoop\n   - Do N (`flow/doN`) FlowGraphBlockNames.DoN\n   - Multi Gate (`flow/multiGate`) FlowGraphBlockNames.MultiGate\n   - Wait All (`flow/waitAll`) FlowGraphBlockNames.WaitAll\n   - Throttle (`flow/throttle`) FlowGraphBlockNames.Throttle\n2. **Delay Nodes**\n   - Set Delay (`flow/setDelay`) FlowGraphBlockNames.SetDelay\n   - Cancel Delay (`flow/cancelDelay`) FlowGraphBlockNames.CancelDelay\n\n### State Manipulation Nodes\n1. **Custom Variable Access**\n   - Variable Get (`variable/get`) FlowGraphBlockNames.GetVariable\n   - Variable Set (`variable/set`) FlowGraphBlockNames.SetVariable\n   - Variable Interpolate (`variable/interpolate`)\n2. **Object Model Access** // TODO fully test this!!!\n   - JSON Pointer Template Parsing (`pointer/get`) [FlowGraphBlockNames.GetProperty, FlowGraphBlockNames.JsonPointerParser]\n   - Effective JSON Pointer Generation (`pointer/set`) [FlowGraphBlockNames.SetProperty, FlowGraphBlockNames.JsonPointerParser]\n   - Pointer Get (`pointer/get`) [FlowGraphBlockNames.GetProperty, FlowGraphBlockNames.JsonPointerParser]\n   - Pointer Set (`pointer/set`) [FlowGraphBlockNames.SetProperty, FlowGraphBlockNames.JsonPointerParser]\n   - Pointer Interpolate (`pointer/interpolate`) [FlowGraphBlockNames.ValueInterpolation, FlowGraphBlockNames.JsonPointerParser, FlowGraphBlockNames.PlayAnimation, FlowGraphBlockNames.BezierCurveEasing]\n\n### Animation Control Nodes\n1. **Animation Play** (`animation/start`) FlowGraphBlockNames.PlayAnimation\n2. **Animation Stop** (`animation/stop`) FlowGraphBlockNames.StopAnimation \n3. **Animation Stop At** (`animation/stopAt`) FlowGraphBlockNames.StopAnimation \n\n### Event Nodes\n1. **Lifecycle Event Nodes**\n   - On Start (`event/onStart`) FlowGraphBlockNames.SceneReadyEvent\n   - On Tick (`event/onTick`) FlowGraphBlockNames.SceneTickEvent\n2. **Custom Event Nodes**\n   - Receive (`event/receive`) FlowGraphBlockNames.ReceiveCustomEvent\n   - Send (`event/send`) FlowGraphBlockNames.SendCustomEvent\n\n */\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./MSFT_sRGBFactors.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./MSFT_sRGBFactors.types\";\r\nexport * from \"./MSFT_sRGBFactors.pure\";\r\n\r\nimport { RegisterMSFT_sRGBFactors } from \"./MSFT_sRGBFactors.pure\";\r\nRegisterMSFT_sRGBFactors();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport {\n    type IKHRInteractivity,\n    type IKHRInteractivity_Declaration,\n    type IKHRInteractivity_Graph,\n    type IKHRInteractivity_Node,\n    type IKHRInteractivity_OutputSocketReference,\n    type IKHRInteractivity_Variable,\n} from \"babylonjs-gltf2interface\";\nimport {\n    getMappingForDeclaration,\n    getNoOpMappingForDeclaration,\n    ParseDebugLogTemplate,\n    type IGLTFToFlowGraphMapping,\n    type IGLTFToFlowGraphMappingObject,\n} from \"./declarationMapper\";\nimport { FlowGraphTypes } from \"core/FlowGraph/flowGraphRichTypes\";\n\n/**\n * Ratified KHR_interactivity specification baseline used by this importer.\n */\nexport const KHR_INTERACTIVITY_SPECIFICATION_COMMIT = \"f798712c5685bc9223a628140fba707db8889300\";\n\n/**\n * Runtime representation of every ratified built-in KHR_interactivity type.\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const gltfTypeToBabylonType: {\n    [key: string]: { length: number; flowGraphType: FlowGraphTypes; elementType: \"number\" | \"boolean\" | \"string\" | \"any\" };\n} = {\n    float: { length: 1, flowGraphType: FlowGraphTypes.Number, elementType: \"number\" },\n    bool: { length: 1, flowGraphType: FlowGraphTypes.Boolean, elementType: \"boolean\" },\n    float2: { length: 2, flowGraphType: FlowGraphTypes.Vector2, elementType: \"number\" },\n    float3: { length: 3, flowGraphType: FlowGraphTypes.Vector3, elementType: \"number\" },\n    float4: { length: 4, flowGraphType: FlowGraphTypes.Vector4, elementType: \"number\" },\n    float4x4: { length: 16, flowGraphType: FlowGraphTypes.Matrix, elementType: \"number\" },\n    float2x2: { length: 4, flowGraphType: FlowGraphTypes.Matrix2D, elementType: \"number\" },\n    float3x3: { length: 9, flowGraphType: FlowGraphTypes.Matrix3D, elementType: \"number\" },\n    int: { length: 1, flowGraphType: FlowGraphTypes.Integer, elementType: \"number\" },\n    ref: { length: 1, flowGraphType: FlowGraphTypes.String, elementType: \"string\" },\n    custom: { length: 0, flowGraphType: FlowGraphTypes.Any, elementType: \"any\" },\n};\n\n/**\n * Classification of a KHR_interactivity declaration.\n */\nexport type KHRInteractivityDeclarationSupport = \"core\" | \"extension\" | \"unsupported-extension\" | \"unknown-core\";\n\n/**\n * A structured KHR_interactivity import diagnostic.\n */\nexport interface IKHRInteractivityDiagnostic {\n    /** JSON pointer identifying the source location. */\n    path: string;\n    /** Human-readable diagnostic text. */\n    message: string;\n    /** Diagnostic severity. */\n    severity: \"error\" | \"warning\";\n}\n\n/**\n * Stable source identity retained on every FlowGraph block lowered from a KHR_interactivity node.\n */\nexport interface IKHRInteractivityBlockProvenance {\n    /** Source graph index. */\n    graphIndex: number;\n    /** Source node index. */\n    nodeIndex: number;\n    /** Source declaration index. */\n    declarationIndex: number;\n    /** Full operation name. */\n    operation: string;\n    /** Role of this block in a one-to-many mapping. Negative roles identify generated helper blocks. */\n    role: number;\n    /** Stable JSON pointer to the source node. */\n    sourcePath: string;\n    /** Original and lowered configuration values used for safe inverse transforms. */\n    configuration?: Record<string, IKHRInteractivityConfigurationProvenance>;\n    /** Importer-generated primitive configuration that must remain unchanged for inverse export. */\n    generatedConfiguration?: Record<string, unknown>;\n    /** Runtime fingerprints for generated configuration that changes representation while parsing. */\n    generatedConfigurationRuntime?: Record<string, IKHRInteractivityInputDefaultProvenance>;\n    /** Importer-generated unconnected input defaults that have no authored KHR socket representation. */\n    generatedInputDefaults?: Record<string, IKHRInteractivityInputDefaultProvenance>;\n}\n\n/**\n * Import-time value retained for an unconnected FlowGraph input that is not represented by an authored KHR socket.\n */\nexport interface IKHRInteractivityInputDefaultProvenance {\n    /** Type-tagged JSON-stable fingerprint of the normalized runtime input value. */\n    runtimeValueFingerprint?: string;\n    /** Whether the import-time value could not be fingerprinted safely. */\n    unrepresentable?: true;\n}\n\n/**\n * Provenance for a transformed KHR configuration value.\n */\nexport interface IKHRInteractivityConfigurationProvenance {\n    /** Exact source configuration array. */\n    sourceValue?: unknown[];\n    /** Lowered FlowGraph configuration value immediately after import. */\n    runtimeValue?: unknown;\n}\n\n/** @internal */\nexport function _NormalizeKHRInteractivityRuntimeValue(value: unknown): unknown[] | undefined {\n    if (value === undefined) {\n        return undefined;\n    }\n    if (value !== null && typeof value === \"object\") {\n        const asArray = (value as { asArray?: () => ArrayLike<unknown> }).asArray;\n        if (typeof asArray === \"function\") {\n            return Array.from(asArray.call(value));\n        }\n        if (\"value\" in value && typeof (value as { value?: unknown }).value !== \"object\") {\n            return [(value as { value: unknown }).value];\n        }\n    }\n    return Array.isArray(value) ? value.slice() : [value];\n}\n\nfunction _EncodeRuntimeValueSnapshot(value: unknown, ancestors: Set<object>): unknown {\n    if (value === undefined) {\n        return [\"undefined\"];\n    }\n    if (value === null) {\n        return [\"null\"];\n    }\n    switch (typeof value) {\n        case \"boolean\":\n            return [\"boolean\", value];\n        case \"number\":\n            return [\"number\", Number.isNaN(value) ? \"NaN\" : value === Infinity ? \"Infinity\" : value === -Infinity ? \"-Infinity\" : Object.is(value, -0) ? \"-0\" : value];\n        case \"string\":\n            return [\"string\", value];\n        case \"object\": {\n            if (Object.getOwnPropertySymbols(value).length > 0) {\n                return undefined;\n            }\n            if (Array.isArray(value)) {\n                const hasNonIndexProperty = Object.getOwnPropertyNames(value).some(\n                    (key) => key !== \"length\" && (!/^(0|[1-9]\\d*)$/.test(key) || Number(key) >= value.length || !(\"value\" in Object.getOwnPropertyDescriptor(value, key)!))\n                );\n                if (hasNonIndexProperty) {\n                    return undefined;\n                }\n            } else {\n                const prototype = Object.getPrototypeOf(value);\n                if (prototype !== Object.prototype && prototype !== null) {\n                    return undefined;\n                }\n                const hasNonJsonProperty = Object.getOwnPropertyNames(value).some(\n                    (key) => !Object.prototype.propertyIsEnumerable.call(value, key) || !(\"value\" in Object.getOwnPropertyDescriptor(value, key)!)\n                );\n                if (hasNonJsonProperty) {\n                    return undefined;\n                }\n            }\n            if (ancestors.has(value)) {\n                return undefined;\n            }\n            ancestors.add(value);\n            let encoded: unknown;\n            if (Array.isArray(value)) {\n                const entries = value.map((entry) => _EncodeRuntimeValueSnapshot(entry, ancestors));\n                encoded = entries.some((entry) => entry === undefined) ? undefined : [\"array\", entries];\n            } else {\n                const entries: unknown[] = [];\n                let unrepresentable = false;\n                for (const key of Object.keys(value).sort()) {\n                    const entry = _EncodeRuntimeValueSnapshot((value as Record<string, unknown>)[key], ancestors);\n                    if (entry === undefined) {\n                        unrepresentable = true;\n                        break;\n                    }\n                    entries.push([key, entry]);\n                }\n                encoded = unrepresentable ? undefined : [\"object\", entries];\n            }\n            ancestors.delete(value);\n            return encoded;\n        }\n        default:\n            return undefined;\n    }\n}\n\n/** @internal */\nexport function _CreateKHRInteractivityRuntimeValueSnapshot(value: unknown): IKHRInteractivityInputDefaultProvenance {\n    try {\n        const encoded = _EncodeRuntimeValueSnapshot(Array.isArray(value) ? value : _NormalizeKHRInteractivityRuntimeValue(value), new Set<object>());\n        return encoded === undefined ? { unrepresentable: true } : { runtimeValueFingerprint: JSON.stringify(encoded) };\n    } catch {\n        return { unrepresentable: true };\n    }\n}\n\n/**\n * Stable source identity retained on a FlowGraph connection lowered from a KHR_interactivity socket.\n */\nexport interface IKHRInteractivitySocketProvenance extends IKHRInteractivityBlockProvenance {\n    /** Socket category. */\n    kind: \"value\" | \"flow\";\n    /** Whether the socket is consumed by or produced from the logical KHR node. */\n    direction: \"input\" | \"output\";\n    /** Exact source KHR socket identifier. */\n    socket: string;\n    /** Exact canonical source value, when this is an input value socket. */\n    sourceValue?: IKHRInteractivity_Variable | IKHRInteractivity_OutputSocketReference;\n    /** Lowered inline runtime value immediately after import. */\n    runtimeValue?: unknown[];\n    /** Type-tagged runtime fingerprint used to distinguish parsing precision changes from edits. */\n    runtimeValueSnapshot?: IKHRInteractivityInputDefaultProvenance;\n}\n\n/**\n * Canonical source retained on a FlowGraph lowered from KHR_interactivity.\n */\nexport interface IKHRInteractivityGraphProvenance {\n    /** Source graph index. */\n    graphIndex: number;\n    /** Ratified specification revision used by the importer. */\n    specificationCommit: string;\n    /** Detached canonical source graph. */\n    source: IKHRInteractivity_Graph;\n    /** Explicit editor-authored variable defaults keyed by canonical variable index. */\n    authoredVariableValues?: Record<number, unknown[]>;\n    /** Explicit editor-authored FlowGraph variable types keyed by canonical variable index. */\n    authoredVariableTypes?: Record<number, string>;\n    /** True when variables were explicitly added, renamed, or deleted in the editor. */\n    authoredVariableStructureChanged?: boolean;\n}\n\n/**\n * Canonical declaration information retained during import.\n */\nexport interface IKHRInteractivityDeclarationModel {\n    /** Declaration index in the source graph. */\n    index: number;\n    /** Full operation name, including the defining extension when present. */\n    operation: string;\n    /** Whether Babylon can execute the declaration. */\n    support: KHRInteractivityDeclarationSupport;\n    /** Exact source declaration. */\n    source: IKHRInteractivity_Declaration;\n}\n\n/**\n * Canonical graph information retained during import.\n */\nexport interface IKHRInteractivityGraphModel {\n    /** Graph index in the root extension. */\n    index: number;\n    /** Stable source path. */\n    path: string;\n    /** Human-readable graph name. */\n    name: string;\n    /** Exact source graph, including extension and extras payloads. */\n    source: IKHRInteractivity_Graph;\n    /** Executable graph with specification defaults and fallbacks applied. */\n    effectiveSource: IKHRInteractivity_Graph;\n    /** Canonical declarations in source order. */\n    declarations: IKHRInteractivityDeclarationModel[];\n    /** Validation diagnostics for this graph. */\n    diagnostics: IKHRInteractivityDiagnostic[];\n    /** Whether this graph is valid and can be lowered to FlowGraph. */\n    valid: boolean;\n}\n\n/**\n * Lossless canonical representation of a KHR_interactivity root extension.\n */\nexport interface IKHRInteractivityDocument {\n    /** Ratified specification revision used for validation. */\n    specificationCommit: string;\n    /** Exact source extension, including unknown extensions and extras. */\n    source: IKHRInteractivity;\n    /** Default graph index, or -1 when the source selection is invalid. */\n    defaultGraphIndex: number;\n    /** Canonical graph models in source order. */\n    graphs: IKHRInteractivityGraphModel[];\n    /** Root-level validation diagnostics. */\n    diagnostics: IKHRInteractivityDiagnostic[];\n}\n\nfunction _cloneJson<T>(value: T): T {\n    if (Array.isArray(value)) {\n        return value.map((entry) => _cloneJson(entry)) as T;\n    }\n    if (value !== null && typeof value === \"object\") {\n        const clone: Record<string, unknown> = {};\n        for (const [key, entry] of Object.entries(value)) {\n            Object.defineProperty(clone, key, {\n                configurable: true,\n                enumerable: true,\n                value: _cloneJson(entry),\n                writable: true,\n            });\n        }\n        return clone as T;\n    }\n    return value;\n}\n\n/**\n * Creates a detached JSON copy of a KHR_interactivity graph.\n * @param graph source graph\n * @returns a lossless JSON copy\n */\nexport function CloneKHRInteractivityGraph(graph: IKHRInteractivity_Graph): IKHRInteractivity_Graph {\n    return _cloneJson(graph);\n}\n\nfunction _isValidIndex(value: unknown, length: number): value is number {\n    return typeof value === \"number\" && Number.isInteger(value) && value >= 0 && value < length;\n}\n\nfunction _isRecord(value: unknown): boolean {\n    return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction _addError(diagnostics: IKHRInteractivityDiagnostic[], path: string, message: string): void {\n    diagnostics.push({ path, message, severity: \"error\" });\n}\n\nfunction _addWarning(diagnostics: IKHRInteractivityDiagnostic[], path: string, message: string): void {\n    diagnostics.push({ path, message, severity: \"warning\" });\n}\n\nfunction _isValidJsonPointer(value: string): boolean {\n    return value === \"\" || /^(?:\\/(?:[^~]|~[01])*)*$/.test(value);\n}\n\nfunction _matchesOutputSocket(\n    mapping: { [name: string]: IGLTFToFlowGraphMappingObject } | undefined,\n    socket: string,\n    declaration: IKHRInteractivityDeclarationModel,\n    node: IKHRInteractivity_Node,\n    graph: IKHRInteractivity_Graph,\n    defaultSocket?: string\n): boolean {\n    if (mapping && Object.prototype.hasOwnProperty.call(mapping, socket)) {\n        return true;\n    }\n    if (socket === defaultSocket && mapping && Object.prototype.hasOwnProperty.call(mapping, defaultSocket)) {\n        return true;\n    }\n    if (!Object.keys(mapping ?? {}).some((name) => name.startsWith(\"[\") && name.endsWith(\"]\"))) {\n        return false;\n    }\n    if (declaration.operation === \"event/receive\") {\n        const eventIndex = node.configuration?.event?.value?.[0];\n        return typeof eventIndex === \"number\" && Object.prototype.hasOwnProperty.call(graph.events?.[eventIndex]?.values ?? {}, socket);\n    }\n    return true;\n}\n\nfunction _validateTypeIndex(typeIndex: unknown, graph: IKHRInteractivity_Graph, diagnostics: IKHRInteractivityDiagnostic[], path: string): typeIndex is number {\n    if (!_isValidIndex(typeIndex, graph.types?.length ?? 0)) {\n        _addError(diagnostics, path, `Type index ${String(typeIndex)} is out of range.`);\n        return false;\n    }\n    return true;\n}\n\nfunction _validateValue(value: IKHRInteractivity_Variable, graph: IKHRInteractivity_Graph, diagnostics: IKHRInteractivityDiagnostic[], path: string): void {\n    if (!_validateTypeIndex(value.type, graph, diagnostics, `${path}/type`)) {\n        return;\n    }\n    if (value.value === undefined) {\n        return;\n    }\n    if (!Array.isArray(value.value)) {\n        _addError(diagnostics, `${path}/value`, \"Value must be an array when present.\");\n        return;\n    }\n    const type = graph.types![value.type];\n    const runtimeType = gltfTypeToBabylonType[type.signature];\n    if (runtimeType && type.signature !== \"custom\" && value.value.length !== runtimeType.length) {\n        _addError(diagnostics, `${path}/value`, `Expected ${runtimeType.length} value component(s) for type \"${type.signature}\", received ${value.value.length}.`);\n    }\n    for (let componentIndex = 0; componentIndex < value.value.length; componentIndex++) {\n        const component = value.value[componentIndex];\n        let valid = true;\n        switch (type.signature) {\n            case \"bool\":\n                valid = typeof component === \"boolean\";\n                break;\n            case \"int\":\n                valid = typeof component === \"number\" && Number.isInteger(component) && component >= -2147483648 && component <= 2147483647;\n                break;\n            case \"float\":\n            case \"float2\":\n            case \"float3\":\n            case \"float4\":\n            case \"float2x2\":\n            case \"float3x3\":\n            case \"float4x4\":\n                valid = typeof component === \"number\" && Number.isFinite(component);\n                break;\n            case \"ref\":\n                valid = typeof component === \"string\" && _isValidJsonPointer(component);\n                break;\n            default:\n                break;\n        }\n        if (!valid) {\n            _addError(diagnostics, `${path}/value/${componentIndex}`, `Value component is invalid for type \"${type.signature}\".`);\n        }\n    }\n}\n\nfunction _getDeclarationMapping(\n    declaration: IKHRInteractivity_Declaration,\n    graph: IKHRInteractivity_Graph,\n    supportedExtensions?: ReadonlySet<string>\n): {\n    mapping: IGLTFToFlowGraphMapping | undefined;\n    support: KHRInteractivityDeclarationSupport;\n} {\n    const extensionEnabled = !declaration.extension || !supportedExtensions || supportedExtensions.has(declaration.extension);\n    const mapping = extensionEnabled ? getMappingForDeclaration(declaration, false) : undefined;\n    if (mapping) {\n        if (declaration.extension && mapping.declarationSchema && !_isCompatibleExtensionDeclaration(declaration, graph, mapping.declarationSchema)) {\n            return { mapping: undefined, support: \"unsupported-extension\" };\n        }\n        return { mapping, support: declaration.extension ? \"extension\" : \"core\" };\n    }\n\n    return {\n        mapping: undefined,\n        support: declaration.extension ? \"unsupported-extension\" : \"unknown-core\",\n    };\n}\n\nfunction _isCompatibleExtensionDeclaration(\n    declaration: IKHRInteractivity_Declaration,\n    graph: IKHRInteractivity_Graph,\n    schema: NonNullable<IGLTFToFlowGraphMapping[\"declarationSchema\"]>\n): boolean {\n    const matches = (actual: typeof declaration.inputValueSockets, expected: Record<string, string>): boolean => {\n        const actualKeys = Object.keys(actual ?? {}).sort();\n        const expectedKeys = Object.keys(expected).sort();\n        if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) {\n            return false;\n        }\n        return actualKeys.every((key) => _isRecord(actual![key]) && graph.types?.[actual![key].type]?.signature === expected[key]);\n    };\n    return matches(declaration.inputValueSockets, schema.inputValueSockets) && matches(declaration.outputValueSockets, schema.outputValueSockets);\n}\n\nfunction _validateConfigurationValue(value: unknown[] | undefined, type: IGLTFToFlowGraphMappingObject[\"configurationType\"]): boolean {\n    if (!Array.isArray(value)) {\n        return false;\n    }\n    const isInt = (entry: unknown) => typeof entry === \"number\" && Number.isInteger(entry) && entry >= -2147483648 && entry <= 2147483647;\n    switch (type) {\n        case \"bool\":\n            return value.length === 1 && typeof value[0] === \"boolean\";\n        case \"int\":\n            return value.length === 1 && isInt(value[0]);\n        case \"int[]\":\n            return value.every(isInt);\n        case \"string\":\n            return value.length === 1 && typeof value[0] === \"string\";\n        default:\n            return value.length > 0;\n    }\n}\n\nfunction _getIndexedArrayLength(graph: IKHRInteractivity_Graph, source: IGLTFToFlowGraphMappingObject[\"indexSource\"], assetNodeCount?: number): number {\n    switch (source) {\n        case \"types\":\n            return graph.types?.length ?? 0;\n        case \"variables\":\n            return graph.variables?.length ?? 0;\n        case \"events\":\n            return graph.events?.length ?? 0;\n        case \"nodes\":\n            return graph.nodes?.length ?? 0;\n        case \"assetNodes\":\n            return assetNodeCount ?? 0;\n        default:\n            return 0;\n    }\n}\n\nfunction _isEffectiveConfigurationValue(\n    configuration: { value?: unknown[] } | undefined,\n    property: IGLTFToFlowGraphMappingObject,\n    graph: IKHRInteractivity_Graph,\n    assetNodeCount?: number\n): boolean {\n    if (!configuration || !_validateConfigurationValue(configuration.value, property.configurationType) || !configuration.value) {\n        return false;\n    }\n    if (property.minItems !== undefined && configuration.value.length < property.minItems) {\n        return false;\n    }\n    if (property.minimum !== undefined && configuration.value.some((value) => typeof value !== \"number\" || value < property.minimum!)) {\n        return false;\n    }\n    if (property.maximum !== undefined && configuration.value.some((value) => typeof value !== \"number\" || value > property.maximum!)) {\n        return false;\n    }\n    if (property.indexSource) {\n        const length = _getIndexedArrayLength(graph, property.indexSource, assetNodeCount);\n        if (configuration.value.some((value) => !_isValidIndex(value, length))) {\n            return false;\n        }\n    }\n    if (property.allowedSignatures) {\n        const typeIndex = configuration.value[0];\n        const signature = typeof typeIndex === \"number\" ? graph.types?.[typeIndex]?.signature : undefined;\n        if (!signature || !property.allowedSignatures.includes(signature)) {\n            return false;\n        }\n    }\n    if (property.allowedValues && configuration.value.some((value) => !property.allowedValues!.includes(value as boolean | number | string))) {\n        return false;\n    }\n    if (property.debugLogTemplate && !ParseDebugLogTemplate(configuration.value[0] as string).valid) {\n        return false;\n    }\n    return true;\n}\n\n/**\n * Creates the executable graph view with all ratified configuration defaults and fallback rules\n * applied without modifying the lossless source graph.\n * @param graph source graph\n * @param declarations canonical declarations\n * @param assetNodeCount number of glTF nodes in the containing asset\n * @returns normalized executable graph\n */\nexport function CreateEffectiveKHRInteractivityGraph(\n    graph: IKHRInteractivity_Graph,\n    declarations: readonly IKHRInteractivityDeclarationModel[],\n    assetNodeCount?: number\n): IKHRInteractivity_Graph {\n    const effective = CloneKHRInteractivityGraph(graph);\n    for (let nodeIndex = 0; nodeIndex < (effective.nodes?.length ?? 0); nodeIndex++) {\n        const node = effective.nodes![nodeIndex];\n        const declaration = declarations[node.declaration];\n        if (!declaration || declaration.support === \"unknown-core\" || declaration.support === \"unsupported-extension\") {\n            continue;\n        }\n        const mapping = getMappingForDeclaration(declaration.source, false);\n        if (!mapping?.configuration) {\n            continue;\n        }\n        const groupedValidity = new Map<string, boolean>();\n        for (const [key, property] of Object.entries(mapping.configuration)) {\n            if (property.configurationGroup) {\n                const valid = _isEffectiveConfigurationValue(node.configuration?.[key], property, effective, assetNodeCount);\n                groupedValidity.set(property.configurationGroup, (groupedValidity.get(property.configurationGroup) ?? true) && valid);\n            }\n        }\n        for (const [key, property] of Object.entries(mapping.configuration)) {\n            const valid =\n                (!property.configurationGroup || groupedValidity.get(property.configurationGroup) === true) &&\n                _isEffectiveConfigurationValue(node.configuration?.[key], property, effective, assetNodeCount);\n            if (!valid && property.defaultValue !== undefined) {\n                node.configuration ??= {};\n                node.configuration[key] = {\n                    value: Array.isArray(property.defaultValue) ? _cloneJson(property.defaultValue) : [property.defaultValue],\n                };\n            } else if (valid && property.uniqueValues && node.configuration?.[key]?.value) {\n                node.configuration[key].value = Array.from(new Set(node.configuration[key].value));\n            }\n        }\n    }\n    return effective;\n}\n\nfunction _getPointerTemplateSockets(pointer: string): { name: string; signature: \"int\" | \"ref\" }[] {\n    const sockets: { name: string; signature: \"int\" | \"ref\" }[] = [];\n    for (const segment of pointer.split(\"/\")) {\n        const signature = segment.startsWith(\"[\") && !segment.startsWith(\"[[\") ? \"int\" : segment.startsWith(\"{\") && !segment.startsWith(\"{{\") ? \"ref\" : undefined;\n        if (signature) {\n            const name = segment\n                .substring(1, segment.length - 1)\n                .replace(/~1/g, \"/\")\n                .replace(/~0/g, \"~\");\n            sockets.push({ name, signature });\n        }\n    }\n    return sockets;\n}\n\nfunction _resolveValueTypeIndex(\n    value: IKHRInteractivity_Variable | { node: number; socket?: string; type?: number },\n    graph: IKHRInteractivity_Graph,\n    declarations: readonly IKHRInteractivityDeclarationModel[],\n    visited: Set<string> = new Set()\n): number | undefined {\n    if (\"node\" in value) {\n        return _resolveOutputTypeIndex(value.node, value.socket ?? \"value\", graph, declarations, visited);\n    }\n    return value.type;\n}\n\nfunction _resolveOutputTypeIndex(\n    nodeIndex: number,\n    socket: string,\n    graph: IKHRInteractivity_Graph,\n    declarations: readonly IKHRInteractivityDeclarationModel[],\n    visited: Set<string> = new Set()\n): number | undefined {\n    const key = `${nodeIndex}:${socket}`;\n    if (visited.has(key)) {\n        return undefined;\n    }\n    visited.add(key);\n    if (!_isValidIndex(nodeIndex, graph.nodes?.length ?? 0)) {\n        return undefined;\n    }\n    const sourceNode = graph.nodes![nodeIndex];\n    if (!_isValidIndex(sourceNode.declaration, declarations.length)) {\n        return undefined;\n    }\n    const declaration = declarations[sourceNode.declaration];\n    const declaredType = declaration.source.outputValueSockets?.[socket]?.type;\n    if (declaredType !== undefined) {\n        return declaredType;\n    }\n    const findTypeIndex = (signature: string): number | undefined => {\n        const index = graph.types?.findIndex((type) => type.signature === signature) ?? -1;\n        return index >= 0 ? index : undefined;\n    };\n    const booleanType = () => findTypeIndex(\"bool\");\n    if (socket === \"isValid\") {\n        return booleanType();\n    }\n    if (declaration.operation === \"pointer/get\" && socket === \"value\") {\n        const configuredType = sourceNode.configuration?.type?.value?.[0];\n        return typeof configuredType === \"number\" ? configuredType : undefined;\n    }\n    if (declaration.operation === \"variable/get\" && socket === \"value\") {\n        const variableIndex = sourceNode.configuration?.variable?.value?.[0];\n        return typeof variableIndex === \"number\" ? graph.variables?.[variableIndex]?.type : undefined;\n    }\n    if (declaration.operation === \"math/switch\" && socket === \"value\") {\n        const defaultInput = sourceNode.values?.default;\n        return defaultInput ? _resolveValueTypeIndex(defaultInput, graph, declarations, visited) : undefined;\n    }\n    if (declaration.operation === \"event/receive\" && socket !== \"event\") {\n        const eventIndex = sourceNode.configuration?.event?.value?.[0];\n        return typeof eventIndex === \"number\" ? graph.events?.[eventIndex]?.values?.[socket]?.type : undefined;\n    }\n    const fixedSignature = _getFixedOutputSignature(declaration.operation, socket);\n    if (fixedSignature) {\n        return findTypeIndex(String(fixedSignature));\n    }\n    const mapping = getMappingForDeclaration(declaration.source, false);\n    const outputMapping = mapping?.outputs?.values?.[socket];\n    const mappedType = outputMapping?.gltfType;\n    const signature = mappedType === \"number\" ? \"float\" : mappedType === \"boolean\" ? \"bool\" : mappedType;\n    if (signature && signature in gltfTypeToBabylonType) {\n        return findTypeIndex(signature);\n    }\n    const typeSource = outputMapping?.typeSourceInput ? sourceNode.values?.[outputMapping.typeSourceInput] : undefined;\n    return typeSource ? _resolveValueTypeIndex(typeSource, graph, declarations, visited) : undefined;\n}\n\nfunction _getFixedOutputSignature(operation: string, socket: string): keyof typeof gltfTypeToBabylonType | undefined {\n    if (socket !== \"value\") {\n        if (\n            (operation === \"math/rgbToOkLCh\" && [\"l\", \"c\", \"h\"].includes(socket)) ||\n            (operation === \"math/rgbFromOkLCh\" && [\"r\", \"g\", \"b\"].includes(socket)) ||\n            operation.startsWith(\"math/extract\")\n        ) {\n            return \"float\";\n        }\n        if (operation === \"math/matDecompose\") {\n            return socket === \"rotation\" ? \"float4\" : socket === \"translation\" || socket === \"scale\" ? \"float3\" : undefined;\n        }\n        if (operation === \"math/quatToAxisAngle\") {\n            return socket === \"axis\" ? \"float3\" : socket === \"angle\" ? \"float\" : undefined;\n        }\n        if ((operation === \"flow/doN\" && socket === \"currentCount\") || (operation === \"flow/for\" && socket === \"index\")) {\n            return \"int\";\n        }\n        if (operation === \"flow/setDelay\" && socket === \"lastDelay\") {\n            return \"ref\";\n        }\n        if (operation === \"flow/throttle\" && socket === \"lastRemainingTime\") {\n            return \"float\";\n        }\n        if ((operation === \"event/onStart\" || operation === \"event/onTick\" || operation === \"event/receive\") && socket === \"event\") {\n            return \"ref\";\n        }\n        if (operation === \"event/onTick\" && socket === \"timeSinceLastTick\") {\n            return \"float\";\n        }\n        if (operation === \"event/onTick\" && socket === \"timeSinceStart\") {\n            return \"float\";\n        }\n        return undefined;\n    }\n    if ([\"math/E\", \"math/Pi\", \"math/Tau\", \"math/Inf\", \"math/NaN\", \"math/random\", \"math/length\", \"math/dot\", \"math/determinant\", \"math/quatAngleBetween\"].includes(operation)) {\n        return \"float\";\n    }\n    if ([\"math/eq\", \"ref/eq\", \"math/lt\", \"math/le\", \"math/gt\", \"math/ge\", \"math/isNaN\", \"math/isInf\", \"type/intToBool\", \"type/floatToBool\"].includes(operation)) {\n        return \"bool\";\n    }\n    if ([\"math/clz\", \"math/ctz\", \"math/popcnt\", \"type/boolToInt\", \"type/floatToInt\"].includes(operation)) {\n        return \"int\";\n    }\n    if ([\"type/boolToFloat\", \"type/intToFloat\"].includes(operation)) {\n        return \"float\";\n    }\n    return undefined;\n}\n\nfunction _validateNode(\n    node: IKHRInteractivity_Node,\n    nodeIndex: number,\n    graph: IKHRInteractivity_Graph,\n    declarations: IKHRInteractivityDeclarationModel[],\n    diagnostics: IKHRInteractivityDiagnostic[],\n    graphPath: string,\n    assetNodeCount?: number\n): void {\n    const path = `${graphPath}/nodes/${nodeIndex}`;\n    if (!_isValidIndex(node.declaration, declarations.length)) {\n        _addError(diagnostics, `${path}/declaration`, `Declaration index ${String(node.declaration)} is out of range.`);\n        return;\n    }\n\n    const declarationModel = declarations[node.declaration];\n    const mapping =\n        declarationModel.support === \"unsupported-extension\" ? getNoOpMappingForDeclaration(declarationModel.source) : getMappingForDeclaration(declarationModel.source, false);\n    if (declarationModel.support === \"unknown-core\" || !mapping) {\n        return;\n    }\n\n    const reportConfigurationIssue = (property: IGLTFToFlowGraphMappingObject, issuePath: string, message: string): void => {\n        if (property.invalidUsesDefault || property.defaultValue !== undefined) {\n            _addWarning(diagnostics, issuePath, `${message} The default configuration will be used.`);\n        } else {\n            _addError(diagnostics, issuePath, message);\n        }\n    };\n    for (const [key, configuration] of Object.entries(node.configuration ?? {})) {\n        if (!_isRecord(configuration)) {\n            _addError(diagnostics, `${path}/configuration/${key}`, `Configuration \"${key}\" must be an object.`);\n            continue;\n        }\n        if (configuration.value !== undefined && !Array.isArray(configuration.value)) {\n            _addError(diagnostics, `${path}/configuration/${key}/value`, \"Configuration value must be an array when present.\");\n        } else if (configuration.value && configuration.value.length === 0) {\n            _addError(diagnostics, `${path}/configuration/${key}/value`, \"Configuration value arrays must contain at least one item when present.\");\n        }\n    }\n    for (const [key, property] of Object.entries(mapping.configuration ?? {})) {\n        const configuration = node.configuration?.[key];\n        const isConfigurationValid = !!configuration && _validateConfigurationValue(configuration.value, property.configurationType);\n        if (!configuration && property.required) {\n            _addError(diagnostics, `${path}/configuration/${key}`, `Required configuration \"${key}\" is missing.`);\n        } else if (configuration && !isConfigurationValid) {\n            reportConfigurationIssue(property, `${path}/configuration/${key}`, `Configuration \"${key}\" is invalid.`);\n        }\n        if (isConfigurationValid && configuration.value && property.minItems !== undefined && configuration.value.length < property.minItems) {\n            _addError(diagnostics, `${path}/configuration/${key}/value`, `Configuration \"${key}\" requires at least ${property.minItems} value(s).`);\n        }\n        if (isConfigurationValid && configuration.value && property.indexSource) {\n            const length = _getIndexedArrayLength(graph, property.indexSource, assetNodeCount);\n            for (let index = 0; index < configuration.value.length; index++) {\n                if (!_isValidIndex(configuration.value[index], length)) {\n                    reportConfigurationIssue(property, `${path}/configuration/${key}/value/${index}`, `Index is out of range for graph ${property.indexSource}.`);\n                }\n            }\n        }\n        if (isConfigurationValid && configuration.value && property.allowedSignatures) {\n            const typeIndex = configuration.value[0];\n            const signature = typeof typeIndex === \"number\" ? graph.types?.[typeIndex]?.signature : undefined;\n            if (!signature || !property.allowedSignatures.includes(signature)) {\n                reportConfigurationIssue(property, `${path}/configuration/${key}/value/0`, `Type \"${String(signature)}\" is not supported by this operation.`);\n            }\n        }\n        if (isConfigurationValid && configuration.value && property.allowedValues && configuration.value.some((value) => !property.allowedValues!.includes(value))) {\n            reportConfigurationIssue(property, `${path}/configuration/${key}/value`, `Configuration \"${key}\" contains an unsupported value.`);\n        }\n        if (isConfigurationValid && configuration.value && property.debugLogTemplate && !ParseDebugLogTemplate(configuration.value[0] as string).valid) {\n            reportConfigurationIssue(property, `${path}/configuration/${key}/value/0`, `Configuration \"${key}\" is not a valid debug message template.`);\n        }\n        if (isConfigurationValid && configuration.value && (property.minimum !== undefined || property.maximum !== undefined)) {\n            const numericValue = configuration.value[0] as number;\n            if ((property.minimum !== undefined && numericValue < property.minimum) || (property.maximum !== undefined && numericValue > property.maximum)) {\n                reportConfigurationIssue(\n                    property,\n                    `${path}/configuration/${key}/value/0`,\n                    `Configuration \"${key}\" must be between ${String(property.minimum)} and ${String(property.maximum)}.`\n                );\n            }\n        }\n        if (isConfigurationValid && configuration.value && property.generatesInputValueSockets) {\n            for (const configuredIndex of configuration.value) {\n                if (typeof configuredIndex !== \"number\" || !_isValidIndex(configuredIndex, graph.variables?.length ?? 0)) {\n                    continue;\n                }\n                const socket = node.values?.[String(configuredIndex)];\n                if (!socket) {\n                    _addError(diagnostics, `${path}/values/${configuredIndex}`, `Required configured input value socket \"${configuredIndex}\" is missing.`);\n                } else if (_resolveValueTypeIndex(socket, graph, declarations) !== graph.variables![configuredIndex].type) {\n                    _addError(diagnostics, `${path}/values/${configuredIndex}/type`, `Configured input value socket \"${configuredIndex}\" has the wrong type.`);\n                }\n            }\n        }\n        if (isConfigurationValid && configuration.value && property.generatesCaseInputValueSockets) {\n            const defaultType = node.values?.default ? _resolveValueTypeIndex(node.values.default, graph, declarations) : undefined;\n            for (const caseValue of configuration.value) {\n                const socket = node.values?.[String(caseValue)];\n                if (!socket) {\n                    _addError(diagnostics, `${path}/values/${caseValue}`, `Required case input value socket \"${caseValue}\" is missing.`);\n                } else if (defaultType !== undefined && _resolveValueTypeIndex(socket, graph, declarations) !== defaultType) {\n                    _addError(diagnostics, `${path}/values/${caseValue}/type`, `Case input value socket \"${caseValue}\" must match the default socket type.`);\n                }\n            }\n        }\n        if (isConfigurationValid && configuration.value && property.pointerTemplate && typeof configuration.value[0] === \"string\") {\n            for (const socketDefinition of _getPointerTemplateSockets(configuration.value[0])) {\n                const socket = node.values?.[socketDefinition.name];\n                const expectedType = graph.types?.findIndex((type) => type.signature === socketDefinition.signature) ?? -1;\n                if (!socket) {\n                    _addError(diagnostics, `${path}/values/${socketDefinition.name}`, `Required pointer template input \"${socketDefinition.name}\" is missing.`);\n                } else if (expectedType < 0 || _resolveValueTypeIndex(socket, graph, declarations) !== expectedType) {\n                    _addError(\n                        diagnostics,\n                        `${path}/values/${socketDefinition.name}/type`,\n                        `Pointer template input \"${socketDefinition.name}\" must have type \"${socketDefinition.signature}\".`\n                    );\n                }\n            }\n        }\n    }\n\n    if (declarationModel.operation === \"debug/log\") {\n        const severityProperty = mapping.configuration?.severity;\n        const messageProperty = mapping.configuration?.message;\n        const severityValid = !!severityProperty && _isEffectiveConfigurationValue(node.configuration?.severity, severityProperty, graph, assetNodeCount);\n        const messageValid = !!messageProperty && _isEffectiveConfigurationValue(node.configuration?.message, messageProperty, graph, assetNodeCount);\n        const message = severityValid && messageValid ? (node.configuration!.message.value![0] as string) : \"\";\n        for (const socket of ParseDebugLogTemplate(message).sockets) {\n            if (!node.values?.[socket]) {\n                _addError(diagnostics, `${path}/values/${socket}`, `Required debug message template input \"${socket}\" is missing.`);\n            }\n        }\n    }\n\n    for (const [key, property] of Object.entries(mapping.inputs?.values ?? {})) {\n        if (!key.startsWith(\"[\") && !node.values?.[key]) {\n            _addError(diagnostics, `${path}/values/${key}`, `Required input value socket \"${key}\" is missing.`);\n        }\n        if (declarationModel.operation === \"event/send\") {\n            const eventIndex = node.configuration?.event?.value?.[0];\n            const event = typeof eventIndex === \"number\" ? graph.events?.[eventIndex] : undefined;\n            for (const [socket, eventValue] of Object.entries(event?.values ?? {})) {\n                const source = node.values?.[socket];\n                if (!source) {\n                    _addError(diagnostics, `${path}/values/${socket}`, `Required custom event input value socket \"${socket}\" is missing.`);\n                } else if (_resolveValueTypeIndex(source, graph, declarations) !== eventValue.type) {\n                    _addError(diagnostics, `${path}/values/${socket}/type`, `Custom event input value socket \"${socket}\" has the wrong type.`);\n                }\n            }\n        }\n        const expectedSignature = property.gltfType === \"number\" ? \"float\" : property.gltfType === \"boolean\" ? \"bool\" : property.gltfType;\n        const source = node.values?.[key];\n        if (source && expectedSignature && expectedSignature in gltfTypeToBabylonType) {\n            const typeIndex = _resolveValueTypeIndex(source, graph, declarations);\n            if (typeIndex !== undefined && graph.types?.[typeIndex]?.signature !== expectedSignature) {\n                _addError(diagnostics, `${path}/values/${key}/type`, `Input value socket \"${key}\" must have type \"${expectedSignature}\".`);\n            }\n        }\n    }\n    if (mapping.validation) {\n        try {\n            const validationNode = _cloneJson(node);\n            for (const value of Object.values(validationNode.values ?? {})) {\n                if (value.type === undefined) {\n                    value.type = _resolveValueTypeIndex(value, graph, declarations);\n                }\n            }\n            const result = mapping.validation(validationNode, graph);\n            if (!result.valid) {\n                _addError(diagnostics, path, result.error ?? `Operation \"${declarationModel.operation}\" is invalid.`);\n            }\n        } catch (error) {\n            _addError(diagnostics, path, (error as Error).message);\n        }\n    }\n    for (const [key, value] of Object.entries(node.values ?? {})) {\n        if (!_isRecord(value)) {\n            _addError(diagnostics, `${path}/values/${key}`, `Input value socket \"${key}\" must be an object.`);\n            continue;\n        }\n        if (declarationModel.support === \"unsupported-extension\" && !declarationModel.source.inputValueSockets?.[key]) {\n            _addError(diagnostics, `${path}/values/${key}`, `Input value socket \"${key}\" is not defined by operation \"${declarationModel.operation}\".`);\n        }\n        if (\"node\" in value) {\n            if (\"value\" in value) {\n                _addError(diagnostics, `${path}/values/${key}`, \"An input value socket cannot define both inline and node sources.\");\n            }\n            if (!_isValidIndex(value.node, graph.nodes?.length ?? 0)) {\n                _addError(diagnostics, `${path}/values/${key}/node`, `Node index ${String(value.node)} is out of range.`);\n                continue;\n            }\n            if (value.node >= nodeIndex) {\n                _addError(diagnostics, `${path}/values/${key}/node`, \"Value connections must reference an earlier node.\");\n            }\n            if (value.type !== undefined) {\n                _validateTypeIndex(value.type, graph, diagnostics, `${path}/values/${key}/type`);\n            }\n            const sourceNode = graph.nodes![value.node];\n            if (_isValidIndex(sourceNode.declaration, declarations.length)) {\n                const sourceDeclaration = declarations[sourceNode.declaration];\n                const sourceMapping =\n                    sourceDeclaration.support === \"unsupported-extension\"\n                        ? getNoOpMappingForDeclaration(sourceDeclaration.source)\n                        : getMappingForDeclaration(sourceDeclaration.source, false);\n                const sourceSocket = value.socket ?? \"value\";\n                const hasMappedSocket = _matchesOutputSocket(sourceMapping?.outputs?.values, sourceSocket, sourceDeclaration, sourceNode, graph, \"value\");\n                if (sourceMapping && !hasMappedSocket) {\n                    _addError(diagnostics, `${path}/values/${key}/socket`, `Output value socket \"${sourceSocket}\" does not exist on node ${value.node}.`);\n                }\n                const declaredOutputType = sourceDeclaration.source.outputValueSockets?.[sourceSocket]?.type;\n                const effectiveOutputType = declaredOutputType ?? _resolveOutputTypeIndex(value.node, sourceSocket, graph, declarations);\n                if (value.type !== undefined) {\n                    const mappedOutputs = sourceMapping?.outputs?.values;\n                    const mappedOutput = mappedOutputs && Object.prototype.hasOwnProperty.call(mappedOutputs, sourceSocket) ? mappedOutputs[sourceSocket] : undefined;\n                    const mappedType = mappedOutput?.gltfType;\n                    const mappedOutputSignature =\n                        mappedType === \"number\"\n                            ? \"float\"\n                            : mappedType === \"boolean\"\n                              ? \"bool\"\n                              : mappedType === \"vector2\"\n                                ? \"float2\"\n                                : mappedType === \"vector3\"\n                                  ? \"float3\"\n                                  : mappedType === \"vector4\"\n                                    ? \"float4\"\n                                    : mappedType;\n                    const fixedOutputSignature =\n                        _getFixedOutputSignature(sourceDeclaration.operation, sourceSocket) ??\n                        (mappedOutputSignature && Object.prototype.hasOwnProperty.call(gltfTypeToBabylonType, mappedOutputSignature) ? mappedOutputSignature : undefined);\n                    const assertedSignature = graph.types?.[value.type]?.signature;\n                    if (\n                        (fixedOutputSignature !== undefined && assertedSignature !== fixedOutputSignature) ||\n                        (fixedOutputSignature === undefined && effectiveOutputType !== undefined && value.type !== effectiveOutputType)\n                    ) {\n                        _addError(diagnostics, `${path}/values/${key}/type`, `Type assertion does not match output socket \"${sourceSocket}\".`);\n                    }\n                }\n            }\n        } else {\n            _validateValue(value, graph, diagnostics, `${path}/values/${key}`);\n        }\n    }\n\n    for (const [key, flow] of Object.entries(node.flows ?? {})) {\n        if (!_isRecord(flow)) {\n            _addError(diagnostics, `${path}/flows/${key}`, `Output flow socket \"${key}\" must be an object.`);\n            continue;\n        }\n        if (!_isValidIndex(flow.node, graph.nodes?.length ?? 0)) {\n            _addError(diagnostics, `${path}/flows/${key}/node`, `Node index ${String(flow.node)} is out of range.`);\n            continue;\n        }\n        if (flow.node <= nodeIndex) {\n            _addError(diagnostics, `${path}/flows/${key}/node`, \"Flow connections must reference a later node.\");\n        }\n    }\n}\n\n/**\n * Creates and validates a canonical copy of one KHR_interactivity graph.\n * @param graph source graph\n * @param index graph index in the root extension\n * @param supportedExtensions enabled extensions that may provide executable operations\n * @param assetNodeCount number of nodes in the containing glTF asset\n * @returns the canonical graph model\n */\nexport function CreateKHRInteractivityGraphModel(\n    graph: IKHRInteractivity_Graph | null | undefined,\n    index: number = 0,\n    supportedExtensions?: ReadonlySet<string>,\n    assetNodeCount?: number\n): IKHRInteractivityGraphModel {\n    const diagnostics: IKHRInteractivityDiagnostic[] = [];\n    const path = `/extensions/KHR_interactivity/graphs/${index}`;\n    if (graph === null || typeof graph !== \"object\" || Array.isArray(graph)) {\n        _addError(diagnostics, path, \"Behavior graph must be an object.\");\n        graph = {};\n    } else {\n        graph = CloneKHRInteractivityGraph(graph);\n    }\n    const invalidEntryDefaults = {\n        types: () => ({ signature: \"custom\" }),\n        variables: () => ({ type: -1 }),\n        events: () => ({}),\n        declarations: () => ({ op: \"\" }),\n        nodes: () => ({ declaration: -1 }),\n    } as const;\n    for (const key of [\"types\", \"variables\", \"events\", \"declarations\", \"nodes\"] as const) {\n        const collection = graph[key] as unknown;\n        if (collection !== undefined && !Array.isArray(collection)) {\n            _addError(diagnostics, `${path}/${key}`, `\"${key}\" must be an array when present.`);\n            (graph as any)[key] = [];\n        } else if (Array.isArray(collection) && collection.length === 0) {\n            _addError(diagnostics, `${path}/${key}`, `\"${key}\" must contain at least one item when present.`);\n        } else if (Array.isArray(collection)) {\n            (graph as any)[key] = collection.map((entry, entryIndex) => {\n                if (entry === null || typeof entry !== \"object\" || Array.isArray(entry)) {\n                    _addError(diagnostics, `${path}/${key}/${entryIndex}`, `Each \"${key}\" item must be an object.`);\n                    return invalidEntryDefaults[key]();\n                }\n                return entry;\n            });\n        }\n    }\n    for (let eventIndex = 0; eventIndex < (graph.events?.length ?? 0); eventIndex++) {\n        const event = graph.events![eventIndex];\n        if (event.values !== undefined && !_isRecord(event.values)) {\n            _addError(diagnostics, `${path}/events/${eventIndex}/values`, '\"values\" must be an object when present.');\n            event.values = undefined;\n        } else if (event.values && Object.keys(event.values).length === 0) {\n            _addError(diagnostics, `${path}/events/${eventIndex}/values`, '\"values\" must contain at least one property when present.');\n        }\n    }\n    for (let declarationIndex = 0; declarationIndex < (graph.declarations?.length ?? 0); declarationIndex++) {\n        const declaration = graph.declarations![declarationIndex];\n        for (const key of [\"inputValueSockets\", \"outputValueSockets\"] as const) {\n            if (declaration[key] !== undefined && !_isRecord(declaration[key])) {\n                _addError(diagnostics, `${path}/declarations/${declarationIndex}/${key}`, `\"${key}\" must be an object when present.`);\n                declaration[key] = undefined;\n            } else if (declaration[key] && Object.keys(declaration[key]!).length === 0) {\n                _addError(diagnostics, `${path}/declarations/${declarationIndex}/${key}`, `\"${key}\" must contain at least one property when present.`);\n            }\n        }\n    }\n    for (let nodeIndex = 0; nodeIndex < (graph.nodes?.length ?? 0); nodeIndex++) {\n        const node = graph.nodes![nodeIndex];\n        for (const key of [\"configuration\", \"values\", \"flows\"] as const) {\n            if (node[key] !== undefined && !_isRecord(node[key])) {\n                _addError(diagnostics, `${path}/nodes/${nodeIndex}/${key}`, `\"${key}\" must be an object when present.`);\n                node[key] = undefined;\n            } else if (node[key] && Object.keys(node[key]!).length === 0) {\n                _addError(diagnostics, `${path}/nodes/${nodeIndex}/${key}`, `\"${key}\" must contain at least one property when present.`);\n            }\n        }\n    }\n    const declarationKeys = new Set<string>();\n    const declarations = (graph.declarations ?? []).map((declaration, declarationIndex) => {\n        const inputSockets = Object.keys(declaration.inputValueSockets ?? {})\n            .sort()\n            .map((key) => {\n                const definition = declaration.inputValueSockets![key];\n                return `${JSON.stringify(key)}:${_isRecord(definition) ? String(definition.type) : \"invalid\"}`;\n            })\n            .join(\",\");\n        const declarationKey = `${JSON.stringify(declaration.op)}:${JSON.stringify(declaration.extension ?? \"\")}:${inputSockets}`;\n        if (declarationKeys.has(declarationKey)) {\n            _addError(diagnostics, `${path}/declarations/${declarationIndex}`, \"Duplicate equivalent declaration.\");\n        }\n        declarationKeys.add(declarationKey);\n        const { support } = _getDeclarationMapping(declaration, graph, supportedExtensions);\n        if (support === \"unknown-core\") {\n            _addError(diagnostics, `${path}/declarations/${declarationIndex}/op`, `Unknown core operation \"${declaration.op}\".`);\n        }\n        if (!declaration.extension && (declaration.inputValueSockets || declaration.outputValueSockets)) {\n            _addError(diagnostics, `${path}/declarations/${declarationIndex}`, \"Core operation declarations cannot define dynamic value sockets.\");\n        }\n        for (const [socket, definition] of Object.entries(declaration.inputValueSockets ?? {})) {\n            if (!_isRecord(definition)) {\n                _addError(diagnostics, `${path}/declarations/${declarationIndex}/inputValueSockets/${socket}`, `Input value socket \"${socket}\" must be an object.`);\n                continue;\n            }\n            _validateTypeIndex(definition.type, graph, diagnostics, `${path}/declarations/${declarationIndex}/inputValueSockets/${socket}/type`);\n        }\n        for (const [socket, definition] of Object.entries(declaration.outputValueSockets ?? {})) {\n            if (!_isRecord(definition)) {\n                _addError(diagnostics, `${path}/declarations/${declarationIndex}/outputValueSockets/${socket}`, `Output value socket \"${socket}\" must be an object.`);\n                continue;\n            }\n            _validateTypeIndex(definition.type, graph, diagnostics, `${path}/declarations/${declarationIndex}/outputValueSockets/${socket}/type`);\n        }\n        return {\n            index: declarationIndex,\n            operation: declaration.extension ? `${declaration.op}:${declaration.extension}` : declaration.op,\n            support,\n            source: declaration,\n        };\n    });\n\n    const signatures = new Set<string>();\n    for (let typeIndex = 0; typeIndex < (graph.types?.length ?? 0); typeIndex++) {\n        const signature = graph.types![typeIndex].signature;\n        if (signature !== \"custom\" && signatures.has(signature)) {\n            _addError(diagnostics, `${path}/types/${typeIndex}/signature`, `Duplicate built-in type signature \"${signature}\".`);\n        }\n        signatures.add(signature);\n        if (signature !== \"custom\" && !gltfTypeToBabylonType[signature]) {\n            _addError(diagnostics, `${path}/types/${typeIndex}/signature`, `Unknown built-in type signature \"${signature}\".`);\n        }\n    }\n\n    for (let variableIndex = 0; variableIndex < (graph.variables?.length ?? 0); variableIndex++) {\n        _validateValue(graph.variables![variableIndex], graph, diagnostics, `${path}/variables/${variableIndex}`);\n    }\n    for (let eventIndex = 0; eventIndex < (graph.events?.length ?? 0); eventIndex++) {\n        const eventId = graph.events![eventIndex].id;\n        if (eventId !== undefined && graph.events!.slice(0, eventIndex).some((event) => event.id === eventId)) {\n            _addError(diagnostics, `${path}/events/${eventIndex}/id`, `Duplicate event id \"${eventId}\".`);\n        }\n        if (graph.events![eventIndex].values && Object.prototype.hasOwnProperty.call(graph.events![eventIndex].values, \"event\")) {\n            _addError(diagnostics, `${path}/events/${eventIndex}/values/event`, 'Custom event value socket id \"event\" is reserved.');\n        }\n        for (const [socket, value] of Object.entries(graph.events![eventIndex].values ?? {})) {\n            if (!_isRecord(value)) {\n                _addError(diagnostics, `${path}/events/${eventIndex}/values/${socket}`, `Event value socket \"${socket}\" must be an object.`);\n                continue;\n            }\n            _validateValue(value, graph, diagnostics, `${path}/events/${eventIndex}/values/${socket}`);\n        }\n    }\n    for (let nodeIndex = 0; nodeIndex < (graph.nodes?.length ?? 0); nodeIndex++) {\n        _validateNode(graph.nodes![nodeIndex], nodeIndex, graph, declarations, diagnostics, path, assetNodeCount);\n    }\n\n    return {\n        index,\n        path,\n        name: graph.name ?? `Graph ${index + 1}`,\n        source: graph,\n        effectiveSource: CreateEffectiveKHRInteractivityGraph(graph, declarations, assetNodeCount),\n        declarations,\n        diagnostics,\n        valid: !diagnostics.some((diagnostic) => diagnostic.severity === \"error\"),\n    };\n}\n\n/**\n * Creates an immutable canonical KHR_interactivity document and validates all graph-local references.\n * @param extension source extension object from the glTF document\n * @param supportedExtensions enabled extensions that may provide executable operations\n * @param assetNodeCount number of nodes in the containing glTF asset\n * @returns the canonical document\n */\nexport function CreateKHRInteractivityDocument(extension: IKHRInteractivity, supportedExtensions?: ReadonlySet<string>, assetNodeCount?: number): IKHRInteractivityDocument {\n    const source = _cloneJson(extension);\n    const diagnostics: IKHRInteractivityDiagnostic[] = [];\n    if (!Array.isArray(source.graphs)) {\n        _addError(diagnostics, \"/extensions/KHR_interactivity/graphs\", '\"graphs\" must be an array.');\n        source.graphs = [];\n    }\n    if (source.graphs.length === 0) {\n        _addError(diagnostics, \"/extensions/KHR_interactivity/graphs\", \"At least one behavior graph is required.\");\n    }\n    const requestedDefaultGraphIndex = source.graph ?? 0;\n    const defaultGraphIndex = _isValidIndex(requestedDefaultGraphIndex, source.graphs.length) ? requestedDefaultGraphIndex : -1;\n    if (defaultGraphIndex === -1) {\n        _addError(diagnostics, \"/extensions/KHR_interactivity/graph\", `Default graph index ${String(requestedDefaultGraphIndex)} is out of range.`);\n    }\n    const graphs = source.graphs.map((graph, index) => CreateKHRInteractivityGraphModel(graph, index, supportedExtensions, assetNodeCount));\n    source.graphs = graphs.map((graph) => graph.source);\n\n    return {\n        specificationCommit: KHR_INTERACTIVITY_SPECIFICATION_COMMIT,\n        source,\n        defaultGraphIndex,\n        graphs,\n        diagnostics,\n    };\n}\n","/**\r\n * KHR_interactivity opaque reference representation.\r\n *\r\n * The specification gives `event/onStart`, `event/onTick`, and `event/receive` a `ref event`\r\n * output value socket — a runtime reference to the event instance that is consumed by\r\n * `event/stopPropagation` and validated via `pointer/get` on\r\n * `/extensions/KHR_interactivity/events/{}`. `flow/setDelay` likewise produces a delay reference\r\n * validated via `/extensions/KHR_interactivity/delays/{}`.\r\n *\r\n * A `ref` value is represented as a JSON Pointer string (the empty string acting as the canonical\r\n * \"null\" reference), so both namespaces are expressed as object-model pointers. These formats are\r\n * specific to this extension and are therefore owned here rather than by the FlowGraph engine.\r\n */\r\n\r\n/**\r\n * The JSON Pointer prefix shared by all KHR_interactivity event references.\r\n */\r\nexport const EventReferencePrefix = \"/extensions/KHR_interactivity/events/\";\r\n\r\n/**\r\n * The JSON Pointer prefix shared by all KHR_interactivity delay references.\r\n */\r\nexport const DelayReferencePrefix = \"/extensions/KHR_interactivity/delays/\";\r\n\r\n/**\r\n * Builds the event reference for a FlowGraph event source key.\r\n *\r\n * Lifecycle events use a constant key so that all instances of the same operation return the same\r\n * reference; custom event receivers use their event id so that receivers of the same event compare\r\n * equal under `ref/eq`.\r\n * @param key the FlowGraph event source key\r\n * @returns the event reference string\r\n */\r\nexport function GetEventReference(key: string): string {\r\n    return EventReferencePrefix + key;\r\n}\r\n\r\n/**\r\n * Extracts the FlowGraph event source key from an event reference.\r\n * @param reference the value to decode\r\n * @returns the event source key, or `undefined` when the value is not an event reference\r\n */\r\nexport function GetEventReferenceKey(reference: string): string | undefined {\r\n    return IsEventReference(reference) ? reference.substring(EventReferencePrefix.length) : undefined;\r\n}\r\n\r\n/**\r\n * Returns whether the provided value is a KHR_interactivity event reference, i.e. a non-empty\r\n * string addressing the events object-model namespace.\r\n * @param value the value to test\r\n * @returns true if the value was produced by an event operation as a reference\r\n */\r\nexport function IsEventReference(value: unknown): value is string {\r\n    return typeof value === \"string\" && value.startsWith(EventReferencePrefix);\r\n}\r\n","import { type IKHRInteractivity_Graph, type IKHRInteractivity_Node, type IKHRInteractivity_OutputSocketReference, type IKHRInteractivity_Variable } from \"babylonjs-gltf2interface\";\nimport { type IGLTF } from \"../../glTFLoaderInterfaces\";\nimport {\n    type IGLTFToFlowGraphMapping,\n    type IGLTFToFlowGraphMappingObject,\n    getMappingForDeclaration,\n    getNoOpMappingForDeclaration,\n    HasDefaultInteractivityFlowInput,\n    NormalizeInteractivityEventDataConfiguration,\n    ParseDebugLogTemplate,\n} from \"./declarationMapper\";\nimport { Logger } from \"core/Misc/logger\";\nimport { type ISerializedFlowGraph, type ISerializedFlowGraphBlock, type ISerializedFlowGraphConnection, type ISerializedFlowGraphContext } from \"core/FlowGraph/typeDefinitions\";\nimport { RandomGUID } from \"core/Misc/guid\";\nimport { FlowGraphBlockNames } from \"core/FlowGraph/Blocks/flowGraphBlockNames\";\nimport { FlowGraphConnectionType } from \"core/FlowGraph/flowGraphConnection\";\nimport { type FlowGraph } from \"core/FlowGraph/flowGraph\";\nimport { FlowGraphTypes } from \"core/FlowGraph/flowGraphRichTypes\";\nimport {\n    _CreateKHRInteractivityRuntimeValueSnapshot,\n    CloneKHRInteractivityGraph,\n    CreateEffectiveKHRInteractivityGraph,\n    gltfTypeToBabylonType,\n    KHR_INTERACTIVITY_SPECIFICATION_COMMIT,\n    type IKHRInteractivityBlockProvenance,\n    type IKHRInteractivityConfigurationProvenance,\n    type IKHRInteractivityDeclarationModel,\n    type IKHRInteractivityGraphProvenance,\n    type IKHRInteractivitySocketProvenance,\n} from \"./interactivityGraphModel\";\nimport { DelayReferencePrefix, EventReferencePrefix } from \"./interactivityReferences\";\n\n/**\n * Description of a KHR_interactivity custom event, as parsed from the\n * glTF `events` array. Used by the importer to register the event with the\n * FlowGraph send/receive event blocks.\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport interface InteractivityEvent {\n    /** Identifier of the event, used to match send and receive blocks. */\n    eventId: string;\n    /**\n     * Optional payload schema for the event. Each entry describes one\n     * value carried by the event: an `id` (the FlowGraph data socket name),\n     * a `type` (glTF interactivity type name) and an optional default\n     * `value`. `eventData` (the boolean) is currently unused.\n     */\n    eventData?: {\n        eventData: boolean;\n        id: string;\n        type: string;\n        value?: any;\n    }[];\n}\nexport { gltfTypeToBabylonType } from \"./interactivityGraphModel\";\n\nfunction _GetOwnMapping<T>(mapping: { [name: string]: T } | undefined, key: string): T | undefined {\n    return mapping && Object.prototype.hasOwnProperty.call(mapping, key) ? mapping[key] : undefined;\n}\n\nfunction _CloneMetadataValue<T>(value: T): T {\n    if (Array.isArray(value)) {\n        return value.map((entry) => _CloneMetadataValue(entry)) as T;\n    }\n    if (value !== null && typeof value === \"object\") {\n        const clone: Record<string, unknown> = {};\n        for (const [key, entry] of Object.entries(value)) {\n            Object.defineProperty(clone, key, {\n                configurable: true,\n                enumerable: true,\n                value: _CloneMetadataValue(entry),\n                writable: true,\n            });\n        }\n        return clone as T;\n    }\n    return value;\n}\n\nfunction _IsSerializableConfigurationValue(value: unknown): boolean {\n    return (\n        value === null ||\n        [\"string\", \"number\", \"boolean\"].includes(typeof value) ||\n        (Array.isArray(value) && value.every(_IsSerializableConfigurationValue)) ||\n        (typeof value === \"object\" && Object.values(value as Record<string, unknown>).every(_IsSerializableConfigurationValue))\n    );\n}\n\n/**\n * Captures import-time defaults for unconnected runtime inputs that have no authored KHR socket.\n * @param flowGraph the fully parsed FlowGraph\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function _CaptureKHRInteractivityRuntimeInputDefaults(flowGraph: FlowGraph): void {\n    for (const block of flowGraph.getAllBlocks()) {\n        const provenance = block.metadata?.khrInteractivity as IKHRInteractivityBlockProvenance | undefined;\n        if (!provenance) {\n            continue;\n        }\n        if (Object.prototype.hasOwnProperty.call(provenance.generatedConfiguration ?? {}, \"eventData\")) {\n            provenance.generatedConfigurationRuntime ||= {};\n            if (!Object.prototype.hasOwnProperty.call(provenance.generatedConfigurationRuntime, \"eventData\")) {\n                Object.defineProperty(provenance.generatedConfigurationRuntime, \"eventData\", {\n                    configurable: true,\n                    enumerable: true,\n                    value: _CreateKHRInteractivityRuntimeValueSnapshot(NormalizeInteractivityEventDataConfiguration(block.config?.eventData)),\n                    writable: true,\n                });\n            }\n        }\n        for (const input of block.dataInputs) {\n            if (input.isConnected()) {\n                continue;\n            }\n            const socketProvenance = input.metadata?.khrInteractivity as IKHRInteractivitySocketProvenance | undefined;\n            if (socketProvenance) {\n                socketProvenance.runtimeValueSnapshot ??= _CreateKHRInteractivityRuntimeValueSnapshot((input as any)._defaultValue);\n                continue;\n            }\n            if (provenance.generatedInputDefaults && Object.prototype.hasOwnProperty.call(provenance.generatedInputDefaults, input.name)) {\n                continue;\n            }\n            provenance.generatedInputDefaults ||= {};\n            Object.defineProperty(provenance.generatedInputDefaults, input.name, {\n                configurable: true,\n                enumerable: true,\n                value: _CreateKHRInteractivityRuntimeValueSnapshot((input as any)._defaultValue),\n                writable: true,\n            });\n        }\n    }\n}\n\n/**\n * Parses a KHR_interactivity graph definition (the raw glTF JSON object) into\n * the serialized FlowGraph form consumed by {@link ParseFlowGraphAsync}.\n *\n * The class walks the interactivity types, declarations, variables, events\n * and nodes in order and emits an {@link ISerializedFlowGraph} via\n * {@link serializeToFlowGraph}.\n */\nexport class InteractivityGraphToFlowGraphParser {\n    /**\n     * Note - the graph should be rejected if the same type is defined twice.\n     * We currently don't validate that.\n     */\n    private _types: { length: number; flowGraphType: FlowGraphTypes; elementType: \"number\" | \"boolean\" | \"string\" | \"any\" }[] = [];\n    private _mappings: { flowGraphMapping: IGLTFToFlowGraphMapping; fullOperationName: string; declaration: IKHRInteractivityDeclarationModel }[] = [];\n    private _staticVariables: { type: FlowGraphTypes; value: any[] }[] = [];\n    private _events: InteractivityEvent[] = [];\n    private _internalEventsCounter: number = 0;\n    private _nodes: { blocks: ISerializedFlowGraphBlock[]; fullOperationName: string }[] = [];\n    /**\n     * Extra blocks the parser inserts between existing nodes (e.g. the seconds→frames multiply for\n     * connected animation-time inputs). Kept separate from any node's `blocks` array so per-node\n     * post-processing that indexes into that array (such as the animation extraProcessors targeting\n     * the last block) is not disturbed, then concatenated into the serialized graph.\n     */\n    private _insertedBlocks: ISerializedFlowGraphBlock[] = [];\n\n    constructor(\n        interactivityGraph: IKHRInteractivity_Graph,\n        private _gltf: IGLTF,\n        public _animationTargetFps: number = 60,\n        private _graphIndex: number = 0,\n        private _supportedExtensions?: ReadonlySet<string>,\n        private _declarationModels?: readonly IKHRInteractivityDeclarationModel[],\n        canonicalGraph?: IKHRInteractivity_Graph\n    ) {\n        this._canonicalGraph = CloneKHRInteractivityGraph(canonicalGraph ?? interactivityGraph);\n        this._interactivityGraph = this._declarationModels\n            ? CreateEffectiveKHRInteractivityGraph(interactivityGraph, this._declarationModels, this._gltf.nodes?.length ?? 0)\n            : CloneKHRInteractivityGraph(interactivityGraph);\n        // start with types\n        this._parseTypes();\n        // continue with declarations\n        this._parseDeclarations();\n        this._parseVariables();\n        this._parseEvents();\n        this._parseNodes();\n    }\n\n    private _interactivityGraph: IKHRInteractivity_Graph;\n    private _canonicalGraph: IKHRInteractivity_Graph;\n\n    private get _strictValidation(): boolean {\n        return !!this._declarationModels;\n    }\n\n    private _getAllowedDynamicValueSockets(operation: string, node: IKHRInteractivity_Node, direction: \"input\" | \"output\"): ReadonlySet<string> | undefined {\n        if ((operation === \"debug/log\" || operation === \"flow/log:BABYLON\") && direction === \"input\") {\n            const message = node.configuration?.[operation === \"debug/log\" ? \"message\" : \"messageTemplate\"]?.value?.[0];\n            return new Set(typeof message === \"string\" ? ParseDebugLogTemplate(message).sockets : []);\n        }\n        if ((operation === \"event/send\" && direction === \"input\") || (operation === \"event/receive\" && direction === \"output\")) {\n            const eventIndex = node.configuration?.event?.value?.[0];\n            if (typeof eventIndex === \"number\") {\n                return new Set(Object.keys(this._interactivityGraph.events?.[eventIndex]?.values ?? {}));\n            }\n        }\n        if (operation === \"variable/set\" && direction === \"input\") {\n            return new Set((node.configuration?.variables?.value ?? []).map(String));\n        }\n        if (operation === \"math/switch\" && direction === \"input\") {\n            return new Set((node.configuration?.cases?.value ?? []).map(String));\n        }\n        if ((operation === \"pointer/get\" || operation === \"pointer/set\" || operation === \"pointer/interpolate\") && direction === \"input\") {\n            const pointer = node.configuration?.pointer?.value?.[0];\n            if (typeof pointer === \"string\") {\n                return new Set(\n                    pointer\n                        .split(\"/\")\n                        .filter((segment) => (segment.startsWith(\"[\") && !segment.startsWith(\"[[\")) || (segment.startsWith(\"{\") && !segment.startsWith(\"{{\")))\n                        .map((segment) =>\n                            segment\n                                .substring(1, segment.length - 1)\n                                .replace(/~1/g, \"/\")\n                                .replace(/~0/g, \"~\")\n                        )\n                );\n            }\n        }\n        return undefined;\n    }\n\n    private _getAllowedDynamicFlowSockets(node: IKHRInteractivity_Node, mapping: IGLTFToFlowGraphMapping, direction: \"input\" | \"output\"): ReadonlySet<string> | undefined {\n        for (const [key, property] of Object.entries(mapping.configuration ?? {})) {\n            const generatesSockets = direction === \"input\" ? property.generatesInputFlowSockets : property.generatesOutputFlowSockets;\n            if (!generatesSockets) {\n                continue;\n            }\n            const configuredValues = node.configuration?.[key]?.value;\n            const validValues =\n                configuredValues &&\n                configuredValues.length > 0 &&\n                (property.configurationType !== \"int\" || configuredValues.length === 1) &&\n                configuredValues.every(\n                    (value) => typeof value === \"number\" && Number.isInteger(value) && value >= (property.minimum ?? -2147483648) && value <= (property.maximum ?? 2147483647)\n                );\n            const values = validValues ? configuredValues : property.defaultValue;\n            if (direction === \"input\") {\n                const count = Array.isArray(values) && typeof values[0] === \"number\" ? values[0] : 0;\n                return new Set(Array.from({ length: count }, (_, index) => String(index)));\n            }\n            return new Set(Array.isArray(values) ? values.map(String) : []);\n        }\n        return undefined;\n    }\n\n    public get arrays() {\n        return {\n            types: this._types,\n            mappings: this._mappings,\n            staticVariables: this._staticVariables,\n            events: this._events,\n            nodes: this._nodes,\n        };\n    }\n\n    private _parseTypes() {\n        if (!this._interactivityGraph.types) {\n            return;\n        }\n        for (const type of this._interactivityGraph.types) {\n            this._types.push(gltfTypeToBabylonType[type.signature]);\n        }\n    }\n\n    private _parseDeclarations() {\n        if (!this._interactivityGraph.declarations) {\n            return;\n        }\n        for (let index = 0; index < this._interactivityGraph.declarations.length; index++) {\n            const declaration = this._interactivityGraph.declarations[index];\n            const declarationModel = this._declarationModels?.[index];\n            const extensionEnabled = !declaration.extension || !this._supportedExtensions || this._supportedExtensions.has(declaration.extension);\n            const supportedMapping =\n                declarationModel?.support === \"unsupported-extension\" ? undefined : extensionEnabled ? getMappingForDeclaration(declaration, false) : undefined;\n            if (!supportedMapping && !declaration.extension) {\n                throw new Error(`Unknown core KHR_interactivity operation \"${declaration.op}\".`);\n            }\n            const mapping = supportedMapping ?? (declaration.extension ? getNoOpMappingForDeclaration(declaration) : undefined);\n            if (!mapping) {\n                Logger.Error([\"No mapping found for declaration\", declaration]);\n                throw new Error(\"Error parsing declarations\");\n            }\n            this._mappings.push({\n                flowGraphMapping: mapping,\n                fullOperationName: declaration.extension ? declaration.op + \":\" + declaration.extension : declaration.op,\n                declaration:\n                    declarationModel ??\n                    ({\n                        index,\n                        operation: declaration.extension ? `${declaration.op}:${declaration.extension}` : declaration.op,\n                        support: supportedMapping ? (declaration.extension ? \"extension\" : \"core\") : \"unsupported-extension\",\n                        source: declaration,\n                    } satisfies IKHRInteractivityDeclarationModel),\n            });\n        }\n    }\n\n    private _parseVariables() {\n        if (!this._interactivityGraph.variables) {\n            return;\n        }\n        for (const variable of this._interactivityGraph.variables) {\n            const parsed = this._parseVariable(variable);\n            // set the default values here\n            this._staticVariables.push(parsed);\n        }\n    }\n\n    private _parseVariable(variable: IKHRInteractivity_Variable, dataTransform?: (value: any, parser: InteractivityGraphToFlowGraphParser) => any) {\n        const type = this._types[variable.type];\n        if (!type) {\n            Logger.Error([\"No type found for variable\", variable]);\n            throw new Error(\"Error parsing variables\");\n        }\n        if (variable.value) {\n            if (this._interactivityGraph.types?.[variable.type]?.signature !== \"custom\" && variable.value.length !== type.length) {\n                Logger.Error([\"Invalid value length for variable\", variable, type]);\n                throw new Error(\"Error parsing variables\");\n            }\n        }\n        const value = variable.value ? variable.value.slice() : [];\n        if (!value.length) {\n            switch (type.flowGraphType) {\n                case FlowGraphTypes.Boolean:\n                    value.push(false);\n                    break;\n                case FlowGraphTypes.Integer:\n                    value.push(0);\n                    break;\n                case FlowGraphTypes.Number:\n                    value.push(NaN);\n                    break;\n                case FlowGraphTypes.String:\n                    // Default for a `ref`-typed value is the null reference, encoded as the empty string.\n                    value.push(\"\" as any);\n                    break;\n                case FlowGraphTypes.Vector2:\n                    value.push(NaN, NaN);\n                    break;\n                case FlowGraphTypes.Vector3:\n                    value.push(NaN, NaN, NaN);\n                    break;\n                case FlowGraphTypes.Vector4:\n                case FlowGraphTypes.Matrix2D:\n                case FlowGraphTypes.Quaternion:\n                    value.push(NaN, NaN, NaN, NaN);\n                    break;\n                case FlowGraphTypes.Matrix:\n                    for (let i = 0; i < 16; i++) {\n                        value.push(NaN);\n                    }\n                    break;\n                case FlowGraphTypes.Matrix3D:\n                    for (let i = 0; i < 9; i++) {\n                        value.push(NaN);\n                    }\n                    break;\n                default:\n                    break;\n            }\n        }\n        // in case of NaN, Infinity, we need to parse the string to the object itself\n        if (type.elementType === \"number\" && typeof value[0] === \"string\") {\n            value[0] = parseFloat(value[0]);\n        } else if (type.flowGraphType === FlowGraphTypes.String && typeof value[0] === \"string\") {\n            value[0] = this._normalizeStaticReference(value[0]);\n        }\n        return { type: type.flowGraphType, value: dataTransform ? dataTransform(value, this) : value };\n    }\n\n    private _normalizeStaticReference(reference: string): string {\n        if (!reference || reference.startsWith(EventReferencePrefix) || reference.startsWith(DelayReferencePrefix)) {\n            return \"\";\n        }\n        if (!reference.startsWith(\"/\")) {\n            return \"\";\n        }\n        let current: unknown = this._gltf;\n        for (const rawSegment of reference.substring(1).split(\"/\")) {\n            const segment = rawSegment.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n            if (Array.isArray(current)) {\n                if (!/^(0|[1-9]\\d*)$/.test(segment)) {\n                    return \"\";\n                }\n                current = current[parseInt(segment, 10)];\n            } else if (current !== null && typeof current === \"object\" && Object.prototype.hasOwnProperty.call(current, segment)) {\n                current = (current as Record<string, unknown>)[segment];\n            } else {\n                return \"\";\n            }\n        }\n        return current !== null && typeof current === \"object\" ? reference : \"\";\n    }\n\n    private _parseEvents() {\n        if (!this._interactivityGraph.events) {\n            return;\n        }\n        const eventIds = new Set(this._interactivityGraph.events.flatMap((event) => (event.id === undefined ? [] : [event.id])));\n        const internalPrefix = `__babylon_khr_internal_${this._graphIndex}_`;\n        for (const event of this._interactivityGraph.events) {\n            let generatedEventId: string | undefined;\n            if (event.id === undefined) {\n                do {\n                    generatedEventId = internalPrefix + this._internalEventsCounter++;\n                } while (eventIds.has(generatedEventId));\n                eventIds.add(generatedEventId);\n            }\n            const converted: InteractivityEvent = {\n                eventId: event.id ?? generatedEventId!,\n            };\n            if (event.values) {\n                converted.eventData = Object.keys(event.values).map((key) => {\n                    const eventValue = event.values?.[key];\n                    if (!eventValue) {\n                        Logger.Error([\"No value found for event key\", key]);\n                        throw new Error(\"Error parsing events\");\n                    }\n                    const type = this._types[eventValue.type];\n                    if (!type) {\n                        Logger.Error([\"No type found for event value\", eventValue]);\n                        throw new Error(\"Error parsing events\");\n                    }\n                    const value = typeof eventValue.value !== \"undefined\" ? this._parseVariable(eventValue) : undefined;\n                    return {\n                        id: key,\n                        type: type.flowGraphType,\n                        eventData: true,\n                        value,\n                    };\n                });\n            }\n            this._events.push(converted);\n        }\n    }\n\n    private _parseNodes() {\n        if (!this._interactivityGraph.nodes) {\n            return;\n        }\n        for (let nodeIndex = 0; nodeIndex < this._interactivityGraph.nodes.length; nodeIndex++) {\n            const node = this._interactivityGraph.nodes[nodeIndex];\n            // some validation\n            if (typeof node.declaration !== \"number\") {\n                Logger.Error([\"No declaration found for node\", node]);\n                throw new Error(\"Error parsing nodes\");\n            }\n            const mapping = this._mappings[node.declaration];\n            if (!mapping) {\n                Logger.Error([\"No mapping found for node\", node]);\n                throw new Error(\"Error parsing nodes\");\n            }\n            if (mapping.flowGraphMapping.validation) {\n                const validationResult = mapping.flowGraphMapping.validation(node, this._interactivityGraph, this._gltf);\n                if (!validationResult.valid) {\n                    throw new Error(`Error validating interactivity node ${this._interactivityGraph.declarations?.[node.declaration].op} - ${validationResult.error}`);\n                }\n            }\n            const blocks: ISerializedFlowGraphBlock[] = [];\n            if (mapping.declaration.support === \"unsupported-extension\") {\n                blocks.push(this._createUnsupportedExtensionBlock(node, nodeIndex, mapping));\n            }\n            // create block(s) for this node using the mapping\n            for (let role = 0; role < mapping.flowGraphMapping.blocks.length; role++) {\n                const blockType = mapping.flowGraphMapping.blocks[role];\n                const block = this._getEmptyBlock(blockType, mapping.fullOperationName, nodeIndex, node.declaration, role);\n                this._parseNodeConfiguration(node, block, mapping.flowGraphMapping, blockType);\n                blocks.push(block);\n            }\n            this._nodes.push({ blocks, fullOperationName: mapping.fullOperationName });\n        }\n    }\n\n    private _createBlockProvenance(nodeIndex: number, declarationIndex: number, operation: string, role: number): IKHRInteractivityBlockProvenance {\n        return {\n            graphIndex: this._graphIndex,\n            nodeIndex,\n            declarationIndex,\n            operation,\n            role,\n            sourcePath: `/extensions/KHR_interactivity/graphs/${this._graphIndex}/nodes/${nodeIndex}`,\n        };\n    }\n\n    private _getEmptyBlock(className: string, type: string, nodeIndex?: number, declarationIndex?: number, role?: number): ISerializedFlowGraphBlock {\n        return {\n            uniqueId: RandomGUID(),\n            className,\n            dataInputs: [],\n            dataOutputs: [],\n            signalInputs: [],\n            signalOutputs: [],\n            config: {},\n            type,\n            metadata:\n                nodeIndex === undefined\n                    ? {}\n                    : {\n                          khrInteractivity: this._createBlockProvenance(nodeIndex, declarationIndex!, type, role ?? 0),\n                      },\n        };\n    }\n\n    private _setSocketProvenance(\n        connection: ISerializedFlowGraphConnection,\n        nodeIndex: number,\n        declarationIndex: number,\n        operation: string,\n        role: number,\n        kind: IKHRInteractivitySocketProvenance[\"kind\"],\n        direction: IKHRInteractivitySocketProvenance[\"direction\"],\n        socket: string\n    ): void {\n        connection.metadata = {\n            ...(connection.metadata ?? {}),\n            khrInteractivity: {\n                ...this._createBlockProvenance(nodeIndex, declarationIndex, operation, role),\n                kind,\n                direction,\n                socket,\n            } satisfies IKHRInteractivitySocketProvenance,\n        };\n    }\n\n    private _getBlockRole(blocks: readonly ISerializedFlowGraphBlock[], block: ISerializedFlowGraphBlock): number {\n        return (block.metadata?.khrInteractivity as IKHRInteractivityBlockProvenance | undefined)?.role ?? blocks.indexOf(block);\n    }\n\n    private _createUnsupportedExtensionBlock(\n        node: IKHRInteractivity_Node,\n        nodeIndex: number,\n        mapping: { flowGraphMapping: IGLTFToFlowGraphMapping; fullOperationName: string; declaration: IKHRInteractivityDeclarationModel }\n    ): ISerializedFlowGraphBlock {\n        const block = this._getEmptyBlock(\"KHR_interactivity/FlowGraphUnsupportedInteractivityBlock\", mapping.fullOperationName, nodeIndex, node.declaration, 0);\n        const inputFlowSockets = new Set<string>();\n        for (const sourceNode of this._interactivityGraph.nodes ?? []) {\n            for (const flow of Object.values(sourceNode.flows ?? {})) {\n                if (flow.node === nodeIndex) {\n                    inputFlowSockets.add(flow.socket ?? \"in\");\n                }\n            }\n        }\n        const toSockets = (sockets: typeof mapping.declaration.source.inputValueSockets) =>\n            Object.entries(sockets ?? {}).map(([name, definition]) => ({\n                name,\n                type: this._types[definition.type]?.flowGraphType,\n                signature: this._interactivityGraph.types?.[definition.type]?.signature,\n            }));\n        block.config = {\n            operation: mapping.fullOperationName,\n            inputValueSockets: toSockets(mapping.declaration.source.inputValueSockets),\n            outputValueSockets: toSockets(mapping.declaration.source.outputValueSockets),\n            inputFlowSockets: Array.from(inputFlowSockets).sort(),\n            outputFlowSockets: Object.keys(node.flows ?? {}).sort(),\n        };\n        for (const socket of block.config.inputValueSockets) {\n            const connection = this._createNewSocketConnection(socket.name);\n            this._setSocketProvenance(connection, nodeIndex, node.declaration, mapping.fullOperationName, 0, \"value\", \"input\", socket.name);\n            block.dataInputs.push(connection);\n        }\n        for (const socket of block.config.outputValueSockets) {\n            const connection = this._createNewSocketConnection(socket.name, true);\n            this._setSocketProvenance(connection, nodeIndex, node.declaration, mapping.fullOperationName, 0, \"value\", \"output\", socket.name);\n            block.dataOutputs.push(connection);\n        }\n        for (const socket of block.config.inputFlowSockets) {\n            const connection = this._createNewSocketConnection(socket);\n            this._setSocketProvenance(connection, nodeIndex, node.declaration, mapping.fullOperationName, 0, \"flow\", \"input\", socket);\n            block.signalInputs.push(connection);\n        }\n        for (const socket of block.config.outputFlowSockets) {\n            const connection = this._createNewSocketConnection(socket, true);\n            this._setSocketProvenance(connection, nodeIndex, node.declaration, mapping.fullOperationName, 0, \"flow\", \"output\", socket);\n            block.signalOutputs.push(connection);\n        }\n        return block;\n    }\n\n    private _parseNodeConfiguration(node: IKHRInteractivity_Node, block: ISerializedFlowGraphBlock, nodeMapping: IGLTFToFlowGraphMapping, blockType: FlowGraphBlockNames | string) {\n        const gltfConfiguration = node.configuration;\n        if (gltfConfiguration) {\n            for (const key in gltfConfiguration) {\n                const gltfProperty = gltfConfiguration[key];\n                if (!gltfProperty) {\n                    throw new Error(\"Error parsing node configuration\");\n                }\n\n                const propertyMapping = nodeMapping.configuration?.[key];\n                if (!propertyMapping && this._strictValidation) {\n                    continue;\n                }\n                if (propertyMapping?.validationOnly) {\n                    continue;\n                }\n                const belongsToBlock = propertyMapping && propertyMapping.toBlock ? propertyMapping.toBlock === blockType : nodeMapping.blocks.indexOf(blockType) === 0;\n                if (belongsToBlock) {\n                    let value = propertyMapping?.defaultValue;\n                    if (gltfProperty?.value) {\n                        value = gltfProperty.value;\n                    }\n\n                    if (!propertyMapping?.isArray) {\n                        if (value.length !== 1) {\n                            Logger.Warn(`Invalid non-array value length: ${value.length}`);\n                        }\n\n                        value = value[0];\n                    }\n\n                    if (propertyMapping?.dataTransformer) {\n                        value = propertyMapping.dataTransformer(value, this);\n                    }\n\n                    if (value !== undefined) {\n                        // Update the flow graph block config.\n                        block.config[propertyMapping?.name || key] = {\n                            value: value,\n                        };\n                    }\n                }\n            }\n        }\n    }\n\n    private _parseNodeConnections(context: ISerializedFlowGraphContext) {\n        for (let i = 0; i < this._nodes.length; i++) {\n            // get the corresponding gltf node\n            const gltfNode = this._interactivityGraph.nodes?.[i];\n            if (!gltfNode) {\n                // should never happen but let's still check\n                Logger.Error([\"No node found for interactivity node\", this._nodes[i]]);\n                throw new Error(\"Error parsing node connections\");\n            }\n            const flowGraphBlocks = this._nodes[i];\n            const outputMapper = this._mappings[gltfNode.declaration];\n            // validate\n            if (!outputMapper) {\n                Logger.Error([\"No mapping found for node\", gltfNode]);\n                throw new Error(\"Error parsing node connections\");\n            }\n            // KHR_interactivity spec section 3.2.4 \"Unsupported Operations\":\n            // nodes referring to unsupported operations are demoted to no-ops.\n            // Activations of their input flow sockets are ignored, their output\n            // flow sockets are never activated, and their output value sockets\n            // return constant type-default values. They have no backing\n            // FlowGraph blocks (blocks.length === 0), so there is nothing to\n            // wire for this node — skip all of its connections.\n            if (flowGraphBlocks.blocks.length === 0) {\n                Logger.Warn(`Skipping connections for no-op node #${i} (unsupported operation: ${flowGraphBlocks.fullOperationName})`);\n                continue;\n            }\n            const flowsFromGLTF = gltfNode.flows || {};\n            const flowsKeys = Object.keys(flowsFromGLTF).sort(); // sorting as some operations require sorted keys\n            // connect the flows\n            for (const flowKey of flowsKeys) {\n                const flow = flowsFromGLTF[flowKey];\n                let flowMapping = _GetOwnMapping(outputMapper.flowGraphMapping.outputs?.flows, flowKey);\n                if (this._strictValidation && flowMapping?.compatibilityOnly) {\n                    flowMapping = undefined;\n                }\n                let outputArrayMapping = false;\n                if (!flowMapping) {\n                    for (const key in outputMapper.flowGraphMapping.outputs?.flows) {\n                        if (key.startsWith(\"[\") && key.endsWith(\"]\")) {\n                            const wildcardMapping = outputMapper.flowGraphMapping.outputs?.flows?.[key];\n                            if (!this._strictValidation || !wildcardMapping?.compatibilityOnly) {\n                                outputArrayMapping = true;\n                                flowMapping = wildcardMapping;\n                                break;\n                            }\n                        }\n                    }\n                }\n                const allowedDynamicOutputs = outputArrayMapping ? this._getAllowedDynamicFlowSockets(gltfNode, outputMapper.flowGraphMapping, \"output\") : undefined;\n                if (this._strictValidation && allowedDynamicOutputs && !allowedDynamicOutputs.has(flowKey)) {\n                    flowMapping = undefined;\n                }\n                if (!flowMapping && !this._isUnsupportedExtensionBlock(flowGraphBlocks.blocks[0])) {\n                    continue;\n                }\n                const socketOutName = flowMapping ? (outputArrayMapping ? flowMapping.name.replace(\"$1\", flowKey) : flowMapping.name) : flowKey;\n                // get the input node of this block\n                const inputNodeId = flow.node;\n                const nodeIn = this._nodes[inputNodeId];\n                if (!nodeIn) {\n                    Logger.Error([\"No node found for input node id\", inputNodeId]);\n                    throw new Error(\"Error parsing node connections\");\n                }\n                // Spec 3.2.4: input flow activations on no-op nodes are ignored,\n                // so a flow connection into a no-op target is itself a no-op.\n                // Drop it instead of crashing on the missing target block.\n                if (nodeIn.blocks.length === 0) {\n                    Logger.Warn(`Dropping flow connection from node #${i} \"${flowKey}\" to no-op node #${inputNodeId} (unsupported operation: ${nodeIn.fullOperationName})`);\n                    continue;\n                }\n                // create a serialized socket\n                const block = (flowMapping && flowMapping.toBlock && flowGraphBlocks.blocks.find((b) => b.className === flowMapping.toBlock)) || flowGraphBlocks.blocks[0];\n                const socketOut = block.signalOutputs.find((socket) => socket.name === socketOutName) ?? this._createNewSocketConnection(socketOutName, true);\n                if (!block.signalOutputs.includes(socketOut)) {\n                    block.signalOutputs.push(socketOut);\n                }\n                this._setSocketProvenance(\n                    socketOut,\n                    i,\n                    gltfNode.declaration,\n                    flowGraphBlocks.fullOperationName,\n                    this._getBlockRole(flowGraphBlocks.blocks, block),\n                    \"flow\",\n                    \"output\",\n                    flowKey\n                );\n                // get the mapper for the input node - in case it mapped to multiple blocks\n                const inputMapper = this._mappings[this._interactivityGraph.nodes![inputNodeId].declaration]?.flowGraphMapping;\n                if (!inputMapper) {\n                    Logger.Error([\"No mapping found for input node\", nodeIn]);\n                    throw new Error(\"Error parsing node connections\");\n                }\n                let flowInMapping = _GetOwnMapping(inputMapper.inputs?.flows, flow.socket || \"in\");\n                if (this._strictValidation && flowInMapping?.compatibilityOnly) {\n                    flowInMapping = undefined;\n                }\n                let arrayMapping = false;\n                if (!flowInMapping) {\n                    for (const key in inputMapper.inputs?.flows) {\n                        if (key.startsWith(\"[\") && key.endsWith(\"]\")) {\n                            const wildcardMapping = inputMapper.inputs?.flows?.[key];\n                            if (!this._strictValidation || !wildcardMapping?.compatibilityOnly) {\n                                arrayMapping = true;\n                                flowInMapping = wildcardMapping;\n                            }\n                        }\n                    }\n                    const allowedDynamicInputs = arrayMapping ? this._getAllowedDynamicFlowSockets(this._interactivityGraph.nodes![inputNodeId], inputMapper, \"input\") : undefined;\n                    if (this._strictValidation && allowedDynamicInputs && !allowedDynamicInputs.has(flow.socket ?? \"in\")) {\n                        flowInMapping = undefined;\n                    }\n                    if (!flowInMapping && (flow.socket ?? \"in\") === \"in\" && HasDefaultInteractivityFlowInput(nodeIn.fullOperationName)) {\n                        flowInMapping = { name: \"in\" };\n                    }\n                    if (!flowInMapping && !this._isUnsupportedExtensionBlock(nodeIn.blocks[0])) {\n                        continue;\n                    }\n                }\n                const nodeInSocketName = flowInMapping ? (arrayMapping ? flowInMapping.name.replace(\"$1\", flow.socket || \"\") : flowInMapping.name) : flow.socket || \"in\";\n                const inputBlock = (flowInMapping && flowInMapping.toBlock && nodeIn.blocks.find((b) => b.className === flowInMapping.toBlock)) || nodeIn.blocks[0];\n                // in all of the flow graph input connections, find the one with the same name as the socket\n                let socketIn = inputBlock.signalInputs.find((s) => s.name === nodeInSocketName);\n                // if the socket doesn't exist, create the input socket for the connection\n                if (!socketIn) {\n                    socketIn = this._createNewSocketConnection(nodeInSocketName);\n                    inputBlock.signalInputs.push(socketIn);\n                }\n                this._setSocketProvenance(\n                    socketIn,\n                    inputNodeId,\n                    this._interactivityGraph.nodes![inputNodeId].declaration,\n                    nodeIn.fullOperationName,\n                    this._getBlockRole(nodeIn.blocks, inputBlock),\n                    \"flow\",\n                    \"input\",\n                    flow.socket ?? \"in\"\n                );\n                // connect the sockets\n                socketIn.connectedPointIds.push(socketOut.uniqueId);\n                socketOut.connectedPointIds.push(socketIn.uniqueId);\n            }\n            // connect the values\n            const valuesFromGLTF = gltfNode.values || {};\n            const valuesKeys = Object.keys(valuesFromGLTF);\n            for (const valueKey of valuesKeys) {\n                const value = valuesFromGLTF[valueKey];\n                let valueMapping = _GetOwnMapping(outputMapper.flowGraphMapping.inputs?.values, valueKey);\n                if (this._strictValidation && valueMapping?.compatibilityOnly) {\n                    valueMapping = undefined;\n                }\n                let arrayMapping = false;\n                if (!valueMapping) {\n                    for (const key in outputMapper.flowGraphMapping.inputs?.values) {\n                        if (key.startsWith(\"[\") && key.endsWith(\"]\")) {\n                            const wildcardMapping = outputMapper.flowGraphMapping.inputs?.values?.[key];\n                            if (!this._strictValidation || !wildcardMapping?.compatibilityOnly) {\n                                arrayMapping = true;\n                                valueMapping = wildcardMapping;\n                            }\n                        }\n                    }\n                }\n                const allowedDynamicInputs = arrayMapping ? this._getAllowedDynamicValueSockets(outputMapper.fullOperationName, gltfNode, \"input\") : undefined;\n                if (!valueMapping || (allowedDynamicInputs && !allowedDynamicInputs.has(valueKey))) {\n                    continue;\n                }\n                const socketInName = valueMapping ? (arrayMapping ? valueMapping.name.replace(\"$1\", valueKey) : valueMapping.name) : valueKey;\n                // create a serialized socket\n                const block = (valueMapping && valueMapping.toBlock && flowGraphBlocks.blocks.find((b) => b.className === valueMapping.toBlock)) || flowGraphBlocks.blocks[0];\n                const socketIn = block.dataInputs.find((socket) => socket.name === socketInName) ?? this._createNewSocketConnection(socketInName);\n                if (!block.dataInputs.includes(socketIn)) {\n                    block.dataInputs.push(socketIn);\n                }\n                this._setSocketProvenance(\n                    socketIn,\n                    i,\n                    gltfNode.declaration,\n                    flowGraphBlocks.fullOperationName,\n                    this._getBlockRole(flowGraphBlocks.blocks, block),\n                    \"value\",\n                    \"input\",\n                    valueKey\n                );\n                const socketProvenance = socketIn.metadata!.khrInteractivity as IKHRInteractivitySocketProvenance;\n                socketProvenance.sourceValue = _CloneMetadataValue(this._canonicalGraph.nodes?.[i]?.values?.[valueKey] ?? value);\n                // Captured before the connected branch below shadows `valueMapping`. When set and the\n                // value is supplied by a connection, the seconds→frames `dataTransformer` cannot run\n                // (it is parse-time only), so the raw connected value is scaled by a runtime multiply.\n                const convertConnectedTimeToFrames = !!valueMapping?.convertConnectedTimeToFrames;\n                if ((value as IKHRInteractivity_Variable).value !== undefined) {\n                    const convertedValue = this._parseVariable(value as IKHRInteractivity_Variable, valueMapping && valueMapping.dataTransformer);\n                    context._connectionValues[socketIn.uniqueId] = convertedValue;\n                    socketIn.defaultValue = convertedValue;\n                    socketProvenance.runtimeValue = _CloneMetadataValue(convertedValue.value);\n                } else if (typeof (value as IKHRInteractivity_OutputSocketReference).node !== \"undefined\") {\n                    const nodeOutId = (value as IKHRInteractivity_OutputSocketReference).node;\n                    const nodeOutSocketName = (value as IKHRInteractivity_OutputSocketReference).socket || \"value\";\n                    const nodeOut = this._nodes[nodeOutId];\n                    if (!nodeOut) {\n                        Logger.Error([\"No node found for output socket reference\", value]);\n                        throw new Error(\"Error parsing node connections\");\n                    }\n                    // Spec 3.2.4: output value sockets of no-op nodes return\n                    // constant type-default values. Leave the consumer's\n                    // dataInput unconnected (no connectedPointIds) so the\n                    // FlowGraph runtime falls back to the RichType default.\n                    if (nodeOut.blocks.length === 0) {\n                        Logger.Warn(\n                            `Dropping value connection from no-op node #${nodeOutId} (unsupported operation: ${nodeOut.fullOperationName}) into node #${i} \"${valueKey}\"; consumer will use type-default value`\n                        );\n                        continue;\n                    }\n                    const outputMapper = this._mappings[this._interactivityGraph.nodes![nodeOutId].declaration]?.flowGraphMapping;\n                    if (!outputMapper) {\n                        Logger.Error([\"No mapping found for output socket reference\", value]);\n                        throw new Error(\"Error parsing node connections\");\n                    }\n                    let valueMapping = _GetOwnMapping(outputMapper.outputs?.values, nodeOutSocketName);\n                    if (this._strictValidation && valueMapping?.compatibilityOnly) {\n                        valueMapping = undefined;\n                    }\n                    let arrayMapping = false;\n                    // check if there is an array mapping defined\n                    if (!valueMapping) {\n                        // search for a value mapping that has an array mapping\n                        for (const key in outputMapper.outputs?.values) {\n                            if (key.startsWith(\"[\") && key.endsWith(\"]\")) {\n                                const wildcardMapping = outputMapper.outputs?.values?.[key];\n                                if (!this._strictValidation || !wildcardMapping?.compatibilityOnly) {\n                                    arrayMapping = true;\n                                    valueMapping = wildcardMapping;\n                                }\n                            }\n                        }\n                        const allowedDynamicOutputs = arrayMapping\n                            ? this._getAllowedDynamicValueSockets(nodeOut.fullOperationName, this._interactivityGraph.nodes![nodeOutId], \"output\")\n                            : undefined;\n                        if (!valueMapping || (allowedDynamicOutputs && !allowedDynamicOutputs.has(nodeOutSocketName))) {\n                            continue;\n                        }\n                    }\n                    const socketOutName = valueMapping ? (arrayMapping ? valueMapping.name.replace(\"$1\", nodeOutSocketName) : valueMapping?.name) : nodeOutSocketName;\n                    const outBlock = (valueMapping && valueMapping.toBlock && nodeOut.blocks.find((b) => b.className === valueMapping.toBlock)) || nodeOut.blocks[0];\n                    let socketOut = outBlock.dataOutputs.find((s) => s.name === socketOutName);\n                    // if the socket doesn't exist, create it\n                    if (!socketOut) {\n                        socketOut = this._createNewSocketConnection(socketOutName, true);\n                        outBlock.dataOutputs.push(socketOut);\n                    }\n                    this._setSocketProvenance(\n                        socketOut,\n                        nodeOutId,\n                        this._interactivityGraph.nodes![nodeOutId].declaration,\n                        nodeOut.fullOperationName,\n                        this._getBlockRole(nodeOut.blocks, outBlock),\n                        \"value\",\n                        \"output\",\n                        nodeOutSocketName\n                    );\n                    // connect the sockets\n                    if (convertConnectedTimeToFrames) {\n                        this._connectWithSecondsToFramesConversion(context, socketOut, socketIn, i, gltfNode.declaration, flowGraphBlocks.fullOperationName);\n                    } else {\n                        socketIn.connectedPointIds.push(socketOut.uniqueId);\n                        socketOut.connectedPointIds.push(socketIn.uniqueId);\n                    }\n                } else {\n                    Logger.Error([\"Invalid value for value connection\", value]);\n                    throw new Error(\"Error parsing node connections\");\n                }\n            }\n\n            // inter block connections\n            if (outputMapper.flowGraphMapping.interBlockConnectors) {\n                for (const connector of outputMapper.flowGraphMapping.interBlockConnectors) {\n                    const input = connector.input;\n                    const output = connector.output;\n                    const isVariable = connector.isVariable;\n                    this._connectFlowGraphNodes(input, output, flowGraphBlocks.blocks[connector.inputBlockIndex], flowGraphBlocks.blocks[connector.outputBlockIndex], isVariable);\n                }\n            }\n\n            if (outputMapper.flowGraphMapping.extraProcessor) {\n                const declaration = this._interactivityGraph.declarations?.[gltfNode.declaration];\n                if (!declaration) {\n                    Logger.Error([\"No declaration found for extra processor\", gltfNode]);\n                    throw new Error(\"Error parsing node connections\");\n                }\n                flowGraphBlocks.blocks = outputMapper.flowGraphMapping.extraProcessor(\n                    gltfNode,\n                    declaration,\n                    outputMapper.flowGraphMapping,\n                    this,\n                    flowGraphBlocks.blocks,\n                    context,\n                    this._gltf\n                );\n            }\n            this._ensureMappedSocketProvenance(i, gltfNode, flowGraphBlocks.blocks, outputMapper);\n        }\n    }\n\n    private _ensureMappedSocketProvenance(\n        nodeIndex: number,\n        node: IKHRInteractivity_Node,\n        blocks: ISerializedFlowGraphBlock[],\n        mapping: { flowGraphMapping: IGLTFToFlowGraphMapping; fullOperationName: string }\n    ): void {\n        const ensureConnections = (\n            socketMappings: Record<string, IGLTFToFlowGraphMappingObject> | undefined,\n            kind: IKHRInteractivitySocketProvenance[\"kind\"],\n            direction: IKHRInteractivitySocketProvenance[\"direction\"]\n        ): void => {\n            for (const [sourceName, property] of Object.entries(socketMappings ?? {})) {\n                if ((sourceName.startsWith(\"[\") && sourceName.endsWith(\"]\")) || (this._strictValidation && property.compatibilityOnly)) {\n                    continue;\n                }\n                const block = (property.toBlock && blocks.find((candidate) => candidate.className === property.toBlock)) || blocks[0];\n                if (!block) {\n                    continue;\n                }\n                const connections =\n                    kind === \"value\" ? (direction === \"input\" ? block.dataInputs : block.dataOutputs) : direction === \"input\" ? block.signalInputs : block.signalOutputs;\n                let connection = connections.find((candidate) => candidate.name === property.name);\n                if (!connection) {\n                    connection = this._createNewSocketConnection(property.name, direction === \"output\");\n                    connections.push(connection);\n                }\n                this._setSocketProvenance(connection, nodeIndex, node.declaration, mapping.fullOperationName, this._getBlockRole(blocks, block), kind, direction, sourceName);\n            }\n        };\n\n        ensureConnections(mapping.flowGraphMapping.outputs?.values, \"value\", \"output\");\n        ensureConnections(mapping.flowGraphMapping.inputs?.flows, \"flow\", \"input\");\n        ensureConnections(mapping.flowGraphMapping.outputs?.flows, \"flow\", \"output\");\n        if (HasDefaultInteractivityFlowInput(mapping.fullOperationName)) {\n            const block = blocks[0];\n            if (block) {\n                let connection = block.signalInputs.find((candidate) => candidate.name === \"in\");\n                if (!connection) {\n                    connection = this._createNewSocketConnection(\"in\");\n                    block.signalInputs.push(connection);\n                }\n                this._setSocketProvenance(connection, nodeIndex, node.declaration, mapping.fullOperationName, this._getBlockRole(blocks, block), \"flow\", \"input\", \"in\");\n            }\n        }\n        for (const [sourceKey, property] of Object.entries(mapping.flowGraphMapping.configuration ?? {})) {\n            const block = (property.toBlock && blocks.find((candidate) => candidate.className === property.toBlock)) || blocks[0];\n            const provenance = block?.metadata?.khrInteractivity as IKHRInteractivityBlockProvenance | undefined;\n            if (!block || !provenance) {\n                continue;\n            }\n            const serializedRuntimeValue = block.config?.[property.name];\n            const runtimeValue =\n                serializedRuntimeValue !== null && typeof serializedRuntimeValue === \"object\" && Object.prototype.hasOwnProperty.call(serializedRuntimeValue, \"value\")\n                    ? serializedRuntimeValue.value\n                    : serializedRuntimeValue;\n            provenance.configuration ||= {};\n            const configurationProvenance: IKHRInteractivityConfigurationProvenance = {\n                sourceValue: _CloneMetadataValue(this._canonicalGraph.nodes?.[nodeIndex]?.configuration?.[sourceKey]?.value),\n                runtimeValue: _CloneMetadataValue(runtimeValue),\n            };\n            Object.defineProperty(provenance.configuration, sourceKey, {\n                configurable: true,\n                enumerable: true,\n                value: configurationProvenance,\n                writable: true,\n            });\n        }\n        for (const block of blocks) {\n            const provenance = block.metadata?.khrInteractivity as IKHRInteractivityBlockProvenance | undefined;\n            if (!provenance) {\n                continue;\n            }\n            const mappedConfigurationNames = new Set(\n                Object.values(mapping.flowGraphMapping.configuration ?? {})\n                    .filter((property) => (property.toBlock ? block.className === property.toBlock : provenance.role === 0))\n                    .map((property) => property.name)\n            );\n            const ignoredConfigurationNames = new Set([\"glTF\"]);\n            for (const [key, value] of Object.entries(block.config ?? {})) {\n                if (mappedConfigurationNames.has(key) || ignoredConfigurationNames.has(key)) {\n                    continue;\n                }\n                const normalizedValue =\n                    key === \"eventData\"\n                        ? NormalizeInteractivityEventDataConfiguration(value)\n                        : value !== null && typeof value === \"object\" && Object.prototype.hasOwnProperty.call(value, \"value\")\n                          ? (value as { value: unknown }).value\n                          : value;\n                if (!_IsSerializableConfigurationValue(normalizedValue)) {\n                    continue;\n                }\n                provenance.generatedConfiguration ||= {};\n                Object.defineProperty(provenance.generatedConfiguration, key, {\n                    configurable: true,\n                    enumerable: true,\n                    value: _CloneMetadataValue(normalizedValue),\n                    writable: true,\n                });\n            }\n        }\n    }\n\n    private _createNewSocketConnection(name: string, isOutput?: boolean): ISerializedFlowGraphConnection {\n        return {\n            uniqueId: RandomGUID(),\n            name,\n            _connectionType: isOutput ? FlowGraphConnectionType.Output : FlowGraphConnectionType.Input,\n            connectedPointIds: [],\n        };\n    }\n\n    private _isUnsupportedExtensionBlock(block: ISerializedFlowGraphBlock | undefined): boolean {\n        return block?.className === \"KHR_interactivity/FlowGraphUnsupportedInteractivityBlock\";\n    }\n\n    /**\n     * Wires an upstream data output into a downstream data input through a runtime multiply block that\n     * scales the value by the animation target fps. This converts a KHR animation time (seconds),\n     * delivered by a connection (e.g. a `pointer/get` on the `maxTime` animation pointer), into the\n     * Babylon animation frames expected by the play/stop-animation blocks. Literal times are already\n     * converted at parse time by the input's `dataTransformer`, so this is only used for connections.\n     * @param context the serialized flow graph context that stores literal socket values\n     * @param upstreamOutput the data output socket providing the time value (in seconds)\n     * @param downstreamInput the data input socket that expects the time in frames\n     * @param nodeIndex source node receiving the converted value\n     * @param declarationIndex source declaration used by the receiving node\n     * @param operation owning KHR operation\n     */\n    private _connectWithSecondsToFramesConversion(\n        context: ISerializedFlowGraphContext,\n        upstreamOutput: ISerializedFlowGraphConnection,\n        downstreamInput: ISerializedFlowGraphConnection,\n        nodeIndex: number,\n        declarationIndex: number,\n        operation: string\n    ): void {\n        const multiplyBlock = this._getEmptyBlock(FlowGraphBlockNames.Multiply, operation, nodeIndex, declarationIndex, -1);\n        // Scalar (float) multiply; matches how the `math/mul` mapping configures the block.\n        multiplyBlock.config = { type: FlowGraphTypes.Number };\n        const inputA = this._createNewSocketConnection(\"a\");\n        const inputB = this._createNewSocketConnection(\"b\");\n        const output = this._createNewSocketConnection(\"value\", true);\n        multiplyBlock.dataInputs.push(inputA, inputB);\n        multiplyBlock.dataOutputs.push(output);\n        // The second factor is the constant animation target fps.\n        const frameRateValue = { type: FlowGraphTypes.Number, value: [this._animationTargetFps] };\n        context._connectionValues[inputB.uniqueId] = frameRateValue;\n        inputB.defaultValue = frameRateValue;\n        // upstream time output -> multiply.a\n        inputA.connectedPointIds.push(upstreamOutput.uniqueId);\n        upstreamOutput.connectedPointIds.push(inputA.uniqueId);\n        // multiply.value (frames) -> downstream time input\n        downstreamInput.connectedPointIds.push(output.uniqueId);\n        output.connectedPointIds.push(downstreamInput.uniqueId);\n        // Register the inserted block separately so serializeToFlowGraph picks it up without\n        // appending to any node's block list (which would break per-node extraProcessors).\n        this._insertedBlocks.push(multiplyBlock);\n    }\n\n    private _connectFlowGraphNodes(input: string, output: string, serializedInput: ISerializedFlowGraphBlock, serializedOutput: ISerializedFlowGraphBlock, isVariable?: boolean) {\n        const inputArray = isVariable ? serializedInput.dataInputs : serializedInput.signalInputs;\n        const outputArray = isVariable ? serializedOutput.dataOutputs : serializedOutput.signalOutputs;\n        const inputConnection = inputArray.find((s) => s.name === input) || this._createNewSocketConnection(input);\n        const outputConnection = outputArray.find((s) => s.name === output) || this._createNewSocketConnection(output, true);\n        // of not found add it to the array\n        if (!inputArray.find((s) => s.name === input)) {\n            inputArray.push(inputConnection);\n        }\n        if (!outputArray.find((s) => s.name === output)) {\n            outputArray.push(outputConnection);\n        }\n        // connect the sockets\n        inputConnection.connectedPointIds.push(outputConnection.uniqueId);\n        outputConnection.connectedPointIds.push(inputConnection.uniqueId);\n    }\n\n    /**\n     * Returns the deterministic FlowGraph user-variable name used for the\n     * static variable at the given declaration index.\n     * @param index zero-based index into the interactivity graph's `variables` array.\n     * @returns the FlowGraph variable name (e.g. `staticVariable_3`).\n     */\n    public getVariableName(index: number) {\n        return \"staticVariable_\" + index;\n    }\n\n    /**\n     * Serializes the parsed interactivity graph into the {@link ISerializedFlowGraph}\n     * payload consumed by `ParseFlowGraphAsync`. Performs node-connection wiring\n     * and seeds the execution context with the graph's static variables.\n     * @returns the serialized FlowGraph for the parsed KHR_interactivity graph.\n     */\n    public serializeToFlowGraph(): ISerializedFlowGraph {\n        const context: ISerializedFlowGraphContext = {\n            uniqueId: RandomGUID(),\n            _userVariables: {},\n            _connectionValues: {},\n        };\n        this._parseNodeConnections(context);\n        for (let i = 0; i < this._staticVariables.length; i++) {\n            const variable = this._staticVariables[i];\n            context._userVariables[this.getVariableName(i)] = variable;\n        }\n\n        const allBlocks = this._nodes.reduce((acc, val) => acc.concat(val.blocks), [] as ISerializedFlowGraphBlock[]).concat(this._insertedBlocks);\n\n        return {\n            name: this._interactivityGraph.name ?? `Graph ${this._graphIndex + 1}`,\n            metadata: {\n                khrInteractivity: {\n                    graphIndex: this._graphIndex,\n                    specificationCommit: KHR_INTERACTIVITY_SPECIFICATION_COMMIT,\n                    source: CloneKHRInteractivityGraph(this._canonicalGraph),\n                } satisfies IKHRInteractivityGraphProvenance,\n            },\n            rightHanded: true,\n            allBlocks,\n            executionContexts: [context],\n        };\n    }\n}\n","import { type IObjectInfo, type IPathToObjectConverter } from \"core/ObjectModel/objectModelInterfaces\";\r\n\r\n/**\r\n * Entry in the composite converter's prefix table. The first entry whose\r\n * `prefix` matches the start of the path wins.\r\n */\r\nexport interface IPathConverterPrefixEntry<T> {\r\n    /** Path prefix to match, e.g. `\"/extensions/BABYLON_scene_objects/\"`. */\r\n    prefix: string;\r\n    /** Converter to delegate to when the path starts with `prefix`. */\r\n    converter: IPathToObjectConverter<T>;\r\n}\r\n\r\n/**\r\n * Composite path-to-object converter that dispatches by path prefix.\r\n *\r\n * The KHR_interactivity object model lives at the top of the JSON tree\r\n * (`/nodes/...`, `/materials/...`, `/extensions/...`) and is resolved by\r\n * `GLTFPathToObjectConverter` (see `gltfPathToObjectConverter`).\r\n *\r\n * Babylon-specific extensions can register additional namespaces here\r\n * (for example `/extensions/BABYLON_scene_objects/...` for refs that point\r\n * at scene objects not described by the source glTF) without forcing every\r\n * caller to know about them — `FlowGraphJsonPointerParserBlock` and the\r\n * existing template substitution machinery treat any path uniformly.\r\n *\r\n * Prefix entries are tried in order; if none matches, the fallback converter\r\n * is used. The fallback is typically the glTF converter, since standard\r\n * KHR_interactivity pointer paths sit at the JSON root and have no shared\r\n * prefix that would distinguish them from a missing namespace.\r\n */\r\nexport class CompositePathToObjectConverter<T> implements IPathToObjectConverter<T> {\r\n    /**\r\n     * @param _prefixes prefix-keyed converter table, tried in order\r\n     * @param _fallback converter used when no prefix entry matches\r\n     */\r\n    public constructor(\r\n        private _prefixes: IPathConverterPrefixEntry<T>[],\r\n        private _fallback: IPathToObjectConverter<T>\r\n    ) {}\r\n\r\n    /**\r\n     * Adds a new prefix entry at the front of the lookup list so it is tried\r\n     * before any entries registered earlier. Useful for late-registered\r\n     * loader extensions that want to override or augment a previously\r\n     * registered namespace.\r\n     * @param entry the entry to add\r\n     */\r\n    public addPrefix(entry: IPathConverterPrefixEntry<T>): void {\r\n        this._prefixes.unshift(entry);\r\n    }\r\n\r\n    /**\r\n     * @param path the JSON Pointer path to resolve\r\n     * @returns an object accessor for the resolved property\r\n     */\r\n    public convert(path: string): IObjectInfo<T> {\r\n        for (const { prefix, converter } of this._prefixes) {\r\n            if (path.startsWith(prefix)) {\r\n                return converter.convert(path);\r\n            }\r\n        }\r\n        return this._fallback.convert(path);\r\n    }\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\n\r\nimport { type Scene } from \"core/scene\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type Vector3, Quaternion, type Matrix } from \"core/Maths/math.vector\";\r\nimport { type IObjectAccessor } from \"core/FlowGraph/typeDefinitions\";\r\nimport { type IObjectInfo, type IPathToObjectConverter } from \"core/ObjectModel/objectModelInterfaces\";\r\n\r\n/**\r\n * Root of the JSON-Pointer namespace under which Babylon-scene objects are\r\n * addressed by KHR_interactivity refs that did not originate from the source\r\n * glTF asset (e.g. refs emitted by engine-specific event blocks).\r\n *\r\n * Trailing `/` is intentional: it lets path-prefix dispatchers like\r\n * {@link CompositePathToObjectConverter} match cleanly.\r\n */\r\nexport const BABYLON_SCENE_OBJECT_MODEL_PREFIX = \"/extensions/BABYLON_scene_objects/\";\r\n\r\n/**\r\n * Shape of the Babylon-scene object model tree consumed by\r\n * {@link BabylonScenePathToObjectConverter}. Mirrors `IGLTFObjectModelTree`\r\n * but is rooted at scene-asset arrays (`transformNodes`, `meshes`, …) and\r\n * keyed by Babylon `uniqueId`. Initially we only expose the property leaves\r\n * needed to validate the seam end-to-end; future leaves can be added without\r\n * any path-converter changes.\r\n */\r\nexport interface IBabylonSceneObjectModelTree {\r\n    /**\r\n     *\r\n     */\r\n    transformNodes: IBabylonObjectCollection<TransformNode>;\r\n    /**\r\n     *\r\n     */\r\n    meshes: IBabylonObjectCollection<AbstractMesh>;\r\n    /**\r\n     *\r\n     */\r\n    materials: IBabylonObjectCollection<Material>;\r\n}\r\n\r\n/**\r\n * Generic per-collection node in the tree. `length` exposes a `.length`\r\n * accessor (mirroring glTF). `__array__` is the per-instance leaf hit when a\r\n * uniqueId index appears in the path.\r\n */\r\nexport interface IBabylonObjectCollection<TBabylon> {\r\n    /**\r\n     *\r\n     */\r\n    length: IObjectAccessor<TBabylon[], TBabylon[], number>;\r\n    /**\r\n     *\r\n     */\r\n    __array__: IBabylonObjectLeaves<TBabylon>;\r\n}\r\n\r\n/** Per-instance accessors. Add new properties here as they are needed. */\r\nexport interface IBabylonObjectLeaves<TBabylon> {\r\n    /** Marks this position as a `getTarget` boundary so the resolver can hand back the instance itself. */\r\n    __target__?: boolean;\r\n    /**\r\n     *\r\n     */\r\n    name?: IObjectAccessor<TBabylon, TBabylon, string>;\r\n    /**\r\n     *\r\n     */\r\n    translation?: IObjectAccessor<TBabylon, TBabylon, Vector3>;\r\n    /**\r\n     *\r\n     */\r\n    rotation?: IObjectAccessor<TBabylon, TBabylon, Quaternion>;\r\n    /**\r\n     *\r\n     */\r\n    scale?: IObjectAccessor<TBabylon, TBabylon, Vector3>;\r\n    /**\r\n     *\r\n     */\r\n    matrix?: IObjectAccessor<TBabylon, TBabylon, Matrix>;\r\n    /**\r\n     *\r\n     */\r\n    globalMatrix?: IObjectAccessor<TBabylon, TBabylon, Matrix>;\r\n    /**\r\n     *\r\n     */\r\n    visible?: IObjectAccessor<TBabylon, TBabylon, boolean>;\r\n}\r\n\r\n/**\r\n * Type aliases used internally to keep the per-property accessor signatures\r\n * narrow without forcing every leaf to be re-typed at the use site.\r\n */\r\ntype AnyAccessor = IObjectAccessor<any, any, any>;\r\n\r\n/**\r\n * Resolves JSON Pointer paths in the `/extensions/BABYLON_scene_objects/...`\r\n * namespace to Babylon scene objects.\r\n *\r\n * The path layout is `/{root}/{collection}/{uniqueId}/{property}` where\r\n * `{root}` is the literal `extensions/BABYLON_scene_objects` prefix and\r\n * `{uniqueId}` is the Babylon `uniqueId` (stable per session) of the target\r\n * instance. For example:\r\n *\r\n * - `/extensions/BABYLON_scene_objects/transformNodes/42/translation`\r\n * - `/extensions/BABYLON_scene_objects/meshes/17/visible`\r\n *\r\n * Composite path dispatchers (see {@link CompositePathToObjectConverter})\r\n * route paths starting with the prefix here; everything else continues to be\r\n * resolved by the standard glTF converter.\r\n */\r\nexport class BabylonScenePathToObjectConverter implements IPathToObjectConverter<IObjectAccessor> {\r\n    public constructor(\r\n        private _scene: Scene,\r\n        private _tree: IBabylonSceneObjectModelTree\r\n    ) {}\r\n\r\n    /**\r\n     * @param path the full JSON Pointer (must start with the Babylon prefix)\r\n     * @returns an object-info container holding the resolved instance and accessor\r\n     */\r\n    public convert(path: string): IObjectInfo<IObjectAccessor> {\r\n        if (!path.startsWith(BABYLON_SCENE_OBJECT_MODEL_PREFIX)) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: path \"${path}\" does not start with the expected prefix \"${BABYLON_SCENE_OBJECT_MODEL_PREFIX}\".`);\r\n        }\r\n\r\n        // Strip the namespace prefix and split. Ignore trailing empty segments\r\n        // so refs of the form \"/extensions/BABYLON_scene_objects/transformNodes/42/\" parse cleanly.\r\n        const tail = path.slice(BABYLON_SCENE_OBJECT_MODEL_PREFIX.length);\r\n        const parts = tail.split(\"/\").filter((p) => p.length > 0);\r\n        if (parts.length === 0) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: path \"${path}\" is missing a collection name.`);\r\n        }\r\n\r\n        const collectionName = parts[0];\r\n        const collection = (this._tree as unknown as Record<string, IBabylonObjectCollection<any> | undefined>)[collectionName];\r\n        if (!collection) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: unknown collection \"${collectionName}\" in path \"${path}\".`);\r\n        }\r\n\r\n        // Handle `<collection>.length` (no instance lookup).\r\n        if (parts.length === 2 && parts[1] === \"length\") {\r\n            const arr = this._getCollectionArray(collectionName);\r\n            return { object: arr, info: collection.length as AnyAccessor };\r\n        }\r\n\r\n        if (parts.length < 2) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: path \"${path}\" is missing an instance id.`);\r\n        }\r\n\r\n        // parseInt would accept \"12abc\" as 12; require an all-digits id so a malformed path fails\r\n        // loudly instead of binding to the wrong instance.\r\n        if (!/^\\d+$/.test(parts[1])) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: invalid uniqueId \"${parts[1]}\" in path \"${path}\".`);\r\n        }\r\n        const uniqueId = parseInt(parts[1], 10);\r\n        if (!Number.isFinite(uniqueId) || uniqueId < 0) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: invalid uniqueId \"${parts[1]}\" in path \"${path}\".`);\r\n        }\r\n\r\n        const instance = this._lookupInstanceByUniqueId(collectionName, uniqueId);\r\n        if (!instance) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: no ${collectionName} instance found with uniqueId ${uniqueId} (path \"${path}\").`);\r\n        }\r\n\r\n        // No property after the id → the ref itself is just a handle to the instance.\r\n        // The accessor's `get` and `getTarget` both return the instance.\r\n        if (parts.length === 2) {\r\n            return {\r\n                object: instance,\r\n                info: this._buildIdentityAccessor(instance),\r\n            };\r\n        }\r\n\r\n        // Walk the leaf descriptors for the requested property path. We keep this\r\n        // very simple right now: only one segment after the id is supported, which\r\n        // covers every property the initial leaves expose. Nested paths can be\r\n        // added later by extending the walker.\r\n        if (parts.length > 3) {\r\n            throw new Error(`BabylonScenePathToObjectConverter: nested property paths are not yet supported (path \"${path}\").`);\r\n        }\r\n        const propertyName = parts[2];\r\n        const leaf = (collection.__array__ as Record<string, IObjectAccessor<any, any, any> | boolean | undefined>)[propertyName];\r\n        if (!leaf || typeof leaf === \"boolean\") {\r\n            throw new Error(`BabylonScenePathToObjectConverter: property \"${propertyName}\" is not registered on ${collectionName} (path \"${path}\").`);\r\n        }\r\n\r\n        return {\r\n            object: instance,\r\n            info: leaf as AnyAccessor,\r\n        };\r\n    }\r\n\r\n    private _getCollectionArray(collectionName: string): readonly any[] {\r\n        switch (collectionName) {\r\n            case \"transformNodes\":\r\n                return this._scene.transformNodes;\r\n            case \"meshes\":\r\n                return this._scene.meshes;\r\n            case \"materials\":\r\n                return this._scene.materials;\r\n            default:\r\n                return [];\r\n        }\r\n    }\r\n\r\n    private _lookupInstanceByUniqueId(collectionName: string, uniqueId: number): unknown | undefined {\r\n        switch (collectionName) {\r\n            case \"transformNodes\": {\r\n                const direct = this._scene.transformNodes.find((n) => n.uniqueId === uniqueId);\r\n                if (direct) {\r\n                    return direct;\r\n                }\r\n                // Meshes are also transform nodes; allow the same path to resolve them.\r\n                return this._scene.meshes.find((m) => m.uniqueId === uniqueId);\r\n            }\r\n            case \"meshes\":\r\n                return this._scene.meshes.find((m) => m.uniqueId === uniqueId);\r\n            case \"materials\":\r\n                return this._scene.materials.find((m) => m.uniqueId === uniqueId);\r\n            default:\r\n                return undefined;\r\n        }\r\n    }\r\n\r\n    private _buildIdentityAccessor(instance: unknown): AnyAccessor {\r\n        return {\r\n            type: \"object\",\r\n            get: () => instance,\r\n            getTarget: () => instance,\r\n            isReadOnly: true,\r\n        };\r\n    }\r\n}\r\n\r\n/**\r\n * Builds the default Babylon-scene object-model tree.\r\n *\r\n * We deliberately start with a minimal set of properties: the goal of this\r\n * tree is to prove the seam (refs in the BABYLON namespace resolving through\r\n * the same `FlowGraphJsonPointerParserBlock` that the glTF refs use) without\r\n * committing to a complete property surface in this PR. Add new leaves here\r\n * as concrete event-source operations need them.\r\n * @returns a fresh Babylon-scene object-model tree with the default property surface.\r\n */\r\nexport function CreateDefaultBabylonSceneObjectModelTree(): IBabylonSceneObjectModelTree {\r\n    return {\r\n        transformNodes: {\r\n            length: {\r\n                type: \"number\",\r\n                get: (arr: TransformNode[]) => arr.length,\r\n                getTarget: (arr: TransformNode[]) => arr,\r\n            },\r\n            __array__: {\r\n                __target__: true,\r\n                name: {\r\n                    type: \"string\",\r\n                    get: (n: TransformNode) => n.name,\r\n                    set: (v: string, n: TransformNode) => {\r\n                        n.name = v;\r\n                    },\r\n                    getTarget: (n: TransformNode) => n,\r\n                },\r\n                translation: {\r\n                    type: \"Vector3\",\r\n                    get: (n: TransformNode) => n.position,\r\n                    set: (v: Vector3, n: TransformNode) => n.position.copyFrom(v),\r\n                    getTarget: (n: TransformNode) => n,\r\n                },\r\n                rotation: {\r\n                    type: \"Quaternion\",\r\n                    get: (n: TransformNode) => n.rotationQuaternion ?? Quaternion.RotationYawPitchRoll(n.rotation.y, n.rotation.x, n.rotation.z),\r\n                    set: (v: Quaternion, n: TransformNode) => {\r\n                        if (!n.rotationQuaternion) {\r\n                            n.rotationQuaternion = v.clone();\r\n                        } else {\r\n                            n.rotationQuaternion.copyFrom(v);\r\n                        }\r\n                    },\r\n                    getTarget: (n: TransformNode) => n,\r\n                },\r\n                scale: {\r\n                    type: \"Vector3\",\r\n                    get: (n: TransformNode) => n.scaling,\r\n                    set: (v: Vector3, n: TransformNode) => n.scaling.copyFrom(v),\r\n                    getTarget: (n: TransformNode) => n,\r\n                },\r\n                matrix: {\r\n                    type: \"Matrix\",\r\n                    get: (n: TransformNode) => n.computeWorldMatrix(false),\r\n                    getTarget: (n: TransformNode) => n,\r\n                    isReadOnly: true,\r\n                },\r\n                globalMatrix: {\r\n                    type: \"Matrix\",\r\n                    get: (n: TransformNode) => n.computeWorldMatrix(true),\r\n                    getTarget: (n: TransformNode) => n,\r\n                    isReadOnly: true,\r\n                },\r\n            },\r\n        },\r\n        meshes: {\r\n            length: {\r\n                type: \"number\",\r\n                get: (arr: AbstractMesh[]) => arr.length,\r\n                getTarget: (arr: AbstractMesh[]) => arr,\r\n            },\r\n            __array__: {\r\n                __target__: true,\r\n                name: {\r\n                    type: \"string\",\r\n                    get: (m: AbstractMesh) => m.name,\r\n                    set: (v: string, m: AbstractMesh) => {\r\n                        m.name = v;\r\n                    },\r\n                    getTarget: (m: AbstractMesh) => m,\r\n                },\r\n                visible: {\r\n                    type: \"boolean\",\r\n                    get: (m: AbstractMesh) => m.isVisible,\r\n                    set: (v: boolean, m: AbstractMesh) => {\r\n                        m.isVisible = v;\r\n                    },\r\n                    getTarget: (m: AbstractMesh) => m,\r\n                },\r\n            },\r\n        },\r\n        materials: {\r\n            length: {\r\n                type: \"number\",\r\n                get: (arr: Material[]) => arr.length,\r\n                getTarget: (arr: Material[]) => arr,\r\n            },\r\n            __array__: {\r\n                __target__: true,\r\n                name: {\r\n                    type: \"string\",\r\n                    get: (m: Material) => m.name,\r\n                    set: (v: string, m: Material) => {\r\n                        m.name = v;\r\n                    },\r\n                    getTarget: (m: Material) => m,\r\n                },\r\n            },\r\n        },\r\n    };\r\n}\r\n","import { type IObjectInfo, type IPathToObjectConverter } from \"core/ObjectModel/objectModelInterfaces\";\r\nimport { type IObjectAccessor } from \"core/FlowGraph/typeDefinitions\";\r\nimport { type FlowGraphContext } from \"core/FlowGraph/flowGraphContext\";\r\nimport { FlowGraphInteger } from \"core/FlowGraph/CustomTypes/flowGraphInteger\";\r\nimport { EventReferencePrefix, DelayReferencePrefix } from \"./KHR_interactivity/interactivityReferences\";\r\nimport { IsDelayActive } from \"core/FlowGraph/flowGraphDelayRegistry\";\r\n\r\n/**\r\n * Sentinel target returned by the validity accessors. The KHR_interactivity\r\n * ref-validity pointers are not backed by a glTF object, so the accessor uses a\r\n * non-null sentinel to satisfy callers that expect a truthy target.\r\n */\r\nconst RefValidityTarget = { isKhrInteractivityRef: true };\r\n\r\n/**\r\n * Path-to-object converter that resolves the KHR_interactivity ref-validity\r\n * pointers `pointer/get` can query (KHR_interactivity spec §4.2.3 Event\r\n * References and §4.2.4 Delay References):\r\n *\r\n *  - `/extensions/KHR_interactivity/events/{}` — valid when the input reference\r\n *    was produced by an event operation (an event reference). Stateless: any\r\n *    event-reference path that reaches this converter is valid; a null ref is\r\n *    rejected earlier by the path-template substitution.\r\n *  - `/extensions/KHR_interactivity/delays/{}` — valid only while the referenced\r\n *    delay index is in the runtime active-delay set (i.e. the delay is scheduled\r\n *    and has not yet fired or been cancelled). This requires the runtime\r\n *    {@link FlowGraphContext}, which is supplied to the accessor `get` as its\r\n *    payload argument by `FlowGraphJsonPointerParserBlock`.\r\n *\r\n * On success `get` returns the input reference value (matching the spec, which\r\n * sets the `value` output to the input reference); on failure it returns\r\n * `undefined`, which the `pointer/get` block surfaces as `isValid = false`.\r\n */\r\nexport class InteractivityRefPathToObjectConverter implements IPathToObjectConverter<IObjectAccessor> {\r\n    /**\r\n     * @param path the (template-substituted) JSON Pointer to resolve\r\n     * @returns an object accessor whose `get` validates the reference\r\n     */\r\n    public convert(path: string): IObjectInfo<IObjectAccessor> {\r\n        const isEmptyEventReference = path === EventReferencePrefix;\r\n        const normalized = path.endsWith(\"/\") ? path.slice(0, -1) : path;\r\n\r\n        if (isEmptyEventReference || normalized.startsWith(EventReferencePrefix)) {\r\n            const key = normalized.substring(EventReferencePrefix.length);\r\n            return {\r\n                object: RefValidityTarget,\r\n                info: {\r\n                    type: \"object\",\r\n                    isReadOnly: true,\r\n                    // A non-empty key means a real event reference was supplied (the\r\n                    // template substitution rejects null refs before we get here).\r\n                    get: () => (isEmptyEventReference ? path : key.length > 0 ? normalized : undefined),\r\n                    getTarget: () => RefValidityTarget,\r\n                },\r\n            };\r\n        }\r\n\r\n        // Delay reference: the substituted segment is the integer delay index. parseInt is too lenient\r\n        // (it would accept \"1abc\" as 1), so require an all-digits segment before converting.\r\n        const rawIndex = normalized.substring(DelayReferencePrefix.length);\r\n        const index = /^\\d+$/.test(rawIndex) ? parseInt(rawIndex, 10) : NaN;\r\n        return {\r\n            object: RefValidityTarget,\r\n            info: {\r\n                type: \"object\",\r\n                isReadOnly: true,\r\n                get: (_target: unknown, _index?: number, payload?: unknown) => {\r\n                    const context = payload as FlowGraphContext | undefined;\r\n                    if (!context || isNaN(index) || index < 0) {\r\n                        return undefined;\r\n                    }\r\n                    return IsDelayActive(context, index) ? new FlowGraphInteger(index) : undefined;\r\n                },\r\n                getTarget: () => RefValidityTarget,\r\n            },\r\n        };\r\n    }\r\n}\r\n","import { type IObjectInfo, type IPathToObjectConverter } from \"core/ObjectModel/objectModelInterfaces\";\r\nimport { type IObjectAccessor } from \"core/FlowGraph/typeDefinitions\";\r\nimport { type IGLTF } from \"../glTFLoaderInterfaces\";\r\n\r\n/**\r\n * Path prefix of the KHR_interactivity asset-capability pointers (spec §4.1 Asset Capabilities).\r\n */\r\nexport const InteractivityAssetCapabilitiesPrefix = \"/extensions/KHR_interactivity/asset/\";\r\n\r\n/**\r\n * Path prefix of the KHR_interactivity runtime-limit pointers (spec §4.2 Implementation-Specific Runtime Limits).\r\n */\r\nexport const InteractivityLimitsPrefix = \"/extensions/KHR_interactivity/limits/\";\r\n\r\n/**\r\n * Highest glTF version this loader can present an asset with.\r\n */\r\nconst MaxSupportedGltfVersion = { major: 2, minor: 0 };\r\n\r\n/**\r\n * The spec allows an implementation to report the maximum `int` value for a runtime limit it does not enforce or\r\n * does not want to disclose. Babylon imposes no hard cap on any of these features.\r\n */\r\nconst UndisclosedRuntimeLimit = 2147483647;\r\n\r\nconst RuntimeLimits: Record<string, number> = {\r\n    maxActiveAnimations: UndisclosedRuntimeLimit,\r\n    maxActiveDelays: UndisclosedRuntimeLimit,\r\n    maxActivePropertyInterpolations: UndisclosedRuntimeLimit,\r\n    maxActiveVariableInterpolations: UndisclosedRuntimeLimit,\r\n};\r\n\r\n/**\r\n * Sentinel target returned by the asset-capability accessors. These pointers are virtual and are not backed by a\r\n * glTF object, so the accessor uses a non-null sentinel to satisfy callers that expect a truthy target.\r\n */\r\nconst AssetCapabilityTarget = { isKhrInteractivityAssetCapability: true };\r\n\r\n/**\r\n * Resolves the glTF version the asset is presented with: the minimum of the version declared in the glTF JSON and\r\n * the maximum version this implementation supports.\r\n * @param version the `asset.version` string from the glTF JSON\r\n * @returns the effective major and minor version components\r\n */\r\nfunction GetEffectiveGltfVersion(version: string | undefined): { major: number; minor: number } {\r\n    const [rawMajor, rawMinor] = (version ?? \"\").split(\".\");\r\n    const major = parseInt(rawMajor, 10);\r\n    const minor = parseInt(rawMinor, 10);\r\n    if (isNaN(major)) {\r\n        return MaxSupportedGltfVersion;\r\n    }\r\n    if (major !== MaxSupportedGltfVersion.major) {\r\n        return major < MaxSupportedGltfVersion.major ? { major, minor: isNaN(minor) ? 0 : minor } : MaxSupportedGltfVersion;\r\n    }\r\n    return { major, minor: Math.min(isNaN(minor) ? 0 : minor, MaxSupportedGltfVersion.minor) };\r\n}\r\n\r\n/**\r\n * Path-to-object converter that resolves the virtual KHR_interactivity pointers describing the capabilities of the\r\n * asset and of the implementation running it:\r\n *\r\n *  - `/extensions/KHR_interactivity/asset/majorVersion` and `.../minorVersion` — the glTF version the asset is\r\n *    presented with.\r\n *  - `/extensions/KHR_interactivity/asset/extensions/<EXTENSION_NAME>/enabled` — whether the extension is both\r\n *    listed in `extensionsUsed` and supported by this loader. Reading an extension that is not used or not\r\n *    supported resolves successfully and yields `false`, so a behavior graph can branch on extension support.\r\n *  - `/extensions/KHR_interactivity/limits/<LIMIT_NAME>` — the implementation-specific runtime limits.\r\n *\r\n * All of these are read-only.\r\n */\r\nexport class InteractivityAssetPathToObjectConverter implements IPathToObjectConverter<IObjectAccessor> {\r\n    /**\r\n     * @param _gltf the loaded glTF, used to read the asset version\r\n     * @param _isExtensionEnabled predicate telling whether a glTF extension is both used by the asset and supported\r\n     * by this loader\r\n     */\r\n    public constructor(\r\n        private _gltf: IGLTF,\r\n        private _isExtensionEnabled: (name: string) => boolean\r\n    ) {}\r\n\r\n    /**\r\n     * @param path the JSON Pointer to resolve\r\n     * @returns an object accessor for the addressed capability\r\n     * @throws if the path does not address a known capability, which `pointer/get` surfaces as `isValid = false`\r\n     */\r\n    public convert(path: string): IObjectInfo<IObjectAccessor> {\r\n        const normalized = path.endsWith(\"/\") ? path.slice(0, -1) : path;\r\n\r\n        if (normalized.startsWith(InteractivityLimitsPrefix)) {\r\n            const limit = RuntimeLimits[normalized.substring(InteractivityLimitsPrefix.length)];\r\n            if (limit === undefined) {\r\n                throw new Error(`Path ${path} is invalid`);\r\n            }\r\n            return this._createAccessor(\"number\", () => limit);\r\n        }\r\n\r\n        const capability = normalized.substring(InteractivityAssetCapabilitiesPrefix.length);\r\n        if (capability === \"majorVersion\" || capability === \"minorVersion\") {\r\n            return this._createAccessor(\"number\", () => GetEffectiveGltfVersion(this._gltf.asset?.version)[capability === \"majorVersion\" ? \"major\" : \"minor\"]);\r\n        }\r\n\r\n        // `extensions/<EXTENSION_NAME>/enabled`. The extension name itself may not contain a slash.\r\n        const segments = capability.split(\"/\");\r\n        if (segments.length === 3 && segments[0] === \"extensions\" && segments[2] === \"enabled\") {\r\n            const extensionName = segments[1];\r\n            return this._createAccessor(\"boolean\", () => this._isExtensionEnabled(extensionName));\r\n        }\r\n\r\n        throw new Error(`Path ${path} is invalid`);\r\n    }\r\n\r\n    private _createAccessor(type: string, get: () => number | boolean): IObjectInfo<IObjectAccessor> {\r\n        return {\r\n            object: AssetCapabilityTarget,\r\n            info: {\r\n                type,\r\n                isReadOnly: true,\r\n                get,\r\n                getTarget: () => AssetCapabilityTarget,\r\n            },\r\n        };\r\n    }\r\n}\r\n","import { type IFlowGraphHostResolver } from \"core/FlowGraph/flowGraphHostResolver\";\r\nimport { GetEventReference, GetEventReferenceKey } from \"./interactivityReferences\";\r\n\r\n/**\r\n * Supplies the KHR_interactivity representation of opaque `ref` values to the FlowGraph engine.\r\n *\r\n * The engine itself has no notion of the glTF object model: it asks this resolver how to represent\r\n * event sources and runtime objects as references, and how to read one back.\r\n */\r\nexport class InteractivityHostResolver implements IFlowGraphHostResolver {\r\n    /**\r\n     * @param key the FlowGraph event source key\r\n     * @returns the KHR_interactivity event reference\r\n     */\r\n    public encodeEventReference(key: string): string {\r\n        return GetEventReference(key);\r\n    }\r\n\r\n    /**\r\n     * @param reference the value to decode\r\n     * @returns the FlowGraph event source key, or `undefined` when the value is not an event reference\r\n     */\r\n    public decodeEventReference(reference: string): string | undefined {\r\n        return GetEventReferenceKey(reference);\r\n    }\r\n\r\n    /**\r\n     * @param reference the reference to decode\r\n     * @param collection optional glTF root collection the reference must address\r\n     * @returns the index the reference denotes, or `undefined` when it is not an indexed JSON Pointer\r\n     */\r\n    public decodeIndexReference(reference: string, collection?: string): number | undefined {\r\n        if (reference.length === 0 || reference[0] !== \"/\") {\r\n            return undefined;\r\n        }\r\n        const prefix = collection ? `/${collection}/` : \"/\";\r\n        if (!reference.startsWith(prefix)) {\r\n            return undefined;\r\n        }\r\n        const tail = collection ? reference.substring(prefix.length) : reference.substring(reference.lastIndexOf(\"/\") + 1);\r\n        // RFC 6901 array indices are unsigned decimal integers with no leading zeros, so reject\r\n        // anything else rather than letting `Number` accept \"0x2\", \"1e1\" or \" 3\".\r\n        if (!/^(0|[1-9]\\d*)$/.test(tail)) {\r\n            return undefined;\r\n        }\r\n        return parseInt(tail, 10);\r\n    }\r\n\r\n    /**\r\n     * Maps a Babylon object loaded from the glTF back to a JSON Pointer addressing it.\r\n     *\r\n     * The glTF loader stamps `_internalMetadata.gltf.pointers` with one entry per JSON Pointer the\r\n     * object can be addressed by; a single-primitive mesh, for example, holds both `/nodes/<i>` and\r\n     * `/meshes/<j>/primitives/<k>`. The hint is the path segment preceding the template parameter\r\n     * being resolved, so a template like `/nodes/{nodeRef}/globalMatrix` picks the `/nodes/<i>`\r\n     * pointer even when another pointer was added to the object first.\r\n     * @param object the Babylon object to address\r\n     * @param hint the expected root segment of the pointer, when known\r\n     * @returns the JSON Pointer for the object, or `undefined` when it is not addressable\r\n     */\r\n    public getObjectReference(object: object, hint?: string): string | undefined {\r\n        const pointers = (object as { _internalMetadata?: { gltf?: { pointers?: unknown } } })._internalMetadata?.gltf?.pointers;\r\n        if (!Array.isArray(pointers)) {\r\n            return undefined;\r\n        }\r\n        const stringPointers = pointers.filter((pointer: unknown): pointer is string => typeof pointer === \"string\");\r\n        if (stringPointers.length === 0) {\r\n            return undefined;\r\n        }\r\n        if (hint) {\r\n            const match = stringPointers.find((pointer) => pointer.split(\"/\")[1] === hint);\r\n            if (match) {\r\n                return match;\r\n            }\r\n        }\r\n        return stringPointers[0];\r\n    }\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport {\n    type IKHRInteractivity,\n    type IKHRInteractivity_Configuration,\n    type IKHRInteractivity_Graph,\n    type IKHRInteractivity_Node,\n    type IKHRInteractivity_OutputSocketReference,\n    type IKHRInteractivity_Variable,\n} from \"babylonjs-gltf2interface\";\nimport { type AnimationGroup } from \"core/Animations/animationGroup\";\nimport { type FlowGraph } from \"core/FlowGraph/flowGraph\";\nimport { type FlowGraphBlock } from \"core/FlowGraph/flowGraphBlock\";\nimport { type FlowGraphDataConnection } from \"core/FlowGraph/flowGraphDataConnection.pure\";\nimport { FlowGraphExecutionBlock } from \"core/FlowGraph/flowGraphExecutionBlock\";\nimport { type FlowGraphSignalConnection } from \"core/FlowGraph/flowGraphSignalConnection.pure\";\nimport { FlowGraphTypes } from \"core/FlowGraph/flowGraphRichTypes.pure\";\nimport { type Material } from \"core/Materials/material\";\nimport { type Node } from \"core/node\";\nimport { type Camera } from \"core/Cameras/camera\";\nimport { Matrix } from \"core/Maths/math.vector.pure\";\nimport { type IGLTF } from \"../../glTFLoaderInterfaces\";\nimport {\n    GetInteractivityOperationRegistry,\n    getMappingForDeclaration,\n    HasDefaultInteractivityFlowInput,\n    NormalizeInteractivityEventDataConfiguration,\n    ParseDebugLogTemplate,\n    type IGLTFToFlowGraphMapping,\n    type IGLTFToFlowGraphMappingObject,\n} from \"./declarationMapper\";\nimport {\n    _CreateKHRInteractivityRuntimeValueSnapshot,\n    _NormalizeKHRInteractivityRuntimeValue,\n    CloneKHRInteractivityGraph,\n    CreateKHRInteractivityGraphModel,\n    gltfTypeToBabylonType,\n    type IKHRInteractivityBlockProvenance,\n    type IKHRInteractivityConfigurationProvenance,\n    type IKHRInteractivityDocument,\n    type IKHRInteractivityGraphProvenance,\n    type IKHRInteractivitySocketProvenance,\n} from \"./interactivityGraphModel\";\n\n/**\n * Export support classification for a FlowGraph block or imported composite.\n */\nexport type KHRInteractivityExportClassification = \"exact\" | \"inverse-composite\" | \"unsupported\" | \"lossy\";\n\n/**\n * Structured KHR_interactivity export diagnostic.\n */\nexport interface IKHRInteractivityExportDiagnostic {\n    /** Stable diagnostic code. */\n    code:\n        | \"GRAPH_SOURCE_MISSING\"\n        | \"GRAPH_COUNT_MISMATCH\"\n        | \"NODE_SOURCE_MISSING\"\n        | \"BLOCK_PROVENANCE_INVALID\"\n        | \"BLOCK_ROLE_MISSING\"\n        | \"BLOCK_ROLE_DUPLICATE\"\n        | \"BLOCK_TYPE_MISMATCH\"\n        | \"BLOCK_UNSUPPORTED\"\n        | \"BLOCK_AMBIGUOUS\"\n        | \"COMPOSITE_CONNECTION_CHANGED\"\n        | \"SOCKET_PROVENANCE_MISSING\"\n        | \"SOCKET_CONNECTION_AMBIGUOUS\"\n        | \"SOCKET_TARGET_UNREPRESENTABLE\"\n        | \"INPUT_DEFAULT_UNREPRESENTABLE\"\n        | \"VALUE_UNREPRESENTABLE\"\n        | \"CONFIGURATION_UNREPRESENTABLE\"\n        | \"REFERENCE_UNRESOLVED\"\n        | \"DEPENDENCY_CYCLE\"\n        | \"GRAPH_INVALID\";\n    /** JSON pointer or FlowGraph location associated with the issue. */\n    path: string;\n    /** Human-readable actionable diagnostic. */\n    message: string;\n    /** Diagnostic severity. */\n    severity: \"error\" | \"warning\";\n    /** Source graph index, when known. */\n    graphIndex?: number;\n    /** Source node index, when known. */\n    nodeIndex?: number;\n    /** FlowGraph block id, when known. */\n    blockId?: string;\n    /** KHR socket id, when known. */\n    socket?: string;\n}\n\n/**\n * Representability result for one logical KHR node or standalone FlowGraph block.\n */\nexport interface IKHRInteractivityNodeExportAnalysis {\n    /** Source graph index. */\n    graphIndex: number;\n    /** Source KHR node index, when this is an imported node. */\n    nodeIndex?: number;\n    /** Full KHR operation name, when known. */\n    operation?: string;\n    /** FlowGraph blocks participating in this logical node. */\n    blockIds: string[];\n    /** Export support classification. */\n    classification: KHRInteractivityExportClassification;\n    /** Diagnostics scoped to this logical node. */\n    diagnostics: IKHRInteractivityExportDiagnostic[];\n}\n\n/**\n * Complete representability analysis for a KHR_interactivity export.\n */\nexport interface IKHRInteractivityExportAnalysis {\n    /** True when every graph can be exported without loss or ambiguity. */\n    representable: boolean;\n    /** Per-node classifications in deterministic graph/source order. */\n    nodes: IKHRInteractivityNodeExportAnalysis[];\n    /** All diagnostics in deterministic order. */\n    diagnostics: IKHRInteractivityExportDiagnostic[];\n}\n\n/**\n * Indexed glTF root collections that KHR_interactivity references can target.\n */\nexport type KhrInteractivityRootCollection = \"nodes\" | \"animations\" | \"cameras\" | \"materials\" | \"meshes\" | \"textures\" | \"images\" | \"samplers\" | \"skins\" | \"scenes\";\n\n/**\n * Final glTF remapping context supplied by the serializer extension.\n */\nexport interface IKHRInteractivitySerializerContext {\n    /**\n     * Gets the final number of glTF nodes.\n     * @returns final glTF node count\n     */\n    getNodeCount(): number;\n    /**\n     * Gets the final glTF node index for a Babylon node.\n     * @param node Babylon node to resolve\n     * @returns final glTF node index, or undefined when the node was not exported\n     */\n    getNodeIndex(node: Node): number | undefined;\n    /**\n     * Gets the final glTF animation index for a Babylon animation group.\n     * @param animation Babylon animation group to resolve\n     * @returns final glTF animation index, or undefined when the animation was not exported\n     */\n    getAnimationIndex(animation: AnimationGroup): number | undefined;\n    /**\n     * Gets the final glTF camera index for a Babylon camera.\n     * @param camera Babylon camera to resolve\n     * @returns final glTF camera index, or undefined when the camera was not exported\n     */\n    getCameraIndex(camera: Camera): number | undefined;\n    /**\n     * Gets the final glTF material index for a Babylon material.\n     * @param material Babylon material to resolve\n     * @returns final glTF material index, or undefined when the material was not exported\n     */\n    getMaterialIndex(material: Material): number | undefined;\n    /**\n     * Gets the final glTF index for an imported Babylon entity in a root collection.\n     * @param collection target glTF root collection\n     * @param entity imported Babylon entity associated with the source entry\n     * @returns final glTF index, or undefined when the entity was not exported uniquely\n     */\n    getRootIndex?(collection: KhrInteractivityRootCollection, entity: object): number | undefined;\n    /**\n     * Writes a companion extension on an already-exported glTF node.\n     * @param nodeIndex final glTF node index\n     * @param extensionName companion extension name\n     * @param value companion extension payload\n     */\n    setNodeExtension(nodeIndex: number, extensionName: string, value: unknown): void;\n}\n\n/**\n * Provider consumed by the KHR_interactivity serializer extension.\n */\nexport interface IKHRInteractivityExportProvider {\n    /** Whether KHR_interactivity must be listed in extensionsRequired. */\n    readonly required: boolean;\n    /** Other extensions referenced or emitted by the interactivity export. */\n    readonly additionalExtensionsUsed: readonly string[];\n    /** Other extensions that must be listed in extensionsRequired. */\n    readonly additionalExtensionsRequired: readonly string[];\n    /**\n     * Gets the detached representability analysis.\n     * @returns current export analysis\n     */\n    analyze(): IKHRInteractivityExportAnalysis;\n    /**\n     * Builds the canonical extension after glTF entity indices are finalized.\n     * @param context final serializer remapping context\n     * @returns ratified KHR_interactivity extension payload\n     */\n    build(context: IKHRInteractivitySerializerContext): IKHRInteractivity;\n}\n\n/**\n * Options used to create a KHR_interactivity export plan.\n */\nexport interface IKHRInteractivityExportOptions {\n    /** Canonical Phase 1 document associated with the FlowGraphs. Required for a lossless export. */\n    document?: IKHRInteractivityDocument;\n    /** Loader glTF tree used to resolve original entity references. */\n    sourceGLTF?: IGLTF;\n    /** Root default graph index. Defaults to the canonical document selection or zero. */\n    defaultGraphIndex?: number;\n    /** Target animation frame rate used by imported animation composites. Defaults to 60. */\n    targetFps?: number;\n    /** Whether the emitted KHR_interactivity extension is required. Defaults to true. */\n    required?: boolean;\n    /** Additional extensions that must be required together with the behavior graph. */\n    additionalExtensionsRequired?: readonly string[];\n}\n\n/**\n * Error thrown when export cannot preserve the authored behavior graph.\n */\nexport class KHRInteractivityExportError extends Error {\n    /**\n     * @param diagnostics precise export diagnostics\n     */\n    public constructor(public readonly diagnostics: readonly IKHRInteractivityExportDiagnostic[]) {\n        super(diagnostics.map((diagnostic) => `${diagnostic.path}: ${diagnostic.message}`).join(\"\\n\"));\n        this.name = \"KHRInteractivityExportError\";\n    }\n}\n\ninterface ILogicalNode {\n    sourceIndex: number;\n    declarationIndex: number;\n    operation: string;\n    mapping?: IGLTFToFlowGraphMapping;\n    blocks: readonly FlowGraphBlock[];\n    classification: KHRInteractivityExportClassification;\n    diagnostics: IKHRInteractivityExportDiagnostic[];\n}\n\ninterface IGraphAnalysis {\n    graph: FlowGraph;\n    graphIndex: number;\n    source: IKHRInteractivity_Graph;\n    nodes: ILogicalNode[];\n    diagnostics: IKHRInteractivityExportDiagnostic[];\n}\n\ninterface IOrderedNodes {\n    nodes: IKHRInteractivity_Node[];\n    sourceIndices: number[];\n}\n\nconst _KnownIndexedRootCollections = new Set<string>([\"nodes\", \"animations\", \"cameras\", \"materials\", \"meshes\", \"textures\", \"images\", \"samplers\", \"skins\", \"scenes\"]);\nconst _UnsupportedBlockClassName = \"FlowGraphUnsupportedInteractivityBlock\";\nconst _CompanionNodeExtensions = [\"KHR_node_hoverability\", \"KHR_node_selectability\", \"KHR_node_visibility\"] as const;\n\nfunction _GetPointerExtensionNames(pointer: string): string[] {\n    const segments = pointer.split(\"/\").map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n    const extensions: string[] = [];\n    for (let index = 0; index < segments.length - 1; index++) {\n        if (segments[index] === \"extensions\" && segments[index + 1]) {\n            extensions.push(segments[index + 1]);\n        }\n    }\n    return extensions;\n}\n\nfunction _CanPreserveNestedExtensionPointer(pointer: string, resolvedCollection?: string): boolean {\n    const segments = pointer.split(\"/\").map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n    const extensionIndex = segments.indexOf(\"extensions\");\n    return (\n        extensionIndex > 1 &&\n        (resolvedCollection ?? segments[1]) === \"nodes\" &&\n        _CompanionNodeExtensions.includes(segments[extensionIndex + 1] as (typeof _CompanionNodeExtensions)[number])\n    );\n}\nconst _FlowGraphTypeToKHRSignature: Readonly<Record<string, string>> = {\n    [FlowGraphTypes.Number]: \"float\",\n    [FlowGraphTypes.Boolean]: \"bool\",\n    [FlowGraphTypes.Integer]: \"int\",\n    [FlowGraphTypes.String]: \"ref\",\n    [FlowGraphTypes.Vector2]: \"float2\",\n    [FlowGraphTypes.Vector3]: \"float3\",\n    [FlowGraphTypes.Vector4]: \"float4\",\n    [FlowGraphTypes.Quaternion]: \"float4\",\n    [FlowGraphTypes.Color3]: \"float3\",\n    [FlowGraphTypes.Color4]: \"float4\",\n    [FlowGraphTypes.Matrix2D]: \"float2x2\",\n    [FlowGraphTypes.Matrix3D]: \"float3x3\",\n    [FlowGraphTypes.Matrix]: \"float4x4\",\n    Mesh: \"ref\",\n    TransformNode: \"ref\",\n    Camera: \"ref\",\n    Light: \"ref\",\n    Material: \"ref\",\n    AnimationGroup: \"ref\",\n};\n\nfunction _CloneJson<T>(value: T): T {\n    if (Array.isArray(value)) {\n        return value.map((entry) => _CloneJson(entry)) as T;\n    }\n    if (value !== null && typeof value === \"object\") {\n        const clone: Record<string, unknown> = {};\n        for (const [key, entry] of Object.entries(value)) {\n            Object.defineProperty(clone, key, {\n                configurable: true,\n                enumerable: true,\n                value: _CloneJson(entry),\n                writable: true,\n            });\n        }\n        return clone as T;\n    }\n    return value;\n}\n\nfunction _GetBlockProvenance(block: FlowGraphBlock): IKHRInteractivityBlockProvenance | undefined {\n    return block.metadata?.khrInteractivity as IKHRInteractivityBlockProvenance | undefined;\n}\n\nfunction _GetSocketProvenance(connection: FlowGraphDataConnection<any> | FlowGraphSignalConnection): IKHRInteractivitySocketProvenance | undefined {\n    return connection.metadata?.khrInteractivity as IKHRInteractivitySocketProvenance | undefined;\n}\n\nfunction _GetOwn<T>(dictionary: Record<string, T> | undefined, key: string): T | undefined {\n    return dictionary && Object.prototype.hasOwnProperty.call(dictionary, key) ? dictionary[key] : undefined;\n}\n\nfunction _FullOperationName(op: string, extension?: string): string {\n    return extension ? `${op}:${extension}` : op;\n}\n\nfunction _RuntimeBlockClassName(className: string): string {\n    return className.substring(className.lastIndexOf(\"/\") + 1);\n}\n\nfunction _GetRoleBlock(blocks: readonly FlowGraphBlock[], role: number): FlowGraphBlock | undefined {\n    return blocks.find((block) => _GetBlockProvenance(block)?.role === role);\n}\n\nfunction _FindDataInput(blocks: readonly FlowGraphBlock[], nodeIndex: number, socket: string): FlowGraphDataConnection<any> | undefined {\n    for (const block of blocks) {\n        for (const input of block.dataInputs) {\n            const provenance = _GetSocketProvenance(input);\n            if (provenance?.nodeIndex === nodeIndex && provenance.kind === \"value\" && provenance.direction === \"input\" && provenance.socket === socket) {\n                return input;\n            }\n        }\n    }\n    return undefined;\n}\n\nfunction _NormalizeValue(value: unknown): unknown[] | undefined {\n    return _NormalizeKHRInteractivityRuntimeValue(value);\n}\n\nfunction _CreateTypedRuntimeValueSnapshot(\n    graph: IKHRInteractivity_Graph,\n    type: number | undefined,\n    value: unknown\n): ReturnType<typeof _CreateKHRInteractivityRuntimeValueSnapshot> {\n    const signature = type === undefined ? undefined : graph.types?.[type]?.signature;\n    const components = Array.isArray(value) ? value : _NormalizeValue(value);\n    return _CreateKHRInteractivityRuntimeValueSnapshot(signature === \"float4x4\" && components ? Matrix.FromArray(components as number[]) : components);\n}\n\nfunction _CreateEventSchemaRuntimeSnapshot(value: unknown): ReturnType<typeof _CreateKHRInteractivityRuntimeValueSnapshot> {\n    const runtimeSchema = Array.isArray(value)\n        ? value.map((entry) => {\n              if (entry === null || typeof entry !== \"object\") {\n                  return entry;\n              }\n              const definition = entry as { type?: unknown; value?: unknown };\n              const runtimeValue =\n                  definition.type === FlowGraphTypes.Matrix && Array.isArray(definition.value)\n                      ? Array.from(Matrix.FromArray(definition.value as number[]).asArray())\n                      : definition.value;\n              return definition.value === undefined ? entry : { ...definition, value: runtimeValue };\n          })\n        : value;\n    return _CreateKHRInteractivityRuntimeValueSnapshot(runtimeSchema);\n}\n\nfunction _ValuesEqual(left: readonly unknown[] | undefined, right: readonly unknown[] | undefined): boolean {\n    if (!left || !right || left.length !== right.length) {\n        return left === right;\n    }\n    for (let index = 0; index < left.length; index++) {\n        if (typeof left[index] === \"number\" && typeof right[index] === \"number\" && Number.isNaN(left[index]) && Number.isNaN(right[index])) {\n            continue;\n        }\n        if (left[index] !== right[index]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nfunction _JsonEquivalent(left: unknown, right: unknown): boolean {\n    if (typeof left === \"number\" && typeof right === \"number\" && Number.isNaN(left) && Number.isNaN(right)) {\n        return true;\n    }\n    if (left === right) {\n        return true;\n    }\n    if (Array.isArray(left) && Array.isArray(right)) {\n        return left.length === right.length && left.every((entry, index) => _JsonEquivalent(entry, right[index]));\n    }\n    if (left !== null && right !== null && typeof left === \"object\" && typeof right === \"object\") {\n        const leftEntries = Object.entries(left);\n        const rightKeys = Object.keys(right);\n        return (\n            leftEntries.length === rightKeys.length &&\n            leftEntries.every(([key, value]) => Object.prototype.hasOwnProperty.call(right, key) && _JsonEquivalent(value, (right as Record<string, unknown>)[key]))\n        );\n    }\n    return false;\n}\n\nfunction _GetTypeDefault(signature: string): unknown[] {\n    switch (signature) {\n        case \"bool\":\n            return [false];\n        case \"int\":\n            return [0];\n        case \"ref\":\n            return [\"\"];\n        case \"float\":\n            return [NaN];\n        case \"float2\":\n            return [NaN, NaN];\n        case \"float3\":\n            return [NaN, NaN, NaN];\n        case \"float4\":\n        case \"float2x2\":\n            return [NaN, NaN, NaN, NaN];\n        case \"float3x3\":\n            return [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN];\n        case \"float4x4\":\n            return [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN];\n        default:\n            return [];\n    }\n}\n\nfunction _GetOrAddInputTypeIndex(\n    graph: IKHRInteractivity_Graph,\n    input: FlowGraphDataConnection<any>,\n    mapping: IGLTFToFlowGraphMappingObject | undefined,\n    logicalNode: ILogicalNode,\n    socket: string\n): number | undefined {\n    if (logicalNode.operation === \"variable/set\" && /^(0|[1-9]\\d*)$/.test(socket)) {\n        return graph.variables?.[parseInt(socket, 10)]?.type;\n    }\n    if (logicalNode.operation === \"event/send\") {\n        const eventProperty = logicalNode.mapping?.configuration?.event;\n        const eventIndex = eventProperty ? _GetMappedConfigurationValue(logicalNode, \"event\", eventProperty, graph)?.[0] : undefined;\n        if (typeof eventIndex === \"number\") {\n            return graph.events?.[eventIndex]?.values?.[socket]?.type;\n        }\n    }\n    if (logicalNode.operation === \"pointer/get\" || logicalNode.operation === \"pointer/set\" || logicalNode.operation === \"pointer/interpolate\") {\n        const pointerProperty = logicalNode.mapping?.configuration?.pointer;\n        const pointer = pointerProperty ? _GetMappedConfigurationValue(logicalNode, \"pointer\", pointerProperty, graph)?.[0] : undefined;\n        if (typeof pointer === \"string\") {\n            const segment = pointer.split(\"/\").find((entry) => entry === `[${socket}]` || entry === `{${socket}}`);\n            const semanticSignature = segment?.startsWith(\"[\") ? \"int\" : segment?.startsWith(\"{\") ? \"ref\" : undefined;\n            if (semanticSignature) {\n                const existing = graph.types?.findIndex((type) => type.signature === semanticSignature) ?? -1;\n                if (existing >= 0) {\n                    return existing;\n                }\n                graph.types ??= [];\n                graph.types.push({ signature: semanticSignature });\n                return graph.types.length - 1;\n            }\n        }\n    }\n    const mappedType = mapping?.gltfType;\n    const signature =\n        mappedType === \"number\"\n            ? \"float\"\n            : mappedType === \"boolean\"\n              ? \"bool\"\n              : mappedType === \"vector2\"\n                ? \"float2\"\n                : mappedType === \"vector3\"\n                  ? \"float3\"\n                  : mappedType === \"vector4\"\n                    ? \"float4\"\n                    : mappedType && mappedType !== \"any\"\n                      ? mappedType\n                      : _FlowGraphTypeToKHRSignature[input.richType.typeName];\n    if (!signature || !gltfTypeToBabylonType[signature]) {\n        return undefined;\n    }\n    graph.types ??= [];\n    const existing = graph.types.findIndex((type) => type.signature === signature);\n    if (existing >= 0) {\n        return existing;\n    }\n    graph.types.push({ signature: signature as NonNullable<IKHRInteractivity_Graph[\"types\"]>[number][\"signature\"] });\n    return graph.types.length - 1;\n}\n\nfunction _GetOrAddVariableTypeIndex(graph: IKHRInteractivity_Graph, flowGraphType: string): number | undefined {\n    const signature = _FlowGraphTypeToKHRSignature[flowGraphType];\n    if (!signature || !gltfTypeToBabylonType[signature]) {\n        return undefined;\n    }\n    graph.types ??= [];\n    const existing = graph.types.findIndex((type) => type.signature === signature);\n    if (existing >= 0) {\n        return existing;\n    }\n    graph.types.push({ signature: signature as NonNullable<IKHRInteractivity_Graph[\"types\"]>[number][\"signature\"] });\n    return graph.types.length - 1;\n}\n\nfunction _GetSourceValue(graph: IKHRInteractivity_Graph, value: IKHRInteractivity_Variable, mapping?: IGLTFToFlowGraphMappingObject, targetFps: number = 60): unknown[] {\n    const signature = graph.types?.[value.type]?.signature ?? \"custom\";\n    const source = value.value?.slice() ?? _GetTypeDefault(signature);\n    if (mapping?.convertConnectedTimeToFrames && source.length === 1 && typeof source[0] === \"number\") {\n        source[0] *= targetFps;\n    }\n    return source;\n}\n\nfunction _GetConfigurationBlock(logicalNode: ILogicalNode, property: IGLTFToFlowGraphMappingObject): FlowGraphBlock | undefined {\n    const targetBlock = property.toBlock;\n    if (targetBlock) {\n        return logicalNode.blocks.find(\n            (block) => block.getClassName() === _RuntimeBlockClassName(targetBlock) || _GetBlockProvenance(block)?.role === logicalNode.mapping?.blocks.indexOf(targetBlock)\n        );\n    }\n    return _GetRoleBlock(logicalNode.blocks, 0);\n}\n\nfunction _GetMappedConfigurationValue(\n    logicalNode: ILogicalNode,\n    key: string,\n    property: IGLTFToFlowGraphMappingObject,\n    sourceGraph: IKHRInteractivity_Graph,\n    preserveCanonicalWhenUnchanged: boolean = true\n): unknown[] | undefined {\n    const block = _GetConfigurationBlock(logicalNode, property);\n    if (!block) {\n        return undefined;\n    }\n    const value = block.config?.[property.name];\n    const provenance = _GetConfigurationProvenance(logicalNode, key, property);\n    if (preserveCanonicalWhenUnchanged && provenance && _ValuesEqual(_NormalizeValue(value), _NormalizeValue(provenance.runtimeValue))) {\n        return provenance.sourceValue ? _CloneJson(provenance.sourceValue) : undefined;\n    }\n    if (property.indexSource === \"variables\") {\n        const names = (Array.isArray(value) ? value : [value]).filter((entry): entry is string => typeof entry === \"string\");\n        const indices = names.map((name) => (/^staticVariable_(0|[1-9]\\d*)$/.test(name) ? parseInt(name.substring(\"staticVariable_\".length), 10) : -1));\n        return indices.every((index) => index >= 0 && index < (sourceGraph.variables?.length ?? 0)) ? indices : undefined;\n    }\n    if (property.indexSource === \"events\") {\n        const eventId = value;\n        const eventIndex = sourceGraph.events?.findIndex((event) => event.id === eventId);\n        return eventIndex !== undefined && eventIndex >= 0 ? [eventIndex] : undefined;\n    }\n    if (property.indexSource === \"assetNodes\" && typeof value === \"string\") {\n        return undefined;\n    }\n    if (key === \"useSlerp\") {\n        return [value === \"Quaternion\"];\n    }\n    return _NormalizeValue(value);\n}\n\nfunction _GetConfigurationProvenance(logicalNode: ILogicalNode, key: string, property: IGLTFToFlowGraphMappingObject): IKHRInteractivityConfigurationProvenance | undefined {\n    const block = _GetConfigurationBlock(logicalNode, property);\n    return block ? _GetOwn(_GetBlockProvenance(block)?.configuration, key) : undefined;\n}\n\nfunction _IsValidConfigurationValue(value: unknown[] | undefined, property: IGLTFToFlowGraphMappingObject, graph: IKHRInteractivity_Graph, assetNodeCount?: number): boolean {\n    if (!value) {\n        return false;\n    }\n    const isInt = (entry: unknown): entry is number => typeof entry === \"number\" && Number.isInteger(entry) && entry >= -2147483648 && entry <= 2147483647;\n    let valid: boolean;\n    switch (property.configurationType) {\n        case \"bool\":\n            valid = value.length === 1 && typeof value[0] === \"boolean\";\n            break;\n        case \"int\":\n            valid = value.length === 1 && isInt(value[0]);\n            break;\n        case \"int[]\":\n            valid = value.every(isInt);\n            break;\n        case \"string\":\n            valid = value.length === 1 && typeof value[0] === \"string\";\n            break;\n        default:\n            valid = value.length > 0;\n            break;\n    }\n    if (!valid || (property.minItems !== undefined && value.length < property.minItems)) {\n        return false;\n    }\n    if (property.minimum !== undefined && value.some((entry) => typeof entry !== \"number\" || entry < property.minimum!)) {\n        return false;\n    }\n    if (property.maximum !== undefined && value.some((entry) => typeof entry !== \"number\" || entry > property.maximum!)) {\n        return false;\n    }\n    if (property.indexSource) {\n        const lengths: Record<NonNullable<IGLTFToFlowGraphMappingObject[\"indexSource\"]>, number> = {\n            types: graph.types?.length ?? 0,\n            variables: graph.variables?.length ?? 0,\n            events: graph.events?.length ?? 0,\n            nodes: graph.nodes?.length ?? 0,\n            assetNodes: assetNodeCount ?? 0,\n        };\n        if (value.some((entry) => !isInt(entry) || entry < 0 || entry >= lengths[property.indexSource!])) {\n            return false;\n        }\n    }\n    if (property.allowedSignatures) {\n        const typeIndex = value[0];\n        const signature = typeof typeIndex === \"number\" ? graph.types?.[typeIndex]?.signature : undefined;\n        if (!signature || !property.allowedSignatures.includes(signature)) {\n            return false;\n        }\n    }\n    if (property.allowedValues && value.some((entry) => !property.allowedValues!.includes(entry as boolean | number | string))) {\n        return false;\n    }\n    if (property.debugLogTemplate && (typeof value[0] !== \"string\" || !ParseDebugLogTemplate(value[0]).valid)) {\n        return false;\n    }\n    return true;\n}\n\nfunction _GetEffectiveConfigurationValue(\n    node: IKHRInteractivity_Node,\n    mapping: IGLTFToFlowGraphMapping,\n    key: string,\n    property: IGLTFToFlowGraphMappingObject,\n    graph: IKHRInteractivity_Graph,\n    logicalNode?: ILogicalNode,\n    assetNodeCount?: number\n): unknown[] | undefined {\n    const getCandidate = (candidateKey: string, candidateProperty: IGLTFToFlowGraphMappingObject): unknown[] | undefined =>\n        logicalNode ? _GetMappedConfigurationValue(logicalNode, candidateKey, candidateProperty, graph) : node.configuration?.[candidateKey]?.value;\n    if (property.configurationGroup) {\n        for (const [candidateKey, candidateProperty] of Object.entries(mapping.configuration ?? {})) {\n            if (\n                candidateProperty.configurationGroup === property.configurationGroup &&\n                !_IsValidConfigurationValue(getCandidate(candidateKey, candidateProperty), candidateProperty, graph, assetNodeCount)\n            ) {\n                return property.defaultValue === undefined ? undefined : _NormalizeValue(property.defaultValue);\n            }\n        }\n    }\n    const candidate = getCandidate(key, property);\n    if (!_IsValidConfigurationValue(candidate, property, graph, assetNodeCount)) {\n        return property.defaultValue === undefined ? undefined : _NormalizeValue(property.defaultValue);\n    }\n    return property.uniqueValues ? Array.from(new Set(candidate)) : candidate;\n}\n\nfunction _PushDiagnostic(\n    diagnostics: IKHRInteractivityExportDiagnostic[],\n    diagnostic: Omit<IKHRInteractivityExportDiagnostic, \"severity\"> & { severity?: IKHRInteractivityExportDiagnostic[\"severity\"] }\n): void {\n    diagnostics.push({ severity: \"error\", ...diagnostic });\n}\n\nfunction _SetOwnProperty<T extends object, K extends PropertyKey>(target: T, key: K, value: unknown): void {\n    Object.defineProperty(target, key, {\n        configurable: true,\n        enumerable: true,\n        value,\n        writable: true,\n    });\n}\n\n/**\n * Detached representability and export plan for one or more FlowGraphs.\n */\nexport class KHRInteractivityExportPlan implements IKHRInteractivityExportProvider {\n    private _analysis!: IKHRInteractivityExportAnalysis;\n    private _graphAnalyses: IGraphAnalysis[] = [];\n    private _additionalExtensionsUsed: string[] = [];\n    private readonly _rootDiagnostics: IKHRInteractivityExportDiagnostic[] = [];\n    private _isPreflight = false;\n\n    /** Whether KHR_interactivity is required in the exported asset. */\n    public readonly required: boolean;\n\n    /** Additional operation/companion extensions referenced by the exported graphs. */\n    public get additionalExtensionsUsed(): readonly string[] {\n        return this._additionalExtensionsUsed;\n    }\n\n    /** Additional extensions explicitly required by the caller. */\n    public readonly additionalExtensionsRequired: readonly string[];\n\n    /**\n     * @param _flowGraphs FlowGraphs to analyze without mutating them\n     * @param _options canonical source and export settings\n     */\n    public constructor(\n        private readonly _flowGraphs: readonly FlowGraph[],\n        private readonly _options: IKHRInteractivityExportOptions = {}\n    ) {\n        this.required = _options.required ?? true;\n        this.additionalExtensionsRequired = Array.from(new Set(_options.additionalExtensionsRequired ?? [])).sort();\n        this._refreshAnalysis();\n    }\n\n    private _refreshAnalysis(): void {\n        this._rootDiagnostics.length = 0;\n        this._graphAnalyses = this._analyzeGraphs();\n        this._additionalExtensionsUsed = Array.from(new Set([...this._collectAdditionalExtensions(), ...this.additionalExtensionsRequired])).sort();\n        const unscopedBuildDiagnostics = this._mergeBuildDiagnostics(this._validateBuildWithSourceIndices());\n        const nodes = this._graphAnalyses.flatMap((graph) =>\n            graph.nodes.map((node): IKHRInteractivityNodeExportAnalysis => ({\n                graphIndex: graph.graphIndex,\n                nodeIndex: node.sourceIndex,\n                operation: node.operation,\n                blockIds: node.blocks.map((block) => block.uniqueId).sort(),\n                classification: node.classification,\n                diagnostics: node.diagnostics.slice(),\n            }))\n        );\n        const diagnostics = this._sortDiagnostics(\n            this._rootDiagnostics.concat(\n                this._graphAnalyses.flatMap((graph) => graph.diagnostics.concat(graph.nodes.flatMap((node) => node.diagnostics))),\n                unscopedBuildDiagnostics\n            )\n        );\n        this._analysis = {\n            representable: !diagnostics.some((diagnostic) => diagnostic.severity === \"error\"),\n            nodes,\n            diagnostics,\n        };\n    }\n\n    private _mergeBuildDiagnostics(diagnostics: IKHRInteractivityExportDiagnostic[]): IKHRInteractivityExportDiagnostic[] {\n        const unscoped: IKHRInteractivityExportDiagnostic[] = [];\n        for (const diagnostic of diagnostics) {\n            const pathNodeIndex = /\\/nodes\\/(\\d+)(?:\\/|$)/.exec(diagnostic.path)?.[1];\n            const nodeIndex = diagnostic.nodeIndex ?? (pathNodeIndex === undefined ? undefined : parseInt(pathNodeIndex, 10));\n            const graph = diagnostic.graphIndex === undefined ? undefined : this._graphAnalyses[diagnostic.graphIndex];\n            const node = nodeIndex === undefined ? undefined : graph?.nodes.find((candidate) => candidate.sourceIndex === nodeIndex);\n            if (!node) {\n                unscoped.push(diagnostic);\n                continue;\n            }\n            if (!node.diagnostics.some((existing) => existing.code === diagnostic.code && existing.path === diagnostic.path && existing.message === diagnostic.message)) {\n                node.diagnostics.push({ ...diagnostic, nodeIndex });\n            }\n            if (diagnostic.severity === \"error\" && (node.classification === \"exact\" || node.classification === \"inverse-composite\")) {\n                node.classification = \"lossy\";\n            }\n        }\n        return unscoped;\n    }\n\n    /**\n     * Gets the detached representability analysis.\n     * @returns current analysis\n     */\n    public analyze(): IKHRInteractivityExportAnalysis {\n        this._refreshAnalysis();\n        return {\n            representable: this._analysis.representable,\n            nodes: this._analysis.nodes.map((node) => ({ ...node, blockIds: node.blockIds.slice(), diagnostics: node.diagnostics.slice() })),\n            diagnostics: this._analysis.diagnostics.slice(),\n        };\n    }\n\n    /**\n     * Builds the extension after final glTF entity remapping is available.\n     * @param context serializer remapping context\n     * @returns canonical KHR_interactivity payload\n     */\n    public build(context: IKHRInteractivitySerializerContext): IKHRInteractivity {\n        this._refreshAnalysis();\n        if (!this._analysis.representable) {\n            throw new KHRInteractivityExportError(this._analysis.diagnostics);\n        }\n        const diagnostics: IKHRInteractivityExportDiagnostic[] = [];\n        const graphs = this._graphAnalyses.map((analysis) => this._buildGraph(analysis, context, diagnostics));\n        this._writeCompanionNodeExtensions(context, diagnostics);\n        if (diagnostics.some((diagnostic) => diagnostic.severity === \"error\")) {\n            throw new KHRInteractivityExportError(this._sortDiagnostics(diagnostics));\n        }\n\n        const source = this._options.document?.source ? _CloneJson(this._options.document.source) : ({ graphs: [] } as IKHRInteractivity);\n        source.graphs = graphs;\n        const defaultGraphIndex = this._options.defaultGraphIndex ?? this._options.document?.defaultGraphIndex ?? 0;\n        if (defaultGraphIndex < 0 || defaultGraphIndex >= graphs.length) {\n            _PushDiagnostic(diagnostics, {\n                code: \"GRAPH_COUNT_MISMATCH\",\n                path: \"/extensions/KHR_interactivity/graph\",\n                message: `Default graph index ${defaultGraphIndex} is outside the exported graph range.`,\n            });\n            throw new KHRInteractivityExportError(diagnostics);\n        }\n        if (defaultGraphIndex !== 0 || source.graph !== undefined) {\n            source.graph = defaultGraphIndex;\n        }\n        return source;\n    }\n\n    private _getSourceGraph(graph: FlowGraph, graphIndex: number): IKHRInteractivity_Graph | undefined {\n        const documentGraph = this._options.document?.graphs[graphIndex]?.source;\n        if (documentGraph) {\n            return CloneKHRInteractivityGraph(documentGraph);\n        }\n        const provenance = graph.metadata?.khrInteractivity as IKHRInteractivityGraphProvenance | undefined;\n        return provenance?.source ? CloneKHRInteractivityGraph(provenance.source) : undefined;\n    }\n\n    private _validateBuildWithSourceIndices(): IKHRInteractivityExportDiagnostic[] {\n        const diagnostics: IKHRInteractivityExportDiagnostic[] = [];\n        const sourceGLTF = this._options.sourceGLTF;\n        const indexOrUndefined = (index: number | undefined): number | undefined => (index !== undefined && index >= 0 ? index : undefined);\n        const context: IKHRInteractivitySerializerContext = {\n            getNodeCount: () => sourceGLTF?.nodes?.length ?? 0,\n            getNodeIndex: (node) => indexOrUndefined(sourceGLTF?.nodes?.findIndex((candidate) => candidate._babylonTransformNode === node)),\n            getAnimationIndex: (animation) => indexOrUndefined(sourceGLTF?.animations?.findIndex((candidate) => candidate._babylonAnimationGroup === animation)),\n            getCameraIndex: (camera) => indexOrUndefined(sourceGLTF?.cameras?.findIndex((candidate) => candidate._babylonCamera === camera)),\n            getMaterialIndex: (material) =>\n                indexOrUndefined(sourceGLTF?.materials?.findIndex((candidate) => Object.values(candidate._data ?? {}).some((entry) => entry.babylonMaterial === material))),\n            getRootIndex: (collection, entity) => this._getSourceRootIndex(collection, entity),\n            setNodeExtension: () => {},\n        };\n        this._isPreflight = true;\n        try {\n            for (const analysis of this._graphAnalyses) {\n                this._buildGraph(analysis, context, diagnostics);\n            }\n            this._writeCompanionNodeExtensions(context, diagnostics);\n        } finally {\n            this._isPreflight = false;\n        }\n        return diagnostics;\n    }\n\n    private _analyzeGraphs(): IGraphAnalysis[] {\n        const analyses: IGraphAnalysis[] = [];\n        if (!this._options.document) {\n            _PushDiagnostic(this._rootDiagnostics, {\n                code: \"GRAPH_SOURCE_MISSING\",\n                path: \"/extensions/KHR_interactivity\",\n                message: \"A canonical KHR_interactivity document is required to preserve root metadata and the default graph selection.\",\n            });\n        }\n        if (this._flowGraphs.length === 0) {\n            _PushDiagnostic(this._rootDiagnostics, {\n                code: \"GRAPH_COUNT_MISMATCH\",\n                path: \"/extensions/KHR_interactivity/graphs\",\n                message: \"At least one FlowGraph is required for KHR_interactivity export.\",\n            });\n            return analyses;\n        }\n        for (const diagnostic of this._options.document?.diagnostics ?? []) {\n            _PushDiagnostic(this._rootDiagnostics, {\n                code: \"GRAPH_INVALID\",\n                path: diagnostic.path,\n                message: diagnostic.message,\n                severity: diagnostic.severity,\n            });\n        }\n        if (this._options.document && this._options.document.graphs.length !== this._flowGraphs.length) {\n            _PushDiagnostic(this._rootDiagnostics, {\n                code: \"GRAPH_COUNT_MISMATCH\",\n                path: \"/extensions/KHR_interactivity/graphs\",\n                message: `Canonical source has ${this._options.document.graphs.length} graph(s), but ${this._flowGraphs.length} FlowGraph(s) were supplied.`,\n            });\n            return analyses;\n        }\n        for (let graphIndex = 0; graphIndex < this._flowGraphs.length; graphIndex++) {\n            const graph = this._flowGraphs[graphIndex];\n            const source = this._getSourceGraph(graph, graphIndex);\n            const diagnostics: IKHRInteractivityExportDiagnostic[] = [];\n            for (const diagnostic of this._options.document?.graphs[graphIndex]?.diagnostics ?? []) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"GRAPH_INVALID\",\n                    graphIndex,\n                    path: diagnostic.path,\n                    message: diagnostic.message,\n                    severity: diagnostic.severity,\n                });\n            }\n            if (!source) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"GRAPH_SOURCE_MISSING\",\n                    graphIndex,\n                    path: `/graphs/${graphIndex}`,\n                    message: \"This FlowGraph has no canonical KHR_interactivity source. Only imported graphs and registered standalone inverse mappings can be exported.\",\n                });\n                const unsupportedNodes = graph.getAllBlocks().map((block): ILogicalNode => ({\n                    sourceIndex: -1,\n                    declarationIndex: -1,\n                    operation: \"\",\n                    blocks: [block],\n                    classification: this._classifyStandaloneBlock(block, diagnostics),\n                    diagnostics: diagnostics.filter((diagnostic) => diagnostic.blockId === block.uniqueId),\n                }));\n                analyses.push({ graph, graphIndex, source: {}, nodes: unsupportedNodes, diagnostics });\n                continue;\n            }\n            analyses.push({\n                graph,\n                graphIndex,\n                source,\n                nodes: this._analyzeImportedNodes(graph, graphIndex, source, diagnostics),\n                diagnostics,\n            });\n        }\n        return analyses;\n    }\n\n    private _classifyStandaloneBlock(block: FlowGraphBlock, diagnostics: IKHRInteractivityExportDiagnostic[]): KHRInteractivityExportClassification {\n        const candidates = GetInteractivityOperationRegistry().filter(\n            (entry) => entry.mapping.blocks.length === 1 && _RuntimeBlockClassName(entry.mapping.blocks[0]) === block.getClassName()\n        );\n        const path = `/blocks/${block.uniqueId}`;\n        if (candidates.length === 0) {\n            _PushDiagnostic(diagnostics, {\n                code: \"BLOCK_UNSUPPORTED\",\n                path,\n                blockId: block.uniqueId,\n                message: `FlowGraph block \"${block.getClassName()}\" has no KHR_interactivity inverse mapping.`,\n            });\n            return \"unsupported\";\n        }\n        _PushDiagnostic(diagnostics, {\n            code: \"BLOCK_AMBIGUOUS\",\n            path,\n            blockId: block.uniqueId,\n            message:\n                candidates.length === 1\n                    ? `FlowGraph block \"${block.getClassName()}\" is not associated with canonical KHR source provenance.`\n                    : `FlowGraph block \"${block.getClassName()}\" is ambiguous between ${candidates.map((entry) => _FullOperationName(entry.op, entry.extension)).join(\", \")}.`,\n        });\n        return \"lossy\";\n    }\n\n    private _analyzeImportedNodes(graph: FlowGraph, graphIndex: number, source: IKHRInteractivity_Graph, graphDiagnostics: IKHRInteractivityExportDiagnostic[]): ILogicalNode[] {\n        const groups = new Map<number, FlowGraphBlock[]>();\n        for (const block of graph.getAllBlocks()) {\n            const provenance = _GetBlockProvenance(block);\n            if (!provenance || provenance.graphIndex !== graphIndex || provenance.nodeIndex < 0) {\n                const diagnostics: IKHRInteractivityExportDiagnostic[] = [];\n                this._classifyStandaloneBlock(block, diagnostics);\n                graphDiagnostics.push(...diagnostics);\n                groups.set(Number.MIN_SAFE_INTEGER + groups.size, [block]);\n                continue;\n            }\n            const group = groups.get(provenance.nodeIndex) ?? [];\n            group.push(block);\n            groups.set(provenance.nodeIndex, group);\n        }\n\n        const logicalNodes: ILogicalNode[] = [];\n        for (let nodeIndex = 0; nodeIndex < (source.nodes?.length ?? 0); nodeIndex++) {\n            const sourceNode = source.nodes![nodeIndex];\n            const declaration = source.declarations?.[sourceNode.declaration];\n            const declarationModel = this._options.document?.graphs[graphIndex]?.declarations[sourceNode.declaration];\n            const operation = declaration ? _FullOperationName(declaration.op, declaration.extension) : \"\";\n            const mapping = declaration && declarationModel?.support !== \"unsupported-extension\" ? getMappingForDeclaration(declaration, false) : undefined;\n            const blocks = groups.get(nodeIndex) ?? [];\n            const diagnostics: IKHRInteractivityExportDiagnostic[] = [];\n            let classification: KHRInteractivityExportClassification = mapping && mapping.blocks.length > 1 ? \"inverse-composite\" : \"exact\";\n            if (!declaration) {\n                classification = \"unsupported\";\n                _PushDiagnostic(diagnostics, {\n                    code: \"NODE_SOURCE_MISSING\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}/declaration`,\n                    message: `Declaration index ${sourceNode.declaration} is unavailable.`,\n                });\n            } else if (declaration.extension === \"BABYLON\") {\n                classification = \"unsupported\";\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_UNSUPPORTED\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                    message: `Compatibility-only operation \"${operation}\" is not part of ratified KHR_interactivity and cannot be exported as standards-compliant data.`,\n                });\n            } else if (!mapping && !declaration.extension) {\n                classification = \"unsupported\";\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_UNSUPPORTED\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                    message: `Unknown core operation \"${declaration.op}\" cannot be exported.`,\n                });\n            } else if (!mapping && declaration.extension) {\n                if (blocks.length !== 1 || blocks[0].getClassName() !== _UnsupportedBlockClassName) {\n                    classification = \"unsupported\";\n                    _PushDiagnostic(diagnostics, {\n                        code: \"BLOCK_TYPE_MISMATCH\",\n                        graphIndex,\n                        nodeIndex,\n                        path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                        message: `Unsupported extension operation \"${operation}\" must remain an intact typed no-op block.`,\n                    });\n                } else {\n                    this._validateUnsupportedExtensionBlock(source, sourceNode, nodeIndex, operation, declaration, blocks[0], graphIndex, diagnostics);\n                    if (diagnostics.some((diagnostic) => diagnostic.severity === \"error\")) {\n                        classification = \"lossy\";\n                    }\n                }\n            } else {\n                this._validateMappedBlocks(graphIndex, nodeIndex, operation, mapping!, blocks, diagnostics);\n                if (diagnostics.some((diagnostic) => diagnostic.severity === \"error\")) {\n                    classification = \"lossy\";\n                }\n            }\n            if (blocks.length === 0) {\n                classification = \"unsupported\";\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_ROLE_MISSING\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                    message: `The FlowGraph blocks for \"${operation}\" were removed.`,\n                });\n            }\n            groups.delete(nodeIndex);\n            logicalNodes.push({\n                sourceIndex: nodeIndex,\n                declarationIndex: sourceNode.declaration,\n                operation,\n                mapping,\n                blocks,\n                classification,\n                diagnostics,\n            });\n        }\n\n        for (const blocks of groups.values()) {\n            const block = blocks[0];\n            const diagnostics: IKHRInteractivityExportDiagnostic[] = [];\n            const classification = this._classifyStandaloneBlock(block, diagnostics);\n            graphDiagnostics.push(...diagnostics);\n            logicalNodes.push({\n                sourceIndex: -1,\n                declarationIndex: -1,\n                operation: \"\",\n                blocks,\n                classification,\n                diagnostics,\n            });\n        }\n        return logicalNodes;\n    }\n\n    private _validateUnsupportedExtensionBlock(\n        graph: IKHRInteractivity_Graph,\n        node: IKHRInteractivity_Node,\n        nodeIndex: number,\n        operation: string,\n        declaration: NonNullable<IKHRInteractivity_Graph[\"declarations\"]>[number],\n        block: FlowGraphBlock,\n        graphIndex: number,\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): void {\n        const config = block.config as {\n            operation?: unknown;\n            inputValueSockets?: unknown;\n            outputValueSockets?: unknown;\n            inputFlowSockets?: unknown;\n            outputFlowSockets?: unknown;\n        };\n        const normalizeValueSockets = (sockets: unknown) =>\n            Array.isArray(sockets)\n                ? sockets\n                      .map((socket) =>\n                          socket !== null && typeof socket === \"object\"\n                              ? { name: (socket as { name?: unknown }).name, signature: (socket as { signature?: unknown }).signature }\n                              : socket\n                      )\n                      .sort((left, right) => String(JSON.stringify(left)).localeCompare(String(JSON.stringify(right))))\n                : sockets;\n        const normalizeFlowSockets = (sockets: unknown) => (Array.isArray(sockets) ? sockets.slice().sort() : sockets);\n        const expectedValueSockets = (sockets: typeof declaration.inputValueSockets) =>\n            Object.entries(sockets ?? {})\n                .map(([name, socket]) => ({ name, signature: graph.types?.[socket.type]?.signature }))\n                .sort((left, right) => left.name.localeCompare(right.name));\n        const expectedInputFlows = Array.from(\n            new Set(\n                (graph.nodes ?? []).flatMap((sourceNode) =>\n                    Object.values(sourceNode.flows ?? {})\n                        .filter((flow) => flow.node === nodeIndex)\n                        .map((flow) => flow.socket ?? \"in\")\n                )\n            )\n        ).sort();\n        const expectedOutputFlows = Object.keys(node.flows ?? {}).sort();\n        const actualConnectionNames = {\n            inputValues: block.dataInputs.map((connection) => connection.name).sort(),\n            outputValues: block.dataOutputs.map((connection) => connection.name).sort(),\n            inputFlows: block instanceof FlowGraphExecutionBlock ? block.signalInputs.map((connection) => connection.name).sort() : [],\n            outputFlows: block instanceof FlowGraphExecutionBlock ? block.signalOutputs.map((connection) => connection.name).sort() : [],\n        };\n        const expectedConnectionNames = {\n            inputValues: Object.keys(declaration.inputValueSockets ?? {}).sort(),\n            outputValues: Object.keys(declaration.outputValueSockets ?? {}).sort(),\n            inputFlows: expectedInputFlows,\n            outputFlows: expectedOutputFlows,\n        };\n        if (\n            config.operation !== operation ||\n            !_JsonEquivalent(normalizeValueSockets(config.inputValueSockets), expectedValueSockets(declaration.inputValueSockets)) ||\n            !_JsonEquivalent(normalizeValueSockets(config.outputValueSockets), expectedValueSockets(declaration.outputValueSockets)) ||\n            !_JsonEquivalent(normalizeFlowSockets(config.inputFlowSockets), expectedInputFlows) ||\n            !_JsonEquivalent(normalizeFlowSockets(config.outputFlowSockets), expectedOutputFlows) ||\n            !_JsonEquivalent(actualConnectionNames, expectedConnectionNames)\n        ) {\n            _PushDiagnostic(diagnostics, {\n                code: \"BLOCK_TYPE_MISMATCH\",\n                graphIndex,\n                nodeIndex,\n                path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                blockId: block.uniqueId,\n                message: `Unsupported extension operation \"${operation}\" has edited socket metadata and can no longer be exported as its canonical typed no-op.`,\n            });\n        }\n    }\n\n    private _validateMappedBlocks(\n        graphIndex: number,\n        nodeIndex: number,\n        operation: string,\n        mapping: IGLTFToFlowGraphMapping,\n        blocks: readonly FlowGraphBlock[],\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): void {\n        for (let role = 0; role < mapping.blocks.length; role++) {\n            const roleBlocks = blocks.filter((block) => _GetBlockProvenance(block)?.role === role);\n            if (roleBlocks.length === 0) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_ROLE_MISSING\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                    message: `Composite \"${operation}\" is missing role ${role} (${mapping.blocks[role]}).`,\n                });\n                continue;\n            }\n            if (roleBlocks.length > 1) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_ROLE_DUPLICATE\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                    message: `Composite \"${operation}\" has more than one block for role ${role}.`,\n                });\n                continue;\n            }\n            if (roleBlocks[0].getClassName() !== _RuntimeBlockClassName(mapping.blocks[role])) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_TYPE_MISMATCH\",\n                    graphIndex,\n                    nodeIndex,\n                    blockId: roleBlocks[0].uniqueId,\n                    path: `/blocks/${roleBlocks[0].uniqueId}`,\n                    message: `Composite role ${role} must be \"${mapping.blocks[role]}\", not \"${roleBlocks[0].getClassName()}\".`,\n                });\n            }\n        }\n        for (const block of blocks) {\n            const provenance = _GetBlockProvenance(block);\n            if (!provenance || provenance.nodeIndex !== nodeIndex || provenance.operation !== operation || provenance.declarationIndex < 0) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_PROVENANCE_INVALID\",\n                    graphIndex,\n                    nodeIndex,\n                    blockId: block.uniqueId,\n                    path: `/blocks/${block.uniqueId}`,\n                    message: `Block provenance no longer identifies the imported \"${operation}\" node.`,\n                });\n            } else if (provenance.role < -1 || provenance.role >= mapping.blocks.length) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"BLOCK_PROVENANCE_INVALID\",\n                    graphIndex,\n                    nodeIndex,\n                    blockId: block.uniqueId,\n                    path: `/blocks/${block.uniqueId}`,\n                    message: `Block role ${provenance.role} is not part of the \"${operation}\" inverse mapping.`,\n                });\n            }\n        }\n        type CompositeConnection = FlowGraphDataConnection<any> | FlowGraphSignalConnection;\n        const allowedInternalPeers = new Map<CompositeConnection, Set<CompositeConnection>>();\n        const allowInternalConnection = (left: CompositeConnection, right: CompositeConnection) => {\n            const leftPeers = allowedInternalPeers.get(left) ?? new Set<CompositeConnection>();\n            leftPeers.add(right);\n            allowedInternalPeers.set(left, leftPeers);\n            const rightPeers = allowedInternalPeers.get(right) ?? new Set<CompositeConnection>();\n            rightPeers.add(left);\n            allowedInternalPeers.set(right, rightPeers);\n        };\n        for (const connector of mapping.interBlockConnectors ?? []) {\n            const inputBlock = _GetRoleBlock(blocks, connector.inputBlockIndex);\n            const outputBlock = _GetRoleBlock(blocks, connector.outputBlockIndex);\n            const input = connector.isVariable\n                ? inputBlock?.dataInputs.find((connection) => connection.name === connector.input)\n                : inputBlock instanceof FlowGraphExecutionBlock\n                  ? inputBlock.signalInputs.find((connection) => connection.name === connector.input)\n                  : undefined;\n            const output = connector.isVariable\n                ? outputBlock?.dataOutputs.find((connection) => connection.name === connector.output)\n                : outputBlock instanceof FlowGraphExecutionBlock\n                  ? outputBlock.signalOutputs.find((connection) => connection.name === connector.output)\n                  : undefined;\n            if (input && output) {\n                allowInternalConnection(input, output);\n            }\n            if (!input || !output || !input._connectedPoint.includes(output as never)) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"COMPOSITE_CONNECTION_CHANGED\",\n                    graphIndex,\n                    nodeIndex,\n                    path: `/graphs/${graphIndex}/nodes/${nodeIndex}`,\n                    message: `Internal composite connection \"${connector.output}\" -> \"${connector.input}\" was changed.`,\n                });\n            }\n        }\n        const reportedUnexpectedConnections = new Set<CompositeConnection>();\n        for (const block of blocks) {\n            const blockProvenance = _GetBlockProvenance(block);\n            for (const [key, expected] of Object.entries(blockProvenance?.generatedConfiguration ?? {})) {\n                const current =\n                    key === \"eventData\"\n                        ? NormalizeInteractivityEventDataConfiguration(block.config?.[key])\n                        : key === \"outputSignalCount\"\n                          ? ((block as { outputSignals?: unknown[]; executionSignals?: unknown[] }).outputSignals?.length ??\n                            (block as { executionSignals?: unknown[] }).executionSignals?.length ??\n                            block.config?.[key])\n                          : block.config?.[key];\n                const runtimeExpected =\n                    _GetOwn(blockProvenance?.generatedConfigurationRuntime, key) ?? (key === \"eventData\" ? _CreateEventSchemaRuntimeSnapshot(expected) : undefined);\n                const currentRuntime = runtimeExpected\n                    ? key === \"eventData\"\n                        ? _CreateEventSchemaRuntimeSnapshot(current)\n                        : _CreateKHRInteractivityRuntimeValueSnapshot(current)\n                    : undefined;\n                if (\n                    runtimeExpected\n                        ? runtimeExpected.unrepresentable || currentRuntime?.unrepresentable || currentRuntime?.runtimeValueFingerprint !== runtimeExpected.runtimeValueFingerprint\n                        : !_JsonEquivalent(current, expected)\n                ) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"CONFIGURATION_UNREPRESENTABLE\",\n                        graphIndex,\n                        nodeIndex,\n                        blockId: block.uniqueId,\n                        path: `/blocks/${block.uniqueId}/config/${key}`,\n                        message: `Importer-generated configuration \"${key}\" was changed and no longer represents \"${operation}\".`,\n                    });\n                }\n            }\n            for (const input of block.dataInputs) {\n                if (input.isConnected() || _GetSocketProvenance(input)) {\n                    continue;\n                }\n                const expected = _GetOwn(blockProvenance?.generatedInputDefaults, input.name);\n                const current = _CreateKHRInteractivityRuntimeValueSnapshot((input as any)._defaultValue);\n                if (!expected || expected.unrepresentable || current.unrepresentable || current.runtimeValueFingerprint !== expected.runtimeValueFingerprint) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"INPUT_DEFAULT_UNREPRESENTABLE\",\n                        graphIndex,\n                        nodeIndex,\n                        blockId: block.uniqueId,\n                        socket: input.name,\n                        path: `/blocks/${block.uniqueId}/dataInputs/${input.name}`,\n                        message: expected?.unrepresentable\n                            ? `Importer-generated input default \"${input.name}\" could not be preserved safely for inverse export.`\n                            : expected\n                              ? `Importer-generated input default \"${input.name}\" was changed and has no KHR_interactivity inverse mapping.`\n                              : `Input default \"${input.name}\" has no import-time provenance or KHR_interactivity inverse mapping.`,\n                    });\n                }\n            }\n            if ((blockProvenance?.role ?? 0) < 0) {\n                continue;\n            }\n            const connections: CompositeConnection[] = [\n                ...block.dataInputs,\n                ...block.dataOutputs,\n                ...(block instanceof FlowGraphExecutionBlock ? block.signalInputs : []),\n                ...(block instanceof FlowGraphExecutionBlock ? block.signalOutputs : []),\n            ];\n            for (const connection of connections) {\n                if (!connection.isConnected() || reportedUnexpectedConnections.has(connection)) {\n                    continue;\n                }\n                const khrFacing =\n                    _GetSocketProvenance(connection) ??\n                    this._inferSocketProvenance(connection, {\n                        sourceIndex: nodeIndex,\n                        declarationIndex: -1,\n                        operation,\n                        mapping,\n                        blocks,\n                        classification: \"exact\",\n                        diagnostics,\n                    });\n                const unexpectedPeers = connection._connectedPoint.filter((peer) => {\n                    const internal = blocks.includes(peer._ownerBlock);\n                    const importerHelper = internal && _GetBlockProvenance(peer._ownerBlock)?.role === -1;\n                    return internal ? !allowedInternalPeers.get(connection)?.has(peer) && !(khrFacing && importerHelper) : !khrFacing;\n                });\n                if (unexpectedPeers.length > 0) {\n                    reportedUnexpectedConnections.add(connection);\n                    unexpectedPeers.forEach((peer) => reportedUnexpectedConnections.add(peer));\n                    _PushDiagnostic(diagnostics, {\n                        code: \"SOCKET_PROVENANCE_MISSING\",\n                        graphIndex,\n                        nodeIndex,\n                        blockId: block.uniqueId,\n                        socket: connection.name,\n                        path: `/blocks/${block.uniqueId}/${connection.name}`,\n                        message: `Connection from socket \"${connection.name}\" is not part of the \"${operation}\" inverse mapping.`,\n                    });\n                }\n            }\n        }\n    }\n\n    private _buildGraph(analysis: IGraphAnalysis, context: IKHRInteractivitySerializerContext, diagnostics: IKHRInteractivityExportDiagnostic[]): IKHRInteractivity_Graph {\n        const graph = CloneKHRInteractivityGraph(analysis.source);\n        const importedName = analysis.source.name ?? `Graph ${analysis.graphIndex + 1}`;\n        if (analysis.source.name !== undefined || analysis.graph.name !== importedName) {\n            graph.name = analysis.graph.name;\n        } else {\n            delete graph.name;\n        }\n        this._updateVariables(graph, analysis.graph, diagnostics, analysis.graphIndex);\n        const logicalBySourceIndex = new Map(analysis.nodes.filter((node) => node.sourceIndex >= 0).map((node) => [node.sourceIndex, node]));\n        const rebuiltNodes = (graph.nodes ?? []).map((sourceNode, nodeIndex) => {\n            const logicalNode = logicalBySourceIndex.get(nodeIndex)!;\n            return this._rebuildNode(graph, sourceNode, logicalNode, analysis, context, diagnostics);\n        });\n        const ordered = this._topologicallyOrderNodes(rebuiltNodes, analysis.graphIndex, diagnostics);\n        if (!ordered) {\n            return graph;\n        }\n        if (analysis.source.nodes !== undefined || ordered.nodes.length > 0) {\n            graph.nodes = ordered.nodes;\n        } else {\n            delete graph.nodes;\n        }\n        this._remapGraphReferences(graph, context, diagnostics, analysis.graphIndex, ordered.sourceIndices);\n        const validation = CreateKHRInteractivityGraphModel(graph, analysis.graphIndex, new Set(this.additionalExtensionsUsed), context.getNodeCount());\n        for (const diagnostic of validation.diagnostics) {\n            if (diagnostic.severity === \"error\") {\n                const finalNodeIndexText = /\\/nodes\\/(\\d+)(?:\\/|$)/.exec(diagnostic.path)?.[1];\n                const finalNodeIndex = finalNodeIndexText === undefined ? undefined : parseInt(finalNodeIndexText, 10);\n                _PushDiagnostic(diagnostics, {\n                    code: \"GRAPH_INVALID\",\n                    graphIndex: analysis.graphIndex,\n                    nodeIndex: finalNodeIndex === undefined ? undefined : ordered.sourceIndices[finalNodeIndex],\n                    path: diagnostic.path,\n                    message: diagnostic.message,\n                });\n            }\n        }\n        return graph;\n    }\n\n    private _rebuildNode(\n        graph: IKHRInteractivity_Graph,\n        sourceNode: IKHRInteractivity_Node,\n        logicalNode: ILogicalNode,\n        graphAnalysis: IGraphAnalysis,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): IKHRInteractivity_Node {\n        const node = _CloneJson(sourceNode);\n        const mapping = logicalNode.mapping;\n        if (mapping) {\n            this._rebuildConfiguration(graph, node, logicalNode, graphAnalysis.graphIndex, context, diagnostics);\n        }\n        for (const socket of Object.keys(sourceNode.values ?? {}).sort()) {\n            if (mapping) {\n                const sourceEffective = this._isEffectiveValueInput(graph, sourceNode, logicalNode, socket, false);\n                const currentEffective = this._isEffectiveValueInput(graph, sourceNode, logicalNode, socket, true);\n                if (!sourceEffective) {\n                    if (currentEffective) {\n                        _PushDiagnostic(diagnostics, {\n                            code: \"CONFIGURATION_UNREPRESENTABLE\",\n                            graphIndex: graphAnalysis.graphIndex,\n                            nodeIndex: logicalNode.sourceIndex,\n                            socket,\n                            path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/values/${socket}`,\n                            message: `Configuration edits made formerly ignored value socket \"${socket}\" effective without an authored FlowGraph socket.`,\n                        });\n                    }\n                    continue;\n                }\n                if (!currentEffective) {\n                    delete node.values![socket];\n                    continue;\n                }\n            }\n            const input = _FindDataInput(logicalNode.blocks, logicalNode.sourceIndex, socket);\n            if (!input) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"SOCKET_PROVENANCE_MISSING\",\n                    graphIndex: graphAnalysis.graphIndex,\n                    nodeIndex: logicalNode.sourceIndex,\n                    socket,\n                    path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/values/${socket}`,\n                    message: `Input value socket \"${socket}\" no longer has KHR_interactivity provenance.`,\n                });\n                continue;\n            }\n            const mappingObject = this._getMappingObject(mapping?.inputs?.values, socket);\n            node.values![socket] = this._rebuildInputValue(graph, sourceNode.values![socket], input, mappingObject, logicalNode, graphAnalysis, diagnostics);\n        }\n        if (node.values && Object.keys(node.values).length === 0) {\n            delete node.values;\n        }\n        const flowOutputs = new Map<string, FlowGraphSignalConnection>();\n        for (const block of logicalNode.blocks) {\n            if (!(block instanceof FlowGraphExecutionBlock)) {\n                continue;\n            }\n            for (const output of block.signalOutputs) {\n                const provenance = _GetSocketProvenance(output) ?? this._inferSocketProvenance(output, logicalNode);\n                if (provenance?.nodeIndex === logicalNode.sourceIndex && provenance.kind === \"flow\" && provenance.direction === \"output\") {\n                    if (!this._isEffectiveFlowOutput(graph, sourceNode, logicalNode, provenance.socket, true)) {\n                        if (output.isConnected()) {\n                            _PushDiagnostic(diagnostics, {\n                                code: \"CONFIGURATION_UNREPRESENTABLE\",\n                                graphIndex: graphAnalysis.graphIndex,\n                                nodeIndex: logicalNode.sourceIndex,\n                                socket: provenance.socket,\n                                path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${provenance.socket}`,\n                                message: `Flow socket \"${provenance.socket}\" is connected but disabled by the edited configuration.`,\n                            });\n                        }\n                        continue;\n                    }\n                    if (flowOutputs.has(provenance.socket)) {\n                        _PushDiagnostic(diagnostics, {\n                            code: \"SOCKET_CONNECTION_AMBIGUOUS\",\n                            graphIndex: graphAnalysis.graphIndex,\n                            nodeIndex: logicalNode.sourceIndex,\n                            socket: provenance.socket,\n                            path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${provenance.socket}`,\n                            message: `Multiple FlowGraph outputs map to KHR flow socket \"${provenance.socket}\".`,\n                        });\n                    } else {\n                        flowOutputs.set(provenance.socket, output);\n                    }\n                }\n            }\n        }\n        const rebuiltFlows: NonNullable<IKHRInteractivity_Node[\"flows\"]> = {};\n        for (const [socket, sourceFlow] of Object.entries(sourceNode.flows ?? {})) {\n            const sourceEffective = this._isEffectiveFlowOutput(graph, sourceNode, logicalNode, socket, false);\n            const currentEffective = this._isEffectiveFlowOutput(graph, sourceNode, logicalNode, socket, true);\n            if (!sourceEffective) {\n                if (currentEffective) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"CONFIGURATION_UNREPRESENTABLE\",\n                        graphIndex: graphAnalysis.graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        socket,\n                        path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${socket}`,\n                        message: `Configuration edits made formerly ignored flow socket \"${socket}\" effective without a live FlowGraph connection.`,\n                    });\n                } else {\n                    _SetOwnProperty(rebuiltFlows, socket, _CloneJson(sourceFlow));\n                }\n            }\n        }\n        for (const [socket, output] of [...flowOutputs.entries()].sort(([left], [right]) => left.localeCompare(right))) {\n            if (output._connectedPoint.length === 0) {\n                const sourceFlow = sourceNode.flows?.[socket];\n                if (sourceFlow) {\n                    const sourceNoOp = this._isNoOpFlowTarget(graph, graphAnalysis, sourceFlow, false);\n                    const currentNoOp = this._isNoOpFlowTarget(graph, graphAnalysis, sourceFlow, true);\n                    if (sourceNoOp && currentNoOp) {\n                        _SetOwnProperty(rebuiltFlows, socket, _CloneJson(sourceFlow));\n                    } else if (sourceNoOp && !currentNoOp) {\n                        _PushDiagnostic(diagnostics, {\n                            code: \"CONFIGURATION_UNREPRESENTABLE\",\n                            graphIndex: graphAnalysis.graphIndex,\n                            nodeIndex: logicalNode.sourceIndex,\n                            socket,\n                            path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${socket}`,\n                            message: `Configuration edits made formerly ignored flow target \"${sourceFlow.socket ?? \"in\"}\" effective without a live FlowGraph connection.`,\n                        });\n                    }\n                }\n                continue;\n            }\n            if (output._connectedPoint.length > 1) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"SOCKET_CONNECTION_AMBIGUOUS\",\n                    graphIndex: graphAnalysis.graphIndex,\n                    nodeIndex: logicalNode.sourceIndex,\n                    socket,\n                    path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${socket}`,\n                    message: `KHR output flow \"${socket}\" must connect to exactly one target; found ${output._connectedPoint.length}.`,\n                });\n                continue;\n            }\n            const target = output._connectedPoint[0];\n            const targetBlockProvenance = _GetBlockProvenance(target._ownerBlock);\n            const targetLogicalNode = targetBlockProvenance ? graphAnalysis.nodes.find((candidate) => candidate.sourceIndex === targetBlockProvenance.nodeIndex) : undefined;\n            const provenance = _GetSocketProvenance(target) ?? (targetLogicalNode ? this._inferSocketProvenance(target, targetLogicalNode) : undefined);\n            if (!provenance || provenance.kind !== \"flow\" || provenance.direction !== \"input\") {\n                _PushDiagnostic(diagnostics, {\n                    code: \"SOCKET_TARGET_UNREPRESENTABLE\",\n                    graphIndex: graphAnalysis.graphIndex,\n                    nodeIndex: logicalNode.sourceIndex,\n                    socket,\n                    path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${socket}`,\n                    message: `Flow target for \"${socket}\" is not part of a representable KHR node.`,\n                });\n                continue;\n            }\n            if (targetLogicalNode) {\n                const targetSourceNode = graph.nodes?.[targetLogicalNode.sourceIndex];\n                if (targetSourceNode && !this._isEffectiveFlowInput(graph, targetSourceNode, targetLogicalNode, provenance.socket, true)) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"CONFIGURATION_UNREPRESENTABLE\",\n                        graphIndex: graphAnalysis.graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        socket,\n                        path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/flows/${socket}`,\n                        message: `Flow target socket \"${provenance.socket}\" is disabled by the target node's edited configuration.`,\n                    });\n                    continue;\n                }\n            }\n            const rebuiltFlow = sourceNode.flows?.[socket]\n                ? _CloneJson(sourceNode.flows[socket])\n                : ({ node: provenance.nodeIndex } as NonNullable<IKHRInteractivity_Node[\"flows\"]>[string]);\n            rebuiltFlow.node = provenance.nodeIndex;\n            if (provenance.socket === \"in\") {\n                delete rebuiltFlow.socket;\n            } else {\n                rebuiltFlow.socket = provenance.socket;\n            }\n            _SetOwnProperty(rebuiltFlows, socket, rebuiltFlow);\n        }\n        if (Object.keys(rebuiltFlows).length > 0) {\n            node.flows = rebuiltFlows;\n        } else {\n            delete node.flows;\n        }\n        if (mapping) {\n            this._remapPointerTemplateInputs(graph, node, logicalNode, graphAnalysis.graphIndex, context, diagnostics);\n        }\n        return node;\n    }\n\n    private _getMappingObject(mapping: { [name: string]: IGLTFToFlowGraphMappingObject } | undefined, socket: string): IGLTFToFlowGraphMappingObject | undefined {\n        const fixed = _GetOwn(mapping, socket);\n        if (fixed) {\n            return fixed;\n        }\n        return Object.entries(mapping ?? {}).find(([key]) => key.startsWith(\"[\") && key.endsWith(\"]\"))?.[1];\n    }\n\n    private _inferSocketProvenance(connection: FlowGraphDataConnection<any> | FlowGraphSignalConnection, logicalNode: ILogicalNode): IKHRInteractivitySocketProvenance | undefined {\n        const mapping = logicalNode.mapping;\n        const block = connection._ownerBlock;\n        const blockProvenance = _GetBlockProvenance(block);\n        if (!mapping || !blockProvenance || blockProvenance.role < 0) {\n            return undefined;\n        }\n        const isDataInput = block.dataInputs.includes(connection as FlowGraphDataConnection<any>);\n        const isDataOutput = block.dataOutputs.includes(connection as FlowGraphDataConnection<any>);\n        const isSignalInput = block instanceof FlowGraphExecutionBlock && block.signalInputs.includes(connection as FlowGraphSignalConnection);\n        const isSignalOutput = block instanceof FlowGraphExecutionBlock && block.signalOutputs.includes(connection as FlowGraphSignalConnection);\n        const kind: IKHRInteractivitySocketProvenance[\"kind\"] = isDataInput || isDataOutput ? \"value\" : \"flow\";\n        const direction: IKHRInteractivitySocketProvenance[\"direction\"] = isDataInput || isSignalInput ? \"input\" : \"output\";\n        if (!isDataInput && !isDataOutput && !isSignalInput && !isSignalOutput) {\n            return undefined;\n        }\n        const socketMappings =\n            kind === \"value\" ? (direction === \"input\" ? mapping.inputs?.values : mapping.outputs?.values) : direction === \"input\" ? mapping.inputs?.flows : mapping.outputs?.flows;\n        for (const [sourceName, property] of Object.entries(socketMappings ?? {})) {\n            if (property.compatibilityOnly) {\n                continue;\n            }\n            const expectedRole = property.toBlock ? mapping.blocks.indexOf(property.toBlock) : 0;\n            if (expectedRole !== blockProvenance.role) {\n                continue;\n            }\n            let inferredSourceName: string | undefined;\n            if (sourceName.startsWith(\"[\") && sourceName.endsWith(\"]\")) {\n                if (kind !== \"flow\" || direction !== \"input\") {\n                    continue;\n                }\n                const [prefix, suffix = \"\"] = property.name.split(\"$1\");\n                if (connection.name.startsWith(prefix) && connection.name.endsWith(suffix)) {\n                    inferredSourceName = connection.name.substring(prefix.length, connection.name.length - suffix.length);\n                }\n            } else if (property.name === connection.name) {\n                inferredSourceName = sourceName;\n            }\n            if (inferredSourceName !== undefined) {\n                return {\n                    ...blockProvenance,\n                    kind,\n                    direction,\n                    socket: inferredSourceName,\n                };\n            }\n        }\n        if (kind === \"flow\" && direction === \"input\" && connection.name === \"in\" && HasDefaultInteractivityFlowInput(logicalNode.operation)) {\n            return {\n                ...blockProvenance,\n                kind,\n                direction,\n                socket: \"in\",\n            };\n        }\n        return undefined;\n    }\n\n    private _isNoOpFlowTarget(\n        graph: IKHRInteractivity_Graph,\n        graphAnalysis: IGraphAnalysis,\n        flow: NonNullable<IKHRInteractivity_Node[\"flows\"]>[string],\n        useCurrentConfiguration: boolean\n    ): boolean {\n        const targetNode = graph.nodes?.[flow.node];\n        const declaration = targetNode ? graph.declarations?.[targetNode.declaration] : undefined;\n        if (!declaration) {\n            return false;\n        }\n        const mapping = getMappingForDeclaration(declaration, false);\n        if (!mapping) {\n            return false;\n        }\n        const socket = flow.socket ?? \"in\";\n        const fixed = _GetOwn(mapping.inputs?.flows, socket);\n        if (fixed && !fixed.compatibilityOnly) {\n            return false;\n        }\n        if (Object.keys(mapping.inputs?.flows ?? {}).some((key) => key.startsWith(\"[\") && key.endsWith(\"]\"))) {\n            const targetLogicalNode = graphAnalysis.nodes.find((candidate) => candidate.sourceIndex === flow.node);\n            const allowedSockets = this._getAllowedDynamicFlowSockets(targetNode!, mapping, \"input\", useCurrentConfiguration ? targetLogicalNode : undefined, graph);\n            return !!allowedSockets && !allowedSockets.has(socket);\n        }\n        return !(socket === \"in\" && HasDefaultInteractivityFlowInput(_FullOperationName(declaration.op, declaration.extension)));\n    }\n\n    private _isEffectiveFlowInput(\n        graph: IKHRInteractivity_Graph,\n        node: IKHRInteractivity_Node,\n        logicalNode: ILogicalNode,\n        socket: string,\n        useCurrentConfiguration: boolean\n    ): boolean {\n        const mapping = logicalNode.mapping;\n        if (!mapping) {\n            return true;\n        }\n        const fixed = _GetOwn(mapping.inputs?.flows, socket);\n        if (fixed && !fixed.compatibilityOnly) {\n            return true;\n        }\n        if (Object.keys(mapping.inputs?.flows ?? {}).some((key) => key.startsWith(\"[\") && key.endsWith(\"]\"))) {\n            const allowedSockets = this._getAllowedDynamicFlowSockets(node, mapping, \"input\", useCurrentConfiguration ? logicalNode : undefined, graph);\n            return !allowedSockets || allowedSockets.has(socket);\n        }\n        return socket === \"in\" && HasDefaultInteractivityFlowInput(logicalNode.operation);\n    }\n\n    private _isEffectiveFlowOutput(\n        graph: IKHRInteractivity_Graph,\n        node: IKHRInteractivity_Node,\n        logicalNode: ILogicalNode,\n        socket: string,\n        useCurrentConfiguration: boolean\n    ): boolean {\n        const mappings = logicalNode.mapping?.outputs?.flows;\n        if (!logicalNode.mapping) {\n            return Object.prototype.hasOwnProperty.call(node.flows ?? {}, socket);\n        }\n        const fixed = _GetOwn(mappings, socket);\n        if (fixed && !fixed.compatibilityOnly) {\n            return true;\n        }\n        if (!Object.keys(mappings ?? {}).some((key) => key.startsWith(\"[\") && key.endsWith(\"]\"))) {\n            return false;\n        }\n        const allowedSockets = logicalNode.mapping\n            ? this._getAllowedDynamicFlowSockets(node, logicalNode.mapping, \"output\", useCurrentConfiguration ? logicalNode : undefined, graph)\n            : undefined;\n        return !allowedSockets || allowedSockets.has(socket);\n    }\n\n    private _getAllowedDynamicFlowSockets(\n        node: IKHRInteractivity_Node,\n        mapping: IGLTFToFlowGraphMapping,\n        direction: \"input\" | \"output\",\n        logicalNode?: ILogicalNode,\n        graph?: IKHRInteractivity_Graph\n    ): ReadonlySet<string> | undefined {\n        for (const [key, property] of Object.entries(mapping.configuration ?? {})) {\n            const generatesSockets = direction === \"input\" ? property.generatesInputFlowSockets : property.generatesOutputFlowSockets;\n            if (!generatesSockets) {\n                continue;\n            }\n            const values = graph\n                ? _GetEffectiveConfigurationValue(node, mapping, key, property, graph, logicalNode, this._options.sourceGLTF?.nodes?.length)\n                : node.configuration?.[key]?.value;\n            const effectiveValues = values ?? (Array.isArray(property.defaultValue) ? property.defaultValue : [property.defaultValue]);\n            if (direction === \"input\") {\n                const count = typeof effectiveValues[0] === \"number\" && Number.isInteger(effectiveValues[0]) && effectiveValues[0] >= 0 ? effectiveValues[0] : 0;\n                return new Set(Array.from({ length: count }, (_, index) => String(index)));\n            }\n            return new Set(effectiveValues.filter((value) => value !== undefined).map(String));\n        }\n        return undefined;\n    }\n\n    private _resolveValueTypeIndex(\n        graph: IKHRInteractivity_Graph,\n        value: IKHRInteractivity_Variable | IKHRInteractivity_OutputSocketReference,\n        visited: Set<string>\n    ): number | undefined {\n        return \"node\" in value ? this._resolveOutputTypeIndex(graph, value.node, value.socket ?? \"value\", visited) : value.type;\n    }\n\n    private _resolveOutputTypeIndex(graph: IKHRInteractivity_Graph, nodeIndex: number, socket: string, visited: Set<string> = new Set()): number | undefined {\n        const key = `${nodeIndex}:${socket}`;\n        if (visited.has(key)) {\n            return undefined;\n        }\n        visited.add(key);\n        const node = graph.nodes?.[nodeIndex];\n        const declaration = node ? graph.declarations?.[node.declaration] : undefined;\n        if (!node || !declaration) {\n            return undefined;\n        }\n        const declaredType = declaration.outputValueSockets?.[socket]?.type;\n        if (declaredType !== undefined) {\n            return declaredType;\n        }\n        if (declaration.op === \"pointer/get\" && socket === \"value\") {\n            const type = node.configuration?.type?.value?.[0];\n            return typeof type === \"number\" ? type : undefined;\n        }\n        if (declaration.op === \"variable/get\" && socket === \"value\") {\n            const variable = node.configuration?.variable?.value?.[0];\n            return typeof variable === \"number\" ? graph.variables?.[variable]?.type : undefined;\n        }\n        if (declaration.op === \"math/switch\" && socket === \"value\") {\n            const defaultValue = node.values?.default;\n            return defaultValue ? this._resolveValueTypeIndex(graph, defaultValue, visited) : undefined;\n        }\n        if (declaration.op === \"event/receive\" && socket !== \"event\") {\n            const event = node.configuration?.event?.value?.[0];\n            return typeof event === \"number\" ? graph.events?.[event]?.values?.[socket]?.type : undefined;\n        }\n        const mapping = getMappingForDeclaration(declaration, false);\n        const outputMapping = this._getMappingObject(mapping?.outputs?.values, socket);\n        const mappedType = outputMapping?.gltfType;\n        const signature =\n            mappedType === \"number\"\n                ? \"float\"\n                : mappedType === \"boolean\"\n                  ? \"bool\"\n                  : mappedType === \"vector2\"\n                    ? \"float2\"\n                    : mappedType === \"vector3\"\n                      ? \"float3\"\n                      : mappedType === \"vector4\"\n                        ? \"float4\"\n                        : mappedType;\n        if (signature && Object.prototype.hasOwnProperty.call(gltfTypeToBabylonType, signature)) {\n            const type = graph.types?.findIndex((candidate) => candidate.signature === signature) ?? -1;\n            return type >= 0 ? type : undefined;\n        }\n        const typeSource = outputMapping?.typeSourceInput ? node.values?.[outputMapping.typeSourceInput] : undefined;\n        return typeSource ? this._resolveValueTypeIndex(graph, typeSource, visited) : undefined;\n    }\n\n    private _isEffectiveValueInput(\n        graph: IKHRInteractivity_Graph,\n        node: IKHRInteractivity_Node,\n        logicalNode: ILogicalNode,\n        socket: string,\n        useCurrentConfiguration: boolean\n    ): boolean {\n        const mappings = logicalNode.mapping?.inputs?.values;\n        const fixed = _GetOwn(mappings, socket);\n        if (fixed && !fixed.compatibilityOnly) {\n            return true;\n        }\n        if (!Object.keys(mappings ?? {}).some((key) => key.startsWith(\"[\") && key.endsWith(\"]\"))) {\n            return false;\n        }\n        const configurationValue = (key: string): unknown[] | undefined => {\n            const property = logicalNode.mapping?.configuration?.[key];\n            return property\n                ? _GetEffectiveConfigurationValue(\n                      node,\n                      logicalNode.mapping!,\n                      key,\n                      property,\n                      graph,\n                      useCurrentConfiguration ? logicalNode : undefined,\n                      this._options.sourceGLTF?.nodes?.length\n                  )\n                : undefined;\n        };\n        switch (logicalNode.operation) {\n            case \"debug/log\": {\n                const message = configurationValue(\"message\")?.[0];\n                return typeof message === \"string\" && ParseDebugLogTemplate(message).sockets.includes(socket);\n            }\n            case \"event/send\": {\n                const eventIndex = configurationValue(\"event\")?.[0];\n                return typeof eventIndex === \"number\" && Object.prototype.hasOwnProperty.call(graph.events?.[eventIndex]?.values ?? {}, socket);\n            }\n            case \"variable/set\":\n                return (configurationValue(\"variables\") ?? []).map(String).includes(socket);\n            case \"math/switch\":\n                return (configurationValue(\"cases\") ?? []).map(String).includes(socket);\n            case \"pointer/get\":\n            case \"pointer/set\":\n            case \"pointer/interpolate\": {\n                const pointer = configurationValue(\"pointer\")?.[0];\n                return (\n                    typeof pointer === \"string\" &&\n                    pointer.split(\"/\").some(\n                        (segment) =>\n                            ((segment.startsWith(\"[\") && !segment.startsWith(\"[[\")) || (segment.startsWith(\"{\") && !segment.startsWith(\"{{\"))) &&\n                            segment\n                                .substring(1, segment.length - 1)\n                                .replace(/~1/g, \"/\")\n                                .replace(/~0/g, \"~\") === socket\n                    )\n                );\n            }\n            default:\n                return true;\n        }\n    }\n\n    private _rebuildInputValue(\n        graph: IKHRInteractivity_Graph,\n        sourceValue: IKHRInteractivity_Variable | IKHRInteractivity_OutputSocketReference,\n        input: FlowGraphDataConnection<any>,\n        mappingObject: IGLTFToFlowGraphMappingObject | undefined,\n        logicalNode: ILogicalNode,\n        graphAnalysis: IGraphAnalysis,\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): IKHRInteractivity_Variable | IKHRInteractivity_OutputSocketReference {\n        let upstream: FlowGraphDataConnection<any> | undefined = input._connectedPoint[0];\n        if (input.isConnected() && mappingObject?.convertConnectedTimeToFrames) {\n            upstream = this._unwrapAnimationTimeHelper(input, logicalNode, graphAnalysis, diagnostics);\n        }\n        if (upstream) {\n            const provenance = _GetSocketProvenance(upstream);\n            if (!provenance || provenance.kind !== \"value\" || provenance.direction !== \"output\") {\n                _PushDiagnostic(diagnostics, {\n                    code: \"SOCKET_TARGET_UNREPRESENTABLE\",\n                    graphIndex: graphAnalysis.graphIndex,\n                    nodeIndex: logicalNode.sourceIndex,\n                    path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/values`,\n                    message: `Value input is connected to a block without representable KHR output provenance.`,\n                });\n                return sourceValue;\n            }\n            const rebuiltReference = _CloneJson(sourceValue) as IKHRInteractivity_OutputSocketReference & { value?: unknown };\n            delete rebuiltReference.value;\n            rebuiltReference.node = provenance.nodeIndex;\n            if (provenance.socket === \"value\") {\n                delete rebuiltReference.socket;\n            } else {\n                rebuiltReference.socket = provenance.socket;\n            }\n            if (rebuiltReference.type !== undefined) {\n                const rebuiltType = this._resolveOutputTypeIndex(graph, provenance.nodeIndex, provenance.socket);\n                if (rebuiltType !== undefined) {\n                    rebuiltReference.type = rebuiltType;\n                }\n            }\n            return rebuiltReference;\n        }\n        const socketProvenance = _GetSocketProvenance(input);\n        const sourceProvenanceValue = socketProvenance?.sourceValue;\n        const current = _NormalizeValue((input as any)._defaultValue);\n        const currentSnapshot = _CreateKHRInteractivityRuntimeValueSnapshot((input as any)._defaultValue);\n        const legacyRuntimeSnapshot =\n            sourceProvenanceValue && !(\"node\" in sourceProvenanceValue)\n                ? _CreateTypedRuntimeValueSnapshot(graph, sourceProvenanceValue.type, socketProvenance?.runtimeValue ?? sourceProvenanceValue.value)\n                : undefined;\n        const importedRuntimeSnapshot = socketProvenance?.runtimeValueSnapshot ?? legacyRuntimeSnapshot;\n        if (\n            !input.isConnected() &&\n            importedRuntimeSnapshot &&\n            !importedRuntimeSnapshot.unrepresentable &&\n            !currentSnapshot.unrepresentable &&\n            currentSnapshot.runtimeValueFingerprint === importedRuntimeSnapshot.runtimeValueFingerprint &&\n            sourceProvenanceValue\n        ) {\n            return _CloneJson(sourceProvenanceValue);\n        }\n        if (!input.isConnected() && socketProvenance?.runtimeValue && _ValuesEqual(current, socketProvenance.runtimeValue) && socketProvenance.sourceValue) {\n            return _CloneJson(socketProvenance.sourceValue);\n        }\n        const canonicalSource = socketProvenance?.sourceValue ?? sourceValue;\n        const type = canonicalSource.type ?? _GetOrAddInputTypeIndex(graph, input, mappingObject, logicalNode, socketProvenance?.socket ?? input.name);\n        if (type === undefined || !graph.types?.[type]) {\n            _PushDiagnostic(diagnostics, {\n                code: \"VALUE_UNREPRESENTABLE\",\n                graphIndex: graphAnalysis.graphIndex,\n                nodeIndex: logicalNode.sourceIndex,\n                path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/values`,\n                message: \"A newly inlined value has no canonical KHR type.\",\n            });\n            return sourceValue;\n        }\n        const original = \"node\" in canonicalSource ? undefined : canonicalSource;\n        const expected = original ? _GetSourceValue(graph, original, mappingObject, this._options.targetFps ?? 60) : undefined;\n        if (_ValuesEqual(current, expected)) {\n            return _CloneJson(canonicalSource);\n        }\n        if (!current) {\n            _PushDiagnostic(diagnostics, {\n                code: \"VALUE_UNREPRESENTABLE\",\n                graphIndex: graphAnalysis.graphIndex,\n                nodeIndex: logicalNode.sourceIndex,\n                path: `/graphs/${graphAnalysis.graphIndex}/nodes/${logicalNode.sourceIndex}/values`,\n                message: \"The FlowGraph input value cannot be converted to a KHR value array.\",\n            });\n            return sourceValue;\n        }\n        if (mappingObject?.convertConnectedTimeToFrames && current.length === 1 && typeof current[0] === \"number\") {\n            current[0] /= this._options.targetFps ?? 60;\n        }\n        const rebuiltValue = _CloneJson(canonicalSource) as IKHRInteractivity_Variable & Partial<IKHRInteractivity_OutputSocketReference>;\n        delete rebuiltValue.node;\n        delete rebuiltValue.socket;\n        rebuiltValue.type = type;\n        rebuiltValue.value = current as NonNullable<IKHRInteractivity_Variable[\"value\"]>;\n        return rebuiltValue;\n    }\n\n    private _unwrapAnimationTimeHelper(\n        input: FlowGraphDataConnection<any>,\n        logicalNode: ILogicalNode,\n        graphAnalysis: IGraphAnalysis,\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): FlowGraphDataConnection<any> | undefined {\n        const graphIndex = graphAnalysis.graphIndex;\n        const helperOutput = input._connectedPoint[0];\n        const helperBlock = helperOutput?._ownerBlock;\n        const helperProvenance = helperBlock ? _GetBlockProvenance(helperBlock) : undefined;\n        if (!helperBlock || helperBlock.getClassName() !== \"FlowGraphMultiplyBlock\" || helperProvenance?.role !== -1 || helperProvenance.nodeIndex !== logicalNode.sourceIndex) {\n            _PushDiagnostic(diagnostics, {\n                code: \"COMPOSITE_CONNECTION_CHANGED\",\n                graphIndex,\n                nodeIndex: logicalNode.sourceIndex,\n                blockId: helperBlock?.uniqueId,\n                path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}`,\n                message: \"The generated seconds-to-frames animation helper was changed.\",\n            });\n            return undefined;\n        }\n        const source = helperBlock.dataInputs.find((connection) => connection.name === \"a\")?._connectedPoint[0];\n        const factor = helperBlock.dataInputs.find((connection) => connection.name === \"b\");\n        const expectedFactor = this._options.targetFps ?? 60;\n        const factorValue = factor ? (factor as any)._defaultValue : undefined;\n        if (!factor || factor.isConnected() || _NormalizeValue(factorValue)?.[0] !== expectedFactor) {\n            _PushDiagnostic(diagnostics, {\n                code: \"COMPOSITE_CONNECTION_CHANGED\",\n                graphIndex,\n                nodeIndex: logicalNode.sourceIndex,\n                blockId: helperBlock.uniqueId,\n                path: `/blocks/${helperBlock.uniqueId}`,\n                message: `Animation time helper must multiply by the target frame rate (${expectedFactor}).`,\n            });\n        }\n        return source;\n    }\n\n    private _rebuildConfiguration(\n        graph: IKHRInteractivity_Graph,\n        node: IKHRInteractivity_Node,\n        logicalNode: ILogicalNode,\n        graphIndex: number,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): void {\n        const changedConfigurationGroups = new Set<string>();\n        const fallbackConfigurationGroups = new Set<string>();\n        for (const [key, property] of Object.entries(logicalNode.mapping?.configuration ?? {})) {\n            if (!property.configurationGroup) {\n                continue;\n            }\n            const block = _GetConfigurationBlock(logicalNode, property);\n            const provenance = _GetConfigurationProvenance(logicalNode, key, property);\n            if (provenance && !_JsonEquivalent(block?.config?.[property.name], provenance.runtimeValue)) {\n                changedConfigurationGroups.add(property.configurationGroup);\n            }\n            if (!_IsValidConfigurationValue(provenance?.sourceValue, property, graph, this._options.sourceGLTF?.nodes?.length)) {\n                fallbackConfigurationGroups.add(property.configurationGroup);\n            }\n        }\n        for (const [key, property] of Object.entries(logicalNode.mapping?.configuration ?? {})) {\n            const groupChanged = !!property.configurationGroup && changedConfigurationGroups.has(property.configurationGroup);\n            const groupUsedFallback = !!property.configurationGroup && fallbackConfigurationGroups.has(property.configurationGroup);\n            const provenance = _GetConfigurationProvenance(logicalNode, key, property);\n            const preserveUnexposedValidMember =\n                groupChanged &&\n                !groupUsedFallback &&\n                provenance !== undefined &&\n                provenance.runtimeValue === undefined &&\n                _IsValidConfigurationValue(provenance.sourceValue, property, graph, this._options.sourceGLTF?.nodes?.length);\n            let current = _GetMappedConfigurationValue(logicalNode, key, property, graph, !groupChanged || preserveUnexposedValidMember);\n            if (groupChanged && current === undefined && property.defaultValue !== undefined) {\n                current = _NormalizeValue(property.defaultValue);\n            }\n            const source = node.configuration?.[key]?.value;\n            if (property.validationOnly && current === undefined && provenance?.runtimeValue === undefined) {\n                continue;\n            }\n            if (groupChanged && !_IsValidConfigurationValue(current, property, graph, this._options.sourceGLTF?.nodes?.length)) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"CONFIGURATION_UNREPRESENTABLE\",\n                    graphIndex,\n                    nodeIndex: logicalNode.sourceIndex,\n                    path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/configuration/${key}`,\n                    message: `Edited configuration group \"${property.configurationGroup}\" does not contain a valid value for \"${key}\".`,\n                });\n                continue;\n            }\n            if (!current) {\n                if (source !== undefined || property.required) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"CONFIGURATION_UNREPRESENTABLE\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/configuration/${key}`,\n                        message: `Configuration \"${key}\" cannot be inverted from the edited FlowGraph composite.`,\n                    });\n                }\n                continue;\n            }\n            if (property.indexSource === \"events\" && current.length === 1 && typeof current[0] === \"number\") {\n                const event = graph.events?.[current[0]];\n                const block = _GetConfigurationBlock(logicalNode, property);\n                const runtimeEventData = NormalizeInteractivityEventDataConfiguration(block?.config?.eventData);\n                const runtimeSchema = runtimeEventData === undefined ? [] : runtimeEventData;\n                const blockProvenance = block ? _GetBlockProvenance(block) : undefined;\n                const importTimeSchema = _GetOwn(blockProvenance?.generatedConfigurationRuntime, \"eventData\");\n                const preservesImportedEvent = provenance && _JsonEquivalent(block?.config?.[property.name], provenance.runtimeValue);\n                const eventSchema = Object.entries(event?.values ?? {})\n                    .map(([id, value]) => ({\n                        id,\n                        type: gltfTypeToBabylonType[graph.types?.[value.type]?.signature ?? \"\"]?.flowGraphType,\n                        ...(value.value === undefined ? {} : { value: value.value.slice() }),\n                    }))\n                    .sort((left, right) => left.id.localeCompare(right.id));\n                const currentSchema = _CreateEventSchemaRuntimeSnapshot(runtimeSchema);\n                const expectedSchema = _CreateEventSchemaRuntimeSnapshot(eventSchema);\n                const schemaMatches =\n                    preservesImportedEvent && importTimeSchema\n                        ? !importTimeSchema.unrepresentable && !currentSchema.unrepresentable && currentSchema.runtimeValueFingerprint === importTimeSchema.runtimeValueFingerprint\n                        : !currentSchema.unrepresentable && !expectedSchema.unrepresentable && currentSchema.runtimeValueFingerprint === expectedSchema.runtimeValueFingerprint;\n                if (!schemaMatches) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"CONFIGURATION_UNREPRESENTABLE\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/configuration/${key}`,\n                        message: `The runtime custom-event payload schema does not match event index ${current[0]}.`,\n                    });\n                    continue;\n                }\n            }\n            const preservesFallback =\n                provenance &&\n                _JsonEquivalent(_GetConfigurationBlock(logicalNode, property)?.config?.[property.name], provenance.runtimeValue) &&\n                !_IsValidConfigurationValue(provenance.sourceValue, property, graph, this._options.sourceGLTF?.nodes?.length);\n            if (!preservesFallback && property.indexSource === \"assetNodes\" && current.length === 1 && typeof current[0] === \"number\") {\n                const sourceNode = this._options.sourceGLTF?.nodes?.[current[0]]?._babylonTransformNode;\n                const remapped = sourceNode ? context.getNodeIndex(sourceNode) : undefined;\n                if (remapped === undefined) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"REFERENCE_UNRESOLVED\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/configuration/${key}`,\n                        message: `Referenced glTF node ${current[0]} was not exported.`,\n                    });\n                    continue;\n                }\n                current[0] = remapped;\n            }\n            if (source === undefined && property.defaultValue !== undefined && _ValuesEqual(current, _NormalizeValue(property.defaultValue))) {\n                continue;\n            }\n            node.configuration ??= {};\n            const rebuiltConfiguration = node.configuration[key] ? _CloneJson(node.configuration[key]) : {};\n            rebuiltConfiguration.value = current as NonNullable<IKHRInteractivity_Configuration[\"value\"]>;\n            _SetOwnProperty(node.configuration, key, rebuiltConfiguration);\n        }\n    }\n\n    private _remapPointerTemplateInputs(\n        graph: IKHRInteractivity_Graph,\n        node: IKHRInteractivity_Node,\n        logicalNode: ILogicalNode,\n        graphIndex: number,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[]\n    ): void {\n        for (const [key, property] of Object.entries(logicalNode.mapping?.configuration ?? {})) {\n            if (!property.pointerTemplate) {\n                continue;\n            }\n            const pointer = node.configuration?.[key]?.value?.[0];\n            if (typeof pointer !== \"string\") {\n                continue;\n            }\n            const segments = pointer.split(\"/\");\n            if (segments[0] !== \"\" || segments.length < 3) {\n                continue;\n            }\n            let collection = segments[1].replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n            const rootPlaceholder = /^\\{([^\\{\\}]+)\\}$/.exec(segments[1]);\n            if (rootPlaceholder) {\n                const rootSocket = node.values?.[rootPlaceholder[1]];\n                const rootReference = rootSocket && !(\"node\" in rootSocket) ? rootSocket.value?.[0] : undefined;\n                const rootMatch = typeof rootReference === \"string\" ? /^\\/([^/]+)$/.exec(rootReference) : undefined;\n                collection = rootMatch?.[1] ?? \"\";\n                if (!_KnownIndexedRootCollections.has(collection)) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"REFERENCE_UNRESOLVED\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        socket: rootPlaceholder[1],\n                        path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/values/${rootPlaceholder[1]}`,\n                        message: `Root collection template input \"${rootPlaceholder[1]}\" cannot be resolved statically for export.`,\n                    });\n                    continue;\n                }\n            }\n            if (!_KnownIndexedRootCollections.has(collection)) {\n                continue;\n            }\n            const indexPlaceholder = /^\\[([^\\[\\]]+)\\]$/.exec(segments[2]);\n            const referenceIndexPlaceholder = /^\\{([^\\{\\}]+)\\}$/.exec(segments[2]);\n            const hasTemplateCollection = !!rootPlaceholder || !!indexPlaceholder || !!referenceIndexPlaceholder;\n            if (\n                hasTemplateCollection &&\n                !this._validateExtensionReferencePreservation(\n                    pointer,\n                    collection,\n                    diagnostics,\n                    graphIndex,\n                    logicalNode.sourceIndex,\n                    `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/configuration/${key}`\n                )\n            ) {\n                continue;\n            }\n            if (indexPlaceholder) {\n                const socket = node.values?.[indexPlaceholder[1]];\n                const path = `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/values/${indexPlaceholder[1]}`;\n                if (!socket || \"node\" in socket) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"REFERENCE_UNRESOLVED\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        socket: indexPlaceholder[1],\n                        path,\n                        message: `Dynamic index template input \"${indexPlaceholder[1]}\" cannot be safely remapped for the exported ${collection} array.`,\n                    });\n                    continue;\n                }\n                const sourceIndex = socket.value?.[0];\n                const remapped =\n                    typeof sourceIndex === \"number\" && Number.isInteger(sourceIndex)\n                        ? this._getRemappedRootIndex(collection as KhrInteractivityRootCollection, sourceIndex, context)\n                        : undefined;\n                if (remapped === undefined) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"REFERENCE_UNRESOLVED\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        socket: indexPlaceholder[1],\n                        path,\n                        message: `Template input \"${indexPlaceholder[1]}\" does not resolve to an exported ${collection} element.`,\n                    });\n                    continue;\n                }\n                socket.value = [remapped];\n            } else if (rootPlaceholder && /^(0|[1-9]\\d*)$/.test(segments[2])) {\n                const sourceIndex = parseInt(segments[2], 10);\n                const remapped = this._getRemappedRootIndex(collection as KhrInteractivityRootCollection, sourceIndex, context);\n                if (remapped === undefined) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"REFERENCE_UNRESOLVED\",\n                        graphIndex,\n                        nodeIndex: logicalNode.sourceIndex,\n                        path: `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/configuration/${key}`,\n                        message: `Static ${collection} index ${sourceIndex} does not resolve to an exported element.`,\n                    });\n                } else {\n                    segments[2] = String(remapped);\n                    node.configuration![key].value![0] = segments.join(\"/\");\n                }\n            }\n        }\n    }\n\n    private _updateVariables(graph: IKHRInteractivity_Graph, flowGraph: FlowGraph, diagnostics: IKHRInteractivityExportDiagnostic[], graphIndex: number): void {\n        const provenance = flowGraph.metadata?.khrInteractivity as IKHRInteractivityGraphProvenance | undefined;\n        if (provenance?.authoredVariableStructureChanged) {\n            _PushDiagnostic(diagnostics, {\n                code: \"VALUE_UNREPRESENTABLE\",\n                graphIndex,\n                path: `/graphs/${graphIndex}/variables`,\n                message: \"Adding, renaming, or deleting variables from an imported KHR_interactivity graph is not supported by lossless export.\",\n            });\n        }\n        const authoredValues = provenance?.authoredVariableValues;\n        const authoredTypes = provenance?.authoredVariableTypes;\n        if (!authoredValues && !authoredTypes) {\n            return;\n        }\n        for (const [indexText, flowGraphType] of Object.entries(authoredTypes ?? {})) {\n            const index = Number(indexText);\n            const variable = graph.variables?.[index];\n            const type = _GetOrAddVariableTypeIndex(graph, flowGraphType);\n            if (!variable || type === undefined) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"VALUE_UNREPRESENTABLE\",\n                    graphIndex,\n                    path: `/graphs/${graphIndex}/variables/${index}/type`,\n                    message: `Authored variable type \"${flowGraphType}\" cannot be represented by KHR_interactivity.`,\n                });\n                continue;\n            }\n            variable.type = type;\n        }\n        for (const [indexText, authoredValue] of Object.entries(authoredValues ?? {})) {\n            const index = Number(indexText);\n            const variable = graph.variables![index];\n            if (!variable) {\n                _PushDiagnostic(diagnostics, {\n                    code: \"VALUE_UNREPRESENTABLE\",\n                    graphIndex,\n                    path: `/graphs/${graphIndex}/variables/${index}`,\n                    message: `Authored variable index ${index} does not exist in the canonical graph.`,\n                });\n                continue;\n            }\n            const normalized = _NormalizeValue(authoredValue);\n            const signature = graph.types?.[variable.type]?.signature;\n            if (!normalized || !signature) {\n                continue;\n            }\n            variable.value = normalized as NonNullable<IKHRInteractivity_Variable[\"value\"]>;\n        }\n    }\n\n    private _remapValueArray(\n        value: unknown[],\n        signature: string,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[],\n        graphIndex: number,\n        nodeIndex?: number,\n        referenceHint?: string | null\n    ): NonNullable<IKHRInteractivity_Variable[\"value\"]> {\n        if (signature !== \"ref\") {\n            return value as NonNullable<IKHRInteractivity_Variable[\"value\"]>;\n        }\n        return value.map((entry) => {\n            if (typeof entry === \"string\") {\n                const hintedCollection = referenceHint?.match(/^\\/([^/]+)\\//)?.[1];\n                if (hintedCollection && _KnownIndexedRootCollections.has(hintedCollection)) {\n                    return this._remapReferenceToCollection(entry, hintedCollection, context, diagnostics, graphIndex, nodeIndex);\n                }\n                return this._remapReference(entry, context, diagnostics, graphIndex, nodeIndex);\n            }\n            if (entry !== null && typeof entry === \"object\") {\n                const hintedCollection = referenceHint?.match(/^\\/([^/]+)\\//)?.[1];\n                if (hintedCollection && _KnownIndexedRootCollections.has(hintedCollection) && context.getRootIndex) {\n                    const index = context.getRootIndex(hintedCollection as KhrInteractivityRootCollection, entry);\n                    if (index !== undefined) {\n                        return `/${hintedCollection}/${index}`;\n                    }\n                }\n                const candidates: [string, number | undefined][] = [\n                    [\"animations\", context.getAnimationIndex(entry as AnimationGroup)],\n                    [\"cameras\", context.getCameraIndex(entry as Camera)],\n                    [\"materials\", context.getMaterialIndex(entry as Material)],\n                    [\"nodes\", context.getNodeIndex(entry as Node)],\n                ];\n                const matches = (hintedCollection ? candidates.filter(([collection]) => collection === hintedCollection) : referenceHint === null ? [] : candidates).filter(\n                    ([, index]) => index !== undefined\n                );\n                if (matches.length === 1) {\n                    return `/${matches[0][0]}/${matches[0][1]}`;\n                }\n                if (this._isPreflight) {\n                    return \"\";\n                }\n            }\n            _PushDiagnostic(diagnostics, {\n                code: \"REFERENCE_UNRESOLVED\",\n                graphIndex,\n                nodeIndex,\n                path: `/graphs/${graphIndex}${nodeIndex === undefined ? \"\" : `/nodes/${nodeIndex}`}`,\n                message: \"An authored reference value does not resolve to an exported glTF entity.\",\n            });\n            return \"\";\n        }) as NonNullable<IKHRInteractivity_Variable[\"value\"]>;\n    }\n\n    private _topologicallyOrderNodes(nodes: IKHRInteractivity_Node[], graphIndex: number, diagnostics: IKHRInteractivityExportDiagnostic[]): IOrderedNodes | undefined {\n        const outgoing = nodes.map(() => new Set<number>());\n        const indegree = nodes.map(() => 0);\n        let hasInvalidDependency = false;\n        const addEdge = (source: number, target: number) => {\n            if (source < 0 || target < 0 || source >= nodes.length || target >= nodes.length) {\n                hasInvalidDependency = true;\n                _PushDiagnostic(diagnostics, {\n                    code: \"SOCKET_TARGET_UNREPRESENTABLE\",\n                    graphIndex,\n                    path: `/graphs/${graphIndex}/nodes`,\n                    message: `Dependency ${source} -> ${target} references a node outside the exported graph.`,\n                });\n                return;\n            }\n            if (source === target) {\n                hasInvalidDependency = true;\n                _PushDiagnostic(diagnostics, {\n                    code: \"DEPENDENCY_CYCLE\",\n                    graphIndex,\n                    nodeIndex: source,\n                    path: `/graphs/${graphIndex}/nodes/${source}`,\n                    message: \"A KHR_interactivity node cannot depend on itself.\",\n                });\n                return;\n            }\n            if (outgoing[source].has(target)) {\n                return;\n            }\n            outgoing[source].add(target);\n            indegree[target]++;\n        };\n        for (let target = 0; target < nodes.length; target++) {\n            for (const value of Object.values(nodes[target].values ?? {})) {\n                if (\"node\" in value) {\n                    addEdge(value.node, target);\n                }\n            }\n            for (const flow of Object.values(nodes[target].flows ?? {})) {\n                addEdge(target, flow.node);\n            }\n        }\n        if (hasInvalidDependency) {\n            return undefined;\n        }\n        const ready = indegree.flatMap((count, index) => (count === 0 ? [index] : []));\n        const order: number[] = [];\n        while (ready.length > 0) {\n            ready.sort((left, right) => left - right);\n            const current = ready.shift()!;\n            order.push(current);\n            for (const target of outgoing[current]) {\n                indegree[target]--;\n                if (indegree[target] === 0) {\n                    ready.push(target);\n                }\n            }\n        }\n        if (order.length !== nodes.length) {\n            _PushDiagnostic(diagnostics, {\n                code: \"DEPENDENCY_CYCLE\",\n                graphIndex,\n                path: `/graphs/${graphIndex}/nodes`,\n                message: \"Value and flow dependencies form a cycle that cannot satisfy KHR_interactivity node ordering constraints.\",\n            });\n            return undefined;\n        }\n        const remap = new Map(order.map((oldIndex, newIndex) => [oldIndex, newIndex]));\n        const ordered = order.map((index) => nodes[index]);\n        for (const node of ordered) {\n            for (const value of Object.values(node.values ?? {})) {\n                if (\"node\" in value) {\n                    value.node = remap.get(value.node)!;\n                }\n            }\n            for (const flow of Object.values(node.flows ?? {})) {\n                flow.node = remap.get(flow.node)!;\n            }\n        }\n        return { nodes: ordered, sourceIndices: order };\n    }\n\n    private _remapGraphReferences(\n        graph: IKHRInteractivity_Graph,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[],\n        graphIndex: number,\n        sourceIndices: readonly number[]\n    ): void {\n        for (let variableIndex = 0; variableIndex < (graph.variables?.length ?? 0); variableIndex++) {\n            const variable = graph.variables![variableIndex];\n            if (graph.types?.[variable.type]?.signature === \"ref\" && variable.value) {\n                const sourceValue = this._options.document?.graphs[graphIndex]?.source.variables?.[variableIndex]?.value?.[0];\n                const currentValue = variable.value[0];\n                const consumerCollection = this._getVariableReferenceCollection(graph, variableIndex);\n                const referenceHint =\n                    consumerCollection === null\n                        ? null\n                        : consumerCollection\n                          ? `/${consumerCollection}/0`\n                          : typeof currentValue === \"object\" || currentValue === sourceValue\n                            ? typeof sourceValue === \"string\"\n                                ? sourceValue\n                                : undefined\n                            : undefined;\n                variable.value = this._remapValueArray(variable.value, \"ref\", context, diagnostics, graphIndex, undefined, referenceHint);\n            }\n        }\n\n        for (const event of graph.events ?? []) {\n            for (const value of Object.values(event.values ?? {})) {\n                if (graph.types?.[value.type]?.signature === \"ref\" && value.value) {\n                    value.value = this._remapValueArray(value.value, \"ref\", context, diagnostics, graphIndex);\n                }\n            }\n        }\n        for (let nodeIndex = 0; nodeIndex < (graph.nodes?.length ?? 0); nodeIndex++) {\n            const node = graph.nodes![nodeIndex];\n            const sourceNodeIndex = sourceIndices[nodeIndex] ?? nodeIndex;\n            const declaration = graph.declarations?.[node.declaration];\n            const mapping = declaration ? getMappingForDeclaration(declaration, false) : undefined;\n            for (const [socket, value] of Object.entries(node.values ?? {})) {\n                if (!(\"node\" in value) && graph.types?.[value.type]?.signature === \"ref\" && value.value) {\n                    const pointerCollection = this._getPointerReferenceCollection(node, mapping, socket);\n                    if (pointerCollection === null) {\n                        _PushDiagnostic(diagnostics, {\n                            code: \"REFERENCE_UNRESOLVED\",\n                            graphIndex,\n                            nodeIndex: sourceNodeIndex,\n                            socket,\n                            path: `/graphs/${graphIndex}/nodes/${sourceNodeIndex}/values/${socket}`,\n                            message: `Pointer template collection for reference input \"${socket}\" cannot be resolved statically.`,\n                        });\n                        continue;\n                    }\n                    const sourceValue = this._options.document?.graphs[graphIndex]?.source.nodes?.[sourceNodeIndex]?.values?.[socket];\n                    const sourceReference = sourceValue && !(\"node\" in sourceValue) ? sourceValue.value?.[0] : undefined;\n                    const currentReference = value.value[0];\n                    const referenceHint = pointerCollection\n                        ? `/${pointerCollection}/0`\n                        : typeof currentReference === \"object\" || currentReference === sourceReference\n                          ? typeof sourceReference === \"string\"\n                              ? sourceReference\n                              : undefined\n                          : undefined;\n                    value.value = this._remapValueArray(value.value, \"ref\", context, diagnostics, graphIndex, sourceNodeIndex, referenceHint);\n                }\n            }\n            for (const [key, property] of Object.entries(mapping?.configuration ?? {})) {\n                if (!property.pointerTemplate) {\n                    continue;\n                }\n                const configuration = node.configuration?.[key];\n                if (configuration?.value) {\n                    configuration.value = configuration.value.map((value) =>\n                        typeof value === \"string\" ? this._remapReference(value, context, diagnostics, graphIndex, sourceNodeIndex) : value\n                    );\n                }\n            }\n        }\n    }\n\n    private _getVariableReferenceCollection(graph: IKHRInteractivity_Graph, variableIndex: number): string | null | undefined {\n        const getterNodes = new Set<number>();\n        for (let nodeIndex = 0; nodeIndex < (graph.nodes?.length ?? 0); nodeIndex++) {\n            const node = graph.nodes![nodeIndex];\n            const declaration = graph.declarations?.[node.declaration];\n            if (declaration?.op === \"variable/get\" && !declaration.extension && node.configuration?.variable?.value?.[0] === variableIndex) {\n                getterNodes.add(nodeIndex);\n            }\n        }\n        const collections = new Set<string>();\n        for (const node of graph.nodes ?? []) {\n            const declaration = graph.declarations?.[node.declaration];\n            const mapping = declaration ? getMappingForDeclaration(declaration, false) : undefined;\n            for (const [socket, value] of Object.entries(node.values ?? {})) {\n                if (!(\"node\" in value) || !getterNodes.has(value.node)) {\n                    continue;\n                }\n                const collection = this._getPointerReferenceCollection(node, mapping, socket);\n                if (collection === null) {\n                    return null;\n                }\n                if (collection) {\n                    collections.add(collection);\n                }\n            }\n        }\n        return collections.size === 1 ? collections.values().next().value : collections.size > 1 ? null : undefined;\n    }\n\n    private _getPointerReferenceCollection(node: IKHRInteractivity_Node, mapping: IGLTFToFlowGraphMapping | undefined, socket: string): string | null | undefined {\n        for (const [key, property] of Object.entries(mapping?.configuration ?? {})) {\n            if (!property.pointerTemplate) {\n                continue;\n            }\n            const pointer = node.configuration?.[key]?.value?.[0];\n            if (typeof pointer !== \"string\") {\n                continue;\n            }\n            const segments = pointer.split(\"/\");\n            const placeholderIndex = segments.findIndex((segment) => segment === `{${socket}}`);\n            if (placeholderIndex > 1) {\n                const parentSegment = segments[placeholderIndex - 1];\n                const parentPlaceholder = /^\\{([^\\{\\}]+)\\}$/.exec(parentSegment);\n                const parentValue = parentPlaceholder ? node.values?.[parentPlaceholder[1]] : undefined;\n                const parentReference = parentValue && !(\"node\" in parentValue) ? parentValue.value?.[0] : undefined;\n                const collection = (parentPlaceholder && typeof parentReference === \"string\" ? (/^\\/([^/]+)$/.exec(parentReference)?.[1] ?? \"\") : parentSegment)\n                    .replace(/~1/g, \"/\")\n                    .replace(/~0/g, \"~\");\n                if (_KnownIndexedRootCollections.has(collection)) {\n                    return collection;\n                }\n                if (parentPlaceholder) {\n                    return null;\n                }\n            }\n        }\n        return undefined;\n    }\n\n    private _getRemappedRootIndex(collection: KhrInteractivityRootCollection, sourceIndex: number, context: IKHRInteractivitySerializerContext): number | undefined {\n        const indices = new Set(\n            this._getSourceRootObjects(collection, sourceIndex)\n                .map((target) => this._getExportedObjectIndex(collection, target, context))\n                .filter((index): index is number => index !== undefined)\n        );\n        return indices.size === 1 ? indices.values().next().value : undefined;\n    }\n\n    private _getSourceRootObjects(collection: KhrInteractivityRootCollection, sourceIndex: number): object[] {\n        const sourceGLTF = this._options.sourceGLTF;\n        switch (collection) {\n            case \"nodes\":\n                return sourceGLTF?.nodes?.[sourceIndex]?._babylonTransformNode ? [sourceGLTF.nodes[sourceIndex]._babylonTransformNode!] : [];\n            case \"animations\":\n                return sourceGLTF?.animations?.[sourceIndex]?._babylonAnimationGroup ? [sourceGLTF.animations[sourceIndex]._babylonAnimationGroup!] : [];\n            case \"cameras\":\n                return sourceGLTF?.cameras?.[sourceIndex]?._babylonCamera ? [sourceGLTF.cameras[sourceIndex]._babylonCamera!] : [];\n            case \"materials\":\n                return Array.from(new Set(Object.values(sourceGLTF?.materials?.[sourceIndex]?._data ?? {}).map((entry) => entry.babylonMaterial)));\n            case \"meshes\":\n                return Array.from(\n                    new Set([\n                        ...(sourceGLTF?.meshes?.[sourceIndex]?.primitives.flatMap((primitive) => (primitive._instanceData ? [primitive._instanceData.babylonSourceMesh] : [])) ??\n                            []),\n                        ...(sourceGLTF?.nodes\n                            ?.filter((node) => node.mesh === sourceIndex)\n                            .flatMap((node) => [...(node._babylonTransformNode ? [node._babylonTransformNode] : []), ...(node._primitiveBabylonMeshes ?? [])]) ?? []),\n                    ])\n                );\n            case \"textures\":\n                return sourceGLTF?.textures?.[sourceIndex]?._babylonTextures?.slice() ?? [];\n            case \"images\":\n                return Array.from(\n                    new Set(\n                        sourceGLTF?.textures\n                            ?.flatMap((texture) => texture._babylonTextureSources ?? [])\n                            .filter((source) => source.imageIndex === sourceIndex)\n                            .map((source) => source.babylonTexture) ?? []\n                    )\n                );\n            case \"samplers\":\n                return Array.from(\n                    new Set(\n                        sourceGLTF?.textures\n                            ?.flatMap((texture) => texture._babylonTextureSources ?? [])\n                            .filter((source) => source.samplerIndex === sourceIndex)\n                            .map((source) => source.babylonTexture) ?? []\n                    )\n                );\n            case \"skins\":\n                return sourceGLTF?.skins?.[sourceIndex]?._data?.babylonSkeleton ? [sourceGLTF.skins[sourceIndex]._data!.babylonSkeleton] : [];\n            case \"scenes\":\n                return sourceIndex === (sourceGLTF?.scene ?? 0) && this._flowGraphs[0]?.scene ? [this._flowGraphs[0].scene] : [];\n        }\n    }\n\n    private _getSourceRootIndex(collection: KhrInteractivityRootCollection, target: object): number | undefined {\n        const roots = this._options.sourceGLTF?.[collection];\n        if (!roots) {\n            return undefined;\n        }\n        const matches: number[] = [];\n        for (let index = 0; index < roots.length; index++) {\n            if (this._getSourceRootObjects(collection, index).includes(target)) {\n                matches.push(index);\n            }\n        }\n        return matches.length === 1 ? matches[0] : undefined;\n    }\n\n    private _getExportedObjectIndex(collection: KhrInteractivityRootCollection, target: object, context: IKHRInteractivitySerializerContext): number | undefined {\n        if (context.getRootIndex) {\n            return context.getRootIndex(collection, target);\n        }\n        switch (collection) {\n            case \"nodes\":\n                return context.getNodeIndex(target as Node);\n            case \"animations\":\n                return context.getAnimationIndex(target as AnimationGroup);\n            case \"cameras\":\n                return context.getCameraIndex(target as Camera);\n            case \"materials\":\n                return context.getMaterialIndex(target as Material);\n            default:\n                return undefined;\n        }\n    }\n\n    private _remapReferenceToCollection(\n        reference: string,\n        targetCollection: string,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[],\n        graphIndex: number,\n        nodeIndex?: number\n    ): string {\n        if (!this._validateExtensionReferencePreservation(reference, targetCollection, diagnostics, graphIndex, nodeIndex)) {\n            return reference;\n        }\n        const match = reference.match(/^\\/([^/]+)\\/(0|[1-9]\\d*)(\\/.*)?$/);\n        if (!match || !_KnownIndexedRootCollections.has(match[1])) {\n            return this._remapReference(reference, context, diagnostics, graphIndex, nodeIndex);\n        }\n        const targets = this._getSourceRootObjects(targetCollection as KhrInteractivityRootCollection, parseInt(match[2], 10));\n        const targetIndices = new Set(\n            targets\n                .map((target) => this._getExportedObjectIndex(targetCollection as KhrInteractivityRootCollection, target, context))\n                .filter((index): index is number => index !== undefined)\n        );\n        const targetIndex = targetIndices.size === 1 ? targetIndices.values().next().value : undefined;\n        if (targetIndex === undefined) {\n            _PushDiagnostic(diagnostics, {\n                code: \"REFERENCE_UNRESOLVED\",\n                graphIndex,\n                nodeIndex,\n                path: `/graphs/${graphIndex}${nodeIndex === undefined ? \"\" : `/nodes/${nodeIndex}`}`,\n                message: `Reference \"${reference}\" cannot be remapped to the exported ${targetCollection} collection.`,\n            });\n            return reference;\n        }\n        return `/${targetCollection}/${targetIndex}${match[3] ?? \"\"}`;\n    }\n\n    private _remapReference(\n        reference: string,\n        context: IKHRInteractivitySerializerContext,\n        diagnostics: IKHRInteractivityExportDiagnostic[],\n        graphIndex: number,\n        nodeIndex?: number\n    ): string {\n        if (!reference || reference.startsWith(\"/extensions/KHR_interactivity/events/\") || reference.startsWith(\"/extensions/KHR_interactivity/delays/\")) {\n            return reference;\n        }\n        const extensionCollection = /^\\/extensions\\/([^/]+)\\/[^/]+\\/(0|[1-9]\\d*)(?:\\/|$)/.exec(reference);\n        if (extensionCollection && extensionCollection[1] !== \"KHR_interactivity\") {\n            _PushDiagnostic(diagnostics, {\n                code: \"REFERENCE_UNRESOLVED\",\n                graphIndex,\n                nodeIndex,\n                path: `/graphs/${graphIndex}${nodeIndex === undefined ? \"\" : `/nodes/${nodeIndex}`}`,\n                message: `Indexed reference \"${reference}\" belongs to ${extensionCollection[1]}, whose serializer index mapping is unavailable.`,\n            });\n            return reference;\n        }\n        const match = reference.match(/^\\/([^/]+)\\/(0|[1-9]\\d*)(\\/.*)?$/);\n        if (!match || !_KnownIndexedRootCollections.has(match[1])) {\n            return reference;\n        }\n        if (!this._validateExtensionReferencePreservation(reference, match[1], diagnostics, graphIndex, nodeIndex)) {\n            return reference;\n        }\n        const collection = match[1];\n        const sourceIndex = parseInt(match[2], 10);\n        const targetIndex = this._getRemappedRootIndex(collection as KhrInteractivityRootCollection, sourceIndex, context);\n        if (targetIndex === undefined) {\n            _PushDiagnostic(diagnostics, {\n                code: \"REFERENCE_UNRESOLVED\",\n                graphIndex,\n                nodeIndex,\n                path: `/graphs/${graphIndex}${nodeIndex === undefined ? \"\" : `/nodes/${nodeIndex}`}`,\n                message: `Reference \"${reference}\" cannot be remapped because its ${collection} target was not exported uniquely.`,\n            });\n            return reference;\n        }\n        return `/${collection}/${targetIndex}${match[3] ?? \"\"}`;\n    }\n\n    private _validateExtensionReferencePreservation(\n        reference: string,\n        resolvedCollection: string,\n        diagnostics: IKHRInteractivityExportDiagnostic[],\n        graphIndex: number,\n        nodeIndex?: number,\n        path = `/graphs/${graphIndex}${nodeIndex === undefined ? \"\" : `/nodes/${nodeIndex}`}`\n    ): boolean {\n        const nestedExtensions = _GetPointerExtensionNames(reference).filter((extension) => extension !== \"KHR_interactivity\");\n        if (nestedExtensions.length === 0 || _CanPreserveNestedExtensionPointer(reference, resolvedCollection)) {\n            return true;\n        }\n        _PushDiagnostic(diagnostics, {\n            code: \"REFERENCE_UNRESOLVED\",\n            graphIndex,\n            nodeIndex,\n            path,\n            message: `Reference \"${reference}\" observes extension-backed data (${nestedExtensions.join(\n                \", \"\n            )}) that the serializer cannot guarantee will retain its source semantics.`,\n        });\n        return false;\n    }\n\n    private _collectAdditionalExtensions(): string[] {\n        const extensions = new Set<string>();\n        const collectReferenceExtension = (value: unknown): void => {\n            if (typeof value !== \"string\") {\n                return;\n            }\n            for (const extensionName of _GetPointerExtensionNames(value)) {\n                if (extensionName !== \"KHR_interactivity\") {\n                    extensions.add(extensionName);\n                }\n            }\n        };\n        const collectPropertyExtensions = (value: unknown): void => {\n            if (Array.isArray(value)) {\n                value.forEach(collectPropertyExtensions);\n                return;\n            }\n            if (value === null || typeof value !== \"object\") {\n                return;\n            }\n            const object = value as Record<string, unknown>;\n            for (const [key, entry] of Object.entries(object)) {\n                if (key === \"extras\") {\n                    continue;\n                }\n                if (key === \"extensions\" && entry !== null && typeof entry === \"object\" && !Array.isArray(entry)) {\n                    for (const [extensionName, extensionPayload] of Object.entries(entry as Record<string, unknown>)) {\n                        if (extensionName !== \"KHR_interactivity\") {\n                            extensions.add(extensionName);\n                        }\n                        collectPropertyExtensions(extensionPayload);\n                    }\n                    continue;\n                }\n                if (key !== \"extensions\") {\n                    collectPropertyExtensions(entry);\n                }\n            }\n        };\n        collectPropertyExtensions(this._options.document?.source);\n        for (const analysis of this._graphAnalyses) {\n            collectPropertyExtensions(analysis.source);\n            for (const variable of analysis.source.variables ?? []) {\n                if (analysis.source.types?.[variable.type]?.signature === \"ref\") {\n                    variable.value?.forEach(collectReferenceExtension);\n                }\n            }\n            for (const event of analysis.source.events ?? []) {\n                for (const value of Object.values(event.values ?? {})) {\n                    if (value && typeof value === \"object\" && analysis.source.types?.[value.type]?.signature === \"ref\") {\n                        value.value?.forEach(collectReferenceExtension);\n                    }\n                }\n            }\n            for (const declaration of analysis.source.declarations ?? []) {\n                if (declaration.extension) {\n                    extensions.add(declaration.extension);\n                }\n            }\n            for (const node of analysis.source.nodes ?? []) {\n                for (const value of Object.values(node.values ?? {})) {\n                    if (value && typeof value === \"object\" && !(\"node\" in value) && analysis.source.types?.[value.type]?.signature === \"ref\") {\n                        value.value?.forEach(collectReferenceExtension);\n                    }\n                }\n                const declaration = analysis.source.declarations?.[node.declaration];\n                const mapping = declaration ? getMappingForDeclaration(declaration, false) : undefined;\n                for (const [key, property] of Object.entries(mapping?.configuration ?? {})) {\n                    if (property.pointerTemplate) {\n                        node.configuration?.[key]?.value?.forEach(collectReferenceExtension);\n                    }\n                }\n            }\n        }\n        for (const node of this._options.sourceGLTF?.nodes ?? []) {\n            for (const extensionName of _CompanionNodeExtensions) {\n                const extension = node.extensions?.[extensionName];\n                if (extension) {\n                    extensions.add(extensionName);\n                    collectPropertyExtensions(extension);\n                }\n            }\n        }\n        return Array.from(extensions).sort();\n    }\n\n    private _writeCompanionNodeExtensions(context: IKHRInteractivitySerializerContext, diagnostics: IKHRInteractivityExportDiagnostic[]): void {\n        for (let sourceIndex = 0; sourceIndex < (this._options.sourceGLTF?.nodes?.length ?? 0); sourceIndex++) {\n            const sourceNode = this._options.sourceGLTF!.nodes![sourceIndex];\n            for (const extensionName of _CompanionNodeExtensions) {\n                const value = sourceNode.extensions?.[extensionName];\n                if (!value) {\n                    continue;\n                }\n                const targetIndex = sourceNode._babylonTransformNode ? context.getNodeIndex(sourceNode._babylonTransformNode) : undefined;\n                if (targetIndex === undefined) {\n                    _PushDiagnostic(diagnostics, {\n                        code: \"REFERENCE_UNRESOLVED\",\n                        path: `/nodes/${sourceIndex}/extensions/${extensionName}`,\n                        message: `Companion extension \"${extensionName}\" targets a node that was not exported.`,\n                    });\n                    continue;\n                }\n                context.setNodeExtension(targetIndex, extensionName, _CloneJson(value));\n            }\n        }\n    }\n\n    private _sortDiagnostics(diagnostics: IKHRInteractivityExportDiagnostic[]): IKHRInteractivityExportDiagnostic[] {\n        return diagnostics\n            .slice()\n            .sort(\n                (left, right) =>\n                    (left.graphIndex ?? -1) - (right.graphIndex ?? -1) ||\n                    (left.nodeIndex ?? -1) - (right.nodeIndex ?? -1) ||\n                    left.path.localeCompare(right.path) ||\n                    left.code.localeCompare(right.code)\n            );\n    }\n}\n\n/**\n * Creates a detached KHR_interactivity export plan without mutating the FlowGraphs.\n * @param flowGraphs graphs to export in root graph order\n * @param options canonical source and serializer settings\n * @returns reusable representability/export provider\n */\nexport function CreateKHRInteractivityExportPlan(flowGraphs: readonly FlowGraph[], options: IKHRInteractivityExportOptions = {}): KHRInteractivityExportPlan {\n    return new KHRInteractivityExportPlan(flowGraphs, options);\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type IKHRInteractivity } from \"babylonjs-gltf2interface\";\r\nimport { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { FlowGraphCoordinator } from \"core/FlowGraph/flowGraphCoordinator\";\r\nimport { ParseFlowGraphAsync } from \"core/FlowGraph/flowGraphParser\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension, registeredGLTFExtensions } from \"../glTFLoaderExtensionRegistry\";\r\nimport { type GLTFPathToObjectConverter } from \"./gltfPathToObjectConverter\";\r\nimport { AddObjectAccessorToKey, GetPathToObjectConverter } from \"./objectModelMapping\";\r\nimport { _CaptureKHRInteractivityRuntimeInputDefaults, InteractivityGraphToFlowGraphParser } from \"./KHR_interactivity/interactivityGraphParser\";\r\nimport { addToBlockFactory } from \"core/FlowGraph/Blocks/flowGraphBlockFactory\";\r\nimport { Quaternion, Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Camera } from \"core/Cameras/camera\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { type IAnimation } from \"../glTFLoaderInterfaces\";\r\nimport { CompositePathToObjectConverter, type IPathConverterPrefixEntry } from \"./compositePathToObjectConverter\";\r\nimport { BabylonScenePathToObjectConverter, BABYLON_SCENE_OBJECT_MODEL_PREFIX, CreateDefaultBabylonSceneObjectModelTree } from \"./babylonScenePathToObjectConverter\";\r\nimport { InteractivityRefPathToObjectConverter } from \"./interactivityRefPathToObjectConverter\";\r\nimport { InteractivityAssetPathToObjectConverter, InteractivityAssetCapabilitiesPrefix, InteractivityLimitsPrefix } from \"./interactivityAssetPathToObjectConverter\";\r\nimport { EventReferencePrefix, DelayReferencePrefix } from \"./KHR_interactivity/interactivityReferences\";\r\nimport { InteractivityHostResolver } from \"./KHR_interactivity/interactivityHostResolver\";\r\nimport { type IObjectAccessor, type ISerializedFlowGraph } from \"core/FlowGraph/typeDefinitions\";\r\nimport { type IPathToObjectConverter } from \"core/ObjectModel/objectModelInterfaces\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport {\r\n    CreateKHRInteractivityDocument,\r\n    type IKHRInteractivityDiagnostic,\r\n    type IKHRInteractivityDocument,\r\n    type IKHRInteractivityGraphModel,\r\n} from \"./KHR_interactivity/interactivityGraphModel\";\r\nimport { type FlowGraph } from \"core/FlowGraph/flowGraph\";\r\n\r\nexport * from \"./KHR_interactivity/interactivityGraphExporter\";\r\nexport { _CaptureKHRInteractivityRuntimeInputDefaults } from \"./KHR_interactivity/interactivityGraphParser\";\r\n\r\nconst NAME = \"KHR_interactivity\";\r\n\r\n/**\r\n * Runtime projection of one canonical KHR_interactivity graph.\r\n */\r\nexport interface IKHRInteractivityGraphImportResult {\r\n    /** Canonical source graph and diagnostics. */\r\n    graph: IKHRInteractivityGraphModel;\r\n    /** Executable FlowGraph serialization when lowering succeeded. */\r\n    serializedFlowGraph?: ISerializedFlowGraph;\r\n    /** Runtime FlowGraph when runtime construction was requested. */\r\n    flowGraph?: FlowGraph;\r\n    /** Coordinator that owns the runtime FlowGraph. */\r\n    coordinator?: FlowGraphCoordinator;\r\n    /** Additional lowering/runtime diagnostics. */\r\n    diagnostics: IKHRInteractivityDiagnostic[];\r\n}\r\n\r\n/**\r\n * Completed KHR_interactivity import result associated with a loaded scene.\r\n */\r\nexport interface IKHRInteractivityImportResult {\r\n    /** Stable zero-based identity of this interactivity asset among assets appended to the scene. */\r\n    assetIndex: number;\r\n    /** Canonical, lossless source document. */\r\n    document: IKHRInteractivityDocument;\r\n    /** Graph import results in source order. */\r\n    graphs: IKHRInteractivityGraphImportResult[];\r\n    /** Shared path converter required by pointer blocks. */\r\n    pathConverter: CompositePathToObjectConverter<IObjectAccessor>;\r\n    /** Live glTF loader data used by glTF data-provider blocks. */\r\n    glTF: GLTFLoader[\"gltf\"];\r\n    /** Scene that owns the imported asset and its runtime object mappings, when retained by the importer. */\r\n    scene?: Scene;\r\n    /** Host resolver that supplies KHR reference semantics to executable graphs. */\r\n    hostResolver: InteractivityHostResolver;\r\n}\r\n\r\nconst _ImportResults = /*#__PURE__*/ new WeakMap<Scene, IKHRInteractivityImportResult[]>();\r\n\r\n/**\r\n * Gets the completed KHR_interactivity import result for a loaded scene.\r\n * @param scene scene loaded from the glTF asset\r\n * @returns the import result, or undefined when the scene has no KHR_interactivity data\r\n */\r\nexport function GetKHRInteractivityImportResult(scene: Scene): IKHRInteractivityImportResult | undefined {\r\n    const results = _ImportResults.get(scene);\r\n    return results?.[results.length - 1];\r\n}\r\n\r\n/**\r\n * Gets every completed KHR_interactivity import result appended to a loaded scene.\r\n * Results remain in asset load order and each result has a stable {@link IKHRInteractivityImportResult.assetIndex}.\r\n * @param scene scene containing the loaded glTF assets\r\n * @returns the scene's import results, or an empty array when it has no KHR_interactivity data\r\n */\r\nexport function GetKHRInteractivityImportResults(scene: Scene): readonly IKHRInteractivityImportResult[] {\r\n    return _ImportResults.get(scene) ?? [];\r\n}\r\n\r\n/**\r\n * Loader extension for KHR_interactivity\r\n */\r\nexport class KHR_interactivity implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n    /** Runs after extensions that contribute interactivity operations and object state. */\r\n    public readonly order = 200;\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _gltfPathConverter?: GLTFPathToObjectConverter<any, any, any>;\r\n    private _pathConverter?: CompositePathToObjectConverter<IObjectAccessor>;\r\n\r\n    /**\r\n     * @internal\r\n     * @param _loader\r\n     */\r\n    constructor(private _loader: GLTFLoader) {\r\n        this.enabled = this._loader.isExtensionUsed(NAME);\r\n        // avoid starting animations automatically.\r\n        _loader._skipStartAnimationStep = true;\r\n    }\r\n\r\n    private _initializePathConverter(scene: Scene): CompositePathToObjectConverter<IObjectAccessor> {\r\n        this._gltfPathConverter = GetPathToObjectConverter(this._loader.gltf, (mapping) => _AddInteractivityObjectModel(scene, this._loader.parent.targetFps, mapping));\r\n        const initialPrefixes: IPathConverterPrefixEntry<IObjectAccessor>[] = [\r\n            {\r\n                prefix: BABYLON_SCENE_OBJECT_MODEL_PREFIX,\r\n                converter: new BabylonScenePathToObjectConverter(scene, CreateDefaultBabylonSceneObjectModelTree()),\r\n            },\r\n        ];\r\n        const refConverter = new InteractivityRefPathToObjectConverter();\r\n        initialPrefixes.push({ prefix: EventReferencePrefix, converter: refConverter });\r\n        initialPrefixes.push({ prefix: DelayReferencePrefix, converter: refConverter });\r\n        const enabledExtensions = new Set(\r\n            (this._loader.gltf.extensionsUsed ?? []).filter((name) => registeredGLTFExtensions.has(name) && this._loader.parent.extensionOptions[name]?.enabled !== false)\r\n        );\r\n        const assetConverter = new InteractivityAssetPathToObjectConverter(this._loader.gltf, (extensionName) => enabledExtensions.has(extensionName));\r\n        initialPrefixes.push({ prefix: InteractivityAssetCapabilitiesPrefix, converter: assetConverter });\r\n        initialPrefixes.push({ prefix: InteractivityLimitsPrefix, converter: assetConverter });\r\n        const pathConverter = new CompositePathToObjectConverter<IObjectAccessor>(initialPrefixes, this._gltfPathConverter as unknown as IPathToObjectConverter<IObjectAccessor>);\r\n        this._pathConverter = pathConverter;\r\n        return pathConverter;\r\n    }\r\n\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n        delete this._gltfPathConverter;\r\n        delete this._pathConverter;\r\n    }\r\n\r\n    public async onReady(): Promise<void> {\r\n        if (!this._loader.babylonScene) {\r\n            return;\r\n        }\r\n        const scene = this._loader.babylonScene;\r\n        const pathConverter = this._initializePathConverter(scene);\r\n        const interactivityDefinition = this._loader.gltf.extensions?.KHR_interactivity as IKHRInteractivity;\r\n        if (!interactivityDefinition) {\r\n            // This can technically throw, but it's not a critical error\r\n            return;\r\n        }\r\n\r\n        const supportedExtensions = new Set(\r\n            (this._loader.gltf.extensionsUsed ?? []).filter((extensionName) => this._loader.parent.extensionOptions[extensionName]?.enabled !== false)\r\n        );\r\n        const document = CreateKHRInteractivityDocument(interactivityDefinition, supportedExtensions, this._loader.gltf.nodes?.length ?? 0);\r\n        const options = this._loader.parent.extensionOptions[NAME];\r\n        const autoStart = options?.autoStart ?? true;\r\n        const parseOnly = options?.parseOnly ?? false;\r\n        const strictValidation = options?.strictValidation ?? true;\r\n        const importResults = _ImportResults.get(scene) ?? [];\r\n        const result: IKHRInteractivityImportResult = {\r\n            assetIndex: importResults.length,\r\n            document,\r\n            graphs: [],\r\n            pathConverter,\r\n            glTF: this._loader.gltf,\r\n            scene,\r\n            hostResolver: new InteractivityHostResolver(),\r\n        };\r\n        importResults.push(result);\r\n        _ImportResults.set(scene, importResults);\r\n\r\n        await Promise.all(\r\n            document.graphs.map(async (graphModel) => {\r\n                const graphResult: IKHRInteractivityGraphImportResult = {\r\n                    graph: graphModel,\r\n                    diagnostics: graphModel.diagnostics.slice(),\r\n                };\r\n                result.graphs[graphModel.index] = graphResult;\r\n                if (!graphModel.valid && strictValidation) {\r\n                    Logger.Error(`KHR_interactivity: rejecting behavior graph #${graphModel.index}: ${graphModel.diagnostics.map((diagnostic) => diagnostic.message).join(\"; \")}`);\r\n                    return;\r\n                }\r\n                try {\r\n                    const parser = new InteractivityGraphToFlowGraphParser(\r\n                        strictValidation ? graphModel.effectiveSource : graphModel.source,\r\n                        this._loader.gltf,\r\n                        this._loader.parent.targetFps,\r\n                        graphModel.index,\r\n                        supportedExtensions,\r\n                        strictValidation ? graphModel.declarations : undefined,\r\n                        graphModel.source\r\n                    );\r\n                    const serializedFlowGraph = parser.serializeToFlowGraph();\r\n                    graphResult.serializedFlowGraph = serializedFlowGraph;\r\n                    if (parseOnly) {\r\n                        return;\r\n                    }\r\n                    const coordinator = new FlowGraphCoordinator({ scene, hostResolver: result.hostResolver });\r\n                    coordinator.dispatchEventsSynchronously = false;\r\n                    graphResult.coordinator = coordinator;\r\n                    graphResult.flowGraph = await ParseFlowGraphAsync(serializedFlowGraph, { coordinator, pathConverter });\r\n                    _CaptureKHRInteractivityRuntimeInputDefaults(graphResult.flowGraph);\r\n                    if (autoStart && graphModel.index === document.defaultGraphIndex) {\r\n                        coordinator.start();\r\n                    }\r\n                } catch (error) {\r\n                    const message = (error as Error)?.message ?? String(error);\r\n                    graphResult.diagnostics.push({\r\n                        path: graphModel.path,\r\n                        message,\r\n                        severity: \"error\",\r\n                    });\r\n                    Logger.Error(`KHR_interactivity: rejecting behavior graph #${graphModel.index}: ${message}`);\r\n                    graphResult.coordinator?.dispose();\r\n                    delete graphResult.coordinator;\r\n                    delete graphResult.flowGraph;\r\n                    delete graphResult.serializedFlowGraph;\r\n                }\r\n            })\r\n        );\r\n    }\r\n}\r\n\r\n/**\r\n * @internal\r\n * populates the object model with the interactivity extension\r\n */\r\nexport function _AddInteractivityObjectModel(scene: Scene, targetFps: number, mapping: object) {\r\n    // Note - all of those are read-only, as per the specs!\r\n\r\n    // active camera rotation\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/rotation\",\r\n        {\r\n            get: () => {\r\n                if (!scene.activeCamera) {\r\n                    return new Quaternion(NaN, NaN, NaN, NaN);\r\n                }\r\n                const quat = Quaternion.FromRotationMatrix(scene.activeCamera.getWorldMatrix()).normalize();\r\n                if (!scene.useRightHandedSystem) {\r\n                    quat.w *= -1; // glTF uses right-handed system, while babylon uses left-handed\r\n                    quat.x *= -1; // glTF uses right-handed system, while babylon uses left-handed\r\n                }\r\n                return quat;\r\n            },\r\n            type: \"Quaternion\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // activeCamera position\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/position\",\r\n        {\r\n            get: () => {\r\n                if (!scene.activeCamera) {\r\n                    return new Vector3(NaN, NaN, NaN);\r\n                }\r\n                const pos = scene.activeCamera.getWorldMatrix().getTranslation(); // not global position\r\n                if (!scene.useRightHandedSystem) {\r\n                    pos.x *= -1; // glTF uses right-handed system, while babylon uses left-handed\r\n                }\r\n                return pos;\r\n            },\r\n            type: \"Vector3\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n\r\n    // activeCamera projection properties. Per the spec these read-only values are NaN when there is no\r\n    // active camera, or when the active camera does not use the projection type of the requested pointer\r\n    // (all perspective properties are NaN for an orthographic camera, and vice-versa).\r\n    const getActivePerspectiveValue = (compute: (camera: Camera) => number): number => {\r\n        const camera = scene.activeCamera;\r\n        if (!camera || camera.mode === Constants.ORTHOGRAPHIC_CAMERA) {\r\n            return NaN;\r\n        }\r\n        return compute(camera);\r\n    };\r\n    const getActiveOrthographicValue = (compute: (camera: Camera) => number): number => {\r\n        const camera = scene.activeCamera;\r\n        if (!camera || camera.mode !== Constants.ORTHOGRAPHIC_CAMERA) {\r\n            return NaN;\r\n        }\r\n        return compute(camera);\r\n    };\r\n\r\n    // perspective/aspectRatio (width over height)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/perspective/aspectRatio\",\r\n        {\r\n            get: () => getActivePerspectiveValue((camera) => camera.getEngine().getAspectRatio(camera)),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // perspective/yfov (vertical field of view, in radians)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/perspective/yfov\",\r\n        {\r\n            get: () =>\r\n                getActivePerspectiveValue((camera) => {\r\n                    // Babylon stores the vertical fov when fovMode is vertical-fixed (the default and what the glTF\r\n                    // loader sets). For a horizontal-fixed camera, convert the horizontal fov to vertical.\r\n                    if (camera.fovMode === Constants.FOVMODE_VERTICAL_FIXED) {\r\n                        return camera.fov;\r\n                    }\r\n                    const aspectRatio = camera.getEngine().getAspectRatio(camera);\r\n                    return aspectRatio ? 2 * Math.atan(Math.tan(camera.fov / 2) / aspectRatio) : camera.fov;\r\n                }),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // perspective/znear (distance to the near clipping plane)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/perspective/znear\",\r\n        {\r\n            get: () => getActivePerspectiveValue((camera) => camera.minZ),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // perspective/zfar (distance to the far clipping plane; Babylon uses maxZ === 0 to mean an infinite far plane)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/perspective/zfar\",\r\n        {\r\n            get: () => getActivePerspectiveValue((camera) => (camera.maxZ === 0 ? Infinity : camera.maxZ)),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // orthographic/xmag (half the orthographic width)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/orthographic/xmag\",\r\n        {\r\n            get: () =>\r\n                getActiveOrthographicValue((camera) => {\r\n                    const halfWidth = camera.getEngine().getRenderWidth() / 2;\r\n                    return ((camera.orthoRight ?? halfWidth) - (camera.orthoLeft ?? -halfWidth)) / 2;\r\n                }),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // orthographic/ymag (half the orthographic height)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/orthographic/ymag\",\r\n        {\r\n            get: () =>\r\n                getActiveOrthographicValue((camera) => {\r\n                    const halfHeight = camera.getEngine().getRenderHeight() / 2;\r\n                    return ((camera.orthoTop ?? halfHeight) - (camera.orthoBottom ?? -halfHeight)) / 2;\r\n                }),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // orthographic/znear (distance to the near clipping plane)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/orthographic/znear\",\r\n        {\r\n            get: () => getActiveOrthographicValue((camera) => camera.minZ),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n    // orthographic/zfar (distance to the far clipping plane)\r\n    AddObjectAccessorToKey(\r\n        \"/extensions/KHR_interactivity/?/activeCamera/orthographic/zfar\",\r\n        {\r\n            get: () => getActiveOrthographicValue((camera) => camera.maxZ),\r\n            type: \"number\",\r\n            getTarget: () => scene.activeCamera,\r\n        },\r\n        mapping\r\n    );\r\n\r\n    const getAnimationFps = (animation: IAnimation): number => animation._babylonAnimationGroup?.targetedAnimations?.[0]?.animation.framePerSecond ?? targetFps;\r\n\r\n    // /animations/{} pointers:\r\n    AddObjectAccessorToKey(\r\n        \"/animations/{}/extensions/KHR_interactivity/isPlaying\",\r\n        {\r\n            get: (animation: IAnimation) => {\r\n                return animation._babylonAnimationGroup?.isPlaying ?? false;\r\n            },\r\n            type: \"boolean\",\r\n            getTarget: (animation: IAnimation) => {\r\n                return animation._babylonAnimationGroup;\r\n            },\r\n        },\r\n        mapping\r\n    );\r\n    AddObjectAccessorToKey(\r\n        \"/animations/{}/extensions/KHR_interactivity/minTime\",\r\n        {\r\n            get: (animation: IAnimation) => {\r\n                return (animation._babylonAnimationGroup?.from ?? 0) / getAnimationFps(animation);\r\n            },\r\n            type: \"number\",\r\n            getTarget: (animation: IAnimation) => {\r\n                return animation._babylonAnimationGroup;\r\n            },\r\n        },\r\n        mapping\r\n    );\r\n    AddObjectAccessorToKey(\r\n        \"/animations/{}/extensions/KHR_interactivity/maxTime\",\r\n        {\r\n            get: (animation: IAnimation) => {\r\n                return (animation._babylonAnimationGroup?.to ?? 0) / getAnimationFps(animation);\r\n            },\r\n            type: \"number\",\r\n            getTarget: (animation: IAnimation) => {\r\n                return animation._babylonAnimationGroup;\r\n            },\r\n        },\r\n        mapping\r\n    );\r\n    // playhead\r\n    AddObjectAccessorToKey(\r\n        \"/animations/{}/extensions/KHR_interactivity/playhead\",\r\n        {\r\n            get: (animation: IAnimation) => {\r\n                return (animation._babylonAnimationGroup?.getRetainedCurrentFrame() ?? 0) / getAnimationFps(animation);\r\n            },\r\n            type: \"number\",\r\n            getTarget: (animation: IAnimation) => {\r\n                return animation._babylonAnimationGroup;\r\n            },\r\n        },\r\n        mapping\r\n    );\r\n    AddObjectAccessorToKey(\r\n        \"/animations/{}/extensions/KHR_interactivity/virtualPlayhead\",\r\n        {\r\n            get: (animation: IAnimation) => {\r\n                return (animation._babylonAnimationGroup?.getVirtualCurrentFrame() ?? 0) / getAnimationFps(animation);\r\n            },\r\n            type: \"number\",\r\n            getTarget: (animation: IAnimation) => {\r\n                return animation._babylonAnimationGroup;\r\n            },\r\n        },\r\n        mapping\r\n    );\r\n}\r\n\r\nlet _RuntimeRegistered = false;\r\n/**\r\n * @internal\r\n * Registers KHR_interactivity runtime dependencies without changing the extension registry.\r\n */\r\nexport function _RegisterKHRInteractivityRuntime(): void {\r\n    if (_RuntimeRegistered) {\r\n        return;\r\n    }\r\n    _RuntimeRegistered = true;\r\n\r\n    addToBlockFactory(NAME, \"FlowGraphGLTFDataProvider\", async () => {\r\n        return (await import(\"./KHR_interactivity/flowGraphGLTFDataProvider\")).FlowGraphGLTFDataProvider;\r\n    });\r\n    addToBlockFactory(NAME, \"FlowGraphUnsupportedInteractivityBlock\", async () => {\r\n        return (await import(\"./KHR_interactivity/flowGraphUnsupportedInteractivityBlock\")).FlowGraphUnsupportedInteractivityBlock;\r\n    });\r\n    addToBlockFactory(NAME, \"FlowGraphObjectReferenceBlock\", async () => {\r\n        return (await import(\"./KHR_interactivity/flowGraphObjectReferenceBlock\")).FlowGraphObjectReferenceBlock;\r\n    });\r\n    addToBlockFactory(NAME, \"FlowGraphEventReferenceBlock\", async () => {\r\n        return (await import(\"./KHR_interactivity/flowGraphEventReferenceBlock\")).FlowGraphEventReferenceBlock;\r\n    });\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_interactivity glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_interactivity(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    _RegisterKHRInteractivityRuntime();\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_interactivity(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_interactivity.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_interactivity.types\";\r\nexport * from \"./KHR_interactivity.pure\";\r\n\r\nimport { RegisterKHR_interactivity } from \"./KHR_interactivity.pure\";\r\nRegisterKHR_interactivity();\r\n","import { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { type INode } from \"../glTFLoaderInterfaces\";\r\nimport { AddObjectAccessorToKey } from \"./objectModelMapping\";\r\n\r\nconst NAME = \"KHR_node_visibility\";\r\n\r\n// object model extension for visibility\r\n\r\n/**\r\n * Loader extension for KHR_node_visibility\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_node_visibility implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader?: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    public onReady(): void {\r\n        if (!this._loader) {\r\n            return;\r\n        }\r\n\r\n        const nodes = this._loader.gltf.nodes;\r\n        if (nodes) {\r\n            for (const node of nodes) {\r\n                const babylonTransformNode = node._babylonTransformNode;\r\n                if (babylonTransformNode) {\r\n                    babylonTransformNode.inheritVisibility = true;\r\n                    if (node.extensions && node.extensions.KHR_node_visibility && node.extensions.KHR_node_visibility.visible === false) {\r\n                        // Apply ``visible: false`` to the same set of meshes the\r\n                        // runtime ``pointer/set`` accessor writes to. The wrapping\r\n                        // ``babylonTransformNode`` is often a non-rendering\r\n                        // ``TransformNode``, so setting ``isVisible`` only there\r\n                        // leaves the primitive child meshes visible. Mirror the\r\n                        // accessor below so assets that author hidden defaults\r\n                        // (e.g. MagicBall.glb's FortuneWords) start hidden as intended.\r\n                        (babylonTransformNode as AbstractMesh).isVisible = false;\r\n                        node._primitiveBabylonMeshes?.forEach((mesh) => {\r\n                            mesh.inheritVisibility = true;\r\n                            mesh.isVisible = false;\r\n                        });\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    public dispose() {\r\n        delete this._loader;\r\n    }\r\n}\r\n\r\nlet _RuntimeRegistered = false;\r\n/**\r\n * @internal\r\n * Registers KHR_node_visibility runtime dependencies without changing the extension registry.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function _RegisterKHRNodeVisibilityRuntime(): void {\r\n    if (_RuntimeRegistered) {\r\n        return;\r\n    }\r\n    _RuntimeRegistered = true;\r\n\r\n    AddObjectAccessorToKey(\"/nodes/{}/extensions/KHR_node_visibility/visible\", {\r\n        get: (node: INode) => {\r\n            const tn = node._babylonTransformNode as any;\r\n            if (tn && tn.isVisible !== undefined) {\r\n                return tn.isVisible;\r\n            }\r\n            return true;\r\n        },\r\n        set: (value: boolean, node: INode) => {\r\n            node._primitiveBabylonMeshes?.forEach((mesh) => {\r\n                mesh.inheritVisibility = true;\r\n            });\r\n            if (node._babylonTransformNode) {\r\n                (node._babylonTransformNode as AbstractMesh).isVisible = value;\r\n            }\r\n            node._primitiveBabylonMeshes?.forEach((mesh) => {\r\n                mesh.isVisible = value;\r\n            });\r\n        },\r\n        getTarget: (node: INode) => node._babylonTransformNode,\r\n        getPropertyName: [() => \"isVisible\"],\r\n        type: \"boolean\",\r\n    });\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_node_visibility glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_node_visibility(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    _RegisterKHRNodeVisibilityRuntime();\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_node_visibility(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_node_visibility.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_node_visibility.types\";\r\nexport * from \"./KHR_node_visibility.pure\";\r\n\r\nimport { RegisterKHR_node_visibility } from \"./KHR_node_visibility.pure\";\r\nRegisterKHR_node_visibility();\r\n","import { type AbstractMesh } from \"core/Meshes/abstractMesh.pure\";\nimport { type INode } from \"../../glTFLoaderInterfaces\";\n\ntype InteractivityNodeState = \"hoverable\" | \"selectable\";\n\nconst _NodeSets = /*#__PURE__*/ new WeakMap<INode, readonly INode[]>();\nconst _Hoverable = /*#__PURE__*/ new WeakMap<INode, boolean>();\nconst _Selectable = /*#__PURE__*/ new WeakMap<INode, boolean>();\n\nfunction _GetStateMap(state: InteractivityNodeState): WeakMap<INode, boolean> {\n    return state === \"selectable\" ? _Selectable : _Hoverable;\n}\n\nfunction _GetLocalState(node: INode, state: InteractivityNodeState): boolean {\n    return _GetStateMap(state).get(node) ?? true;\n}\n\nfunction _GetEffectiveState(node: INode, state: InteractivityNodeState): boolean {\n    let current: INode | undefined = node;\n    while (current) {\n        if (!_GetLocalState(current, state)) {\n            return false;\n        }\n        current = current.parent;\n    }\n    return true;\n}\n\nfunction _ApplyMeshState(mesh: AbstractMesh, state: InteractivityNodeState, value: boolean): void {\n    if (state === \"selectable\") {\n        mesh.isPickable = value;\n    } else {\n        mesh._isPointerMovePickable = value;\n    }\n}\n\nfunction _ApplyNodeState(node: INode, state: InteractivityNodeState): void {\n    const effective = _GetEffectiveState(node, state);\n    const meshes = node._primitiveBabylonMeshes ?? [];\n    for (const mesh of meshes) {\n        _ApplyMeshState(mesh, state, effective);\n    }\n    const transformNode = node._babylonTransformNode;\n    if (transformNode && \"isPickable\" in transformNode) {\n        _ApplyMeshState(transformNode as AbstractMesh, state, effective);\n    }\n}\n\nfunction _IsDescendantNode(node: INode, ancestor: INode): boolean {\n    let current: INode | undefined = node;\n    while (current) {\n        if (current === ancestor) {\n            return true;\n        }\n        current = current.parent;\n    }\n    return false;\n}\n\n/**\n * Initializes authored and inherited selectability or hoverability state.\n * @param nodes all nodes in the glTF asset\n * @param state state kind to initialize\n * @param getAuthoredState reads the extension-authored local state\n */\nexport function InitializeInteractivityNodeState(nodes: readonly INode[], state: InteractivityNodeState, getAuthoredState: (node: INode) => boolean | undefined): void {\n    const stateMap = _GetStateMap(state);\n    for (const node of nodes) {\n        _NodeSets.set(node, nodes);\n        stateMap.set(node, getAuthoredState(node) ?? true);\n    }\n    for (const node of nodes) {\n        _ApplyNodeState(node, state);\n    }\n}\n\n/**\n * Gets the locally authored runtime state for a node.\n * @param node glTF node\n * @param state state kind\n * @returns local state, defaulting to true\n */\nexport function GetInteractivityNodeState(node: INode, state: InteractivityNodeState): boolean {\n    return _GetLocalState(node, state);\n}\n\n/**\n * Updates local state and reapplies inherited state to the affected subtree.\n * @param node glTF node\n * @param state state kind\n * @param value new local state\n */\nexport function SetInteractivityNodeState(node: INode, state: InteractivityNodeState, value: boolean): void {\n    _GetStateMap(state).set(node, value);\n    const nodes = _NodeSets.get(node) ?? [node];\n    for (const candidate of nodes) {\n        if (_IsDescendantNode(candidate, node)) {\n            _ApplyNodeState(candidate, state);\n        }\n    }\n}\n","import { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { FlowGraphBlockNames } from \"core/FlowGraph/Blocks/flowGraphBlockNames\";\r\nimport { addNewInteractivityFlowGraphMapping } from \"./KHR_interactivity/declarationMapper\";\r\nimport { type INode } from \"../glTFLoaderInterfaces\";\r\nimport { AddObjectAccessorToKey } from \"./objectModelMapping\";\r\nimport { GetInteractivityNodeState, InitializeInteractivityNodeState, SetInteractivityNodeState } from \"./KHR_interactivity/interactivityNodeState\";\r\nimport { FlowGraphTypes } from \"core/FlowGraph/flowGraphRichTypes.pure\";\r\n\r\nconst NAME = \"KHR_node_selectability\";\r\n\r\n// add the interactivity mapping for the onSelect event\r\n\r\n// object model extension for selectable\r\n\r\n/**\r\n * Loader extension for KHR_selectability\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_node_selectability implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n    /** Applies node state before KHR_interactivity graphs start. */\r\n    public readonly order = 100;\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-misused-promises\r\n    public async onReady(): Promise<void> {\r\n        InitializeInteractivityNodeState(this._loader.gltf.nodes ?? [], \"selectable\", (node) => node.extensions?.KHR_node_selectability?.selectable);\r\n    }\r\n\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n}\r\n\r\nlet _RuntimeRegistered = false;\r\n/**\r\n * @internal\r\n * Registers KHR_node_selectability runtime dependencies without changing the extension registry.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function _RegisterKHRNodeSelectabilityRuntime(): void {\r\n    if (_RuntimeRegistered) {\r\n        return;\r\n    }\r\n    _RuntimeRegistered = true;\r\n\r\n    addNewInteractivityFlowGraphMapping(\"event/onSelect\", NAME, {\r\n        // using GetVariable as the nodeIndex is a configuration and not a value (i.e. it's not mutable)\r\n        blocks: [\r\n            FlowGraphBlockNames.MeshPickEvent,\r\n            FlowGraphBlockNames.GetVariable,\r\n            FlowGraphBlockNames.IndexOf,\r\n            \"KHR_interactivity/FlowGraphGLTFDataProvider\",\r\n            \"KHR_interactivity/FlowGraphEventReferenceBlock\",\r\n        ],\r\n        declarationSchema: {\r\n            inputValueSockets: {},\r\n            outputValueSockets: {\r\n                selectedNode: \"ref\",\r\n                selectionRayOrigin: \"float3\",\r\n                selectionPoint: \"float3\",\r\n                controllerIndex: \"int\",\r\n                event: \"ref\",\r\n            },\r\n        },\r\n        configuration: {\r\n            nodeIndex: {\r\n                name: \"variable\",\r\n                configurationType: \"int\",\r\n                toBlock: FlowGraphBlockNames.GetVariable,\r\n                indexSource: \"assetNodes\",\r\n                invalidUsesDefault: true,\r\n                dataTransformer(data) {\r\n                    return \"pickedMesh_\" + data;\r\n                },\r\n            },\r\n        },\r\n        outputs: {\r\n            values: {\r\n                selectedNodeIndex: { name: \"index\", toBlock: FlowGraphBlockNames.IndexOf },\r\n                // `selectedNode` is the new ref-typed output from the Opaque-Reference\r\n                // spec update. It's the picked Babylon mesh itself, available directly\r\n                // from FlowGraphMeshPickEventBlock.pickedMesh — no IndexOf lookup needed.\r\n                selectedNode: { name: \"nodeReference\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                controllerIndex: { name: \"controllerIndex\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                selectionPoint: { name: \"selectionPoint\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                selectionRayOrigin: { name: \"selectionRayOrigin\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                event: { name: \"value\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n            },\r\n            flows: {\r\n                out: { name: \"out\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n            },\r\n        },\r\n        interBlockConnectors: [\r\n            {\r\n                input: \"asset\",\r\n                output: \"value\",\r\n                inputBlockIndex: 0,\r\n                outputBlockIndex: 1,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"array\",\r\n                output: \"nodes\",\r\n                inputBlockIndex: 2,\r\n                outputBlockIndex: 3,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"object\",\r\n                output: \"pickedMesh\",\r\n                inputBlockIndex: 2,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"node\",\r\n                output: \"pickedMesh\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"controllerIndexInput\",\r\n                output: \"pointerId\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"selectionPointInput\",\r\n                output: \"pickedPoint\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"selectionRayOriginInput\",\r\n                output: \"pickOrigin\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"in\",\r\n                output: \"done\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n            },\r\n        ],\r\n        extraProcessor(gltfBlock, _declaration, _mapping, _arrays, serializedObjects, context, globalGLTF) {\r\n            // find the listener nodeIndex value\r\n            const nodeIndex = gltfBlock.configuration?.[\"nodeIndex\"]?.value?.[0];\r\n            const validNodeIndex = typeof nodeIndex === \"number\" && Number.isInteger(nodeIndex) && nodeIndex >= 0 && nodeIndex < (globalGLTF?.nodes?.length ?? 0);\r\n            const variableName = validNodeIndex ? \"pickedMesh_\" + nodeIndex : \"pickedMesh_unbound\";\r\n            // find the nodeIndex value\r\n            serializedObjects[1].config.variable = variableName;\r\n            context._userVariables[variableName] = validNodeIndex\r\n                ? {\r\n                      className: \"Mesh\",\r\n                      id: globalGLTF?.nodes?.[nodeIndex]._babylonTransformNode?.id,\r\n                      uniqueId: globalGLTF?.nodes?.[nodeIndex]._babylonTransformNode?.uniqueId,\r\n                  }\r\n                : { type: FlowGraphTypes.Any, value: [{}] };\r\n            const eventKey = `${NAME}:event/onSelect:${nodeIndex}`;\r\n            serializedObjects[0].config.eventKey = eventKey;\r\n            serializedObjects[0].config.useNaNDefaults = true;\r\n            serializedObjects[0].config.pointerIdDefault = -1;\r\n            serializedObjects[4].config.eventKey = eventKey;\r\n            return serializedObjects;\r\n        },\r\n    });\r\n\r\n    AddObjectAccessorToKey(\"/nodes/{}/extensions/KHR_node_selectability/selectable\", {\r\n        get: (node: INode) => {\r\n            return GetInteractivityNodeState(node, \"selectable\");\r\n        },\r\n        set: (value: boolean, node: INode) => {\r\n            SetInteractivityNodeState(node, \"selectable\", value);\r\n        },\r\n        getTarget: (node: INode) => node._babylonTransformNode,\r\n        getPropertyName: [() => \"isPickable\"],\r\n        type: \"boolean\",\r\n    });\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_node_selectability glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_node_selectability(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    _RegisterKHRNodeSelectabilityRuntime();\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_node_selectability(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_node_selectability.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_node_selectability.types\";\r\nexport * from \"./KHR_node_selectability.pure\";\r\n\r\nimport { RegisterKHR_node_selectability } from \"./KHR_node_selectability.pure\";\r\nRegisterKHR_node_selectability();\r\n","import { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\nimport { FlowGraphBlockNames } from \"core/FlowGraph/Blocks/flowGraphBlockNames\";\r\nimport { addNewInteractivityFlowGraphMapping } from \"./KHR_interactivity/declarationMapper\";\r\nimport { type INode } from \"../glTFLoaderInterfaces\";\r\nimport { AddObjectAccessorToKey } from \"./objectModelMapping\";\r\nimport { GetInteractivityNodeState, InitializeInteractivityNodeState, SetInteractivityNodeState } from \"./KHR_interactivity/interactivityNodeState\";\r\nimport { FlowGraphTypes } from \"core/FlowGraph/flowGraphRichTypes.pure\";\r\n\r\nconst NAME = \"KHR_node_hoverability\";\r\n\r\n// interactivity\r\nconst MeshPointerOverPrefix = \"targetMeshPointerOver_\";\r\n\r\nconst MeshPointerOutPrefix = \"targetMeshPointerOut_\";\r\n\r\n/**\r\n * Loader extension for KHR_node_hoverability\r\n * @see https://github.com/KhronosGroup/glTF/pull/2426\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_node_hoverability implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n    /** Applies node state before KHR_interactivity graphs start. */\r\n    public readonly order = 100;\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled: boolean;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n        this.enabled = loader.isExtensionUsed(NAME);\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-misused-promises\r\n    public async onReady(): Promise<void> {\r\n        InitializeInteractivityNodeState(this._loader.gltf.nodes ?? [], \"hoverable\", (node) => node.extensions?.KHR_node_hoverability?.hoverable);\r\n    }\r\n\r\n    public dispose() {\r\n        (this._loader as any) = null;\r\n    }\r\n}\r\n\r\nlet _RuntimeRegistered = false;\r\n/**\r\n * @internal\r\n * Registers KHR_node_hoverability runtime dependencies without changing the extension registry.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function _RegisterKHRNodeHoverabilityRuntime(): void {\r\n    if (_RuntimeRegistered) {\r\n        return;\r\n    }\r\n    _RuntimeRegistered = true;\r\n\r\n    addNewInteractivityFlowGraphMapping(\"event/onHoverIn\", NAME, {\r\n        // using GetVariable as the nodeIndex is a configuration and not a value (i.e. it's not mutable)\r\n        blocks: [\r\n            FlowGraphBlockNames.PointerOverEvent,\r\n            FlowGraphBlockNames.GetVariable,\r\n            FlowGraphBlockNames.IndexOf,\r\n            \"KHR_interactivity/FlowGraphGLTFDataProvider\",\r\n            \"KHR_interactivity/FlowGraphEventReferenceBlock\",\r\n        ],\r\n        declarationSchema: {\r\n            inputValueSockets: {},\r\n            outputValueSockets: {\r\n                hoveredNode: \"ref\",\r\n                controllerIndex: \"int\",\r\n                event: \"ref\",\r\n            },\r\n        },\r\n        configuration: {\r\n            nodeIndex: {\r\n                name: \"variable\",\r\n                configurationType: \"int\",\r\n                toBlock: FlowGraphBlockNames.GetVariable,\r\n                indexSource: \"assetNodes\",\r\n                invalidUsesDefault: true,\r\n                dataTransformer(data) {\r\n                    return MeshPointerOverPrefix + data;\r\n                },\r\n            },\r\n        },\r\n        outputs: {\r\n            values: {\r\n                hoverNodeIndex: { name: \"index\", toBlock: FlowGraphBlockNames.IndexOf },\r\n                hoveredNode: { name: \"nodeReference\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                controllerIndex: { name: \"controllerIndex\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                event: { name: \"value\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n            },\r\n            flows: {\r\n                out: { name: \"out\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n            },\r\n        },\r\n        interBlockConnectors: [\r\n            {\r\n                input: \"targetMesh\",\r\n                output: \"value\",\r\n                inputBlockIndex: 0,\r\n                outputBlockIndex: 1,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"array\",\r\n                output: \"nodes\",\r\n                inputBlockIndex: 2,\r\n                outputBlockIndex: 3,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"object\",\r\n                output: \"meshUnderPointer\",\r\n                inputBlockIndex: 2,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"node\",\r\n                output: \"meshUnderPointer\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"controllerIndexInput\",\r\n                output: \"pointerId\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"in\",\r\n                output: \"done\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n            },\r\n        ],\r\n        extraProcessor(gltfBlock, _declaration, _mapping, _arrays, serializedObjects, context, globalGLTF) {\r\n            // find the listener nodeIndex value\r\n            const nodeIndex = gltfBlock.configuration?.[\"nodeIndex\"]?.value?.[0];\r\n            const validNodeIndex = typeof nodeIndex === \"number\" && Number.isInteger(nodeIndex) && nodeIndex >= 0 && nodeIndex < (globalGLTF?.nodes?.length ?? 0);\r\n            const variableName = validNodeIndex ? MeshPointerOverPrefix + nodeIndex : MeshPointerOverPrefix + \"unbound\";\r\n            // find the nodeIndex value\r\n            serializedObjects[1].config.variable = variableName;\r\n            context._userVariables[variableName] = validNodeIndex\r\n                ? {\r\n                      className: \"Mesh\",\r\n                      id: globalGLTF?.nodes?.[nodeIndex]._babylonTransformNode?.id,\r\n                      uniqueId: globalGLTF?.nodes?.[nodeIndex]._babylonTransformNode?.uniqueId,\r\n                  }\r\n                : { type: FlowGraphTypes.Any, value: [{}] };\r\n            const eventKey = `${NAME}:event/onHoverIn:${nodeIndex}`;\r\n            serializedObjects[0].config.eventKey = eventKey;\r\n            serializedObjects[4].config.eventKey = eventKey;\r\n            return serializedObjects;\r\n        },\r\n    });\r\n\r\n    addNewInteractivityFlowGraphMapping(\"event/onHoverOut\", NAME, {\r\n        // using GetVariable as the nodeIndex is a configuration and not a value (i.e. it's not mutable)\r\n        blocks: [\r\n            FlowGraphBlockNames.PointerOutEvent,\r\n            FlowGraphBlockNames.GetVariable,\r\n            FlowGraphBlockNames.IndexOf,\r\n            \"KHR_interactivity/FlowGraphGLTFDataProvider\",\r\n            \"KHR_interactivity/FlowGraphEventReferenceBlock\",\r\n        ],\r\n        declarationSchema: {\r\n            inputValueSockets: {},\r\n            outputValueSockets: {\r\n                hoveredNode: \"ref\",\r\n                controllerIndex: \"int\",\r\n                event: \"ref\",\r\n            },\r\n        },\r\n        configuration: {\r\n            nodeIndex: {\r\n                name: \"variable\",\r\n                configurationType: \"int\",\r\n                toBlock: FlowGraphBlockNames.GetVariable,\r\n                indexSource: \"assetNodes\",\r\n                invalidUsesDefault: true,\r\n                dataTransformer(data) {\r\n                    return MeshPointerOutPrefix + data;\r\n                },\r\n            },\r\n        },\r\n        outputs: {\r\n            values: {\r\n                hoverNodeIndex: { name: \"index\", toBlock: FlowGraphBlockNames.IndexOf },\r\n                hoveredNode: { name: \"nodeReference\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                controllerIndex: { name: \"controllerIndex\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n                event: { name: \"value\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n            },\r\n            flows: {\r\n                out: { name: \"out\", toBlock: \"KHR_interactivity/FlowGraphEventReferenceBlock\" },\r\n            },\r\n        },\r\n        interBlockConnectors: [\r\n            {\r\n                input: \"targetMesh\",\r\n                output: \"value\",\r\n                inputBlockIndex: 0,\r\n                outputBlockIndex: 1,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"array\",\r\n                output: \"nodes\",\r\n                inputBlockIndex: 2,\r\n                outputBlockIndex: 3,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"object\",\r\n                output: \"meshOutOfPointer\",\r\n                inputBlockIndex: 2,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"node\",\r\n                output: \"meshOutOfPointer\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"controllerIndexInput\",\r\n                output: \"pointerId\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n                isVariable: true,\r\n            },\r\n            {\r\n                input: \"in\",\r\n                output: \"done\",\r\n                inputBlockIndex: 4,\r\n                outputBlockIndex: 0,\r\n            },\r\n        ],\r\n        extraProcessor(gltfBlock, _declaration, _mapping, _arrays, serializedObjects, context, globalGLTF) {\r\n            const nodeIndex = gltfBlock.configuration?.[\"nodeIndex\"]?.value?.[0];\r\n            const validNodeIndex = typeof nodeIndex === \"number\" && Number.isInteger(nodeIndex) && nodeIndex >= 0 && nodeIndex < (globalGLTF?.nodes?.length ?? 0);\r\n            const variableName = validNodeIndex ? MeshPointerOutPrefix + nodeIndex : MeshPointerOutPrefix + \"unbound\";\r\n            // find the nodeIndex value\r\n            serializedObjects[1].config.variable = variableName;\r\n            context._userVariables[variableName] = validNodeIndex\r\n                ? {\r\n                      className: \"Mesh\",\r\n                      id: globalGLTF?.nodes?.[nodeIndex]._babylonTransformNode?.id,\r\n                      uniqueId: globalGLTF?.nodes?.[nodeIndex]._babylonTransformNode?.uniqueId,\r\n                  }\r\n                : { type: FlowGraphTypes.Any, value: [{}] };\r\n            const eventKey = `${NAME}:event/onHoverOut:${nodeIndex}`;\r\n            serializedObjects[0].config.eventKey = eventKey;\r\n            serializedObjects[4].config.eventKey = eventKey;\r\n            return serializedObjects;\r\n        },\r\n    });\r\n\r\n    AddObjectAccessorToKey(\"/nodes/{}/extensions/KHR_node_hoverability/hoverable\", {\r\n        get: (node: INode) => {\r\n            return GetInteractivityNodeState(node, \"hoverable\");\r\n        },\r\n        set: (value: boolean, node: INode) => {\r\n            SetInteractivityNodeState(node, \"hoverable\", value);\r\n        },\r\n        getTarget: (node: INode) => node._babylonTransformNode,\r\n        getPropertyName: [() => \"pointerOverDisableMeshTesting\"],\r\n        type: \"boolean\",\r\n    });\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the KHR_node_hoverability glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function RegisterKHR_node_hoverability(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    _RegisterKHRNodeHoverabilityRuntime();\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, true, (loader) => new KHR_node_hoverability(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./KHR_node_hoverability.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./KHR_node_hoverability.types\";\r\nexport * from \"./KHR_node_hoverability.pure\";\r\n\r\nimport { RegisterKHR_node_hoverability } from \"./KHR_node_hoverability.pure\";\r\nRegisterKHR_node_hoverability();\r\n","import { type Nullable } from \"core/types\";\r\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\r\nimport { type Camera } from \"core/Cameras/camera.pure\";\r\nimport { type AnimationGroup } from \"core/Animations/animationGroup.pure\";\r\n\r\nimport { type IProperty } from \"babylonjs-gltf2interface\";\r\nimport { type INode, type ICamera, type IMaterial, type IAnimation } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { type GLTFLoader } from \"../glTFLoader.pure\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"ExtrasAsMetadata\";\r\n\r\ninterface IObjectWithMetadata {\r\n    metadata: any;\r\n}\r\n\r\n/**\r\n * Store glTF extras (if present) in BJS objects' metadata\r\n */\r\nexport class ExtrasAsMetadata implements IGLTFLoaderExtension {\r\n    /**\r\n     * The name of this extension.\r\n     */\r\n    public readonly name = NAME;\r\n\r\n    /**\r\n     * Defines whether this extension is enabled.\r\n     */\r\n    public enabled = true;\r\n\r\n    private _loader: GLTFLoader;\r\n\r\n    private _assignExtras(babylonObject: IObjectWithMetadata, gltfProp: IProperty): void {\r\n        if (gltfProp.extras && Object.keys(gltfProp.extras).length > 0) {\r\n            const metadata = (babylonObject.metadata = babylonObject.metadata || {});\r\n            const gltf = (metadata.gltf = metadata.gltf || {});\r\n            gltf.extras = gltfProp.extras;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public constructor(loader: GLTFLoader) {\r\n        this._loader = loader;\r\n    }\r\n\r\n    /** @internal */\r\n    public dispose(): void {\r\n        (this._loader as any) = null;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {\r\n        return this._loader.loadNodeAsync(context, node, (babylonTransformNode): void => {\r\n            this._assignExtras(babylonTransformNode, node);\r\n            assign(babylonTransformNode);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadCameraAsync(context: string, camera: ICamera, assign: (babylonCamera: Camera) => void): Nullable<Promise<Camera>> {\r\n        return this._loader.loadCameraAsync(context, camera, (babylonCamera): void => {\r\n            this._assignExtras(babylonCamera, camera);\r\n            assign(babylonCamera);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    public createMaterial(context: string, material: IMaterial, babylonDrawMode: number): Nullable<Material> {\r\n        const babylonMaterial = this._loader.createMaterial(context, material, babylonDrawMode);\r\n        this._assignExtras(babylonMaterial, material);\r\n        return babylonMaterial;\r\n    }\r\n\r\n    /**\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadAnimationAsync(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>> {\r\n        // eslint-disable-next-line github/no-then\r\n        return this._loader.loadAnimationAsync(context, animation).then((babylonAnimation: AnimationGroup) => {\r\n            this._assignExtras(babylonAnimation, animation);\r\n            return babylonAnimation;\r\n        });\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the ExtrasAsMetadata glTF loader extension.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterExtrasAsMetadata(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    unregisterGLTFExtension(NAME);\r\n\r\n    registerGLTFExtension(NAME, false, (loader) => new ExtrasAsMetadata(loader));\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./ExtrasAsMetadata.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./ExtrasAsMetadata.types\";\r\nexport * from \"./ExtrasAsMetadata.pure\";\r\n\r\nimport { RegisterExtrasAsMetadata } from \"./ExtrasAsMetadata.pure\";\r\nRegisterExtrasAsMetadata();\r\n","import { type IFlowGraphBlockConfiguration, FlowGraphBlock } from \"core/FlowGraph/flowGraphBlock\";\nimport { type IGLTF } from \"../../glTFLoaderInterfaces\";\nimport { type FlowGraphDataConnection } from \"core/FlowGraph/flowGraphDataConnection\";\nimport { type AnimationGroup } from \"core/Animations/animationGroup\";\nimport { type TransformNode } from \"core/Meshes/transformNode\";\nimport { RichTypeAny } from \"core/FlowGraph/flowGraphRichTypes\";\n\n/**\n * a configuration interface for this block\n */\nexport interface IFlowGraphGLTFDataProviderBlockConfiguration extends IFlowGraphBlockConfiguration {\n    /**\n     * the glTF object to provide data from\n     */\n    glTF?: IGLTF;\n}\n\n/**\n * a glTF-based FlowGraph block that provides arrays with babylon object, based on the glTF tree\n * Can be used, for example, to get animation index from a glTF animation\n */\nexport class FlowGraphGLTFDataProvider extends FlowGraphBlock {\n    /**\n     * Output: an array of animation groups\n     * Corresponds directly to the glTF animations array\n     */\n    public readonly animationGroups: FlowGraphDataConnection<AnimationGroup[]>;\n\n    /**\n     * Output an array of (Transform) nodes\n     * Corresponds directly to the glTF nodes array\n     */\n    public readonly nodes: FlowGraphDataConnection<TransformNode[]>;\n\n    constructor(config: IFlowGraphGLTFDataProviderBlockConfiguration = {}) {\n        super(config);\n        const glTF = config.glTF;\n        // glTF may be undefined when the block is re-created from serialized data\n        // (e.g. in the Flow Graph Editor) where the live glTF parse tree is unavailable.\n        const animationGroups = glTF?.animations?.map((a) => a._babylonAnimationGroup) || [];\n        this.animationGroups = this.registerDataOutput(\"animationGroups\", RichTypeAny, animationGroups);\n        const nodes = glTF?.nodes?.map((n) => n._babylonTransformNode) || [];\n        this.nodes = this.registerDataOutput(\"nodes\", RichTypeAny, nodes);\n    }\n\n    public override getClassName(): string {\n        return \"FlowGraphGLTFDataProvider\";\n    }\n}\n","import { FlowGraphBlock, type IFlowGraphBlockConfiguration } from \"core/FlowGraph/flowGraphBlock\";\nimport { type FlowGraphContext } from \"core/FlowGraph/flowGraphContext\";\nimport { type FlowGraphDataConnection } from \"core/FlowGraph/flowGraphDataConnection.pure\";\nimport { RichTypeAny, RichTypeString } from \"core/FlowGraph/flowGraphRichTypes.pure\";\n\n/**\n * Resolves a runtime object to its owning glTF node reference.\n * @param context active FlowGraph context\n * @param value runtime object, usually a picked primitive\n * @returns the owning node reference or the null reference\n */\nexport function GetInteractivityObjectReference(context: FlowGraphContext, value: object | undefined): string {\n    let object = value as (object & { parent?: object }) | undefined;\n    while (object) {\n        const candidate = context.getObjectReference(object, \"nodes\");\n        if (candidate?.startsWith(\"/nodes/\")) {\n            return candidate;\n        }\n        object = object.parent;\n    }\n    return \"\";\n}\n\n/**\n * Converts a runtime object into the opaque reference used by KHR_interactivity.\n */\nexport class FlowGraphObjectReferenceBlock extends FlowGraphBlock {\n    /** Runtime object to encode. */\n    public readonly object: FlowGraphDataConnection<object | undefined>;\n    /** Opaque KHR_interactivity reference. */\n    public readonly value: FlowGraphDataConnection<string>;\n\n    constructor(config?: IFlowGraphBlockConfiguration) {\n        super(config);\n        this.object = this.registerDataInput(\"object\", RichTypeAny);\n        this.value = this.registerDataOutput(\"value\", RichTypeString, \"\");\n    }\n\n    /** @internal */\n    public override _updateOutputs(context: FlowGraphContext): void {\n        this.value.setValue(GetInteractivityObjectReference(context, this.object.getValue(context)), context);\n    }\n\n    /** @returns the serialized class name */\n    public override getClassName(): string {\n        return \"FlowGraphObjectReferenceBlock\";\n    }\n}\n","import { type IFlowGraphBlockConfiguration } from \"core/FlowGraph/flowGraphBlock\";\nimport { type FlowGraphContext } from \"core/FlowGraph/flowGraphContext\";\nimport { type FlowGraphDataConnection } from \"core/FlowGraph/flowGraphDataConnection.pure\";\nimport { RichTypeAny, RichTypeNumber, RichTypeString, RichTypeVector3 } from \"core/FlowGraph/flowGraphRichTypes.pure\";\nimport { FlowGraphExecutionBlock } from \"core/FlowGraph/flowGraphExecutionBlock\";\nimport { Matrix, Vector3 } from \"core/Maths/math.vector.pure\";\nimport { GetInteractivityObjectReference } from \"./flowGraphObjectReferenceBlock\";\nimport { type FlowGraphSignalConnection } from \"core/FlowGraph/flowGraphSignalConnection.pure\";\n\n/**\n * Configuration for a KHR event reference output.\n */\nexport interface IFlowGraphEventReferenceBlockConfiguration extends IFlowGraphBlockConfiguration {\n    /** Stable key shared by equivalent event operations. */\n    eventKey?: string;\n}\n\n/**\n * Produces the opaque reference associated with a KHR event operation.\n */\nexport class FlowGraphEventReferenceBlock extends FlowGraphExecutionBlock {\n    private readonly _assetInverse = Matrix.Identity();\n    private readonly _selectionPointValue = Vector3.Zero();\n    private readonly _selectionRayOriginValue = Vector3.Zero();\n    /** Output flow activated after event values are captured. */\n    public readonly out: FlowGraphSignalConnection;\n    /** Runtime node associated with the event. */\n    public readonly node: FlowGraphDataConnection<object | undefined>;\n    /** Controller index associated with the event. */\n    public readonly controllerIndexInput: FlowGraphDataConnection<number>;\n    /** Selection point associated with the event. */\n    public readonly selectionPointInput: FlowGraphDataConnection<Vector3>;\n    /** Selection ray origin associated with the event. */\n    public readonly selectionRayOriginInput: FlowGraphDataConnection<Vector3>;\n    /** Opaque node reference. */\n    public readonly nodeReference: FlowGraphDataConnection<string>;\n    /** Retained controller index. */\n    public readonly controllerIndex: FlowGraphDataConnection<number>;\n    /** Retained selection point. */\n    public readonly selectionPoint: FlowGraphDataConnection<Vector3>;\n    /** Retained selection ray origin. */\n    public readonly selectionRayOrigin: FlowGraphDataConnection<Vector3>;\n    /** Opaque event reference. */\n    public readonly value: FlowGraphDataConnection<string>;\n\n    constructor(public override config: IFlowGraphEventReferenceBlockConfiguration) {\n        super(config);\n        const nanVector = new Vector3(NaN, NaN, NaN);\n        this.node = this.registerDataInput(\"node\", RichTypeAny);\n        this.controllerIndexInput = this.registerDataInput(\"controllerIndexInput\", RichTypeNumber, -1);\n        this.selectionPointInput = this.registerDataInput(\"selectionPointInput\", RichTypeVector3, nanVector);\n        this.selectionRayOriginInput = this.registerDataInput(\"selectionRayOriginInput\", RichTypeVector3, nanVector);\n        this.nodeReference = this.registerDataOutput(\"nodeReference\", RichTypeString, \"\");\n        this.controllerIndex = this.registerDataOutput(\"controllerIndex\", RichTypeNumber, -1);\n        this.selectionPoint = this.registerDataOutput(\"selectionPoint\", RichTypeVector3, nanVector);\n        this.selectionRayOrigin = this.registerDataOutput(\"selectionRayOrigin\", RichTypeVector3, nanVector);\n        this.value = this.registerDataOutput(\"value\", RichTypeString, \"\");\n        this.out = this._registerSignalOutput(\"out\");\n    }\n\n    /** @internal */\n    public override _execute(context: FlowGraphContext): void {\n        this.nodeReference.setValue(GetInteractivityObjectReference(context, this.node.getValue(context)), context);\n        const pointerId = this.controllerIndexInput.getValue(context);\n        if (pointerId < 0) {\n            this.controllerIndex.setValue(-1, context);\n        } else {\n            const controllerIndices = context._getGlobalContextVariable(\"khrInteractivityControllerIndices\", new Map<number, number>()) as Map<number, number>;\n            let controllerIndex = controllerIndices.get(pointerId);\n            if (controllerIndex === undefined) {\n                controllerIndex = controllerIndices.size;\n                controllerIndices.set(pointerId, controllerIndex);\n                context._setGlobalContextVariable(\"khrInteractivityControllerIndices\", controllerIndices);\n            }\n            this.controllerIndex.setValue(controllerIndex, context);\n        }\n        const node = this.node.getValue(context) as { parent?: any; getWorldMatrix?: () => Matrix } | undefined;\n        let root = node?.parent;\n        while (root?.parent) {\n            root = root.parent;\n        }\n        if (root?.getWorldMatrix) {\n            root.getWorldMatrix().invertToRef(this._assetInverse);\n            Vector3.TransformCoordinatesToRef(this.selectionPointInput.getValue(context), this._assetInverse, this._selectionPointValue);\n            Vector3.TransformCoordinatesToRef(this.selectionRayOriginInput.getValue(context), this._assetInverse, this._selectionRayOriginValue);\n            this.selectionPoint.setValue(this._selectionPointValue, context);\n            this.selectionRayOrigin.setValue(this._selectionRayOriginValue, context);\n        } else {\n            this.selectionPoint.setValue(this.selectionPointInput.getValue(context), context);\n            this.selectionRayOrigin.setValue(this.selectionRayOriginInput.getValue(context), context);\n        }\n        this.value.setValue(context.getEventReference(this.config.eventKey ?? \"gltf:manual\"), context);\n        this.out._activateSignal(context);\n    }\n\n    /** @returns the serialized class name */\n    public override getClassName(): string {\n        return \"FlowGraphEventReferenceBlock\";\n    }\n}\n","import { FlowGraphExecutionBlock } from \"core/FlowGraph/flowGraphExecutionBlock\";\nimport { type IFlowGraphBlockConfiguration } from \"core/FlowGraph/flowGraphBlock\";\nimport { type FlowGraphContext } from \"core/FlowGraph/flowGraphContext\";\nimport { type FlowGraphSignalConnection } from \"core/FlowGraph/flowGraphSignalConnection.pure\";\nimport { getRichTypeByFlowGraphType } from \"core/FlowGraph/flowGraphRichTypes.pure\";\nimport { FlowGraphInteger } from \"core/FlowGraph/CustomTypes/flowGraphInteger.pure\";\nimport { FlowGraphMatrix2D, FlowGraphMatrix3D } from \"core/FlowGraph/CustomTypes/flowGraphMatrix\";\nimport { Matrix, Vector2, Vector3, Vector4 } from \"core/Maths/math.vector.pure\";\n\n/**\n * Socket definition retained for an unsupported extension operation.\n */\nexport interface IFlowGraphUnsupportedInteractivitySocket {\n    /** Socket name. */\n    name: string;\n    /** FlowGraph runtime type name. */\n    type?: string;\n    /** Exact KHR_interactivity type signature. */\n    signature?: string;\n}\n\nfunction _GetDefaultValue(signature?: string): unknown {\n    switch (signature) {\n        case \"bool\":\n            return false;\n        case \"int\":\n            return new FlowGraphInteger(0);\n        case \"float\":\n            return NaN;\n        case \"float2\":\n            return new Vector2(NaN, NaN);\n        case \"float3\":\n            return new Vector3(NaN, NaN, NaN);\n        case \"float4\":\n            return new Vector4(NaN, NaN, NaN, NaN);\n        case \"float2x2\":\n            return new FlowGraphMatrix2D([NaN, NaN, NaN, NaN]);\n        case \"float3x3\":\n            return new FlowGraphMatrix3D([NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]);\n        case \"float4x4\":\n            return Matrix.FromArray([NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]);\n        case \"ref\":\n            return \"\";\n        default:\n            return undefined;\n    }\n}\n\n/**\n * Configuration for an unsupported KHR_interactivity extension operation.\n */\nexport interface IFlowGraphUnsupportedInteractivityBlockConfiguration extends IFlowGraphBlockConfiguration {\n    /** Full extension operation name. */\n    operation: string;\n    /** Input value sockets declared by the extension. */\n    inputValueSockets: IFlowGraphUnsupportedInteractivitySocket[];\n    /** Output value sockets declared by the extension. */\n    outputValueSockets: IFlowGraphUnsupportedInteractivitySocket[];\n    /** Input flow sockets used by the source graph. */\n    inputFlowSockets: string[];\n    /** Output flow sockets used by the source graph. */\n    outputFlowSockets: string[];\n}\n\n/**\n * Inspectable runtime no-op for an operation owned by an unsupported glTF extension.\n */\nexport class FlowGraphUnsupportedInteractivityBlock extends FlowGraphExecutionBlock {\n    constructor(public override config: IFlowGraphUnsupportedInteractivityBlockConfiguration) {\n        super(config);\n        this._unregisterSignalInput(\"in\");\n        this._unregisterSignalOutput(\"error\");\n\n        for (const socket of config.inputValueSockets ?? []) {\n            this.registerDataInput(socket.name, getRichTypeByFlowGraphType(socket.type));\n        }\n        for (const socket of config.outputValueSockets ?? []) {\n            this.registerDataOutput(socket.name, getRichTypeByFlowGraphType(socket.type), _GetDefaultValue(socket.signature));\n        }\n        for (const socket of config.inputFlowSockets ?? []) {\n            this._registerSignalInput(socket);\n        }\n        for (const socket of config.outputFlowSockets ?? []) {\n            this._registerSignalOutput(socket);\n        }\n    }\n\n    /** @internal */\n    public override _execute(_context: FlowGraphContext, _callingSignal: FlowGraphSignalConnection): void {\n        // Unsupported extension operations are required to behave as no-ops.\n    }\n\n    /** @returns the serialized class name */\n    public override getClassName(): string {\n        return \"FlowGraphUnsupportedInteractivityBlock\";\n    }\n}\n","import { type Nullable } from \"core/types\";\r\nimport { Color3 } from \"core/Maths/math.color\";\r\nimport { Texture } from \"core/Materials/Textures/texture\";\r\nimport { StandardMaterial } from \"core/Materials/standardMaterial\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Deferred } from \"core/Misc/deferred\";\r\n\r\nimport { type Scene } from \"core/scene\";\r\nimport { type AssetContainer } from \"core/assetContainer\";\r\n/**\r\n * Class reading and parsing the MTL file bundled with the obj file.\r\n */\r\nexport class MTLFileLoader {\r\n    /**\r\n     * Invert Y-Axis of referenced textures on load\r\n     */\r\n    public static INVERT_TEXTURE_Y = true;\r\n\r\n    /**\r\n     * All material loaded from the mtl will be set here\r\n     */\r\n    public materials: StandardMaterial[] = [];\r\n\r\n    /**\r\n     * This function will read the mtl file and create each material described inside\r\n     * This function could be improve by adding :\r\n     * -some component missing (Ni, Tf...)\r\n     * -including the specific options available\r\n     *\r\n     * @param scene defines the scene the material will be created in\r\n     * @param data defines the mtl data to parse\r\n     * @param rootUrl defines the rooturl to use in order to load relative dependencies\r\n     * @param assetContainer defines the asset container to store the material in (can be null)\r\n     * @param invertTextureY defines whether referenced textures are inverted on the Y axis\r\n     * @param materialNames defines which materials to load, or all materials if omitted\r\n     * @param trackTextureLoading collects texture loading promises and starts delayed textures when true; defaults to false\r\n     * @returns the texture loading promises, or an empty array when trackTextureLoading is false\r\n     */\r\n    public parseMTL(\r\n        scene: Scene,\r\n        data: string | ArrayBuffer,\r\n        rootUrl: string,\r\n        assetContainer: Nullable<AssetContainer>,\r\n        invertTextureY = MTLFileLoader.INVERT_TEXTURE_Y,\r\n        materialNames?: ReadonlySet<string>,\r\n        trackTextureLoading = false\r\n    ): Promise<void>[] {\r\n        const textureLoadPromises: Nullable<Promise<void>[]> = trackTextureLoading ? [] : null;\r\n        if (data instanceof ArrayBuffer) {\r\n            return textureLoadPromises ?? [];\r\n        }\r\n\r\n        //Split the lines from the file\r\n        const lines = data.split(\"\\n\");\r\n        // whitespace char ie: [ \\t\\r\\n\\f]\r\n        const delimiterPattern = /\\s+/;\r\n        //Array with RGB colors\r\n        let color: number[];\r\n        //New material\r\n        let material: Nullable<StandardMaterial> = null;\r\n\r\n        //Look at each line\r\n        for (let i = 0; i < lines.length; i++) {\r\n            const line = lines[i].trim();\r\n\r\n            // Blank line or comment\r\n            if (line.length === 0 || line.charAt(0) === \"#\") {\r\n                continue;\r\n            }\r\n\r\n            //Get the first parameter (keyword)\r\n            const pos = line.indexOf(\" \");\r\n            let key = pos >= 0 ? line.substring(0, pos) : line;\r\n            key = key.toLowerCase();\r\n\r\n            //Get the data following the key\r\n            const value: string = pos >= 0 ? line.substring(pos + 1).trim() : \"\";\r\n\r\n            //This mtl keyword will create the new material\r\n            if (key === \"newmtl\") {\r\n                //Check if it is the first material.\r\n                // Materials specifications are described after this keyword.\r\n                if (material) {\r\n                    //Add the previous material in the material array.\r\n                    this.materials.push(material);\r\n                }\r\n                if (materialNames && !materialNames.has(value)) {\r\n                    material = null;\r\n                    continue;\r\n                }\r\n                //Create a new material.\r\n                // value is the name of the material read in the mtl file\r\n\r\n                const blockEntityCollection = scene._blockEntityCollection;\r\n                scene._blockEntityCollection = !!assetContainer;\r\n                try {\r\n                    material = new StandardMaterial(value, scene);\r\n                    material._parentContainer = assetContainer;\r\n                    assetContainer?.materials.push(material);\r\n                } finally {\r\n                    scene._blockEntityCollection = blockEntityCollection;\r\n                }\r\n            } else if (key === \"kd\" && material) {\r\n                // Diffuse color (color under white light) using RGB values\r\n\r\n                //value  = \"r g b\"\r\n                color = value.split(delimiterPattern, 3).map(parseFloat);\r\n                //color = [r,g,b]\r\n                //Set tghe color into the material\r\n                material.diffuseColor = Color3.FromArray(color);\r\n            } else if (key === \"ka\" && material) {\r\n                // Ambient color (color under shadow) using RGB values\r\n\r\n                //value = \"r g b\"\r\n                color = value.split(delimiterPattern, 3).map(parseFloat);\r\n                //color = [r,g,b]\r\n                //Set tghe color into the material\r\n                material.ambientColor = Color3.FromArray(color);\r\n            } else if (key === \"ks\" && material) {\r\n                // Specular color (color when light is reflected from shiny surface) using RGB values\r\n\r\n                //value = \"r g b\"\r\n                color = value.split(delimiterPattern, 3).map(parseFloat);\r\n                //color = [r,g,b]\r\n                //Set the color into the material\r\n                material.specularColor = Color3.FromArray(color);\r\n            } else if (key === \"ke\" && material) {\r\n                // Emissive color using RGB values\r\n                color = value.split(delimiterPattern, 3).map(parseFloat);\r\n                material.emissiveColor = Color3.FromArray(color);\r\n            } else if (key === \"ns\" && material) {\r\n                //value = \"Integer\"\r\n                material.specularPower = parseFloat(value);\r\n            } else if (key === \"d\" && material) {\r\n                //d is dissolve for current material. It mean alpha for BABYLON\r\n                material.alpha = parseFloat(value);\r\n\r\n                //Texture\r\n                //This part can be improved by adding the possible options of texture\r\n            } else if (key === \"map_ka\" && material) {\r\n                // ambient texture map with a loaded image\r\n                //We must first get the folder of the image\r\n                material.ambientTexture = MTLFileLoader._GetTexture(rootUrl, value, scene, assetContainer, invertTextureY, textureLoadPromises);\r\n            } else if (key === \"map_kd\" && material) {\r\n                // Diffuse texture map with a loaded image\r\n                material.diffuseTexture = MTLFileLoader._GetTexture(rootUrl, value, scene, assetContainer, invertTextureY, textureLoadPromises);\r\n            } else if (key === \"map_ks\" && material) {\r\n                // Specular texture map with a loaded image\r\n                //We must first get the folder of the image\r\n                material.specularTexture = MTLFileLoader._GetTexture(rootUrl, value, scene, assetContainer, invertTextureY, textureLoadPromises);\r\n            } else if (key === \"map_ns\") {\r\n                //Specular\r\n                //Specular highlight component\r\n                //We must first get the folder of the image\r\n                //\r\n                //Not supported by BABYLON\r\n                //\r\n                //    continue;\r\n            } else if (key === \"map_bump\" && material) {\r\n                //The bump texture\r\n                const values = value.split(delimiterPattern);\r\n                const bumpMultiplierIndex = values.indexOf(\"-bm\");\r\n                let bumpMultiplier: Nullable<string> = null;\r\n\r\n                if (bumpMultiplierIndex >= 0) {\r\n                    bumpMultiplier = values[bumpMultiplierIndex + 1];\r\n                    values.splice(bumpMultiplierIndex, 2); // remove\r\n                }\r\n\r\n                material.bumpTexture = MTLFileLoader._GetTexture(rootUrl, values.join(\" \"), scene, assetContainer, invertTextureY, textureLoadPromises);\r\n                if (material.bumpTexture && bumpMultiplier !== null) {\r\n                    material.bumpTexture.level = parseFloat(bumpMultiplier);\r\n                }\r\n            } else if (key === \"map_d\" && material) {\r\n                // The dissolve of the material\r\n                material.opacityTexture = MTLFileLoader._GetTexture(rootUrl, value, scene, assetContainer, invertTextureY, textureLoadPromises);\r\n\r\n                //Options for illumination\r\n            } else if (key === \"illum\") {\r\n                //Illumination\r\n                if (value === \"0\") {\r\n                    //That mean Kd == Kd\r\n                } else if (value === \"1\") {\r\n                    //Color on and Ambient on\r\n                } else if (value === \"2\") {\r\n                    //Highlight on\r\n                } else if (value === \"3\") {\r\n                    //Reflection on and Ray trace on\r\n                } else if (value === \"4\") {\r\n                    //Transparency: Glass on, Reflection: Ray trace on\r\n                } else if (value === \"5\") {\r\n                    //Reflection: Fresnel on and Ray trace on\r\n                } else if (value === \"6\") {\r\n                    //Transparency: Refraction on, Reflection: Fresnel off and Ray trace on\r\n                } else if (value === \"7\") {\r\n                    //Transparency: Refraction on, Reflection: Fresnel on and Ray trace on\r\n                } else if (value === \"8\") {\r\n                    //Reflection on and Ray trace off\r\n                } else if (value === \"9\") {\r\n                    //Transparency: Glass on, Reflection: Ray trace off\r\n                } else if (value === \"10\") {\r\n                    //Casts shadows onto invisible surfaces\r\n                }\r\n            } else {\r\n                // console.log(\"Unhandled expression at line : \" + i +'\\n' + \"with value : \" + line);\r\n            }\r\n        }\r\n        //At the end of the file, add the last material\r\n        if (material) {\r\n            this.materials.push(material);\r\n        }\r\n\r\n        return textureLoadPromises ?? [];\r\n    }\r\n\r\n    /**\r\n     * Gets the texture for the material.\r\n     *\r\n     * If the material is imported from input file,\r\n     * We sanitize the url to ensure it takes the texture from aside the material.\r\n     *\r\n     * @param rootUrl The root url to load from\r\n     * @param value The value stored in the mtl\r\n     * @param scene\r\n     * @param assetContainer The asset container to store the texture in\r\n     * @param invertTextureY Whether to invert the texture on the Y axis\r\n     * @param textureLoadPromises The promises to wait for when loading asynchronously\r\n     * @returns The Texture\r\n     */\r\n    private static _GetTexture(\r\n        rootUrl: string,\r\n        value: string,\r\n        scene: Scene,\r\n        assetContainer: Nullable<AssetContainer>,\r\n        invertTextureY: boolean,\r\n        textureLoadPromises?: Nullable<Promise<void>[]>\r\n    ): Nullable<Texture> {\r\n        if (!value) {\r\n            return null;\r\n        }\r\n\r\n        let url = rootUrl;\r\n        // Load from input file.\r\n        if (rootUrl === \"file:\") {\r\n            let lastDelimiter = value.lastIndexOf(\"\\\\\");\r\n            if (lastDelimiter === -1) {\r\n                lastDelimiter = value.lastIndexOf(\"/\");\r\n            }\r\n\r\n            if (lastDelimiter > -1) {\r\n                url += value.substring(lastDelimiter + 1);\r\n            } else {\r\n                url += value;\r\n            }\r\n        }\r\n        // Not from input file.\r\n        else {\r\n            url += value;\r\n        }\r\n\r\n        const deferred = textureLoadPromises ? new Deferred<void>() : null;\r\n        if (deferred) {\r\n            // Parsing may throw before returning the array. Observe rejection without changing the original promise returned to the caller.\r\n            // eslint-disable-next-line github/no-then\r\n            void deferred.promise.catch(() => undefined);\r\n            textureLoadPromises!.push(deferred.promise);\r\n        }\r\n\r\n        let texture: Texture | undefined;\r\n        const removeFailedTextureFromCache = () => {\r\n            const internalTexture = texture?.getInternalTexture();\r\n            if (!internalTexture) {\r\n                return;\r\n            }\r\n\r\n            const texturesCache = scene.getEngine().getLoadedTexturesCache();\r\n            const cacheIndex = texturesCache.indexOf(internalTexture);\r\n            if (cacheIndex !== -1) {\r\n                texturesCache.splice(cacheIndex, 1);\r\n            }\r\n        };\r\n\r\n        const blockEntityCollection = scene._blockEntityCollection;\r\n        scene._blockEntityCollection = !!assetContainer;\r\n        try {\r\n            texture = new Texture(url, scene, {\r\n                invertY: invertTextureY,\r\n                onLoad: deferred?.resolve,\r\n                onError: (message, exception) => {\r\n                    if (texture) {\r\n                        removeFailedTextureFromCache();\r\n                    } else {\r\n                        queueMicrotask(removeFailedTextureFromCache);\r\n                    }\r\n                    if (deferred) {\r\n                        deferred.reject(new Error(`${url}: ${exception?.message || message || \"Failed to load texture\"}`));\r\n                    }\r\n                },\r\n            });\r\n            texture._parentContainer = assetContainer;\r\n            assetContainer?.textures.push(texture);\r\n        } finally {\r\n            scene._blockEntityCollection = blockEntityCollection;\r\n        }\r\n\r\n        // A container is not rendered yet, so delayed loading cannot wait for a material bind.\r\n        if (deferred && texture.delayLoadState === Constants.DELAYLOADSTATE_NOTLOADED) {\r\n            texture.delayLoad();\r\n        }\r\n        return texture;\r\n    }\r\n}\r\n","import { type AssetContainer } from \"core/assetContainer\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { StandardMaterial } from \"core/Materials/standardMaterial\";\r\nimport { Color3, Color4 } from \"core/Maths/math.color\";\r\nimport { Vector2, Vector3 } from \"core/Maths/math.vector\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { Geometry } from \"core/Meshes/geometry\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type OBJLoadingOptions } from \"./objLoadingOptions\";\r\nimport { Logger } from \"core/Misc/logger\";\r\n\r\ntype MeshObject = {\r\n    name: string;\r\n    indices: Nullable<Array<number>>;\r\n    positions: Nullable<Array<number>>;\r\n    normals: Nullable<Array<number>>;\r\n    colors: Nullable<Array<number>>;\r\n    uvs: Nullable<Array<number>>;\r\n    materialName: string;\r\n    directMaterial?: Nullable<Material>;\r\n    isObject: boolean; // If the entity is defined as an object (\"o\"), or group (\"g\")\r\n    _babylonMesh?: AbstractMesh; // The corresponding Babylon mesh\r\n    hasLines?: boolean; // If the mesh has lines\r\n};\r\n\r\n/**\r\n * Class used to load mesh data from OBJ content\r\n */\r\nexport class SolidParser {\r\n    // Descriptor\r\n    /** Object descriptor */\r\n    public static ObjectDescriptor = /^o/;\r\n    /** Group descriptor */\r\n    public static GroupDescriptor = /^g/;\r\n    /** Material lib descriptor */\r\n    public static MtlLibGroupDescriptor = /^mtllib /;\r\n    /** Use a material descriptor */\r\n    public static UseMtlDescriptor = /^usemtl /;\r\n    /** Smooth descriptor */\r\n    public static SmoothDescriptor = /^s /;\r\n\r\n    // Patterns\r\n    /** Pattern used to detect a vertex */\r\n    public static VertexPattern = /^v(\\s+[\\d|.|+|\\-|e|E]+){3,7}/;\r\n    /** Pattern used to detect a normal */\r\n    public static NormalPattern = /^vn(\\s+[\\d|.|+|\\-|e|E]+)( +[\\d|.|+|\\-|e|E]+)( +[\\d|.|+|\\-|e|E]+)/;\r\n    /** Pattern used to detect a UV set */\r\n    public static UVPattern = /^vt(\\s+[\\d|.|+|\\-|e|E]+)( +[\\d|.|+|\\-|e|E]+)/;\r\n    /** Pattern used to detect a first kind of face (f vertex vertex vertex) */\r\n    public static FacePattern1 = /^f\\s+(([\\d]{1,}[\\s]?){3,})+/;\r\n    /** Pattern used to detect a second kind of face (f vertex/uvs vertex/uvs vertex/uvs) */\r\n    public static FacePattern2 = /^f\\s+((([\\d]{1,}\\/[\\d]{1,}[\\s]?){3,})+)/;\r\n    /** Pattern used to detect a third kind of face (f vertex/uvs/normal vertex/uvs/normal vertex/uvs/normal) */\r\n    public static FacePattern3 = /^f\\s+((([\\d]{1,}\\/[\\d]{1,}\\/[\\d]{1,}[\\s]?){3,})+)/;\r\n    /** Pattern used to detect a fourth kind of face (f vertex//normal vertex//normal vertex//normal)*/\r\n    public static FacePattern4 = /^f\\s+((([\\d]{1,}\\/\\/[\\d]{1,}[\\s]?){3,})+)/;\r\n    /** Pattern used to detect a fifth kind of face (f -vertex/-uvs/-normal -vertex/-uvs/-normal -vertex/-uvs/-normal) */\r\n    public static FacePattern5 = /^f\\s+(((-[\\d]{1,}\\/-[\\d]{1,}\\/-[\\d]{1,}[\\s]?){3,})+)/;\r\n    /** Pattern used to detect a line(l vertex vertex) */\r\n    public static LinePattern1 = /^l\\s+(([\\d]{1,}[\\s]?){2,})+/;\r\n    /** Pattern used to detect a second kind of line (l vertex/uvs vertex/uvs) */\r\n    public static LinePattern2 = /^l\\s+((([\\d]{1,}\\/[\\d]{1,}[\\s]?){2,})+)/;\r\n    /** Pattern used to detect a third kind of line (l vertex/uvs/normal vertex/uvs/normal) */\r\n    public static LinePattern3 = /^l\\s+((([\\d]{1,}\\/[\\d]{1,}\\/[\\d]{1,}[\\s]?){2,})+)/;\r\n\r\n    private _loadingOptions: OBJLoadingOptions;\r\n    private _positions: Array<Vector3> = []; //values for the positions of vertices\r\n    private _normals: Array<Vector3> = []; //Values for the normals\r\n    private _uvs: Array<Vector2> = []; //Values for the textures\r\n    private _colors: Array<Color4> = [];\r\n    private _extColors: Array<Color4> = []; //Extension color\r\n    private _meshesFromObj: Array<MeshObject> = []; //[mesh] Contains all the obj meshes\r\n    private _handledMesh: MeshObject; //The current mesh of meshes array\r\n    private _indicesForBabylon: Array<number> = []; //The list of indices for VertexData\r\n    private _wrappedPositionForBabylon: Array<Vector3> = []; //The list of position in vectors\r\n    private _wrappedUvsForBabylon: Array<Vector2> = []; //Array with all value of uvs to match with the indices\r\n    private _wrappedColorsForBabylon: Array<Color4> = []; // Array with all color values to match with the indices\r\n    private _wrappedNormalsForBabylon: Array<Vector3> = []; //Array with all value of normals to match with the indices\r\n    private _tuplePosNorm: Array<{ normals: Array<number>; idx: Array<number>; uv: Array<number> }> = []; //Create a tuple with indice of Position, Normal, UV  [pos, norm, uvs]\r\n    private _curPositionInIndices = 0;\r\n    private _hasMeshes: boolean = false; //Meshes are defined in the file\r\n    private _unwrappedPositionsForBabylon: Array<number> = []; //Value of positionForBabylon w/o Vector3() [x,y,z]\r\n    private _unwrappedColorsForBabylon: Array<number> = []; // Value of colorForBabylon w/o Color4() [r,g,b,a]\r\n    private _unwrappedNormalsForBabylon: Array<number> = []; //Value of normalsForBabylon w/o Vector3()  [x,y,z]\r\n    private _unwrappedUVForBabylon: Array<number> = []; //Value of uvsForBabylon w/o Vector3()      [x,y,z]\r\n    private _triangles: Array<string> = []; //Indices from new triangles coming from polygons\r\n    private _materialNameFromObj: string = \"\"; //The name of the current material\r\n    private _objMeshName: string = \"\"; //The name of the current obj mesh\r\n    private _increment: number = 1; //Id for meshes created by the multimaterial\r\n    private _isFirstMaterial: boolean = true;\r\n    private _grayColor = new Color4(0.5, 0.5, 0.5, 1);\r\n    private _materialToUse: string[];\r\n    private _babylonMeshesArray: Array<Mesh>;\r\n    private _pushTriangle: (faces: Array<string>, faceIndex: number) => void;\r\n    private _handednessSign: number;\r\n    private _hasLineData: boolean = false; //If this mesh has line segment(l) data\r\n\r\n    /**\r\n     * Creates a new SolidParser\r\n     * @param materialToUse defines the array to fill with the list of materials to use (it will be filled by the parse function)\r\n     * @param babylonMeshesArray defines the array to fill with the list of loaded meshes (it will be filled by the parse function)\r\n     * @param loadingOptions defines the loading options to use\r\n     */\r\n    public constructor(materialToUse: string[], babylonMeshesArray: Array<Mesh>, loadingOptions: OBJLoadingOptions) {\r\n        this._materialToUse = materialToUse;\r\n        this._babylonMeshesArray = babylonMeshesArray;\r\n        this._loadingOptions = loadingOptions;\r\n    }\r\n\r\n    /**\r\n     * Search for obj in the given array.\r\n     * This function is called to check if a couple of data already exists in an array.\r\n     *\r\n     * If found, returns the index of the founded tuple index. Returns -1 if not found\r\n     * @param arr Array<{ normals: Array<number>, idx: Array<number> }>\r\n     * @param obj Array<number>\r\n     * @returns {boolean}\r\n     */\r\n    private _isInArray(arr: Array<{ normals: Array<number>; idx: Array<number> }>, obj: Array<number>) {\r\n        if (!arr[obj[0]]) {\r\n            arr[obj[0]] = { normals: [], idx: [] };\r\n        }\r\n        const idx = arr[obj[0]].normals.indexOf(obj[1]);\r\n\r\n        return idx === -1 ? -1 : arr[obj[0]].idx[idx];\r\n    }\r\n\r\n    private _isInArrayUV(arr: Array<{ normals: Array<number>; idx: Array<number>; uv: Array<number> }>, obj: Array<number>) {\r\n        if (!arr[obj[0]]) {\r\n            arr[obj[0]] = { normals: [], idx: [], uv: [] };\r\n        }\r\n        const idx = arr[obj[0]].normals.indexOf(obj[1]);\r\n\r\n        if (idx != 1 && obj[2] === arr[obj[0]].uv[idx]) {\r\n            return arr[obj[0]].idx[idx];\r\n        }\r\n        return -1;\r\n    }\r\n\r\n    /**\r\n     * This function set the data for each triangle.\r\n     * Data are position, normals and uvs\r\n     * If a tuple of (position, normal) is not set, add the data into the corresponding array\r\n     * If the tuple already exist, add only their indice\r\n     *\r\n     * @param data The vertex's data\r\n     * * indicesPositionFromObj: The index in positions array\r\n     * * indicesUvsFromObj: The index in uvs array\r\n     * * indicesNormalFromObj: The index in normals array\r\n     * * positionVectorFromOBJ: The value of position at index objIndice\r\n     * * textureVectorFromOBJ: The value of uvs\r\n     * * normalsVectorFromOBJ: The value of normals at index objNormale\r\n     * * positionColorsFromOBJ: The value of color at index objIndice\r\n     */\r\n    private _setData(data: {\r\n        indicePositionFromObj: number;\r\n        indiceUvsFromObj?: number;\r\n        indiceNormalFromObj?: number;\r\n        positionVectorFromOBJ: Vector3;\r\n        textureVectorFromOBJ?: Vector2;\r\n        normalsVectorFromOBJ?: Vector3;\r\n        positionColorsFromOBJ?: Color4;\r\n    }) {\r\n        //Use default values if undefined\r\n        data.indiceUvsFromObj ??= -1;\r\n        data.indiceNormalFromObj ??= -1;\r\n\r\n        //Check if this tuple already exists in the list of tuples\r\n        let _index: number;\r\n        if (this._loadingOptions.optimizeWithUV) {\r\n            _index = this._isInArrayUV(this._tuplePosNorm, [data.indicePositionFromObj, data.indiceNormalFromObj, data.indiceUvsFromObj]);\r\n        } else {\r\n            _index = this._isInArray(this._tuplePosNorm, [data.indicePositionFromObj, data.indiceNormalFromObj]);\r\n        }\r\n\r\n        //If it not exists\r\n        if (_index === -1) {\r\n            //Add an new indice.\r\n            //The array of indices is only an array with his length equal to the number of triangles - 1.\r\n            //We add vertices data in this order\r\n            this._indicesForBabylon.push(this._wrappedPositionForBabylon.length);\r\n            //Push the position of vertice for Babylon\r\n            //Each element is a Vector3(x,y,z)\r\n            this._wrappedPositionForBabylon.push(data.positionVectorFromOBJ);\r\n\r\n            if (data.textureVectorFromOBJ !== undefined) {\r\n                //Push the uvs for Babylon\r\n                //Each element is a Vector2(u,v)\r\n                this._wrappedUvsForBabylon.push(data.textureVectorFromOBJ);\r\n            }\r\n            if (data.normalsVectorFromOBJ !== undefined) {\r\n                //Push the normals for Babylon\r\n                //Each element is a Vector3(x,y,z)\r\n                this._wrappedNormalsForBabylon.push(data.normalsVectorFromOBJ);\r\n            }\r\n            if (data.positionColorsFromOBJ !== undefined) {\r\n                //Push the colors for Babylon\r\n                //Each element is a BABYLON.Color4(r,g,b,a)\r\n                this._wrappedColorsForBabylon.push(data.positionColorsFromOBJ);\r\n            }\r\n\r\n            //Add the tuple in the comparison list\r\n            this._tuplePosNorm[data.indicePositionFromObj].normals.push(data.indiceNormalFromObj);\r\n            this._tuplePosNorm[data.indicePositionFromObj].idx.push(this._curPositionInIndices++);\r\n            if (this._loadingOptions.optimizeWithUV) {\r\n                this._tuplePosNorm[data.indicePositionFromObj].uv.push(data.indiceUvsFromObj);\r\n            }\r\n        } else {\r\n            //The tuple already exists\r\n            //Add the index of the already existing tuple\r\n            //At this index we can get the value of position, normal, color and uvs of vertex\r\n            this._indicesForBabylon.push(_index);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Transform Vector() and BABYLON.Color() objects into numbers in an array\r\n     */\r\n    private _unwrapData() {\r\n        try {\r\n            //Every array has the same length\r\n            for (let l = 0; l < this._wrappedPositionForBabylon.length; l++) {\r\n                //Push the x, y, z values of each element in the unwrapped array\r\n                this._unwrappedPositionsForBabylon.push(\r\n                    this._wrappedPositionForBabylon[l].x * this._handednessSign,\r\n                    this._wrappedPositionForBabylon[l].y,\r\n                    this._wrappedPositionForBabylon[l].z\r\n                );\r\n                if (this._wrappedNormalsForBabylon.length) {\r\n                    this._unwrappedNormalsForBabylon.push(\r\n                        this._wrappedNormalsForBabylon[l].x * this._handednessSign,\r\n                        this._wrappedNormalsForBabylon[l].y,\r\n                        this._wrappedNormalsForBabylon[l].z\r\n                    );\r\n                }\r\n                if (this._wrappedUvsForBabylon.length) {\r\n                    this._unwrappedUVForBabylon.push(this._wrappedUvsForBabylon[l].x, this._wrappedUvsForBabylon[l].y); //z is an optional value not supported by BABYLON\r\n                }\r\n                if (this._wrappedColorsForBabylon.length) {\r\n                    //Push the r, g, b, a values of each element in the unwrapped array\r\n                    this._unwrappedColorsForBabylon.push(\r\n                        this._wrappedColorsForBabylon[l].r,\r\n                        this._wrappedColorsForBabylon[l].g,\r\n                        this._wrappedColorsForBabylon[l].b,\r\n                        this._wrappedColorsForBabylon[l].a\r\n                    );\r\n                }\r\n            }\r\n            // Reset arrays for the next new meshes\r\n            this._wrappedPositionForBabylon.length = 0;\r\n            this._wrappedNormalsForBabylon.length = 0;\r\n            this._wrappedUvsForBabylon.length = 0;\r\n            this._wrappedColorsForBabylon.length = 0;\r\n            this._tuplePosNorm.length = 0;\r\n            this._curPositionInIndices = 0;\r\n        } catch (e) {\r\n            throw new Error(\"Unable to unwrap data while parsing OBJ data.\", { cause: e });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Create triangles from polygons\r\n     * It is important to notice that a triangle is a polygon\r\n     * We get 5 patterns of face defined in OBJ File :\r\n     * facePattern1 = [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"]\r\n     * facePattern2 = [\"1/1\",\"2/2\",\"3/3\",\"4/4\",\"5/5\",\"6/6\"]\r\n     * facePattern3 = [\"1/1/1\",\"2/2/2\",\"3/3/3\",\"4/4/4\",\"5/5/5\",\"6/6/6\"]\r\n     * facePattern4 = [\"1//1\",\"2//2\",\"3//3\",\"4//4\",\"5//5\",\"6//6\"]\r\n     * facePattern5 = [\"-1/-1/-1\",\"-2/-2/-2\",\"-3/-3/-3\",\"-4/-4/-4\",\"-5/-5/-5\",\"-6/-6/-6\"]\r\n     * Each pattern is divided by the same method\r\n     * @param faces Array[String] The indices of elements\r\n     * @param v Integer The variable to increment\r\n     */\r\n    private _getTriangles(faces: Array<string>, v: number) {\r\n        //Work for each element of the array\r\n        for (let faceIndex = v; faceIndex < faces.length - 1; faceIndex++) {\r\n            //Add on the triangle variable the indexes to obtain triangles\r\n            this._pushTriangle(faces, faceIndex);\r\n        }\r\n\r\n        //Result obtained after 2 iterations:\r\n        //Pattern1 => triangle = [\"1\",\"2\",\"3\",\"1\",\"3\",\"4\"];\r\n        //Pattern2 => triangle = [\"1/1\",\"2/2\",\"3/3\",\"1/1\",\"3/3\",\"4/4\"];\r\n        //Pattern3 => triangle = [\"1/1/1\",\"2/2/2\",\"3/3/3\",\"1/1/1\",\"3/3/3\",\"4/4/4\"];\r\n        //Pattern4 => triangle = [\"1//1\",\"2//2\",\"3//3\",\"1//1\",\"3//3\",\"4//4\"];\r\n        //Pattern5 => triangle = [\"-1/-1/-1\",\"-2/-2/-2\",\"-3/-3/-3\",\"-1/-1/-1\",\"-3/-3/-3\",\"-4/-4/-4\"];\r\n    }\r\n\r\n    /**\r\n     * To get color between color and extension color\r\n     * @param index Integer The index of the element in the array\r\n     * @returns value of target color\r\n     */\r\n    private _getColor(index: number) {\r\n        if (this._loadingOptions.importVertexColors) {\r\n            return this._extColors[index] ?? this._colors[index];\r\n        } else {\r\n            return undefined;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Create triangles and push the data for each polygon for the pattern 1\r\n     * In this pattern we get vertice positions\r\n     * @param face\r\n     * @param v\r\n     */\r\n    private _setDataForCurrentFaceWithPattern1(face: Array<string>, v: number) {\r\n        //Get the indices of triangles for each polygon\r\n        this._getTriangles(face, v);\r\n        //For each element in the triangles array.\r\n        //This var could contains 1 to an infinity of triangles\r\n        for (let k = 0; k < this._triangles.length; k++) {\r\n            // Set position indice\r\n            const indicePositionFromObj = parseInt(this._triangles[k]) - 1;\r\n\r\n            this._setData({\r\n                indicePositionFromObj,\r\n                positionVectorFromOBJ: this._positions[indicePositionFromObj],\r\n                positionColorsFromOBJ: this._getColor(indicePositionFromObj),\r\n            });\r\n        }\r\n        //Reset variable for the next line\r\n        this._triangles.length = 0;\r\n    }\r\n\r\n    /**\r\n     * Create triangles and push the data for each polygon for the pattern 2\r\n     * In this pattern we get vertice positions and uvs\r\n     * @param face\r\n     * @param v\r\n     */\r\n    private _setDataForCurrentFaceWithPattern2(face: Array<string>, v: number) {\r\n        //Get the indices of triangles for each polygon\r\n        this._getTriangles(face, v);\r\n        for (let k = 0; k < this._triangles.length; k++) {\r\n            //triangle[k] = \"1/1\"\r\n            //Split the data for getting position and uv\r\n            const point = this._triangles[k].split(\"/\"); // [\"1\", \"1\"]\r\n            //Set position indice\r\n            const indicePositionFromObj = parseInt(point[0]) - 1;\r\n            //Set uv indice\r\n            const indiceUvsFromObj = parseInt(point[1]) - 1;\r\n\r\n            this._setData({\r\n                indicePositionFromObj,\r\n                indiceUvsFromObj,\r\n                positionVectorFromOBJ: this._positions[indicePositionFromObj],\r\n                textureVectorFromOBJ: this._uvs[indiceUvsFromObj],\r\n                positionColorsFromOBJ: this._getColor(indicePositionFromObj),\r\n            });\r\n        }\r\n\r\n        //Reset variable for the next line\r\n        this._triangles.length = 0;\r\n    }\r\n\r\n    /**\r\n     * Create triangles and push the data for each polygon for the pattern 3\r\n     * In this pattern we get vertice positions, uvs and normals\r\n     * @param face\r\n     * @param v\r\n     */\r\n    private _setDataForCurrentFaceWithPattern3(face: Array<string>, v: number) {\r\n        //Get the indices of triangles for each polygon\r\n        this._getTriangles(face, v);\r\n\r\n        for (let k = 0; k < this._triangles.length; k++) {\r\n            //triangle[k] = \"1/1/1\"\r\n            //Split the data for getting position, uv, and normals\r\n            const point = this._triangles[k].split(\"/\"); // [\"1\", \"1\", \"1\"]\r\n            // Set position indice\r\n            const indicePositionFromObj = parseInt(point[0]) - 1;\r\n            // Set uv indice\r\n            const indiceUvsFromObj = parseInt(point[1]) - 1;\r\n            // Set normal indice\r\n            const indiceNormalFromObj = parseInt(point[2]) - 1;\r\n\r\n            this._setData({\r\n                indicePositionFromObj,\r\n                indiceUvsFromObj,\r\n                indiceNormalFromObj,\r\n                positionVectorFromOBJ: this._positions[indicePositionFromObj],\r\n                textureVectorFromOBJ: this._uvs[indiceUvsFromObj],\r\n                normalsVectorFromOBJ: this._normals[indiceNormalFromObj],\r\n            });\r\n        }\r\n        //Reset variable for the next line\r\n        this._triangles.length = 0;\r\n    }\r\n\r\n    /**\r\n     * Create triangles and push the data for each polygon for the pattern 4\r\n     * In this pattern we get vertice positions and normals\r\n     * @param face\r\n     * @param v\r\n     */\r\n    private _setDataForCurrentFaceWithPattern4(face: Array<string>, v: number) {\r\n        this._getTriangles(face, v);\r\n\r\n        for (let k = 0; k < this._triangles.length; k++) {\r\n            //triangle[k] = \"1//1\"\r\n            //Split the data for getting position and normals\r\n            const point = this._triangles[k].split(\"//\"); // [\"1\", \"1\"]\r\n            // We check indices, and normals\r\n            const indicePositionFromObj = parseInt(point[0]) - 1;\r\n            const indiceNormalFromObj = parseInt(point[1]) - 1;\r\n\r\n            this._setData({\r\n                indicePositionFromObj,\r\n                indiceNormalFromObj,\r\n                positionVectorFromOBJ: this._positions[indicePositionFromObj],\r\n                normalsVectorFromOBJ: this._normals[indiceNormalFromObj],\r\n                positionColorsFromOBJ: this._getColor(indicePositionFromObj),\r\n            });\r\n        }\r\n        //Reset variable for the next line\r\n        this._triangles.length = 0;\r\n    }\r\n\r\n    /*\r\n     * Create triangles and push the data for each polygon for the pattern 3\r\n     * In this pattern we get vertice positions, uvs and normals\r\n     * @param face\r\n     * @param v\r\n     */\r\n    private _setDataForCurrentFaceWithPattern5(face: Array<string>, v: number) {\r\n        //Get the indices of triangles for each polygon\r\n        this._getTriangles(face, v);\r\n\r\n        for (let k = 0; k < this._triangles.length; k++) {\r\n            //triangle[k] = \"-1/-1/-1\"\r\n            //Split the data for getting position, uv, and normals\r\n            const point = this._triangles[k].split(\"/\"); // [\"-1\", \"-1\", \"-1\"]\r\n            // Set position indice\r\n            const indicePositionFromObj = this._positions.length + parseInt(point[0]);\r\n            // Set uv indice\r\n            const indiceUvsFromObj = this._uvs.length + parseInt(point[1]);\r\n            // Set normal indice\r\n            const indiceNormalFromObj = this._normals.length + parseInt(point[2]);\r\n\r\n            this._setData({\r\n                indicePositionFromObj,\r\n                indiceUvsFromObj,\r\n                indiceNormalFromObj,\r\n                positionVectorFromOBJ: this._positions[indicePositionFromObj],\r\n                textureVectorFromOBJ: this._uvs[indiceUvsFromObj],\r\n                normalsVectorFromOBJ: this._normals[indiceNormalFromObj],\r\n                positionColorsFromOBJ: this._getColor(indicePositionFromObj),\r\n            });\r\n        }\r\n        //Reset variable for the next line\r\n        this._triangles.length = 0;\r\n    }\r\n\r\n    private _addPreviousObjMesh() {\r\n        //Check if it is not the first mesh. Otherwise we don't have data.\r\n        if (this._meshesFromObj.length > 0) {\r\n            //Get the previous mesh for applying the data about the faces\r\n            //=> in obj file, faces definition append after the name of the mesh\r\n            this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1];\r\n\r\n            //Set the data into Array for the mesh\r\n            this._unwrapData();\r\n\r\n            if (this._loadingOptions.useLegacyBehavior) {\r\n                // Reverse tab. Otherwise face are displayed in the wrong sens\r\n                this._indicesForBabylon.reverse();\r\n            }\r\n\r\n            //Set the information for the mesh\r\n            //Slice the array to avoid rewriting because of the fact this is the same var which be rewrited\r\n            this._handledMesh.indices = this._indicesForBabylon.slice();\r\n            this._handledMesh.positions = this._unwrappedPositionsForBabylon.slice();\r\n            if (this._unwrappedNormalsForBabylon.length) {\r\n                this._handledMesh.normals = this._unwrappedNormalsForBabylon.slice();\r\n            }\r\n            if (this._unwrappedUVForBabylon.length) {\r\n                this._handledMesh.uvs = this._unwrappedUVForBabylon.slice();\r\n            }\r\n            if (this._unwrappedColorsForBabylon.length) {\r\n                this._handledMesh.colors = this._unwrappedColorsForBabylon.slice();\r\n            }\r\n            this._handledMesh.hasLines = this._hasLineData;\r\n\r\n            //Reset the array for the next mesh\r\n            this._indicesForBabylon.length = 0;\r\n            this._unwrappedPositionsForBabylon.length = 0;\r\n            this._unwrappedColorsForBabylon.length = 0;\r\n            this._unwrappedNormalsForBabylon.length = 0;\r\n            this._unwrappedUVForBabylon.length = 0;\r\n            this._hasLineData = false;\r\n        }\r\n    }\r\n\r\n    private _optimizeNormals(mesh: AbstractMesh): void {\r\n        const positions = mesh.getVerticesData(VertexBuffer.PositionKind);\r\n        const normals = mesh.getVerticesData(VertexBuffer.NormalKind);\r\n        const mapVertices: { [key: string]: number[] } = {};\r\n\r\n        if (!positions || !normals) {\r\n            return;\r\n        }\r\n\r\n        for (let i = 0; i < positions.length / 3; i++) {\r\n            const x = positions[i * 3 + 0];\r\n            const y = positions[i * 3 + 1];\r\n            const z = positions[i * 3 + 2];\r\n            const key = x + \"_\" + y + \"_\" + z;\r\n\r\n            let lst = mapVertices[key];\r\n            if (!lst) {\r\n                lst = [];\r\n                mapVertices[key] = lst;\r\n            }\r\n            lst.push(i);\r\n        }\r\n\r\n        const normal = new Vector3();\r\n        for (const key in mapVertices) {\r\n            const lst = mapVertices[key];\r\n            if (lst.length < 2) {\r\n                continue;\r\n            }\r\n\r\n            const v0Idx = lst[0];\r\n            for (let i = 1; i < lst.length; ++i) {\r\n                const vIdx = lst[i];\r\n                normals[v0Idx * 3 + 0] += normals[vIdx * 3 + 0];\r\n                normals[v0Idx * 3 + 1] += normals[vIdx * 3 + 1];\r\n                normals[v0Idx * 3 + 2] += normals[vIdx * 3 + 2];\r\n            }\r\n\r\n            normal.copyFromFloats(normals[v0Idx * 3 + 0], normals[v0Idx * 3 + 1], normals[v0Idx * 3 + 2]);\r\n            normal.normalize();\r\n\r\n            for (let i = 0; i < lst.length; ++i) {\r\n                const vIdx = lst[i];\r\n                normals[vIdx * 3 + 0] = normal.x;\r\n                normals[vIdx * 3 + 1] = normal.y;\r\n                normals[vIdx * 3 + 2] = normal.z;\r\n            }\r\n        }\r\n        mesh.setVerticesData(VertexBuffer.NormalKind, normals);\r\n    }\r\n\r\n    private static _IsLineElement(line: string) {\r\n        return line.startsWith(\"l\");\r\n    }\r\n\r\n    private static _IsObjectElement(line: string) {\r\n        return line.startsWith(\"o\");\r\n    }\r\n\r\n    private static _IsGroupElement(line: string) {\r\n        return line.startsWith(\"g\");\r\n    }\r\n\r\n    private static _GetZbrushMRGB(line: string, notParse: boolean) {\r\n        if (!line.startsWith(\"mrgb\")) {\r\n            return null;\r\n        }\r\n        line = line.replace(\"mrgb\", \"\").trim();\r\n        // if include vertex color , not load mrgb anymore\r\n        if (notParse) {\r\n            return [];\r\n        }\r\n        const regex = /[a-z0-9]/g;\r\n        const regArray = line.match(regex);\r\n        if (!regArray || regArray.length % 8 !== 0) {\r\n            return [];\r\n        }\r\n        const array: Color4[] = [];\r\n        for (let regIndex = 0; regIndex < regArray.length / 8; regIndex++) {\r\n            //each item is MMRRGGBB, m is material index\r\n            // const m = regArray[regIndex * 8 + 0] + regArray[regIndex * 8 + 1];\r\n            const r = regArray[regIndex * 8 + 2] + regArray[regIndex * 8 + 3];\r\n            const g = regArray[regIndex * 8 + 4] + regArray[regIndex * 8 + 5];\r\n            const b = regArray[regIndex * 8 + 6] + regArray[regIndex * 8 + 7];\r\n            array.push(new Color4(parseInt(r, 16) / 255, parseInt(g, 16) / 255, parseInt(b, 16) / 255, 1));\r\n        }\r\n        return array;\r\n    }\r\n\r\n    /**\r\n     * Function used to parse an OBJ string\r\n     * @param meshesNames defines the list of meshes to load (all if not defined)\r\n     * @param data defines the OBJ string\r\n     * @param scene defines the hosting scene\r\n     * @param assetContainer defines the asset container to load data in\r\n     * @param onFileToLoadFound defines a callback that will be called if a MTL file is found\r\n     */\r\n    public parse(meshesNames: any, data: string, scene: Scene, assetContainer: Nullable<AssetContainer>, onFileToLoadFound: (fileToLoad: string) => void): void {\r\n        //Move Santitize here to forbid delete zbrush data\r\n        // Sanitize data\r\n        data = data.replace(/#MRGB/g, \"mrgb\");\r\n        data = data.replace(/#.*$/gm, \"\").trim();\r\n        if (this._loadingOptions.useLegacyBehavior) {\r\n            this._pushTriangle = (faces, faceIndex) => this._triangles.push(faces[0], faces[faceIndex], faces[faceIndex + 1]);\r\n            this._handednessSign = 1;\r\n        } else if (scene.useRightHandedSystem) {\r\n            this._pushTriangle = (faces, faceIndex) => this._triangles.push(faces[0], faces[faceIndex + 1], faces[faceIndex]);\r\n            this._handednessSign = 1;\r\n        } else {\r\n            this._pushTriangle = (faces, faceIndex) => this._triangles.push(faces[0], faces[faceIndex], faces[faceIndex + 1]);\r\n            this._handednessSign = -1;\r\n        }\r\n\r\n        // Split the file into lines\r\n        // Preprocess line data\r\n        const linesOBJ = data.split(\"\\n\");\r\n        const lineLines: string[][] = [];\r\n        let currentGroup: string[] = [];\r\n\r\n        lineLines.push(currentGroup);\r\n\r\n        for (let i = 0; i < linesOBJ.length; i++) {\r\n            const line = linesOBJ[i].trim().replace(/\\s\\s/g, \" \");\r\n\r\n            // Comment or newLine\r\n            if (line.length === 0 || line.charAt(0) === \"#\") {\r\n                continue;\r\n            }\r\n\r\n            if (SolidParser._IsGroupElement(line) || SolidParser._IsObjectElement(line)) {\r\n                currentGroup = [];\r\n                lineLines.push(currentGroup);\r\n            }\r\n\r\n            if (SolidParser._IsLineElement(line)) {\r\n                const lineValues = line.split(\" \");\r\n                // create line elements with two vertices only\r\n                for (let i = 1; i < lineValues.length - 1; i++) {\r\n                    currentGroup.push(`l ${lineValues[i]} ${lineValues[i + 1]}`);\r\n                }\r\n            } else {\r\n                currentGroup.push(line);\r\n            }\r\n        }\r\n\r\n        const lines = lineLines.flat();\r\n        // Look at each line\r\n        for (let i = 0; i < lines.length; i++) {\r\n            const line = lines[i].trim().replace(/\\s\\s/g, \" \");\r\n            let result;\r\n            // Comment or newLine\r\n            if (line.length === 0 || line.charAt(0) === \"#\") {\r\n                continue;\r\n            } else if (SolidParser.VertexPattern.test(line)) {\r\n                //Get information about one position possible for the vertices\r\n                result = line.match(/[^ ]+/g)!; // match will return non-null due to passing regex pattern\r\n\r\n                // Value of result with line: \"v 1.0 2.0 3.0\"\r\n                // [\"v\", \"1.0\", \"2.0\", \"3.0\"]\r\n                // Create a Vector3 with the position x, y, z\r\n                this._positions.push(new Vector3(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])));\r\n\r\n                if (this._loadingOptions.importVertexColors) {\r\n                    if (result.length >= 7) {\r\n                        const r = parseFloat(result[4]);\r\n                        const g = parseFloat(result[5]);\r\n                        const b = parseFloat(result[6]);\r\n\r\n                        this._colors.push(\r\n                            new Color4(r > 1 ? r / 255 : r, g > 1 ? g / 255 : g, b > 1 ? b / 255 : b, result.length === 7 || result[7] === undefined ? 1 : parseFloat(result[7]))\r\n                        );\r\n                    } else {\r\n                        // TODO: maybe push NULL and if all are NULL to skip (and remove grayColor var).\r\n                        this._colors.push(this._grayColor);\r\n                    }\r\n                }\r\n            } else if ((result = SolidParser.NormalPattern.exec(line)) !== null) {\r\n                //Create a Vector3 with the normals x, y, z\r\n                //Value of result\r\n                // [\"vn 1.0 2.0 3.0\", \"1.0\", \"2.0\", \"3.0\"]\r\n                //Add the Vector in the list of normals\r\n                this._normals.push(new Vector3(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])));\r\n            } else if ((result = SolidParser.UVPattern.exec(line)) !== null) {\r\n                //Create a Vector2 with the normals u, v\r\n                //Value of result\r\n                // [\"vt 0.1 0.2 0.3\", \"0.1\", \"0.2\"]\r\n                //Add the Vector in the list of uvs\r\n                this._uvs.push(new Vector2(parseFloat(result[1]) * this._loadingOptions.UVScaling.x, parseFloat(result[2]) * this._loadingOptions.UVScaling.y));\r\n\r\n                //Identify patterns of faces\r\n                //Face could be defined in different type of pattern\r\n            } else if ((result = SolidParser.FacePattern3.exec(line)) !== null) {\r\n                //Value of result:\r\n                //[\"f 1/1/1 2/2/2 3/3/3\", \"1/1/1 2/2/2 3/3/3\"...]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern3(\r\n                    result[1].trim().split(\" \"), // [\"1/1/1\", \"2/2/2\", \"3/3/3\"]\r\n                    1\r\n                );\r\n            } else if ((result = SolidParser.FacePattern4.exec(line)) !== null) {\r\n                //Value of result:\r\n                //[\"f 1//1 2//2 3//3\", \"1//1 2//2 3//3\"...]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern4(\r\n                    result[1].trim().split(\" \"), // [\"1//1\", \"2//2\", \"3//3\"]\r\n                    1\r\n                );\r\n            } else if ((result = SolidParser.FacePattern5.exec(line)) !== null) {\r\n                //Value of result:\r\n                //[\"f -1/-1/-1 -2/-2/-2 -3/-3/-3\", \"-1/-1/-1 -2/-2/-2 -3/-3/-3\"...]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern5(\r\n                    result[1].trim().split(\" \"), // [\"-1/-1/-1\", \"-2/-2/-2\", \"-3/-3/-3\"]\r\n                    1\r\n                );\r\n            } else if ((result = SolidParser.FacePattern2.exec(line)) !== null) {\r\n                //Value of result:\r\n                //[\"f 1/1 2/2 3/3\", \"1/1 2/2 3/3\"...]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern2(\r\n                    result[1].trim().split(\" \"), // [\"1/1\", \"2/2\", \"3/3\"]\r\n                    1\r\n                );\r\n            } else if ((result = SolidParser.FacePattern1.exec(line)) !== null) {\r\n                //Value of result\r\n                //[\"f 1 2 3\", \"1 2 3\"...]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern1(\r\n                    result[1].trim().split(\" \"), // [\"1\", \"2\", \"3\"]\r\n                    1\r\n                );\r\n\r\n                // Define a mesh or an object\r\n                // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh\r\n            } else if ((result = SolidParser.LinePattern1.exec(line)) !== null) {\r\n                //Value of result\r\n                //[\"l 1 2\"]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern1(\r\n                    result[1].trim().split(\" \"), // [\"1\", \"2\"]\r\n                    0\r\n                );\r\n                this._hasLineData = true;\r\n\r\n                // Define a mesh or an object\r\n                // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh\r\n            } else if ((result = SolidParser.LinePattern2.exec(line)) !== null) {\r\n                //Value of result\r\n                //[\"l 1/1 2/2\"]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern2(\r\n                    result[1].trim().split(\" \"), // [\"1/1\", \"2/2\"]\r\n                    0\r\n                );\r\n                this._hasLineData = true;\r\n\r\n                // Define a mesh or an object\r\n                // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh\r\n            } else if ((result = SolidParser._GetZbrushMRGB(line, !this._loadingOptions.importVertexColors))) {\r\n                for (const element of result) {\r\n                    this._extColors.push(element);\r\n                }\r\n            } else if ((result = SolidParser.LinePattern3.exec(line)) !== null) {\r\n                //Value of result\r\n                //[\"l 1/1/1 2/2/2\"]\r\n\r\n                //Set the data for this face\r\n                this._setDataForCurrentFaceWithPattern3(\r\n                    result[1].trim().split(\" \"), // [\"1/1/1\", \"2/2/2\"]\r\n                    0\r\n                );\r\n                this._hasLineData = true;\r\n\r\n                // Define a mesh or an object\r\n                // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh\r\n            } else if (SolidParser.GroupDescriptor.test(line) || SolidParser.ObjectDescriptor.test(line)) {\r\n                // Create a new mesh corresponding to the name of the group.\r\n                // Definition of the mesh\r\n                const objMesh: MeshObject = {\r\n                    name: line.substring(2).trim(), //Set the name of the current obj mesh\r\n                    indices: null,\r\n                    positions: null,\r\n                    normals: null,\r\n                    uvs: null,\r\n                    colors: null,\r\n                    materialName: this._materialNameFromObj,\r\n                    isObject: SolidParser.ObjectDescriptor.test(line),\r\n                };\r\n                this._addPreviousObjMesh();\r\n\r\n                //Push the last mesh created with only the name\r\n                this._meshesFromObj.push(objMesh);\r\n\r\n                //Set this variable to indicate that now meshesFromObj has objects defined inside\r\n                this._hasMeshes = true;\r\n                this._isFirstMaterial = true;\r\n                this._increment = 1;\r\n                //Keyword for applying a material\r\n            } else if (SolidParser.UseMtlDescriptor.test(line)) {\r\n                //Get the name of the material\r\n                this._materialNameFromObj = line.substring(7).trim();\r\n\r\n                //If this new material is in the same mesh\r\n\r\n                if (!this._isFirstMaterial || !this._hasMeshes) {\r\n                    //Set the data for the previous mesh\r\n                    this._addPreviousObjMesh();\r\n                    //Create a new mesh\r\n                    const objMesh: MeshObject =\r\n                        //Set the name of the current obj mesh\r\n                        {\r\n                            name: (this._objMeshName || \"mesh\") + \"_mm\" + this._increment.toString(), //Set the name of the current obj mesh\r\n                            indices: null,\r\n                            positions: null,\r\n                            normals: null,\r\n                            uvs: null,\r\n                            colors: null,\r\n                            materialName: this._materialNameFromObj,\r\n                            isObject: false,\r\n                        };\r\n                    this._increment++;\r\n                    //If meshes are already defined\r\n                    this._meshesFromObj.push(objMesh);\r\n                    this._hasMeshes = true;\r\n                }\r\n                //Set the material name if the previous line define a mesh\r\n\r\n                if (this._hasMeshes && this._isFirstMaterial) {\r\n                    //Set the material name to the previous mesh (1 material per mesh)\r\n                    this._meshesFromObj[this._meshesFromObj.length - 1].materialName = this._materialNameFromObj;\r\n                    this._isFirstMaterial = false;\r\n                }\r\n                // Keyword for loading the mtl file\r\n            } else if (SolidParser.MtlLibGroupDescriptor.test(line)) {\r\n                // Get the name of mtl file\r\n                onFileToLoadFound(line.substring(7).trim());\r\n\r\n                // Apply smoothing\r\n            } else if (SolidParser.SmoothDescriptor.test(line)) {\r\n                // smooth shading => apply smoothing\r\n                // Today I don't know it work with babylon and with obj.\r\n                // With the obj file  an integer is set\r\n            } else {\r\n                //If there is another possibility\r\n                Logger.Log(\"Unhandled expression at line : \" + line);\r\n            }\r\n        }\r\n        // At the end of the file, add the last mesh into the meshesFromObj array\r\n        if (this._hasMeshes) {\r\n            // Set the data for the last mesh\r\n            this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1];\r\n\r\n            if (this._loadingOptions.useLegacyBehavior) {\r\n                //Reverse indices for displaying faces in the good sense\r\n                this._indicesForBabylon.reverse();\r\n            }\r\n\r\n            //Get the good array\r\n            this._unwrapData();\r\n            //Set array\r\n            this._handledMesh.indices = this._indicesForBabylon;\r\n            this._handledMesh.positions = this._unwrappedPositionsForBabylon;\r\n            if (this._unwrappedNormalsForBabylon.length) {\r\n                this._handledMesh.normals = this._unwrappedNormalsForBabylon;\r\n            }\r\n            if (this._unwrappedUVForBabylon.length) {\r\n                this._handledMesh.uvs = this._unwrappedUVForBabylon;\r\n            }\r\n            if (this._unwrappedColorsForBabylon.length) {\r\n                this._handledMesh.colors = this._unwrappedColorsForBabylon;\r\n            }\r\n            this._handledMesh.hasLines = this._hasLineData;\r\n        }\r\n\r\n        // If any o or g keyword not found, create a mesh with a random id\r\n        if (!this._hasMeshes) {\r\n            let newMaterial: Nullable<StandardMaterial> = null;\r\n            if (this._indicesForBabylon.length) {\r\n                if (this._loadingOptions.useLegacyBehavior) {\r\n                    // reverse tab of indices\r\n                    this._indicesForBabylon.reverse();\r\n                }\r\n\r\n                //Get positions normals uvs\r\n                this._unwrapData();\r\n            } else {\r\n                // There is no indices in the file. We will have to switch to point cloud rendering\r\n                for (const pos of this._positions) {\r\n                    this._unwrappedPositionsForBabylon.push(pos.x, pos.y, pos.z);\r\n                }\r\n\r\n                if (this._normals.length) {\r\n                    for (const normal of this._normals) {\r\n                        this._unwrappedNormalsForBabylon.push(normal.x, normal.y, normal.z);\r\n                    }\r\n                }\r\n\r\n                if (this._uvs.length) {\r\n                    for (const uv of this._uvs) {\r\n                        this._unwrappedUVForBabylon.push(uv.x, uv.y);\r\n                    }\r\n                }\r\n\r\n                if (this._extColors.length) {\r\n                    for (const color of this._extColors) {\r\n                        this._unwrappedColorsForBabylon.push(color.r, color.g, color.b, color.a);\r\n                    }\r\n                } else {\r\n                    if (this._colors.length) {\r\n                        for (const color of this._colors) {\r\n                            this._unwrappedColorsForBabylon.push(color.r, color.g, color.b, color.a);\r\n                        }\r\n                    }\r\n                }\r\n\r\n                if (!this._materialNameFromObj) {\r\n                    // Create a material with point cloud on\r\n                    const blockEntityCollection = scene._blockEntityCollection;\r\n                    scene._blockEntityCollection = !!assetContainer;\r\n                    try {\r\n                        newMaterial = new StandardMaterial(Geometry.RandomId(), scene);\r\n                        newMaterial._parentContainer = assetContainer;\r\n                        assetContainer?.materials.push(newMaterial);\r\n                    } finally {\r\n                        scene._blockEntityCollection = blockEntityCollection;\r\n                    }\r\n\r\n                    newMaterial.pointsCloud = true;\r\n\r\n                    this._materialNameFromObj = newMaterial.name;\r\n\r\n                    if (!this._normals.length) {\r\n                        newMaterial.disableLighting = true;\r\n                        newMaterial.emissiveColor = Color3.White();\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Set data for one mesh\r\n            this._meshesFromObj.push({\r\n                name: Geometry.RandomId(),\r\n                indices: this._indicesForBabylon,\r\n                positions: this._unwrappedPositionsForBabylon,\r\n                colors: this._unwrappedColorsForBabylon,\r\n                normals: this._unwrappedNormalsForBabylon,\r\n                uvs: this._unwrappedUVForBabylon,\r\n                materialName: this._materialNameFromObj,\r\n                directMaterial: newMaterial,\r\n                isObject: true,\r\n                hasLines: this._hasLineData,\r\n            });\r\n        }\r\n\r\n        //Set data for each mesh\r\n        for (let j = 0; j < this._meshesFromObj.length; j++) {\r\n            //check meshesNames (stlFileLoader)\r\n            if (meshesNames && this._meshesFromObj[j].name) {\r\n                if (meshesNames instanceof Array) {\r\n                    if (meshesNames.indexOf(this._meshesFromObj[j].name) === -1) {\r\n                        continue;\r\n                    }\r\n                } else {\r\n                    if (this._meshesFromObj[j].name !== meshesNames) {\r\n                        continue;\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Get the current mesh\r\n            //Set the data with VertexBuffer for each mesh\r\n            this._handledMesh = this._meshesFromObj[j];\r\n            //Create a Mesh with the name of the obj mesh\r\n\r\n            const blockEntityCollection = scene._blockEntityCollection;\r\n            scene._blockEntityCollection = !!assetContainer;\r\n            let babylonMesh: Mesh;\r\n            try {\r\n                babylonMesh = new Mesh(this._meshesFromObj[j].name, scene);\r\n                babylonMesh._parentContainer = assetContainer;\r\n                assetContainer?.meshes.push(babylonMesh);\r\n            } finally {\r\n                scene._blockEntityCollection = blockEntityCollection;\r\n            }\r\n            this._handledMesh._babylonMesh = babylonMesh;\r\n            // If this is a group mesh, it should have an object mesh as a parent. So look for the first object mesh that appears before it.\r\n            if (!this._handledMesh.isObject) {\r\n                for (let k = j - 1; k >= 0; --k) {\r\n                    if (this._meshesFromObj[k].isObject && this._meshesFromObj[k]._babylonMesh) {\r\n                        babylonMesh.parent = this._meshesFromObj[k]._babylonMesh!;\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Push the name of the material to an array\r\n            //This is indispensable for the importMesh function\r\n            this._materialToUse.push(this._meshesFromObj[j].materialName);\r\n            //If the mesh is a line mesh\r\n            if (this._handledMesh.hasLines) {\r\n                babylonMesh._internalMetadata ??= {};\r\n                babylonMesh._internalMetadata[\"_isLine\"] = true; //this is a line mesh\r\n            }\r\n\r\n            if (this._handledMesh.positions?.length === 0) {\r\n                //Push the mesh into an array\r\n                this._babylonMeshesArray.push(babylonMesh);\r\n                continue;\r\n            }\r\n\r\n            const vertexData: VertexData = new VertexData(); //The container for the values\r\n            //Set the data for the babylonMesh\r\n            vertexData.indices = this._handledMesh.indices;\r\n            vertexData.positions = this._handledMesh.positions;\r\n            // Empty arrays are truthy; binding a zero-length buffer causes \"Vertex buffer is not big enough for the draw call\".\r\n            if (this._loadingOptions.computeNormals || !this._handledMesh.normals?.length) {\r\n                // Compute normals if requested or if normals are not defined\r\n                const normals: Array<number> = new Array<number>();\r\n                VertexData.ComputeNormals(this._handledMesh.positions, this._handledMesh.indices, normals);\r\n                vertexData.normals = normals;\r\n            } else {\r\n                vertexData.normals = this._handledMesh.normals;\r\n            }\r\n            if (this._handledMesh.uvs?.length) {\r\n                vertexData.uvs = this._handledMesh.uvs;\r\n            }\r\n            if (this._handledMesh.colors?.length) {\r\n                vertexData.colors = this._handledMesh.colors;\r\n            }\r\n            //Set the data from the VertexBuffer to the current Mesh\r\n            const blockEntityCollectionBeforeGeometry = scene._blockEntityCollection;\r\n            scene._blockEntityCollection = !!assetContainer;\r\n            try {\r\n                vertexData.applyToMesh(babylonMesh);\r\n                babylonMesh.geometry!._parentContainer = assetContainer;\r\n                assetContainer?.geometries.push(babylonMesh.geometry!);\r\n            } finally {\r\n                scene._blockEntityCollection = blockEntityCollectionBeforeGeometry;\r\n            }\r\n            if (this._loadingOptions.invertY) {\r\n                babylonMesh.scaling.y *= -1;\r\n            }\r\n            if (this._loadingOptions.optimizeNormals) {\r\n                this._optimizeNormals(babylonMesh);\r\n            }\r\n\r\n            //Push the mesh into an array\r\n            this._babylonMeshesArray.push(babylonMesh);\r\n\r\n            if (this._handledMesh.directMaterial) {\r\n                babylonMesh.material = this._handledMesh.directMaterial;\r\n            }\r\n        }\r\n    }\r\n}\r\n","import { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const OBJFileLoaderMetadata = {\r\n    name: \"obj\",\r\n\r\n    // Read the file as bytes so the loader can decode non-UTF-8 OBJ files.\r\n    extensions: {\r\n        \".obj\": { isBinary: true },\r\n    } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n","/* eslint-disable @typescript-eslint/promise-function-async */\r\nimport { type Nullable } from \"core/types\";\r\nimport { Vector2 } from \"core/Maths/math.vector.pure\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport {\r\n    type ISceneLoaderPluginAsync,\r\n    type ISceneLoaderPluginFactory,\r\n    type ISceneLoaderPlugin,\r\n    type ISceneLoaderAsyncResult,\r\n    type SceneLoaderPluginOptions,\r\n    RegisterSceneLoaderPlugin,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type WebRequest } from \"core/Misc/webRequest\";\r\nimport { OBJFileLoaderMetadata } from \"./objFileLoader.metadata\";\r\nimport { MTLFileLoader } from \"./mtlFileLoader\";\r\nimport { type OBJLoadingOptions } from \"./objLoadingOptions\";\r\nimport { SolidParser } from \"./solidParser\";\r\nimport { type Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { StandardMaterial } from \"core/Materials/standardMaterial.pure\";\r\nimport { type Geometry } from \"core/Meshes/geometry\";\r\n\r\n/**\r\n * OBJ file type loader.\r\n * This is a babylon scene loader plugin.\r\n */\r\nexport class OBJFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\r\n    /**\r\n     * Defines the character encoding used to decode OBJ and MTL files.\r\n     */\r\n    public static ENCODING = \"auto\";\r\n    /**\r\n     * Defines if UVs are optimized by default during load.\r\n     */\r\n    public static OPTIMIZE_WITH_UV = true;\r\n    /**\r\n     * Invert model on y-axis (does a model scaling inversion)\r\n     */\r\n    public static INVERT_Y = false;\r\n    /**\r\n     * Invert Y-Axis of referenced textures on load\r\n     */\r\n    public static get INVERT_TEXTURE_Y() {\r\n        return MTLFileLoader.INVERT_TEXTURE_Y;\r\n    }\r\n\r\n    public static set INVERT_TEXTURE_Y(value: boolean) {\r\n        MTLFileLoader.INVERT_TEXTURE_Y = value;\r\n    }\r\n\r\n    /**\r\n     * Wait for referenced textures to finish loading before completing the OBJ load.\r\n     * Defaults to false for backwards compatibility.\r\n     */\r\n    public static WAIT_FOR_TEXTURES = false;\r\n\r\n    /**\r\n     * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.\r\n     */\r\n    public static IMPORT_VERTEX_COLORS = false;\r\n    /**\r\n     * Compute the normals for the model, even if normals are present in the file.\r\n     */\r\n    public static COMPUTE_NORMALS = false;\r\n    /**\r\n     * Optimize the normals for the model. Lighting can be uneven if you use OptimizeWithUV = true because new vertices can be created for the same location if they pertain to different faces.\r\n     * Using OptimizehNormals = true will help smoothing the lighting by averaging the normals of those vertices.\r\n     */\r\n    public static OPTIMIZE_NORMALS = false;\r\n    /**\r\n     * Defines custom scaling of UV coordinates of loaded meshes.\r\n     */\r\n    public static UV_SCALING = /*#__PURE__*/ new Vector2(1, 1);\r\n    /**\r\n     * Skip loading the materials even if defined in the OBJ file (materials are ignored).\r\n     */\r\n    public static SKIP_MATERIALS = false;\r\n\r\n    /**\r\n     * When a material fails to load OBJ loader will silently fail and onSuccess() callback will be triggered.\r\n     *\r\n     * Defaults to true for backwards compatibility.\r\n     */\r\n    public static MATERIAL_LOADING_FAILS_SILENTLY = true;\r\n\r\n    /**\r\n     * Loads assets without handedness conversions. This flag is for compatibility. Use it only if absolutely required. Defaults to false.\r\n     */\r\n    public static USE_LEGACY_BEHAVIOR = false;\r\n\r\n    /**\r\n     * Defines the name of the plugin.\r\n     */\r\n    public readonly name = OBJFileLoaderMetadata.name;\r\n    /**\r\n     * Defines the extension the plugin is able to load.\r\n     */\r\n    public readonly extensions = OBJFileLoaderMetadata.extensions;\r\n\r\n    private _assetContainer: Nullable<AssetContainer> = null;\r\n\r\n    private _loadingOptions: OBJLoadingOptions;\r\n\r\n    /**\r\n     * Creates loader for .OBJ files\r\n     *\r\n     * @param loadingOptions options for loading and parsing OBJ/MTL files.\r\n     */\r\n    constructor(loadingOptions?: Partial<Readonly<OBJLoadingOptions>>) {\r\n        this._loadingOptions = { ...OBJFileLoader._DefaultLoadingOptions, ...(loadingOptions ?? {}) };\r\n    }\r\n\r\n    private static get _DefaultLoadingOptions(): OBJLoadingOptions {\r\n        return {\r\n            encoding: OBJFileLoader.ENCODING,\r\n            computeNormals: OBJFileLoader.COMPUTE_NORMALS,\r\n            optimizeNormals: OBJFileLoader.OPTIMIZE_NORMALS,\r\n            importVertexColors: OBJFileLoader.IMPORT_VERTEX_COLORS,\r\n            invertY: OBJFileLoader.INVERT_Y,\r\n            invertTextureY: OBJFileLoader.INVERT_TEXTURE_Y,\r\n            waitForTextures: OBJFileLoader.WAIT_FOR_TEXTURES,\r\n            // eslint-disable-next-line @typescript-eslint/naming-convention\r\n            UVScaling: OBJFileLoader.UV_SCALING,\r\n            materialLoadingFailsSilently: OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY,\r\n            optimizeWithUV: OBJFileLoader.OPTIMIZE_WITH_UV,\r\n            skipMaterials: OBJFileLoader.SKIP_MATERIALS,\r\n            useLegacyBehavior: OBJFileLoader.USE_LEGACY_BEHAVIOR,\r\n        };\r\n    }\r\n\r\n    /**\r\n     * Calls synchronously the MTL file attached to this obj.\r\n     * Load function or importMesh function don't enable to load 2 files in the same time asynchronously.\r\n     * Without this function materials are not displayed in the first frame (but displayed after).\r\n     * In consequence it is impossible to get material information in your HTML file\r\n     *\r\n     * @param url The URL of the MTL file\r\n     * @param rootUrl defines where to load data from\r\n     * @param onSuccess Callback function to be called when the MTL file is loaded\r\n     * @param onFailure\r\n     */\r\n    private _loadMTL(\r\n        url: string,\r\n        rootUrl: string,\r\n        onSuccess: (response: string | ArrayBuffer, responseUrl?: string) => any,\r\n        onFailure: (pathOfFile: string, exception?: any) => void\r\n    ) {\r\n        //The complete path to the mtl file\r\n        const pathOfFile = rootUrl + url;\r\n\r\n        // Loads through the babylon tools to allow fileInput search.\r\n        Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, true, (request?: WebRequest, exception?: any) => {\r\n            onFailure(pathOfFile, exception);\r\n        });\r\n    }\r\n\r\n    private _decode(data: string | ArrayBuffer): string {\r\n        if (typeof data === \"string\") {\r\n            return data;\r\n        }\r\n\r\n        const bytes = new Uint8Array(data);\r\n        const encoding = this._loadingOptions.encoding ?? \"auto\";\r\n        if (encoding !== \"auto\") {\r\n            return new TextDecoder(encoding).decode(bytes);\r\n        }\r\n\r\n        if (bytes[0] === 0xff && bytes[1] === 0xfe) {\r\n            return new TextDecoder(\"utf-16le\").decode(bytes);\r\n        }\r\n        if (bytes[0] === 0xfe && bytes[1] === 0xff) {\r\n            return new TextDecoder(\"utf-16be\").decode(bytes);\r\n        }\r\n\r\n        try {\r\n            return new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\r\n        } catch {\r\n            return new TextDecoder(\"gb18030\").decode(bytes);\r\n        }\r\n    }\r\n\r\n    /** @internal */\r\n    createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync | ISceneLoaderPlugin {\r\n        return new OBJFileLoader(options[OBJFileLoaderMetadata.name]);\r\n    }\r\n\r\n    /**\r\n     * If the data string can be loaded directly.\r\n     * @returns if the data can be loaded directly\r\n     */\r\n    public canDirectLoad(): boolean {\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Imports one or more meshes from the loaded OBJ data and adds them to the scene\r\n     * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file\r\n     * @param scene the scene the meshes should be added to\r\n     * @param data the OBJ data to load\r\n     * @param rootUrl root url to load from\r\n     * @returns a promise containing the loaded meshes, particles, skeletons and animations\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string): Promise<ISceneLoaderAsyncResult> {\r\n        //get the meshes from OBJ file\r\n        // eslint-disable-next-line github/no-then\r\n        return this._parseSolidAsync(meshesNames, scene, data, rootUrl).then((meshes) => {\r\n            const geometries: Geometry[] = [];\r\n            for (let i = 0; i < meshes.length; ++i) {\r\n                const geometry = (meshes[i] as Mesh).geometry;\r\n                if (geometry) {\r\n                    geometries.push(geometry);\r\n                }\r\n            }\r\n            return {\r\n                meshes: meshes,\r\n                particleSystems: [],\r\n                skeletons: [],\r\n                animationGroups: [],\r\n                transformNodes: [],\r\n                geometries: geometries,\r\n                lights: [],\r\n                spriteManagers: [],\r\n            };\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Imports all objects from the loaded OBJ data and adds them to the scene\r\n     * @param scene the scene the objects should be added to\r\n     * @param data the OBJ data to load\r\n     * @param rootUrl root url to load from\r\n     * @returns a promise which completes when objects have been loaded to the scene\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string): Promise<void> {\r\n        //Get the 3D model\r\n        // eslint-disable-next-line github/no-then\r\n        return this.importMeshAsync(null, scene, data, rootUrl).then(() => {\r\n            // return void\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Load into an asset container.\r\n     * @param scene The scene to load into\r\n     * @param data The data to import\r\n     * @param rootUrl The root url for scene and resources\r\n     * @returns The loaded asset container\r\n     */\r\n    public async loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string): Promise<AssetContainer> {\r\n        const container = new AssetContainer(scene);\r\n        this._assetContainer = container;\r\n\r\n        try {\r\n            // Resources are collected as they are created, including before texture loading settles.\r\n            await this.importMeshAsync(null, scene, data, rootUrl);\r\n            return container;\r\n        } catch (ex) {\r\n            container.dispose();\r\n            throw ex;\r\n        } finally {\r\n            this._assetContainer = null;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Read the OBJ file and create an Array of meshes.\r\n     * Each mesh contains all information given by the OBJ and the MTL file.\r\n     * i.e. vertices positions and indices, optional normals values, optional UV values, optional material\r\n     * @param meshesNames defines a string or array of strings of the mesh names that should be loaded from the file\r\n     * @param scene defines the scene where are displayed the data\r\n     * @param data defines the content of the obj file\r\n     * @param rootUrl defines the path to the folder\r\n     * @returns the list of loaded meshes\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _parseSolidAsync(meshesNames: any, scene: Scene, data: string | ArrayBuffer, rootUrl: string): Promise<Array<AbstractMesh>> {\r\n        let fileToLoad: string = \"\"; //The name of the mtlFile to load\r\n        const materialsFromMTLFile: MTLFileLoader = new MTLFileLoader();\r\n        const materialToUse: string[] = [];\r\n        const babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon\r\n\r\n        data = this._decode(data);\r\n\r\n        // Sanitize data\r\n        data = data.replace(/#.*$/gm, \"\").trim();\r\n\r\n        // Main function\r\n        const solidParser = new SolidParser(materialToUse, babylonMeshesArray, this._loadingOptions);\r\n\r\n        solidParser.parse(meshesNames, data, scene, this._assetContainer, (fileName: string) => {\r\n            fileToLoad = fileName;\r\n        });\r\n\r\n        // load the materials\r\n        const mtlPromises: Array<Promise<void>> = [];\r\n        // Check if we have a file to load\r\n        if (fileToLoad !== \"\" && !this._loadingOptions.skipMaterials) {\r\n            // Load the MTL and optionally wait for the textures used by the selected meshes.\r\n            mtlPromises.push(\r\n                new Promise((resolve, reject) => {\r\n                    this._loadMTL(\r\n                        fileToLoad,\r\n                        rootUrl,\r\n                        async (dataLoaded) => {\r\n                            try {\r\n                                //Create materials thanks MTLLoader function\r\n                                const textureLoadPromises = materialsFromMTLFile.parseMTL(\r\n                                    scene,\r\n                                    this._decode(dataLoaded),\r\n                                    rootUrl,\r\n                                    this._assetContainer,\r\n                                    this._loadingOptions.invertTextureY,\r\n                                    new Set(materialToUse),\r\n                                    this._loadingOptions.waitForTextures\r\n                                );\r\n                                // Parsing creates the selected materials synchronously; only their textures are pending.\r\n                                for (let n = 0; n < materialsFromMTLFile.materials.length; ++n) {\r\n                                    const material = materialsFromMTLFile.materials[n];\r\n                                    for (let index = materialToUse.indexOf(material.name); index !== -1; index = materialToUse.indexOf(material.name, index + 1)) {\r\n                                        const mesh = babylonMeshesArray[index];\r\n                                        mesh.material = material;\r\n\r\n                                        if (!mesh.getTotalIndices()) {\r\n                                            // No indices, we need to turn on point cloud\r\n                                            material.pointsCloud = true;\r\n                                        }\r\n                                    }\r\n                                }\r\n                                if (this._loadingOptions.waitForTextures) {\r\n                                    const results = await Promise.allSettled(textureLoadPromises);\r\n                                    const rejected = results.find((result) => result.status === \"rejected\");\r\n                                    if (rejected) {\r\n                                        throw rejected.reason;\r\n                                    }\r\n                                }\r\n                                resolve();\r\n                            } catch (e) {\r\n                                Tools.Warn(`Error processing MTL file: '${fileToLoad}'`);\r\n                                if (this._loadingOptions.materialLoadingFailsSilently) {\r\n                                    resolve();\r\n                                } else {\r\n                                    // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n                                    reject(e);\r\n                                }\r\n                            }\r\n                        },\r\n                        (pathOfFile: string, exception?: any) => {\r\n                            Tools.Warn(`Error downloading MTL file: '${fileToLoad}'`);\r\n                            if (this._loadingOptions.materialLoadingFailsSilently) {\r\n                                resolve();\r\n                            } else {\r\n                                // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n                                reject(exception);\r\n                            }\r\n                        }\r\n                    );\r\n                })\r\n            );\r\n        }\r\n        //Return an array with all Mesh\r\n        // eslint-disable-next-line github/no-then\r\n        return Promise.all(mtlPromises).then(() => {\r\n            const isLine = (mesh: AbstractMesh) => Boolean(mesh._internalMetadata?.[\"_isLine\"] ?? false);\r\n\r\n            // Iterate over the mesh, determine if it is a line mesh, clone or modify the material to line rendering.\r\n            babylonMeshesArray.forEach((mesh) => {\r\n                if (isLine(mesh)) {\r\n                    let mat = mesh.material;\r\n                    if (!mat) {\r\n                        const blockEntityCollection = scene._blockEntityCollection;\r\n                        scene._blockEntityCollection = !!this._assetContainer;\r\n                        try {\r\n                            mat = new StandardMaterial(mesh.name + \"_line\", scene);\r\n                            mat._parentContainer = this._assetContainer;\r\n                            this._assetContainer?.materials.push(mat);\r\n                        } finally {\r\n                            scene._blockEntityCollection = blockEntityCollection;\r\n                        }\r\n                    }\r\n                    // If another mesh is using this material and it is not a line then we need to clone it.\r\n                    const needClone = mat.getBindedMeshes().filter((e) => !isLine(e)).length > 0;\r\n                    if (needClone) {\r\n                        // Clone only the material; keep the MTL texture objects shared.\r\n                        const sourceMaterial = mat as StandardMaterial;\r\n                        const { ambientTexture, diffuseTexture, specularTexture, bumpTexture, opacityTexture } = sourceMaterial;\r\n                        const blockEntityCollection = scene._blockEntityCollection;\r\n                        let lineMaterial: StandardMaterial;\r\n                        try {\r\n                            sourceMaterial.ambientTexture = null;\r\n                            sourceMaterial.diffuseTexture = null;\r\n                            sourceMaterial.specularTexture = null;\r\n                            sourceMaterial.bumpTexture = null;\r\n                            sourceMaterial.opacityTexture = null;\r\n                            scene._blockEntityCollection = !!this._assetContainer;\r\n                            lineMaterial = sourceMaterial.clone(sourceMaterial.name + \"_line\");\r\n                            lineMaterial._parentContainer = this._assetContainer;\r\n                            this._assetContainer?.materials.push(lineMaterial);\r\n                        } finally {\r\n                            scene._blockEntityCollection = blockEntityCollection;\r\n                            sourceMaterial.ambientTexture = ambientTexture;\r\n                            sourceMaterial.diffuseTexture = diffuseTexture;\r\n                            sourceMaterial.specularTexture = specularTexture;\r\n                            sourceMaterial.bumpTexture = bumpTexture;\r\n                            sourceMaterial.opacityTexture = opacityTexture;\r\n                        }\r\n                        lineMaterial.ambientTexture = ambientTexture;\r\n                        lineMaterial.diffuseTexture = diffuseTexture;\r\n                        lineMaterial.specularTexture = specularTexture;\r\n                        lineMaterial.bumpTexture = bumpTexture;\r\n                        lineMaterial.opacityTexture = opacityTexture;\r\n                        mat = lineMaterial;\r\n                    }\r\n                    mat.wireframe = true;\r\n                    mesh.material = mat;\r\n                }\r\n            });\r\n            babylonMeshesArray.forEach((mesh) => {\r\n                if (mesh._internalMetadata) {\r\n                    mesh._internalMetadata[\"_isLine\"] = undefined;\r\n                }\r\n            });\r\n\r\n            return babylonMeshesArray;\r\n        });\r\n    }\r\n}\r\n\r\n//Add this loader into the register plugin\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the OBJFileLoader scene loader plugin.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterOBJFileLoader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    RegisterSceneLoaderPlugin(new OBJFileLoader());\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./objFileLoader.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./objFileLoader.types\";\r\nexport * from \"./objFileLoader.pure\";\r\n\r\nimport { RegisterOBJFileLoader } from \"./objFileLoader.pure\";\r\nRegisterOBJFileLoader();\r\n","import { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const STLFileLoaderMetadata = {\r\n    name: \"stl\",\r\n\r\n    extensions: {\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".stl\": { isBinary: true },\r\n    } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer.pure\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { type ISceneLoaderPlugin, RegisterSceneLoaderPlugin } from \"core/Loading/sceneLoader\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { STLFileLoaderMetadata } from \"./stlFileLoader.metadata\";\r\n\r\n/**\r\n * STL file type loader.\r\n * This is a babylon scene loader plugin.\r\n */\r\nexport class STLFileLoader implements ISceneLoaderPlugin {\r\n    /** @internal */\r\n    public solidPattern = /solid (\\S*)([\\S\\s]*?)endsolid[ ]*(\\S*)/g;\r\n\r\n    /** @internal */\r\n    public facetsPattern = /facet([\\s\\S]*?)endfacet/g;\r\n    /** @internal */\r\n    public normalPattern = /normal[\\s]+([-+]?[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?)+[\\s]+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)+[\\s]+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)+/g;\r\n    /** @internal */\r\n    public vertexPattern = /vertex[\\s]+([-+]?[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?)+[\\s]+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)+[\\s]+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)+/g;\r\n\r\n    /**\r\n     * Defines the name of the plugin.\r\n     */\r\n    public readonly name = STLFileLoaderMetadata.name;\r\n\r\n    /**\r\n     * Defines the extensions the stl loader is able to load.\r\n     * force data to come in as an ArrayBuffer\r\n     * we'll convert to string if it looks like it's an ASCII .stl\r\n     */\r\n    public readonly extensions = STLFileLoaderMetadata.extensions;\r\n\r\n    /**\r\n     * Defines if Y and Z axes are swapped or not when loading an STL file.\r\n     * The default is false to maintain backward compatibility. When set to\r\n     * true, coordinates from the STL file are used without change.\r\n     */\r\n    public static DO_NOT_ALTER_FILE_COORDINATES = false;\r\n\r\n    /**\r\n     * Import meshes into a scene.\r\n     * @param meshesNames An array of mesh names, a single mesh name, or empty string for all meshes that filter what meshes are imported\r\n     * @param scene The scene to import into\r\n     * @param data The data to import\r\n     * @param rootUrl The root url for scene and resources\r\n     * @param meshes The meshes array to import into\r\n     * @returns True if successful or false otherwise\r\n     */\r\n    public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>): boolean {\r\n        let matches;\r\n\r\n        if (typeof data !== \"string\") {\r\n            if (this._isBinary(data)) {\r\n                // binary .stl\r\n                const babylonMesh = new Mesh(\"stlmesh\", scene);\r\n                this._parseBinary(babylonMesh, data);\r\n                if (meshes) {\r\n                    meshes.push(babylonMesh);\r\n                }\r\n                return true;\r\n            }\r\n\r\n            // ASCII .stl\r\n\r\n            // convert to string\r\n            data = new TextDecoder().decode(new Uint8Array(data));\r\n        }\r\n\r\n        //if arrived here, data is a string, containing the STLA data.\r\n\r\n        while ((matches = this.solidPattern.exec(data))) {\r\n            let meshName = matches[1];\r\n            const meshNameFromEnd = matches[3];\r\n            if (meshNameFromEnd && meshName != meshNameFromEnd) {\r\n                Tools.Error(\"Error in STL, solid name != endsolid name\");\r\n                return false;\r\n            }\r\n\r\n            // check meshesNames\r\n            if (meshesNames && meshName) {\r\n                if (meshesNames instanceof Array) {\r\n                    if (!meshesNames.indexOf(meshName)) {\r\n                        continue;\r\n                    }\r\n                } else {\r\n                    if (meshName !== meshesNames) {\r\n                        continue;\r\n                    }\r\n                }\r\n            }\r\n\r\n            // stl mesh name can be empty as well\r\n            meshName = meshName || \"stlmesh\";\r\n\r\n            const babylonMesh = new Mesh(meshName, scene);\r\n            this._parseASCII(babylonMesh, matches[2]);\r\n            if (meshes) {\r\n                meshes.push(babylonMesh);\r\n            }\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * Load into a scene.\r\n     * @param scene The scene to load into\r\n     * @param data The data to import\r\n     * @param rootUrl The root url for scene and resources\r\n     * @returns true if successful or false otherwise\r\n     */\r\n    public load(scene: Scene, data: any, rootUrl: string): boolean {\r\n        const result = this.importMesh(null, scene, data, rootUrl, null);\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * Load into an asset container.\r\n     * @param scene The scene to load into\r\n     * @param data The data to import\r\n     * @param rootUrl The root url for scene and resources\r\n     * @returns The loaded asset container\r\n     */\r\n    public loadAssetContainer(scene: Scene, data: string, rootUrl: string): AssetContainer {\r\n        const container = new AssetContainer(scene);\r\n        scene._blockEntityCollection = true;\r\n        this.importMesh(null, scene, data, rootUrl, container.meshes);\r\n        scene._blockEntityCollection = false;\r\n        return container;\r\n    }\r\n\r\n    private _isBinary(data: any) {\r\n        // check if file size is correct for binary stl\r\n        const reader = new DataView(data);\r\n\r\n        // A Binary STL header is 80 bytes, if the data size is not great than\r\n        // that then it's not a binary STL.\r\n        if (reader.byteLength <= 80) {\r\n            return false;\r\n        }\r\n\r\n        const faceSize = (32 / 8) * 3 + (32 / 8) * 3 * 3 + 16 / 8;\r\n        const nFaces = reader.getUint32(80, true);\r\n\r\n        if (80 + 32 / 8 + nFaces * faceSize === reader.byteLength) {\r\n            return true;\r\n        }\r\n\r\n        // US-ASCII begin with 's', 'o', 'l', 'i', 'd'\r\n        const ascii = [115, 111, 108, 105, 100];\r\n        for (let off = 0; off < 5; off++) {\r\n            if (reader.getUint8(off) !== ascii[off]) {\r\n                return true;\r\n            }\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    private _parseBinary(mesh: Mesh, data: ArrayBuffer) {\r\n        const reader = new DataView(data);\r\n        const faces = reader.getUint32(80, true);\r\n\r\n        const dataOffset = 84;\r\n        const faceLength = 12 * 4 + 2;\r\n\r\n        let offset = 0;\r\n\r\n        const positions = new Float32Array(faces * 3 * 3);\r\n        const normals = new Float32Array(faces * 3 * 3);\r\n        const indices = new Uint32Array(faces * 3);\r\n        let indicesCount = 0;\r\n\r\n        for (let face = 0; face < faces; face++) {\r\n            const start = dataOffset + face * faceLength;\r\n            const normalX = reader.getFloat32(start, true);\r\n            const normalY = reader.getFloat32(start + 4, true);\r\n            const normalZ = reader.getFloat32(start + 8, true);\r\n\r\n            for (let i = 1; i <= 3; i++) {\r\n                const vertexstart = start + i * 12;\r\n\r\n                // ordering is intentional to match ascii import\r\n                positions[offset] = reader.getFloat32(vertexstart, true);\r\n                normals[offset] = normalX;\r\n\r\n                if (!STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) {\r\n                    positions[offset + 2] = reader.getFloat32(vertexstart + 4, true);\r\n                    positions[offset + 1] = reader.getFloat32(vertexstart + 8, true);\r\n\r\n                    normals[offset + 2] = normalY;\r\n                    normals[offset + 1] = normalZ;\r\n                } else {\r\n                    positions[offset + 1] = reader.getFloat32(vertexstart + 4, true);\r\n                    positions[offset + 2] = reader.getFloat32(vertexstart + 8, true);\r\n\r\n                    normals[offset + 1] = normalY;\r\n                    normals[offset + 2] = normalZ;\r\n                }\r\n\r\n                offset += 3;\r\n            }\r\n\r\n            if (STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) {\r\n                indices[indicesCount] = indicesCount;\r\n                indices[indicesCount + 1] = indicesCount + 2;\r\n                indices[indicesCount + 2] = indicesCount + 1;\r\n                indicesCount += 3;\r\n            } else {\r\n                indices[indicesCount] = indicesCount++;\r\n                indices[indicesCount] = indicesCount++;\r\n                indices[indicesCount] = indicesCount++;\r\n            }\r\n        }\r\n\r\n        mesh.setVerticesData(VertexBuffer.PositionKind, positions);\r\n        mesh.setVerticesData(VertexBuffer.NormalKind, normals);\r\n        mesh.setIndices(indices);\r\n        mesh.computeWorldMatrix(true);\r\n    }\r\n\r\n    private _parseASCII(mesh: Mesh, solidData: string) {\r\n        const positions = [];\r\n        const normals = [];\r\n        const indices = [];\r\n        let indicesCount = 0;\r\n\r\n        //load facets, ignoring loop as the standard doesn't define it can contain more than vertices\r\n        let matches;\r\n        while ((matches = this.facetsPattern.exec(solidData))) {\r\n            const facet = matches[1];\r\n            //one normal per face\r\n            const normalMatches = this.normalPattern.exec(facet);\r\n            this.normalPattern.lastIndex = 0;\r\n            if (!normalMatches) {\r\n                continue;\r\n            }\r\n            const normal = [Number(normalMatches[1]), Number(normalMatches[5]), Number(normalMatches[3])];\r\n\r\n            let vertexMatch;\r\n            while ((vertexMatch = this.vertexPattern.exec(facet))) {\r\n                if (!STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) {\r\n                    positions.push(Number(vertexMatch[1]), Number(vertexMatch[5]), Number(vertexMatch[3]));\r\n                    normals.push(normal[0], normal[1], normal[2]);\r\n                } else {\r\n                    positions.push(Number(vertexMatch[1]), Number(vertexMatch[3]), Number(vertexMatch[5]));\r\n\r\n                    // Flipping the second and third component because inverted\r\n                    // when normal was declared.\r\n                    normals.push(normal[0], normal[2], normal[1]);\r\n                }\r\n            }\r\n            if (STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) {\r\n                indices.push(indicesCount, indicesCount + 2, indicesCount + 1);\r\n                indicesCount += 3;\r\n            } else {\r\n                indices.push(indicesCount++, indicesCount++, indicesCount++);\r\n            }\r\n            this.vertexPattern.lastIndex = 0;\r\n        }\r\n\r\n        this.facetsPattern.lastIndex = 0;\r\n        mesh.setVerticesData(VertexBuffer.PositionKind, positions);\r\n        mesh.setVerticesData(VertexBuffer.NormalKind, normals);\r\n        mesh.setIndices(indices);\r\n        mesh.computeWorldMatrix(true);\r\n    }\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the STLFileLoader scene loader plugin.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterSTLFileLoader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    RegisterSceneLoaderPlugin(new STLFileLoader());\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./stlFileLoader.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./stlFileLoader.types\";\r\nexport * from \"./stlFileLoader.pure\";\r\n\r\nimport \"core/Materials/standardMaterial\";\r\n\r\nimport { RegisterSTLFileLoader } from \"./stlFileLoader.pure\";\r\nRegisterSTLFileLoader();\r\n","import { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const SPLATFileLoaderMetadata = {\r\n    name: \"splat\",\r\n\r\n    extensions: {\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".splat\": { isBinary: true },\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".ply\": { isBinary: true },\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".spz\": { isBinary: true },\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".json\": { isBinary: false }, // For SOG metadata files\r\n        // eslint-disable-next-line @typescript-eslint/naming-convention\r\n        \".sog\": { isBinary: true },\r\n    } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n","import { type Scene } from \"core/scene\";\r\nimport { type IParsedSplat, type ISogTexturePack, Mode } from \"./splatDefs\";\r\nimport { AllocateShBuffers } from \"core/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure\";\r\nimport { Scalar } from \"core/Maths/math.scalar\";\r\nimport { type AbstractEngine } from \"core/Engines\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { RawTexture } from \"core/Materials/Textures/rawTexture\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { type GaussianSplattingDownloadManager, type DownloadGroupId } from \"./gaussianSplattingDownloadManager\";\r\n\r\n/**\r\n * Definition of a SOG data file\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport interface SOGDataFile {\r\n    /**\r\n     * index 0 is number of splats index 1 is number of components per splat (3 for vec3, 4 for vec4, etc.)\r\n     */\r\n    shape: number[];\r\n    /**\r\n     * type of components\r\n     */\r\n    dtype: string;\r\n    /**\r\n     * min range of data\r\n     */\r\n    mins?: number | number[];\r\n    /**\r\n     * max range of data\r\n     */\r\n    maxs?: number | number[];\r\n    /**\r\n     * palette for indexed data (quantized)\r\n     */\r\n    codebook?: number[]; // Only for version 2\r\n    /**\r\n     * type of encoding\r\n     */\r\n    encoding?: string;\r\n    /**\r\n     * number of bits for quantization (if any)\r\n     */\r\n    quantization?: number;\r\n    /**\r\n     * webp file names\r\n     */\r\n    files: string[];\r\n    /**\r\n     * SH band count (if applicable)\r\n     */\r\n    bands?: number;\r\n}\r\n\r\n/**\r\n * Definition of the root SOG data file\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport interface SOGRootData {\r\n    /**\r\n     * version of the SOG format\r\n     */\r\n    version?: number;\r\n    /**\r\n     * mean positions of the splats\r\n     */\r\n    means: SOGDataFile;\r\n    /**\r\n     * scales of the splats\r\n     */\r\n    scales: SOGDataFile;\r\n    /**\r\n     * quaternions of the splats\r\n     */\r\n    quats: SOGDataFile;\r\n    /**\r\n     * SH0 coefficients of the splats (base color)\r\n     */\r\n    sh0: SOGDataFile;\r\n    /**\r\n     *  Optional higher order SH coefficients of the splats (lighting information)\r\n     */\r\n    shN?: SOGDataFile;\r\n    /**\r\n     * number of splats (optional, can be inferred from means.shape[0])\r\n     */\r\n    count?: number;\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\ninterface IWebPImage {\r\n    bits: Uint8Array;\r\n    width: number;\r\n    height: number;\r\n}\r\nconst SH_C0 = 0.28209479177387814;\r\n\r\nasync function LoadWebpImageData(rootUrlOrData: string | Uint8Array, filename: string, engine: AbstractEngine): Promise<IWebPImage> {\r\n    const promise = new Promise<IWebPImage>((resolve, reject) => {\r\n        const image = engine.createCanvasImage();\r\n        if (!image) {\r\n            throw new Error(\"Failed to create ImageBitmap\");\r\n        }\r\n        image.onload = () => {\r\n            try {\r\n                // Draw to canvas\r\n                const canvas = engine.createCanvas(image.width, image.height);\r\n                if (!canvas) {\r\n                    throw new Error(\"Failed to create canvas\");\r\n                }\r\n                const ctx = canvas.getContext(\"2d\");\r\n                if (!ctx) {\r\n                    throw new Error(\"Failed to get 2D context\");\r\n                }\r\n                ctx.drawImage(image, 0, 0);\r\n\r\n                // Extract pixel data (RGBA per pixel)\r\n                const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n                resolve({ bits: new Uint8Array(imageData.data.buffer), width: imageData.width, height: imageData.height });\r\n            } catch (error) {\r\n                // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n                reject(`Error loading image ${image.src} with exception: ${error}`);\r\n            }\r\n        };\r\n        image.onerror = (error) => {\r\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\r\n            reject(`Error loading image ${image.src} with exception: ${error}`);\r\n        };\r\n\r\n        image.crossOrigin = \"anonymous\"; // To avoid CORS issues\r\n        let objectUrl: string | undefined;\r\n        if (typeof rootUrlOrData === \"string\") {\r\n            // old behavior: URL + filename\r\n            if (!filename) {\r\n                throw new Error(\"filename is required when using a URL\");\r\n            }\r\n            image.src = rootUrlOrData + filename;\r\n        } else {\r\n            // new behavior: Uint8Array\r\n            const blob = new Blob([rootUrlOrData as any], { type: \"image/webp\" });\r\n            objectUrl = URL.createObjectURL(blob);\r\n            image.src = objectUrl;\r\n        }\r\n    });\r\n    return await promise;\r\n}\r\n\r\nasync function ParseSogDatas(data: SOGRootData, imageDataArrays: IWebPImage[], scene: Scene): Promise<IParsedSplat> {\r\n    const splatCount = data.count ? data.count : data.means.shape[0];\r\n    const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32\r\n    const buffer = new ArrayBuffer(rowOutputLength * splatCount);\r\n\r\n    const position = new Float32Array(buffer);\r\n    const scale = new Float32Array(buffer);\r\n    const rgba = new Uint8ClampedArray(buffer);\r\n    const rot = new Uint8ClampedArray(buffer);\r\n\r\n    // Undo the symmetric log transform used at encode time:\r\n    const unlog = (n: number) => Math.sign(n) * (Math.exp(Math.abs(n)) - 1);\r\n\r\n    const meansl = imageDataArrays[0].bits;\r\n    const meansu = imageDataArrays[1].bits;\r\n    // Check that data.means.mins is an array\r\n    if (!Array.isArray(data.means.mins) || !Array.isArray(data.means.maxs)) {\r\n        throw new Error(\"Missing arrays in SOG data.\");\r\n    }\r\n\r\n    // --- Positions\r\n    for (let i = 0; i < splatCount; i++) {\r\n        const index = i * 4;\r\n        for (let j = 0; j < 3; j++) {\r\n            const meansMin = data.means.mins[j];\r\n            const meansMax = data.means.maxs[j];\r\n            const meansup = meansu[index + j];\r\n            const meanslow = meansl[index + j];\r\n            const q = (meansup << 8) | meanslow;\r\n            const n = Scalar.Lerp(meansMin, meansMax, q / 65535);\r\n            position[i * 8 + j] = unlog(n);\r\n        }\r\n    }\r\n\r\n    // --- Scales\r\n    const scales = imageDataArrays[2].bits;\r\n    if (data.version === 2) {\r\n        if (!data.scales.codebook) {\r\n            throw new Error(\"Missing codebook in SOG version 2 scales data.\");\r\n        }\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const index = i * 4;\r\n            for (let j = 0; j < 3; j++) {\r\n                const sc = data.scales.codebook[scales[index + j]];\r\n                const sce = Math.exp(sc);\r\n                scale[i * 8 + 3 + j] = sce;\r\n            }\r\n        }\r\n    } else {\r\n        if (!Array.isArray(data.scales.mins) || !Array.isArray(data.scales.maxs)) {\r\n            throw new Error(\"Missing arrays in SOG scales data.\");\r\n        }\r\n\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const index = i * 4;\r\n            for (let j = 0; j < 3; j++) {\r\n                const sc = scales[index + j];\r\n                const lsc = Scalar.Lerp(data.scales.mins[j], data.scales.maxs[j], sc / 255);\r\n                const lsce = Math.exp(lsc);\r\n                scale[i * 8 + 3 + j] = lsce;\r\n            }\r\n        }\r\n    }\r\n\r\n    // --- Colors/SH0\r\n    const colors = imageDataArrays[4].bits;\r\n    if (data.version === 2) {\r\n        if (!data.sh0.codebook) {\r\n            throw new Error(\"Missing codebook in SOG version 2 sh0 data.\");\r\n        }\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const index = i * 4;\r\n            for (let j = 0; j < 3; j++) {\r\n                const component = 0.5 + data.sh0.codebook[colors[index + j]] * SH_C0;\r\n                rgba[i * 32 + 24 + j] = Math.max(0, Math.min(255, Math.round(255 * component)));\r\n            }\r\n            rgba[i * 32 + 24 + 3] = colors[index + 3];\r\n        }\r\n    } else {\r\n        if (!Array.isArray(data.sh0.mins) || !Array.isArray(data.sh0.maxs)) {\r\n            throw new Error(\"Missing arrays in SOG sh0 data.\");\r\n        }\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const index = i * 4;\r\n            for (let j = 0; j < 4; j++) {\r\n                const colorsMin = data.sh0.mins[j];\r\n                const colorsMax = data.sh0.maxs[j];\r\n\r\n                const colort = colors[index + j];\r\n                const c = Scalar.Lerp(colorsMin, colorsMax, colort / 255);\r\n\r\n                let csh;\r\n                if (j < 3) {\r\n                    csh = 0.5 + c * SH_C0;\r\n                } else {\r\n                    csh = 1.0 / (1.0 + Math.exp(-c));\r\n                }\r\n\r\n                rgba[i * 32 + 24 + j] = Math.max(0, Math.min(255, Math.round(255 * csh)));\r\n            }\r\n        }\r\n    }\r\n\r\n    // --- Rotations\r\n    // Dequantize the stored three components:\r\n    const toComp = (c: number) => ((c / 255 - 0.5) * 2.0) / Math.SQRT2;\r\n\r\n    const quatArray = imageDataArrays[3].bits;\r\n    for (let i = 0; i < splatCount; i++) {\r\n        const quatsr = quatArray[i * 4 + 0];\r\n        const quatsg = quatArray[i * 4 + 1];\r\n        const quatsb = quatArray[i * 4 + 2];\r\n        const quatsa = quatArray[i * 4 + 3];\r\n\r\n        const a = toComp(quatsr);\r\n        const b = toComp(quatsg);\r\n        const c = toComp(quatsb);\r\n\r\n        const mode = quatsa - 252; // 0..3 (R,G,B,A is one of the four components)\r\n\r\n        // Reconstruct the omitted component so that ||q|| = 1 and w.l.o.g. the omitted one is non-negative\r\n        const t = a * a + b * b + c * c;\r\n        const d = Math.sqrt(Math.max(0, 1 - t));\r\n\r\n        // Place components according to mode\r\n        let q: [number, number, number, number];\r\n        switch (mode) {\r\n            case 0:\r\n                q = [d, a, b, c];\r\n                break; // omitted = x\r\n            case 1:\r\n                q = [a, d, b, c];\r\n                break; // omitted = y\r\n            case 2:\r\n                q = [a, b, d, c];\r\n                break; // omitted = z\r\n            case 3:\r\n                q = [a, b, c, d];\r\n                break; // omitted = w\r\n            default:\r\n                throw new Error(\"Invalid quaternion mode\");\r\n        }\r\n\r\n        rot[i * 32 + 28 + 0] = q[0] * 127.5 + 127.5;\r\n        rot[i * 32 + 28 + 1] = q[1] * 127.5 + 127.5;\r\n        rot[i * 32 + 28 + 2] = q[2] * 127.5 + 127.5;\r\n        rot[i * 32 + 28 + 3] = q[3] * 127.5 + 127.5;\r\n    }\r\n\r\n    // --- SH\r\n    if (data.shN) {\r\n        const coeffs = data.shN.bands ? (data.shN.bands + 1) ** 2 - 1 : data.shN.shape[1] / 3; // 3 components per coeff\r\n        const shDegree = data.shN.bands !== undefined && data.shN.bands !== null ? data.shN.bands : Math.round(Math.sqrt(coeffs + 1) - 1);\r\n        const shCentroids = imageDataArrays[5].bits;\r\n        const shLabelsData = imageDataArrays[6].bits;\r\n        const shCentroidsWidth = imageDataArrays[5].width;\r\n\r\n        const shComponentCount = coeffs * 3;\r\n\r\n        const textureCount = Math.ceil(shComponentCount / 16); // 4 components can be stored per texture, 4 sh per component\r\n        //let shIndexRead = byteOffset;\r\n\r\n        const engine = scene.getEngine();\r\n        const width = engine.getCaps().maxTextureSize;\r\n        const height = Math.ceil(splatCount / width);\r\n\r\n        // sh is an array of uint8array that will be used to create sh textures\r\n        const sh = AllocateShBuffers(textureCount, height * width * 4 * 4);\r\n\r\n        if (data.version === 2) {\r\n            if (!data.shN.codebook) {\r\n                throw new Error(\"Missing codebook in SOG version 2 shN data.\");\r\n            }\r\n\r\n            for (let i = 0; i < splatCount; i++) {\r\n                const n = shLabelsData[i * 4 + 0] + (shLabelsData[i * 4 + 1] << 8);\r\n                const u = (n % 64) * coeffs;\r\n                const v = Math.floor(n / 64);\r\n\r\n                for (let k = 0; k < coeffs; k++) {\r\n                    for (let j = 0; j < 3; j++) {\r\n                        const shIndexWrite = k * 3 + j;\r\n                        const textureIndex = Math.floor(shIndexWrite / 16);\r\n                        const shArray = sh[textureIndex];\r\n                        const byteIndexInTexture = shIndexWrite % 16; // [0..15]\r\n                        const offsetPerSplat = i * 16; // 16 sh values per texture per splat.\r\n\r\n                        const shValue = data.shN.codebook[shCentroids[(u + k) * 4 + j + v * shCentroidsWidth * 4]] * 127.5 + 127.5;\r\n                        shArray[byteIndexInTexture + offsetPerSplat] = Math.max(0, Math.min(255, shValue));\r\n                    }\r\n                }\r\n            }\r\n        } else {\r\n            for (let i = 0; i < splatCount; i++) {\r\n                const n = shLabelsData[i * 4 + 0] + (shLabelsData[i * 4 + 1] << 8);\r\n                const u = (n % 64) * coeffs;\r\n                const v = Math.floor(n / 64);\r\n                const shMin = data.shN.mins as number;\r\n                const shMax = data.shN.maxs as number;\r\n\r\n                for (let j = 0; j < 3; j++) {\r\n                    for (let k = 0; k < coeffs / 3; k++) {\r\n                        const shIndexWrite = k * 3 + j;\r\n                        const textureIndex = Math.floor(shIndexWrite / 16);\r\n                        const shArray = sh[textureIndex];\r\n                        const byteIndexInTexture = shIndexWrite % 16; // [0..15]\r\n                        const offsetPerSplat = i * 16; // 16 sh values per texture per splat.\r\n\r\n                        const shValue = Scalar.Lerp(shMin, shMax, shCentroids[(u + k) * 4 + j + v * shCentroidsWidth * 4] / 255) * 127.5 + 127.5;\r\n                        shArray[byteIndexInTexture + offsetPerSplat] = Math.max(0, Math.min(255, shValue));\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        return await new Promise((resolve) => {\r\n            resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false, sh: sh, shDegree: shDegree });\r\n        });\r\n    }\r\n\r\n    return await new Promise((resolve) => {\r\n        resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false });\r\n    });\r\n}\r\n\r\n/**\r\n * Parse SOG data from either a SOGRootData object (with webp files loaded from rootUrl) or from a Map of filenames to Uint8Array file data (including meta.json)\r\n * @param dataOrFiles Either the SOGRootData or a Map of filenames to Uint8Array file data (including meta.json)\r\n * @param rootUrl Base URL to load webp files from (if dataOrFiles is SOGRootData)\r\n * @param scene The Babylon.js scene\r\n * @returns Parsed data\r\n */\r\nexport async function ParseSogMeta(dataOrFiles: SOGRootData | Map<string, Uint8Array>, rootUrl: string, scene: Scene): Promise<IParsedSplat> {\r\n    let data: SOGRootData;\r\n    let files: Map<string, Uint8Array> | undefined;\r\n\r\n    if (dataOrFiles instanceof Map) {\r\n        files = dataOrFiles;\r\n\r\n        const metaFile = files.get(\"meta.json\");\r\n        if (!metaFile) {\r\n            throw new Error(\"meta.json not found in files Map\");\r\n        }\r\n\r\n        data = JSON.parse(new TextDecoder().decode(metaFile)) as SOGRootData;\r\n    } else {\r\n        data = dataOrFiles;\r\n    }\r\n\r\n    // Collect all file names\r\n    const urls = [...data.means.files, ...data.scales.files, ...data.quats.files, ...data.sh0.files];\r\n    if (data.shN) {\r\n        urls.push(...data.shN.files);\r\n    }\r\n\r\n    // Load webp images in parallel\r\n    const imageDataArrays: IWebPImage[] = await Promise.all(\r\n        urls.map(async (fileName) => {\r\n            if (files && files.has(fileName)) {\r\n                // load from in-memory Uint8Array\r\n                const fileData = files.get(fileName)!;\r\n                return await LoadWebpImageData(fileData, fileName, scene.getEngine());\r\n            } else {\r\n                // fallback: load from URL\r\n                return await LoadWebpImageData(rootUrl, fileName, scene.getEngine());\r\n            }\r\n        })\r\n    );\r\n\r\n    return await ParseSogDatas(data, imageDataArrays, scene);\r\n}\r\n\r\nfunction CreateSogTexture(scene: Scene, bits: Uint8Array, width: number, height: number): RawTexture {\r\n    const tex = new RawTexture(bits, width, height, Constants.TEXTUREFORMAT_RGBA, scene, false, false, Constants.TEXTURE_NEAREST_SAMPLINGMODE, Constants.TEXTURETYPE_UNSIGNED_BYTE);\r\n    tex.wrapU = Constants.TEXTURE_CLAMP_ADDRESSMODE;\r\n    tex.wrapV = Constants.TEXTURE_CLAMP_ADDRESSMODE;\r\n    return tex;\r\n}\r\n\r\nfunction CreateSogTextureFromImage(scene: Scene, image: IWebPImage): RawTexture {\r\n    return CreateSogTexture(scene, image.bits, image.width, image.height);\r\n}\r\n\r\n/**\r\n * Loads a SOG attribute image straight onto a GPU texture using `createImageBitmap` (decoded off the main\r\n * thread, with `premultiplyAlpha`/`colorSpaceConversion` set to \"none\" so the raw data bytes are preserved)\r\n * and a direct `texImage2D` upload — avoiding the `<img>` + 2D-canvas `getImageData` readback that stalls the\r\n * frame. Falls back to the canvas path when `createImageBitmap` is unavailable or fails. Use only for textures\r\n * whose pixels are never read back on the CPU (scales, quats, sh0, shN); means_l/means_u still go through the\r\n * readback path because their bytes are needed to decode positions for the sort worker.\r\n * @param rootUrlOrData base URL (string) or the raw file bytes (Uint8Array)\r\n * @param filename file name (used only with a URL)\r\n * @param scene hosting scene\r\n * @returns a GPU texture holding the raw image bytes\r\n */\r\nasync function LoadSogTextureDirectAsync(rootUrlOrData: string | Uint8Array, filename: string, scene: Scene): Promise<RawTexture> {\r\n    const engine = scene.getEngine();\r\n    if (typeof createImageBitmap === \"function\") {\r\n        try {\r\n            // A typed blob is required: createImageBitmap can fail to decode a typeless blob (and the\r\n            // content-type is lost when loading via LoadFileAsync), which would force the slow canvas fallback.\r\n            const mimeType = filename.toLowerCase().endsWith(\".png\") ? \"image/png\" : \"image/webp\";\r\n            let blob: Blob;\r\n            if (typeof rootUrlOrData === \"string\") {\r\n                const buffer = (await Tools.LoadFileAsync(rootUrlOrData + filename, true)) as ArrayBuffer;\r\n                blob = new Blob([buffer], { type: mimeType });\r\n            } else {\r\n                blob = new Blob([rootUrlOrData as any], { type: mimeType });\r\n            }\r\n            const bitmap = await createImageBitmap(blob, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" });\r\n            try {\r\n                const tex = new RawTexture(\r\n                    null,\r\n                    bitmap.width,\r\n                    bitmap.height,\r\n                    Constants.TEXTUREFORMAT_RGBA,\r\n                    scene,\r\n                    false,\r\n                    false,\r\n                    Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n                    Constants.TEXTURETYPE_UNSIGNED_BYTE\r\n                );\r\n                tex.wrapU = Constants.TEXTURE_CLAMP_ADDRESSMODE;\r\n                tex.wrapV = Constants.TEXTURE_CLAMP_ADDRESSMODE;\r\n                const internal = tex.getInternalTexture();\r\n                if (internal) {\r\n                    // invertY=false / premulAlpha=false keep the byte layout identical to the canvas path.\r\n                    engine.updateDynamicTexture(internal, bitmap, false, false);\r\n                }\r\n                return tex;\r\n            } finally {\r\n                bitmap.close();\r\n            }\r\n        } catch {\r\n            // Fall through to the canvas readback path below.\r\n        }\r\n    }\r\n    const image = await LoadWebpImageData(rootUrlOrData, filename, engine);\r\n    return CreateSogTextureFromImage(scene, image);\r\n}\r\n\r\nfunction DecodeSogPositions(data: SOGRootData, meansl: Uint8Array, meansu: Uint8Array, splatCount: number): Float32Array {\r\n    const unlog = (n: number) => Math.sign(n) * (Math.exp(Math.abs(n)) - 1);\r\n    if (!Array.isArray(data.means.mins) || !Array.isArray(data.means.maxs)) {\r\n        throw new Error(\"Missing arrays in SOG data.\");\r\n    }\r\n    // Stride-4 layout (x,y,z,w) expected by the depth-sort worker and the centers texture.\r\n    const positions = new Float32Array(splatCount * 4);\r\n    for (let i = 0; i < splatCount; i++) {\r\n        const index = i * 4;\r\n        for (let j = 0; j < 3; j++) {\r\n            const q = (meansu[index + j] << 8) | meansl[index + j];\r\n            const n = Scalar.Lerp(data.means.mins[j], data.means.maxs[j], q / 65535);\r\n            positions[i * 4 + j] = unlog(n);\r\n        }\r\n        positions[i * 4 + 3] = 1.0;\r\n    }\r\n    return positions;\r\n}\r\n\r\n/**\r\n * Parse SOG data and produce a set of GPU textures + dequantization parameters.\r\n * The shader will sample these raw RGBA8 textures and reconstruct positions/scales/rotations/colors/SH on the GPU.\r\n * @param dataOrFiles Either the SOGRootData or a Map of filenames to Uint8Array file data (including meta.json)\r\n * @param rootUrl Base URL to load webp files from (if dataOrFiles is SOGRootData)\r\n * @param scene The Babylon.js scene\r\n * @param computeCpuPositions When true (default), means_l/means_u are read back on the CPU and `pack.positions`\r\n *   is decoded for the sort worker / bounding box. Pass false when the caller will instead read the decoded\r\n *   centers back from the GPU work buffer — then every attribute (including means) uses the fast direct\r\n *   ImageBitmap upload (no `getImageData` readback) and `pack.positions` is left empty.\r\n * @param downloadManager Optional download manager that throttles and retries the per-file image downloads\r\n *   (used by the LOD streamer). When omitted, files are fetched directly. Only applies when loading from a URL.\r\n * @param downloadGroupId Optional group tag passed to the download manager so this file's image downloads can\r\n *   be cancelled together if the streamer no longer needs them.\r\n * @returns Parsed splat info with `sogTextures` populated.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-restricted-types\r\nexport async function ParseSogMetaAsTextures(\r\n    dataOrFiles: SOGRootData | Map<string, Uint8Array>,\r\n    rootUrl: string,\r\n    scene: Scene,\r\n    computeCpuPositions = true,\r\n    downloadManager?: GaussianSplattingDownloadManager,\r\n    downloadGroupId?: DownloadGroupId\r\n): Promise<IParsedSplat> {\r\n    let data: SOGRootData;\r\n    let files: Map<string, Uint8Array> | undefined;\r\n\r\n    if (dataOrFiles instanceof Map) {\r\n        files = dataOrFiles;\r\n        const metaFile = files.get(\"meta.json\");\r\n        if (!metaFile) {\r\n            throw new Error(\"meta.json not found in files Map\");\r\n        }\r\n        data = JSON.parse(new TextDecoder().decode(metaFile)) as SOGRootData;\r\n    } else {\r\n        data = dataOrFiles;\r\n    }\r\n\r\n    // Attribute textures (scales/quats/sh0/shN) are only sampled on the GPU, so they always upload straight\r\n    // from a decoded ImageBitmap (no getImageData readback). means_l/means_u additionally need their CPU bytes\r\n    // when computeCpuPositions is set (to decode positions for the sort worker) — those go through the\r\n    // <img>+canvas path; otherwise means also use the fast direct upload. All loads run in parallel.\r\n    const loadMeansImageAsync = async (fileName: string): Promise<IWebPImage> => {\r\n        if (files && files.has(fileName)) {\r\n            return await LoadWebpImageData(files.get(fileName)!, fileName, scene.getEngine());\r\n        }\r\n        if (downloadManager) {\r\n            const bytes = new Uint8Array(await downloadManager.loadFileAsync(rootUrl + fileName, downloadGroupId));\r\n            return await LoadWebpImageData(bytes, fileName, scene.getEngine());\r\n        }\r\n        return await LoadWebpImageData(rootUrl, fileName, scene.getEngine());\r\n    };\r\n    const loadGpuTextureAsync = async (fileName: string): Promise<RawTexture> => {\r\n        if (files && files.has(fileName)) {\r\n            return await LoadSogTextureDirectAsync(files.get(fileName)!, fileName, scene);\r\n        }\r\n        if (downloadManager) {\r\n            const bytes = new Uint8Array(await downloadManager.loadFileAsync(rootUrl + fileName, downloadGroupId));\r\n            return await LoadSogTextureDirectAsync(bytes, fileName, scene);\r\n        }\r\n        return await LoadSogTextureDirectAsync(rootUrl, fileName, scene);\r\n    };\r\n\r\n    const gpuFiles = [...data.scales.files, ...data.quats.files, ...data.sh0.files, ...(data.shN?.files ?? [])];\r\n\r\n    let meansL: RawTexture;\r\n    let meansU: RawTexture;\r\n    let meansWidth: number;\r\n    let meansHeight: number;\r\n    let meansImages: Nullable<[IWebPImage, IWebPImage]> = null;\r\n    let gpuTextures: RawTexture[];\r\n\r\n    if (computeCpuPositions) {\r\n        const [images, gpu] = await Promise.all([Promise.all(data.means.files.map(loadMeansImageAsync)), Promise.all(gpuFiles.map(loadGpuTextureAsync))]);\r\n        meansImages = [images[0], images[1]];\r\n        gpuTextures = gpu;\r\n        meansL = CreateSogTextureFromImage(scene, images[0]);\r\n        meansU = CreateSogTextureFromImage(scene, images[1]);\r\n        meansWidth = images[0].width;\r\n        meansHeight = images[0].height;\r\n    } else {\r\n        const [meansTex, gpu] = await Promise.all([Promise.all(data.means.files.map(loadGpuTextureAsync)), Promise.all(gpuFiles.map(loadGpuTextureAsync))]);\r\n        gpuTextures = gpu;\r\n        meansL = meansTex[0];\r\n        meansU = meansTex[1];\r\n        const size = (meansL as Texture).getSize();\r\n        meansWidth = size.width;\r\n        meansHeight = size.height;\r\n    }\r\n\r\n    const splatCount = data.count ?? data.means.shape[0];\r\n    const splatTexelCount = meansWidth * meansHeight;\r\n    if (splatTexelCount < splatCount) {\r\n        throw new Error(`SOG texture contains ${splatTexelCount} texels, but metadata references ${splatCount} splats.`);\r\n    }\r\n\r\n    const scales = gpuTextures[0];\r\n    const quats = gpuTextures[1];\r\n    const sh0 = gpuTextures[2];\r\n\r\n    let shCentroids: RawTexture | undefined;\r\n    let shLabels: RawTexture | undefined;\r\n    let shCoeffCount = 0;\r\n    let shDegree = 0;\r\n\r\n    if (data.shN && gpuTextures.length >= 5) {\r\n        shCentroids = gpuTextures[3];\r\n        shLabels = gpuTextures[4];\r\n\r\n        shCoeffCount = data.shN.bands ? (data.shN.bands + 1) ** 2 - 1 : data.shN.shape[1] / 3;\r\n        shDegree = data.shN.bands ?? Math.round(Math.sqrt(shCoeffCount + 1) - 1);\r\n    }\r\n\r\n    // Optional codebook packed into a 1D R32F texture: [scales(256) | sh0(256) | shN(256)]\r\n    let codebookTexture: RawTexture | undefined;\r\n    if (data.version === 2) {\r\n        const codebookSize = 256;\r\n        const packed = new Float32Array(codebookSize * 3);\r\n        if (data.scales.codebook) {\r\n            packed.set(data.scales.codebook.slice(0, codebookSize), 0);\r\n        }\r\n        if (data.sh0.codebook) {\r\n            packed.set(data.sh0.codebook.slice(0, codebookSize), codebookSize);\r\n        }\r\n        if (data.shN?.codebook) {\r\n            packed.set(data.shN.codebook.slice(0, codebookSize), codebookSize * 2);\r\n        }\r\n        codebookTexture = new RawTexture(\r\n            packed,\r\n            codebookSize * 3,\r\n            1,\r\n            Constants.TEXTUREFORMAT_R,\r\n            scene,\r\n            false,\r\n            false,\r\n            Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n            Constants.TEXTURETYPE_FLOAT\r\n        );\r\n        codebookTexture.wrapU = Constants.TEXTURE_CLAMP_ADDRESSMODE;\r\n        codebookTexture.wrapV = Constants.TEXTURE_CLAMP_ADDRESSMODE;\r\n    }\r\n\r\n    const meansMins = data.means.mins as number[];\r\n    const meansMaxs = data.means.maxs as number[];\r\n\r\n    const pack: ISogTexturePack = {\r\n        version: (data.version === 2 ? 2 : 1) as 1 | 2,\r\n        splatCount,\r\n        shDegree,\r\n        meansTextureL: meansL,\r\n        meansTextureU: meansU,\r\n        scalesTexture: scales,\r\n        quatsTexture: quats,\r\n        sh0Texture: sh0,\r\n        shCentroidsTexture: shCentroids,\r\n        shLabelsTexture: shLabels,\r\n        codebookTexture,\r\n        meansMin: [meansMins[0], meansMins[1], meansMins[2]],\r\n        meansMax: [meansMaxs[0], meansMaxs[1], meansMaxs[2]],\r\n        scalesMin: Array.isArray(data.scales.mins) ? [data.scales.mins[0], data.scales.mins[1], data.scales.mins[2]] : undefined,\r\n        scalesMax: Array.isArray(data.scales.maxs) ? [data.scales.maxs[0], data.scales.maxs[1], data.scales.maxs[2]] : undefined,\r\n        sh0Min: Array.isArray(data.sh0.mins) ? [data.sh0.mins[0], data.sh0.mins[1], data.sh0.mins[2], data.sh0.mins[3]] : undefined,\r\n        sh0Max: Array.isArray(data.sh0.maxs) ? [data.sh0.maxs[0], data.sh0.maxs[1], data.sh0.maxs[2], data.sh0.maxs[3]] : undefined,\r\n        shnMin: typeof data.shN?.mins === \"number\" ? data.shN.mins : undefined,\r\n        shnMax: typeof data.shN?.maxs === \"number\" ? data.shN.maxs : undefined,\r\n        shCoeffCount,\r\n        positions: meansImages ? DecodeSogPositions(data, meansImages[0].bits, meansImages[1].bits, splatCount) : new Float32Array(0),\r\n    };\r\n\r\n    return { mode: Mode.Splat, data: new ArrayBuffer(0), hasVertexColors: false, shDegree, sogTextures: pack };\r\n}\r\n","/** This file must only contain pure code and pure imports */\r\n\r\n/**\r\n * Shared shader names for the SOG -> decoded work-buffer copy pass.\r\n */\r\nexport const GaussianSplattingWorkBufferShaderName = \"gsSogDecodeToWorkBuffer\";\r\n\r\n/**\r\n * Pass-through vertex shader (GLSL): the geometry is a fullscreen triangle already in NDC.\r\n */\r\nexport const GaussianSplattingWorkBufferVertexShaderGLSL = `precision highp float;\r\nattribute vec3 position;\r\nvoid main() {\r\n    gl_Position = vec4(position.xy, 0.0, 1.0);\r\n}\r\n`;\r\n\r\n/**\r\n * Fragment shader (GLSL/WebGL2): decodes one SOG source file into the decoded GS work-buffer layout,\r\n * writing each splat into its allocated pixel. Mirrors the USE_SOG decode in ShadersInclude/gaussianSplatting.fx\r\n * but outputs the decoded MRT (center, covA, covB, color) consumed by the standard (non-SOG) draw path.\r\n *\r\n * MRT layout: 0 = center (x,y,z,1), 1 = covA (Sigma00,01,02,11), 2 = covB (Sigma12,22,0,0), 3 = color (rgba).\r\n */\r\nexport const GaussianSplattingWorkBufferFragmentShaderGLSL = `precision highp float;\r\nprecision highp int;\r\n\r\nuniform sampler2D sogMeansLTex;\r\nuniform sampler2D sogMeansUTex;\r\nuniform sampler2D sogScalesTex;\r\nuniform sampler2D sogQuatsTex;\r\nuniform sampler2D sogSh0Tex;\r\nuniform sampler2D sogCodebookTex;\r\n\r\nuniform vec3 sogMeansMin;\r\nuniform vec3 sogMeansMax;\r\nuniform vec3 sogScalesMin;\r\nuniform vec3 sogScalesMax;\r\nuniform vec4 sogSh0Min;\r\nuniform vec4 sogSh0Max;\r\nuniform int uVersion;\r\nuniform int uOffset;\r\nuniform int uCount;\r\nuniform int uDestWidth;\r\nuniform int uSrcWidth;\r\n\r\nlayout(location = 0) out vec4 glFragData[4];\r\n\r\nmat3 transposeM(mat3 m) {\r\n    return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]);\r\n}\r\n\r\nvoid main() {\r\n    ivec2 p = ivec2(gl_FragCoord.xy);\r\n    int global = p.y * uDestWidth + p.x;\r\n    if (global < uOffset || global >= uOffset + uCount) {\r\n        discard;\r\n    }\r\n    int k = global - uOffset;\r\n    ivec2 src = ivec2(k - (k / uSrcWidth) * uSrcWidth, k / uSrcWidth);\r\n\r\n    vec3 mL = texelFetch(sogMeansLTex, src, 0).xyz;\r\n    vec3 mU = texelFetch(sogMeansUTex, src, 0).xyz;\r\n    vec3 sRaw = texelFetch(sogScalesTex, src, 0).xyz;\r\n    vec4 qRaw = texelFetch(sogQuatsTex, src, 0);\r\n    vec4 c0 = texelFetch(sogSh0Tex, src, 0);\r\n\r\n    // Position: q16 = (u<<8)|l normalized; n = lerp(min,max,q16); pos = sign(n)*(exp(|n|)-1)\r\n    vec3 q16 = (mU * 256.0 + mL) * (255.0 / 65535.0);\r\n    vec3 nPos = mix(sogMeansMin, sogMeansMax, q16);\r\n    vec3 center = sign(nPos) * (exp(abs(nPos)) - vec3(1.0));\r\n\r\n    // Scale (v1: lerp+exp ; v2: codebook lookup)\r\n    vec3 splatScale;\r\n    if (uVersion == 2) {\r\n        vec3 sIdx = floor(sRaw * 255.0 + 0.5);\r\n        splatScale.x = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.x), 0), 0).r);\r\n        splatScale.y = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.y), 0), 0).r);\r\n        splatScale.z = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.z), 0), 0).r);\r\n    } else {\r\n        splatScale = exp(mix(sogScalesMin, sogScalesMax, sRaw));\r\n    }\r\n\r\n    // Quaternion (largest-omitted, mode in alpha as 252 + omitted-index)\r\n    const float invSqrt2 = 0.70710678118;\r\n    vec3 qabc = (qRaw.xyz - vec3(0.5)) * 2.0 * invSqrt2;\r\n    int qMode = int(qRaw.w * 255.0 + 0.5) - 252;\r\n    float qd = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\r\n    vec4 quat;\r\n    if (qMode == 0) {\r\n        quat = vec4(qd, qabc.x, qabc.y, qabc.z);\r\n    } else if (qMode == 1) {\r\n        quat = vec4(qabc.x, qd, qabc.y, qabc.z);\r\n    } else if (qMode == 2) {\r\n        quat = vec4(qabc.x, qabc.y, qd, qabc.z);\r\n    } else {\r\n        quat = vec4(qabc.x, qabc.y, qabc.z, qd);\r\n    }\r\n\r\n    float qw = quat.x, qx = quat.y, qy = quat.z, qz = quat.w;\r\n    mat3 R = mat3(\r\n        1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\r\n        2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\r\n        2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\r\n    );\r\n    mat3 S2 = mat3(\r\n        4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\r\n        0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\r\n        0.0, 0.0, 4.0 * splatScale.z * splatScale.z\r\n    );\r\n    mat3 Sigma = R * S2 * transposeM(R);\r\n\r\n    // Color (sh0)\r\n    const float SH_C0 = 0.28209479177387814;\r\n    vec3 colRgb;\r\n    float colA;\r\n    if (uVersion == 2) {\r\n        vec3 c3;\r\n        c3.x = texelFetch(sogCodebookTex, ivec2(256 + int(c0.x * 255.0 + 0.5), 0), 0).r;\r\n        c3.y = texelFetch(sogCodebookTex, ivec2(256 + int(c0.y * 255.0 + 0.5), 0), 0).r;\r\n        c3.z = texelFetch(sogCodebookTex, ivec2(256 + int(c0.z * 255.0 + 0.5), 0), 0).r;\r\n        colRgb = vec3(0.5) + c3 * SH_C0;\r\n        colA = c0.w;\r\n    } else {\r\n        vec4 cLerp = mix(sogSh0Min, sogSh0Max, c0);\r\n        colRgb = vec3(0.5) + cLerp.xyz * SH_C0;\r\n        colA = 1.0 / (1.0 + exp(-cLerp.w));\r\n    }\r\n\r\n    glFragData[0] = vec4(center, 1.0);\r\n    glFragData[1] = vec4(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\r\n    glFragData[2] = vec4(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\r\n    glFragData[3] = vec4(colRgb, colA);\r\n}\r\n`;\r\n\r\n/**\r\n * Pass-through vertex shader (WGSL).\r\n */\r\nexport const GaussianSplattingWorkBufferVertexShaderWGSL = `\r\nattribute position : vec3<f32>;\r\n@vertex\r\nfn main(input : VertexInputs) -> FragmentInputs {\r\n    vertexOutputs.position = vec4<f32>(input.position.xy, 0.0, 1.0);\r\n}\r\n`;\r\n\r\n/**\r\n * Fragment shader (WGSL/WebGPU) — same decode as the GLSL variant, writing 4 MRT attachments.\r\n */\r\nexport const GaussianSplattingWorkBufferFragmentShaderWGSL = `\r\nvar sogMeansLTexSampler : sampler;\r\nvar sogMeansLTex : texture_2d<f32>;\r\nvar sogMeansUTexSampler : sampler;\r\nvar sogMeansUTex : texture_2d<f32>;\r\nvar sogScalesTexSampler : sampler;\r\nvar sogScalesTex : texture_2d<f32>;\r\nvar sogQuatsTexSampler : sampler;\r\nvar sogQuatsTex : texture_2d<f32>;\r\nvar sogSh0TexSampler : sampler;\r\nvar sogSh0Tex : texture_2d<f32>;\r\nvar sogCodebookTexSampler : sampler;\r\nvar sogCodebookTex : texture_2d<f32>;\r\n\r\nuniform sogMeansMin : vec3<f32>;\r\nuniform sogMeansMax : vec3<f32>;\r\nuniform sogScalesMin : vec3<f32>;\r\nuniform sogScalesMax : vec3<f32>;\r\nuniform sogSh0Min : vec4<f32>;\r\nuniform sogSh0Max : vec4<f32>;\r\nuniform uVersion : i32;\r\nuniform uOffset : i32;\r\nuniform uCount : i32;\r\nuniform uDestWidth : i32;\r\nuniform uSrcWidth : i32;\r\n\r\n@fragment\r\nfn main(input : FragmentInputs) -> FragmentOutputs {\r\n    let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\r\n    let global : i32 = p.y * uniforms.uDestWidth + p.x;\r\n    if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\r\n        discard;\r\n    }\r\n    let k : i32 = global - uniforms.uOffset;\r\n    let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\r\n\r\n    let mL : vec3<f32> = textureLoad(sogMeansLTex, src, 0).xyz;\r\n    let mU : vec3<f32> = textureLoad(sogMeansUTex, src, 0).xyz;\r\n    let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\r\n    let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\r\n    let c0 : vec4<f32> = textureLoad(sogSh0Tex, src, 0);\r\n\r\n    let q16 : vec3<f32> = (mU * 256.0 + mL) * (255.0 / 65535.0);\r\n    let nPos : vec3<f32> = mix(uniforms.sogMeansMin, uniforms.sogMeansMax, q16);\r\n    let center : vec3<f32> = sign(nPos) * (exp(abs(nPos)) - vec3<f32>(1.0));\r\n\r\n    var splatScale : vec3<f32>;\r\n    if (uniforms.uVersion == 2) {\r\n        let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\r\n        splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\r\n        splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\r\n        splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\r\n    } else {\r\n        splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\r\n    }\r\n\r\n    let invSqrt2 : f32 = 0.70710678118;\r\n    let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\r\n    let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\r\n    let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\r\n    var quat : vec4<f32>;\r\n    if (qMode == 0) {\r\n        quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\r\n    } else if (qMode == 1) {\r\n        quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\r\n    } else if (qMode == 2) {\r\n        quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\r\n    } else {\r\n        quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\r\n    }\r\n\r\n    let qw : f32 = quat.x;\r\n    let qx : f32 = quat.y;\r\n    let qy : f32 = quat.z;\r\n    let qz : f32 = quat.w;\r\n    let R : mat3x3<f32> = mat3x3<f32>(\r\n        1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\r\n        2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\r\n        2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\r\n    );\r\n    let S2 : mat3x3<f32> = mat3x3<f32>(\r\n        4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\r\n        0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\r\n        0.0, 0.0, 4.0 * splatScale.z * splatScale.z\r\n    );\r\n    let Sigma : mat3x3<f32> = R * S2 * transpose(R);\r\n\r\n    let SH_C0 : f32 = 0.28209479177387814;\r\n    var colRgb : vec3<f32>;\r\n    var colA : f32;\r\n    if (uniforms.uVersion == 2) {\r\n        var c3 : vec3<f32>;\r\n        c3.x = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.x * 255.0 + 0.5), 0), 0).r;\r\n        c3.y = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.y * 255.0 + 0.5), 0), 0).r;\r\n        c3.z = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.z * 255.0 + 0.5), 0), 0).r;\r\n        colRgb = vec3<f32>(0.5) + c3 * SH_C0;\r\n        colA = c0.w;\r\n    } else {\r\n        let cLerp : vec4<f32> = mix(uniforms.sogSh0Min, uniforms.sogSh0Max, c0);\r\n        colRgb = vec3<f32>(0.5) + cLerp.xyz * SH_C0;\r\n        colA = 1.0 / (1.0 + exp(-cLerp.w));\r\n    }\r\n\r\n    fragmentOutputs.fragData0 = vec4<f32>(center, 1.0);\r\n    fragmentOutputs.fragData1 = vec4<f32>(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\r\n    fragmentOutputs.fragData2 = vec4<f32>(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\r\n    fragmentOutputs.fragData3 = vec4<f32>(colRgb, colA);\r\n}\r\n`;\r\n\r\n/**\r\n * Shader name for the rotation/scale decode pass (the three half-float textures voxel-IBL shadowing consumes).\r\n */\r\nexport const GaussianSplattingWorkBufferRotationDecodeShaderName = \"gsSogRotDecodeToWorkBuffer\";\r\n\r\n/**\r\n * Rotation/scale decode fragment shader (GLSL/WebGL2). Reconstructs each splat's rotation matrix R and scale and\r\n * writes the three half-float textures the voxel shader samples (rotationsATexture/B/Scale). The layout lets the\r\n * voxel shader reconstruct the same R and scale, so streamed splats get the same ellipsoid the draw path renders:\r\n *   rotA     = (R col0.xyz, R col1.x)\r\n *   rotB     = (R col1.yz, R col2.xy)\r\n *   rotScale = (R col2.z, 2*scale.x, 2*scale.y, 2*scale.z)\r\n */\r\nexport const GaussianSplattingWorkBufferRotationDecodeFragmentShaderGLSL = `precision highp float;\r\nprecision highp int;\r\n\r\nuniform sampler2D sogScalesTex;\r\nuniform sampler2D sogQuatsTex;\r\nuniform sampler2D sogCodebookTex;\r\n\r\nuniform vec3 sogScalesMin;\r\nuniform vec3 sogScalesMax;\r\nuniform int uVersion;\r\nuniform int uOffset;\r\nuniform int uCount;\r\nuniform int uDestWidth;\r\nuniform int uSrcWidth;\r\n\r\nlayout(location = 0) out vec4 glFragData[3];\r\n\r\nvoid main() {\r\n    ivec2 p = ivec2(gl_FragCoord.xy);\r\n    int global = p.y * uDestWidth + p.x;\r\n    if (global < uOffset || global >= uOffset + uCount) {\r\n        discard;\r\n    }\r\n    int k = global - uOffset;\r\n    ivec2 src = ivec2(k - (k / uSrcWidth) * uSrcWidth, k / uSrcWidth);\r\n\r\n    vec3 sRaw = texelFetch(sogScalesTex, src, 0).xyz;\r\n    vec4 qRaw = texelFetch(sogQuatsTex, src, 0);\r\n\r\n    vec3 splatScale;\r\n    if (uVersion == 2) {\r\n        vec3 sIdx = floor(sRaw * 255.0 + 0.5);\r\n        splatScale.x = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.x), 0), 0).r);\r\n        splatScale.y = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.y), 0), 0).r);\r\n        splatScale.z = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.z), 0), 0).r);\r\n    } else {\r\n        splatScale = exp(mix(sogScalesMin, sogScalesMax, sRaw));\r\n    }\r\n\r\n    const float invSqrt2 = 0.70710678118;\r\n    vec3 qabc = (qRaw.xyz - vec3(0.5)) * 2.0 * invSqrt2;\r\n    int qMode = int(qRaw.w * 255.0 + 0.5) - 252;\r\n    float qd = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\r\n    vec4 quat;\r\n    if (qMode == 0) {\r\n        quat = vec4(qd, qabc.x, qabc.y, qabc.z);\r\n    } else if (qMode == 1) {\r\n        quat = vec4(qabc.x, qd, qabc.y, qabc.z);\r\n    } else if (qMode == 2) {\r\n        quat = vec4(qabc.x, qabc.y, qd, qabc.z);\r\n    } else {\r\n        quat = vec4(qabc.x, qabc.y, qabc.z, qd);\r\n    }\r\n\r\n    float qw = quat.x, qx = quat.y, qy = quat.z, qz = quat.w;\r\n    mat3 R = mat3(\r\n        1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\r\n        2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\r\n        2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\r\n    );\r\n\r\n    glFragData[0] = vec4(R[0], R[1].x);\r\n    glFragData[1] = vec4(R[1].y, R[1].z, R[2].x, R[2].y);\r\n    glFragData[2] = vec4(R[2].z, 2.0 * splatScale.x, 2.0 * splatScale.y, 2.0 * splatScale.z);\r\n}\r\n`;\r\n\r\n/**\r\n * Rotation/scale decode fragment shader (WGSL/WebGPU) — same decode as the GLSL variant, writing 3 half-float MRT\r\n * attachments.\r\n */\r\nexport const GaussianSplattingWorkBufferRotationDecodeFragmentShaderWGSL = `\r\nvar sogScalesTexSampler : sampler;\r\nvar sogScalesTex : texture_2d<f32>;\r\nvar sogQuatsTexSampler : sampler;\r\nvar sogQuatsTex : texture_2d<f32>;\r\nvar sogCodebookTexSampler : sampler;\r\nvar sogCodebookTex : texture_2d<f32>;\r\n\r\nuniform sogScalesMin : vec3<f32>;\r\nuniform sogScalesMax : vec3<f32>;\r\nuniform uVersion : i32;\r\nuniform uOffset : i32;\r\nuniform uCount : i32;\r\nuniform uDestWidth : i32;\r\nuniform uSrcWidth : i32;\r\n\r\n@fragment\r\nfn main(input : FragmentInputs) -> FragmentOutputs {\r\n    let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\r\n    let global : i32 = p.y * uniforms.uDestWidth + p.x;\r\n    if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\r\n        discard;\r\n    }\r\n    let k : i32 = global - uniforms.uOffset;\r\n    let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\r\n\r\n    let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\r\n    let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\r\n\r\n    var splatScale : vec3<f32>;\r\n    if (uniforms.uVersion == 2) {\r\n        let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\r\n        splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\r\n        splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\r\n        splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\r\n    } else {\r\n        splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\r\n    }\r\n\r\n    let invSqrt2 : f32 = 0.70710678118;\r\n    let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\r\n    let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\r\n    let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\r\n    var quat : vec4<f32>;\r\n    if (qMode == 0) {\r\n        quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\r\n    } else if (qMode == 1) {\r\n        quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\r\n    } else if (qMode == 2) {\r\n        quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\r\n    } else {\r\n        quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\r\n    }\r\n\r\n    let qw : f32 = quat.x;\r\n    let qx : f32 = quat.y;\r\n    let qy : f32 = quat.z;\r\n    let qz : f32 = quat.w;\r\n    let R : mat3x3<f32> = mat3x3<f32>(\r\n        1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\r\n        2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\r\n        2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\r\n    );\r\n\r\n    fragmentOutputs.fragData0 = vec4<f32>(R[0], R[1].x);\r\n    fragmentOutputs.fragData1 = vec4<f32>(R[1].y, R[1].z, R[2].x, R[2].y);\r\n    fragmentOutputs.fragData2 = vec4<f32>(R[2].z, 2.0 * splatScale.x, 2.0 * splatScale.y, 2.0 * splatScale.z);\r\n}\r\n`;\r\n\r\n/**\r\n * Shader name for the SOG higher-order SH decode pass (bakes one packed-u32 SH texture per pass).\r\n */\r\nexport const GaussianSplattingWorkBufferShDecodeShaderName = \"gsSogShDecodeToWorkBuffer\";\r\n\r\n/**\r\n * SH decode fragment shader (GLSL/WebGL2). Decodes one SOG file's higher-order spherical-harmonics into one\r\n * packed-u32 SH texture at the region offset, in the layout the draw path's `computeSHWeighted`/`decompose`\r\n * expects (16 SH scalar-bytes per RGBA-u32 texel, little-endian; one texel per splat). Run once per SH texture\r\n * (`uShTextureIndex` selects the 16 scalars written this pass). Coefficients this file lacks are written neutral\r\n * (128 == 0 after `decompose`), so a lower-band file mixes correctly with higher-band ones.\r\n */\r\nexport const GaussianSplattingWorkBufferShDecodeFragmentShaderGLSL = `precision highp float;\r\nprecision highp int;\r\n\r\nuniform sampler2D sogShLabelsTex;\r\nuniform sampler2D sogShCentroidsTex;\r\nuniform sampler2D sogCodebookTex;\r\nuniform float sogShnMin;\r\nuniform float sogShnMax;\r\nuniform int uVersion;\r\nuniform int uOffset;\r\nuniform int uCount;\r\nuniform int uDestWidth;\r\nuniform int uSrcWidth;\r\nuniform int uCoeffs;\r\nuniform int uShTextureIndex;\r\n\r\nlayout(location = 0) out uvec4 outSh;\r\n\r\nvoid main() {\r\n    ivec2 p = ivec2(gl_FragCoord.xy);\r\n    int global = p.y * uDestWidth + p.x;\r\n    if (global < uOffset || global >= uOffset + uCount) {\r\n        discard;\r\n    }\r\n    int kLocal = global - uOffset;\r\n\r\n    // 16-bit label for this source splat (LSB in r, MSB in g), indexed over the labels texture's own width.\r\n    ivec2 lsz = textureSize(sogShLabelsTex, 0);\r\n    ivec2 lsrc = ivec2(kLocal - (kLocal / lsz.x) * lsz.x, kLocal / lsz.x);\r\n    vec4 labelRaw = texelFetch(sogShLabelsTex, lsrc, 0);\r\n    int n = int(labelRaw.r * 255.0 + 0.5) + int(labelRaw.g * 255.0 + 0.5) * 256;\r\n    int u = (n - (n / 64) * 64) * uCoeffs;\r\n    int v = n / 64;\r\n\r\n    uint packed0 = 0u;\r\n    uint packed1 = 0u;\r\n    uint packed2 = 0u;\r\n    uint packed3 = 0u;\r\n\r\n    for (int b = 0; b < 16; b++) {\r\n        int s = uShTextureIndex * 16 + b; // flat SH scalar index\r\n        int kc = s / 3;                    // higher-order coefficient (0-based)\r\n        int j = s - kc * 3;                // channel (0=r,1=g,2=b)\r\n        float byteVal = 128.0;             // neutral (decompose(128) ~= 0)\r\n        if (kc < uCoeffs) {\r\n            vec4 centroidRaw = texelFetch(sogShCentroidsTex, ivec2(u + kc, v), 0);\r\n            float ch = (j == 0) ? centroidRaw.r : ((j == 1) ? centroidRaw.g : centroidRaw.b);\r\n            float coeff;\r\n            if (uVersion == 2) {\r\n                int cidx = int(ch * 255.0 + 0.5);\r\n                coeff = texelFetch(sogCodebookTex, ivec2(512 + cidx, 0), 0).r;\r\n            } else {\r\n                coeff = mix(sogShnMin, sogShnMax, ch);\r\n            }\r\n            byteVal = clamp(coeff * 127.5 + 127.5, 0.0, 255.0);\r\n        }\r\n        uint bv = uint(byteVal + 0.5);\r\n        int comp = b / 4;\r\n        uint contrib = bv << uint((b - comp * 4) * 8);\r\n        if (comp == 0) { packed0 |= contrib; }\r\n        else if (comp == 1) { packed1 |= contrib; }\r\n        else if (comp == 2) { packed2 |= contrib; }\r\n        else { packed3 |= contrib; }\r\n    }\r\n    outSh = uvec4(packed0, packed1, packed2, packed3);\r\n}\r\n`;\r\n\r\n/**\r\n * SH decode fragment shader (WGSL/WebGPU) — same as the GLSL variant. The integer output (`vec4<u32>` fragData)\r\n * requires the WGSL processor's integer-fragData support.\r\n */\r\nexport const GaussianSplattingWorkBufferShDecodeFragmentShaderWGSL = `\r\nvar sogShLabelsTexSampler : sampler;\r\nvar sogShLabelsTex : texture_2d<f32>;\r\nvar sogShCentroidsTexSampler : sampler;\r\nvar sogShCentroidsTex : texture_2d<f32>;\r\nvar sogCodebookTexSampler : sampler;\r\nvar sogCodebookTex : texture_2d<f32>;\r\n\r\nuniform sogShnMin : f32;\r\nuniform sogShnMax : f32;\r\nuniform uVersion : i32;\r\nuniform uOffset : i32;\r\nuniform uCount : i32;\r\nuniform uDestWidth : i32;\r\nuniform uSrcWidth : i32;\r\nuniform uCoeffs : i32;\r\nuniform uShTextureIndex : i32;\r\n\r\n@fragment\r\nfn main(input : FragmentInputs) -> FragmentOutputs {\r\n    let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\r\n    let global : i32 = p.y * uniforms.uDestWidth + p.x;\r\n    if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\r\n        discard;\r\n    }\r\n    let kLocal : i32 = global - uniforms.uOffset;\r\n\r\n    let lsz : vec2<i32> = vec2<i32>(textureDimensions(sogShLabelsTex, 0));\r\n    let lsrc : vec2<i32> = vec2<i32>(kLocal - (kLocal / lsz.x) * lsz.x, kLocal / lsz.x);\r\n    let labelRaw : vec4<f32> = textureLoad(sogShLabelsTex, lsrc, 0);\r\n    let n : i32 = i32(labelRaw.r * 255.0 + 0.5) + i32(labelRaw.g * 255.0 + 0.5) * 256;\r\n    let u : i32 = (n - (n / 64) * 64) * uniforms.uCoeffs;\r\n    let v : i32 = n / 64;\r\n\r\n    var packed : array<u32, 4> = array<u32, 4>(0u, 0u, 0u, 0u);\r\n\r\n    for (var b : i32 = 0; b < 16; b = b + 1) {\r\n        let s : i32 = uniforms.uShTextureIndex * 16 + b;\r\n        let kc : i32 = s / 3;\r\n        let j : i32 = s - kc * 3;\r\n        var byteVal : f32 = 128.0;\r\n        if (kc < uniforms.uCoeffs) {\r\n            let centroidRaw : vec4<f32> = textureLoad(sogShCentroidsTex, vec2<i32>(u + kc, v), 0);\r\n            var ch : f32 = centroidRaw.b;\r\n            if (j == 0) { ch = centroidRaw.r; } else if (j == 1) { ch = centroidRaw.g; }\r\n            var coeff : f32;\r\n            if (uniforms.uVersion == 2) {\r\n                let cidx : i32 = i32(ch * 255.0 + 0.5);\r\n                coeff = textureLoad(sogCodebookTex, vec2<i32>(512 + cidx, 0), 0).r;\r\n            } else {\r\n                coeff = mix(uniforms.sogShnMin, uniforms.sogShnMax, ch);\r\n            }\r\n            byteVal = clamp(coeff * 127.5 + 127.5, 0.0, 255.0);\r\n        }\r\n        let bv : u32 = u32(byteVal + 0.5);\r\n        let comp : i32 = b / 4;\r\n        packed[comp] = packed[comp] | (bv << u32((b - comp * 4) * 8));\r\n    }\r\n    fragmentOutputs.fragData0 = vec4<u32>(packed[0], packed[1], packed[2], packed[3]);\r\n}\r\n`;\r\n\r\n/**\r\n * Shader name for the work-buffer relayout (defrag/compaction) copy pass.\r\n */\r\nexport const GaussianSplattingWorkBufferRelayoutShaderName = \"gsWorkBufferRelayout\";\r\n\r\n/**\r\n * Relayout copy fragment shader (GLSL/WebGL2). Copies the four decoded work-buffer textures from a source\r\n * layout to a destination layout, one output texel per draw. In map mode (`uUseMap == 1`) each destination\r\n * texel reads its source splat index from `uMapTex` (R32F; a negative value marks a gap and is discarded so\r\n * the cleared destination stays zero). In identity mode the source texel equals the destination texel.\r\n */\r\nexport const GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL = `precision highp float;\r\nprecision highp int;\r\n\r\nuniform sampler2D uMapTex;\r\nuniform sampler2D uSrc0;\r\nuniform sampler2D uSrc1;\r\nuniform sampler2D uSrc2;\r\nuniform sampler2D uSrc3;\r\nuniform int uDstWidth;\r\nuniform int uSrcWidth;\r\nuniform int uUseMap;\r\n// Region-scoped relayout (hosted compound atlas), both default 0 (standalone square path unchanged):\r\n//   uSrcBaseOffset — added to the map's (region-local) source index so pass 1 reads the correct GLOBAL atlas texel.\r\n//   uDstBaseRow    — subtracted from the atlas destination row so pass 2's identity copy reads the region-local temp.\r\nuniform int uSrcBaseOffset;\r\nuniform int uDstBaseRow;\r\n\r\nlayout(location = 0) out vec4 glFragData[4];\r\n\r\nvoid main() {\r\n    ivec2 p = ivec2(gl_FragCoord.xy);\r\n    int srcIdx;\r\n    if (uUseMap == 1) {\r\n        float m = texelFetch(uMapTex, p, 0).r;\r\n        if (m < 0.0) {\r\n            discard;\r\n        }\r\n        srcIdx = uSrcBaseOffset + int(m + 0.5);\r\n    } else {\r\n        srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\r\n    }\r\n    ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\r\n    glFragData[0] = texelFetch(uSrc0, s, 0);\r\n    glFragData[1] = texelFetch(uSrc1, s, 0);\r\n    glFragData[2] = texelFetch(uSrc2, s, 0);\r\n    glFragData[3] = texelFetch(uSrc3, s, 0);\r\n}\r\n`;\r\n\r\n/**\r\n * Shader name for the INTEGER (packed-u32 SH) relayout/backup copy pass. Same index/map/base math as the float\r\n * relayout shader, but samples ONE integer SH source texture (`usampler2D`) and writes ONE integer attachment,\r\n * so it moves one baked SH texture per pass (parallel to the four-out float copy).\r\n */\r\nexport const GaussianSplattingWorkBufferShCopyShaderName = \"gsWorkBufferShCopy\";\r\n\r\n/**\r\n * Integer SH relayout/backup copy fragment shader (GLSL/WebGL2). Copies one packed-u32 SH texture from a source\r\n * layout to a destination layout, one output texel per draw. Map mode (`uUseMap == 1`) reads each destination\r\n * texel's source splat index from `uMapTex` (R32F; negative = gap, discarded); identity mode copies texel-for-texel\r\n * (region backup/restore). `uSrcBaseOffset`/`uDstBaseRow` scope the copy to a hosted region's atlas rows (default 0).\r\n */\r\nexport const GaussianSplattingWorkBufferShCopyFragmentShaderGLSL = `precision highp float;\r\nprecision highp int;\r\nprecision highp usampler2D;\r\n\r\nuniform sampler2D uMapTex;\r\nuniform usampler2D uSrcSh;\r\nuniform int uDstWidth;\r\nuniform int uSrcWidth;\r\nuniform int uUseMap;\r\nuniform int uSrcBaseOffset;\r\nuniform int uDstBaseRow;\r\n\r\nlayout(location = 0) out uvec4 outSh;\r\n\r\nvoid main() {\r\n    ivec2 p = ivec2(gl_FragCoord.xy);\r\n    int srcIdx;\r\n    if (uUseMap == 1) {\r\n        float m = texelFetch(uMapTex, p, 0).r;\r\n        if (m < 0.0) {\r\n            discard;\r\n        }\r\n        srcIdx = uSrcBaseOffset + int(m + 0.5);\r\n    } else {\r\n        srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\r\n    }\r\n    ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\r\n    outSh = texelFetch(uSrcSh, s, 0);\r\n}\r\n`;\r\n\r\n/**\r\n * Integer SH relayout/backup copy fragment shader (WGSL/WebGPU) — same copy as the GLSL variant. The integer output\r\n * (`vec4<u32>` fragData) requires the WGSL processor's integer-fragData support.\r\n */\r\nexport const GaussianSplattingWorkBufferShCopyFragmentShaderWGSL = `\r\nvar uMapTexSampler : sampler;\r\nvar uMapTex : texture_2d<f32>;\r\n// Integer source sampled via textureLoad only — NO paired sampler (a sampler on a Uint texture fails WebGPU\r\n// validation: \"None of the supported sample types (Uint)\"). Mirrors the draw shader's shTexture0 declaration.\r\nvar uSrcSh : texture_2d<u32>;\r\n\r\nuniform uDstWidth : i32;\r\nuniform uSrcWidth : i32;\r\nuniform uUseMap : i32;\r\nuniform uSrcBaseOffset : i32;\r\nuniform uDstBaseRow : i32;\r\n\r\n@fragment\r\nfn main(input : FragmentInputs) -> FragmentOutputs {\r\n    let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\r\n    var srcIdx : i32;\r\n    if (uniforms.uUseMap == 1) {\r\n        let m : f32 = textureLoad(uMapTex, p, 0).r;\r\n        if (m < 0.0) {\r\n            discard;\r\n        }\r\n        srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\r\n    } else {\r\n        srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\r\n    }\r\n    let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\r\n    // Wrap in an explicit vec4<u32> so the WGSL processor emits an integer fragData location (its detection keys\r\n    // off a literal vec4<u32>/vec4u in the assignment; a bare textureLoad(...) would default to vec4<f32>).\r\n    fragmentOutputs.fragData0 = vec4<u32>(textureLoad(uSrcSh, s, 0));\r\n}\r\n`;\r\n\r\n/**\r\n * Shader name for the rotation/scale relayout/backup copy pass. Same index/map/base math as the four-out float\r\n * relayout shader, but moves the THREE half-float rotation/scale textures in one pass (their own separate atlas).\r\n */\r\nexport const GaussianSplattingWorkBufferRotCopyShaderName = \"gsWorkBufferRotCopy\";\r\n\r\n/**\r\n * Rotation/scale relayout/backup copy fragment shader (GLSL/WebGL2). Copies the three half-float rotation/scale\r\n * textures from a source layout to a destination layout, one output texel per draw. Identical to the four-out\r\n * float relayout shader but with three attachments (the rotation atlas has no fourth texture).\r\n */\r\nexport const GaussianSplattingWorkBufferRotCopyFragmentShaderGLSL = `precision highp float;\r\nprecision highp int;\r\n\r\nuniform sampler2D uMapTex;\r\nuniform sampler2D uSrc0;\r\nuniform sampler2D uSrc1;\r\nuniform sampler2D uSrc2;\r\nuniform int uDstWidth;\r\nuniform int uSrcWidth;\r\nuniform int uUseMap;\r\nuniform int uSrcBaseOffset;\r\nuniform int uDstBaseRow;\r\n\r\nlayout(location = 0) out vec4 glFragData[3];\r\n\r\nvoid main() {\r\n    ivec2 p = ivec2(gl_FragCoord.xy);\r\n    int srcIdx;\r\n    if (uUseMap == 1) {\r\n        float m = texelFetch(uMapTex, p, 0).r;\r\n        if (m < 0.0) {\r\n            discard;\r\n        }\r\n        srcIdx = uSrcBaseOffset + int(m + 0.5);\r\n    } else {\r\n        srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\r\n    }\r\n    ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\r\n    glFragData[0] = texelFetch(uSrc0, s, 0);\r\n    glFragData[1] = texelFetch(uSrc1, s, 0);\r\n    glFragData[2] = texelFetch(uSrc2, s, 0);\r\n}\r\n`;\r\n\r\n/**\r\n * Rotation/scale relayout/backup copy fragment shader (WGSL/WebGPU) — same copy as the GLSL variant, 3 attachments.\r\n */\r\nexport const GaussianSplattingWorkBufferRotCopyFragmentShaderWGSL = `\r\nvar uMapTexSampler : sampler;\r\nvar uMapTex : texture_2d<f32>;\r\nvar uSrc0Sampler : sampler;\r\nvar uSrc0 : texture_2d<f32>;\r\nvar uSrc1Sampler : sampler;\r\nvar uSrc1 : texture_2d<f32>;\r\nvar uSrc2Sampler : sampler;\r\nvar uSrc2 : texture_2d<f32>;\r\n\r\nuniform uDstWidth : i32;\r\nuniform uSrcWidth : i32;\r\nuniform uUseMap : i32;\r\nuniform uSrcBaseOffset : i32;\r\nuniform uDstBaseRow : i32;\r\n\r\n@fragment\r\nfn main(input : FragmentInputs) -> FragmentOutputs {\r\n    let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\r\n    var srcIdx : i32;\r\n    if (uniforms.uUseMap == 1) {\r\n        let m : f32 = textureLoad(uMapTex, p, 0).r;\r\n        if (m < 0.0) {\r\n            discard;\r\n        }\r\n        srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\r\n    } else {\r\n        srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\r\n    }\r\n    let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\r\n    fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\r\n    fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\r\n    fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\r\n}\r\n`;\r\n\r\n/**\r\n * Relayout copy fragment shader (WGSL/WebGPU) — same copy as the GLSL variant.\r\n */\r\nexport const GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL = `\r\nvar uMapTexSampler : sampler;\r\nvar uMapTex : texture_2d<f32>;\r\nvar uSrc0Sampler : sampler;\r\nvar uSrc0 : texture_2d<f32>;\r\nvar uSrc1Sampler : sampler;\r\nvar uSrc1 : texture_2d<f32>;\r\nvar uSrc2Sampler : sampler;\r\nvar uSrc2 : texture_2d<f32>;\r\nvar uSrc3Sampler : sampler;\r\nvar uSrc3 : texture_2d<f32>;\r\n\r\nuniform uDstWidth : i32;\r\nuniform uSrcWidth : i32;\r\nuniform uUseMap : i32;\r\n// Region-scoped relayout (hosted compound atlas), both default 0 (standalone square path unchanged).\r\nuniform uSrcBaseOffset : i32;\r\nuniform uDstBaseRow : i32;\r\n\r\n@fragment\r\nfn main(input : FragmentInputs) -> FragmentOutputs {\r\n    let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\r\n    var srcIdx : i32;\r\n    if (uniforms.uUseMap == 1) {\r\n        let m : f32 = textureLoad(uMapTex, p, 0).r;\r\n        if (m < 0.0) {\r\n            discard;\r\n        }\r\n        srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\r\n    } else {\r\n        srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\r\n    }\r\n    let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\r\n    fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\r\n    fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\r\n    fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\r\n    fragmentOutputs.fragData3 = textureLoad(uSrc3, s, 0);\r\n}\r\n`;\r\n","import { Logger } from \"core/Misc/logger\";\r\nimport { MultiRenderTarget } from \"core/Materials/Textures/multiRenderTarget\";\r\nimport { ShaderMaterial } from \"core/Materials/shaderMaterial\";\r\nimport { ShaderLanguage } from \"core/Materials/shaderLanguage\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { Color4 } from \"core/Maths/math.color\";\r\nimport { Vector3, Vector4 } from \"core/Maths/math.vector\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type ISogTexturePack } from \"./splatDefs\";\r\nimport {\r\n    GaussianSplattingWorkBufferVertexShaderGLSL,\r\n    GaussianSplattingWorkBufferFragmentShaderGLSL,\r\n    GaussianSplattingWorkBufferVertexShaderWGSL,\r\n    GaussianSplattingWorkBufferFragmentShaderWGSL,\r\n    GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL,\r\n    GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL,\r\n    GaussianSplattingWorkBufferRelayoutShaderName,\r\n    GaussianSplattingWorkBufferShDecodeShaderName,\r\n    GaussianSplattingWorkBufferShDecodeFragmentShaderGLSL,\r\n    GaussianSplattingWorkBufferShDecodeFragmentShaderWGSL,\r\n    GaussianSplattingWorkBufferShCopyShaderName,\r\n    GaussianSplattingWorkBufferShCopyFragmentShaderGLSL,\r\n    GaussianSplattingWorkBufferShCopyFragmentShaderWGSL,\r\n    GaussianSplattingWorkBufferRotationDecodeShaderName,\r\n    GaussianSplattingWorkBufferRotationDecodeFragmentShaderGLSL,\r\n    GaussianSplattingWorkBufferRotationDecodeFragmentShaderWGSL,\r\n    GaussianSplattingWorkBufferRotCopyShaderName,\r\n    GaussianSplattingWorkBufferRotCopyFragmentShaderGLSL,\r\n    GaussianSplattingWorkBufferRotCopyFragmentShaderWGSL,\r\n} from \"./gaussianSplattingWorkBufferShaders\";\r\nimport { RawTexture } from \"core/Materials/Textures/rawTexture\";\r\n\r\n/**\r\n * A unified, GPU-decoded Gaussian Splatting work buffer.\r\n *\r\n * Holds a square MRT texture set (centers / covA / covB / colors) sized to a fixed splat capacity\r\n * (`ceil(sqrt(capacity))`). Each streamed SOG file is decoded directly on the GPU\r\n * (no CPU readback) into its allocated pixel range. The decoded textures are consumed unchanged by the\r\n * standard (non-SOG) Gaussian Splatting draw path.\r\n *\r\n * @experimental\r\n */\r\nexport class GaussianSplattingWorkBuffer {\r\n    private readonly _scene: Scene;\r\n    // Not readonly: a hosted work buffer is rebound to the compound's NEW atlas MRT after a grow (see rebindAtlas).\r\n    private _mrt: MultiRenderTarget;\r\n    private readonly _textureSize: number;\r\n    private readonly _shaderLanguage: ShaderLanguage;\r\n    private readonly _material: ShaderMaterial;\r\n    private readonly _quad: Mesh;\r\n    // When true this work buffer owns (and disposes) its MRT. False when it wraps an external atlas (a compound\r\n    // mesh's MRT) it must not dispose. In the external case the MRT is wide (dstWidth x atlasHeight), decodes are\r\n    // offset by _baseOffset (the reserved region's first splat), and _textureSize is the atlas WIDTH.\r\n    private readonly _ownsMrt: boolean;\r\n    // Not readonly: a hosted region can be RELOCATED to a new base when the compound compacts its atlas\r\n    // (reclaiming a removed part's rows). backupRegion() reads from the old base, setBaseOffset() updates it,\r\n    // then rebindAtlas() + restoreRegion() writes to the new base.\r\n    private _baseOffset: number;\r\n    // Splat count this work buffer addresses. Standalone: the whole (square) buffer. Hosted: the reserved\r\n    // region's (row-aligned) capacity — used to scope a relayout to the region's atlas rows.\r\n    private readonly _capacity: number;\r\n    // Relayout (defrag) copy material, created lazily on first relayout.\r\n    private _copyMaterial: Nullable<ShaderMaterial> = null;\r\n    // Reusable destination->source index map for the relayout pass (created lazily, sized to the work buffer).\r\n    private _relayoutMapData: Nullable<Float32Array> = null;\r\n    private _relayoutMapTexture: Nullable<RawTexture> = null;\r\n    // Transient backup of a hosted region's four textures, held between backupRegion() and restoreRegion() so the\r\n    // GPU-decoded data survives the compound recreating its atlas on a grow (adding a part / a second stream).\r\n    private _backupMrt: Nullable<MultiRenderTarget> = null;\r\n    private _disposed = false;\r\n    // Reused WebGL framebuffer for the async centers readback (created lazily, freed in dispose).\r\n    private _readFbo: Nullable<WebGLFramebuffer> = null;\r\n\r\n    // Higher-order spherical-harmonics. Each SH texture is its own single-attachment integer render target\r\n    // (RGBA_INTEGER/UNSIGNED_INTEGER, 16 SH scalar-bytes per texel) so a decode/relayout pass writes exactly one\r\n    // attachment, keeping within WebGPU's per-sample color-attachment byte budget. Empty when SH is off.\r\n    private _shMrts: MultiRenderTarget[] = [];\r\n    // True when this work buffer owns (and disposes) its SH render targets (standalone). False when they are the\r\n    // hosting compound's shared SH atlas (hosted) — borrowed, not disposed. Rebound alongside the core atlas.\r\n    private _ownsShMrts = false;\r\n    // The SH decode material (packed-u32 dequant), created only when SH is requested. Reused across files/passes.\r\n    private _shMaterial: Nullable<ShaderMaterial> = null;\r\n    // Integer SH relayout/backup copy material (usampler2D -> uvec4), created lazily alongside the float copy.\r\n    private _shCopyMaterial: Nullable<ShaderMaterial> = null;\r\n    // Transient region-sized integer backups of the SH textures, held between backupRegion() and restoreRegion()\r\n    // so the baked SH survives the compound recreating its SH atlas on a grow/compaction (parallel to _backupMrt).\r\n    private _backupShMrts: Nullable<MultiRenderTarget[]> = null;\r\n\r\n    // Rotation/scale. One 3-attachment half-float render target (rotA / rotB / rotScale) holding the per-splat\r\n    // rotation matrix + scale that voxel-based IBL shadowing consumes. Null when rotation decode is off.\r\n    private _rotMrt: Nullable<MultiRenderTarget> = null;\r\n    // True when this work buffer owns (and disposes) its rotation target (standalone). False when it is the hosting\r\n    // compound's shared rotation atlas (hosted) — borrowed, rebound alongside the core atlas, never disposed here.\r\n    private _ownsRotMrt = false;\r\n    // The rotation/scale decode material, created only when rotation is requested. Reused across files.\r\n    private _rotMaterial: Nullable<ShaderMaterial> = null;\r\n    // Rotation/scale relayout/backup copy material (3-out float copy), created lazily alongside the float copy.\r\n    private _rotCopyMaterial: Nullable<ShaderMaterial> = null;\r\n    // Transient region-sized backup of the rotation textures, held between backupRegion() and restoreRegion() so the\r\n    // decoded rotation/scale survives the compound recreating its rotation atlas on a grow/compaction.\r\n    private _backupRotMrt: Nullable<MultiRenderTarget> = null;\r\n\r\n    /**\r\n     * True when the engine supports the non-blocking GPU readback used by {@link readCentersRangeAsync}:\r\n     * WebGL2 (PBO + fence) or WebGPU (copyTextureToBuffer + mapAsync). When false (e.g. WebGL1), callers must\r\n     * decode positions on the CPU instead.\r\n     */\r\n    public get supportsAsyncCentersReadback(): boolean {\r\n        const engine = this._scene.getEngine();\r\n        if (engine.isWebGPU) {\r\n            return true;\r\n        }\r\n        const glEngine = engine as unknown as { _gl?: WebGL2RenderingContext; _readPixelsAsync?: unknown; webGLVersion?: number };\r\n        return !!glEngine._gl && typeof glEngine._readPixelsAsync === \"function\" && (glEngine.webGLVersion ?? 0) >= 2;\r\n    }\r\n\r\n    /**\r\n     * Square edge length (in pixels) of the work-buffer textures.\r\n     */\r\n    public get textureSize(): number {\r\n        return this._textureSize;\r\n    }\r\n\r\n    /**\r\n     * The decoded work-buffer textures: [centers, covA, covB, colors].\r\n     */\r\n    public get textures(): Texture[] {\r\n        return this._mrt.textures;\r\n    }\r\n\r\n    /**\r\n     * The baked higher-order SH textures (packed-u32, one per `ceil(coeffs*3/16)`), consumed by the draw path's\r\n     * `computeSHWeighted`/`decompose` as `shTexture0..N`. Empty when SH decoding is not enabled.\r\n     */\r\n    public get shTextures(): Texture[] {\r\n        return this._shMrts.map((m) => m.textures[0]);\r\n    }\r\n\r\n    /**\r\n     * The decoded rotation/scale textures ([rotationsA, rotationsB, rotationScale], half-float), consumed by the\r\n     * voxel-IBL path as `rotationsATexture`/`rotationsBTexture`/`rotationScaleTexture`. Empty when rotation decode\r\n     * is not enabled.\r\n     */\r\n    public get rotationTextures(): Texture[] {\r\n        return this._rotMrt ? this._rotMrt.textures : [];\r\n    }\r\n\r\n    /**\r\n     * Creates a work buffer sized to hold `capacity` splats.\r\n     *\r\n     * Standalone (default): the work buffer creates and owns a square MRT sized `ceil(sqrt(capacity))`, with\r\n     * decodes addressed from splat 0.\r\n     *\r\n     * Hosted (`externalAtlas` provided): the work buffer decodes/reads back into an externally-owned MRT (a\r\n     * compound mesh's shared atlas) instead of creating its own. Decodes are placed at `externalAtlas.baseOffset`\r\n     * (the reserved region's first splat) and addressed over `externalAtlas.width` (the wide atlas width), so the\r\n     * streamed splats land in the compound's atlas and sort/draw together with the static parts.\r\n     * @param scene hosting scene\r\n     * @param capacity total number of splats the work buffer must address\r\n     * @param externalAtlas optional external atlas to decode into instead of creating an owned square MRT\r\n     * @param sh optional higher-order SH decode configuration. `textureCount = ceil(coeffs*3/16)` for the max SH\r\n     *   degree across the streamed files. Standalone: the work buffer creates that many owned single-attachment\r\n     *   integer render targets. Hosted: `externalMrts` are the compound's shared SH atlas targets (borrowed).\r\n     * @param rotationScale optional rotation/scale decode configuration (for voxel-IBL shadows). When present the\r\n     *   work buffer decodes each splat's rotation matrix + scale into a 3-attachment half-float target. Standalone:\r\n     *   the work buffer creates and owns that target. Hosted: `externalMrt` is the compound's shared rotation atlas.\r\n     */\r\n    constructor(\r\n        scene: Scene,\r\n        capacity: number,\r\n        externalAtlas?: { mrt: MultiRenderTarget; width: number; baseOffset: number },\r\n        sh?: { textureCount: number; externalMrts?: MultiRenderTarget[] },\r\n        rotationScale?: { externalMrt?: MultiRenderTarget }\r\n    ) {\r\n        this._scene = scene;\r\n        this._shaderLanguage = scene.getEngine().isWebGPU ? ShaderLanguage.WGSL : ShaderLanguage.GLSL;\r\n        this._capacity = Math.max(1, capacity);\r\n\r\n        if (externalAtlas) {\r\n            this._mrt = externalAtlas.mrt;\r\n            this._textureSize = externalAtlas.width;\r\n            this._baseOffset = externalAtlas.baseOffset;\r\n            this._ownsMrt = false;\r\n        } else {\r\n            this._textureSize = Math.max(1, Math.ceil(Math.sqrt(Math.max(1, capacity))));\r\n            this._baseOffset = 0;\r\n            this._ownsMrt = true;\r\n            // The decode buffer accumulates (clear disabled) so each decode preserves previously-decoded files.\r\n            this._mrt = this._createMrt(\"gsWorkBuffer\", true);\r\n        }\r\n\r\n        // Higher-order SH: one single-attachment integer target per packed-u32 SH texture. Standalone owns square\r\n        // targets sized like the core atlas; hosted borrows the compound's wide shared SH atlas targets.\r\n        if (sh && sh.textureCount > 0) {\r\n            if (sh.externalMrts) {\r\n                this._shMrts = sh.externalMrts.slice(0, sh.textureCount);\r\n                this._ownsShMrts = false;\r\n            } else {\r\n                for (let k = 0; k < sh.textureCount; k++) {\r\n                    this._shMrts.push(this._createShMrt(`gsWorkBufferSh${k}`, true));\r\n                }\r\n                this._ownsShMrts = true;\r\n            }\r\n            this._shMaterial = this._createShMaterial();\r\n        }\r\n\r\n        // Rotation/scale: one 3-attachment half-float target. Standalone owns a square target sized like the core\r\n        // atlas; hosted borrows the compound's wide shared rotation atlas.\r\n        if (rotationScale) {\r\n            if (rotationScale.externalMrt) {\r\n                this._rotMrt = rotationScale.externalMrt;\r\n                this._ownsRotMrt = false;\r\n            } else {\r\n                this._rotMrt = this._createRotMrt(\"gsWorkBufferRot\", true);\r\n                this._ownsRotMrt = true;\r\n            }\r\n            this._rotMaterial = this._createRotMaterial();\r\n        }\r\n\r\n        // One persistent decode material + fullscreen-triangle quad, reused (with per-file uniforms)\r\n        // for every decode so the shader is compiled only once.\r\n        this._material = this._createMaterial();\r\n        this._quad = this._createQuad();\r\n        this._quad.material = this._material;\r\n\r\n        // Hosted: start compiling the copy shader now so backupRegion()/restoreRegion() are ready by the time\r\n        // the compound grows its atlas (a synchronous, non-frame-driven event we can't wait on).\r\n        if (!this._ownsMrt) {\r\n            this.isRelayoutReady();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Rebinds a hosted work buffer to a new atlas MRT (after the compound recreated it on a grow). No-op for a\r\n     * standalone work buffer, which owns its MRT.\r\n     * @param mrt the compound's new shared atlas\r\n     */\r\n    public rebindAtlas(mrt: MultiRenderTarget): void {\r\n        if (!this._ownsMrt) {\r\n            this._mrt = mrt;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Rebinds a hosted work buffer to the compound's NEW shared SH atlas (after the compound recreated it on a\r\n     * grow/compaction). No-op when SH isn't in use or the work buffer owns its SH targets (standalone).\r\n     * @param shMrts the compound's new shared SH render targets (one per packed-u32 SH texture)\r\n     */\r\n    public rebindShAtlas(shMrts: Nullable<MultiRenderTarget[]>): void {\r\n        if (!this._ownsShMrts && shMrts && this._shMrts.length) {\r\n            this._shMrts = shMrts.slice(0, this._shMrts.length);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Rebinds a hosted work buffer to the compound's NEW shared rotation atlas (after the compound recreated it on a\r\n     * grow/compaction). No-op when rotation isn't in use or the work buffer owns its rotation target (standalone).\r\n     * @param rotMrt the compound's new shared rotation atlas\r\n     */\r\n    public rebindRotAtlas(rotMrt: Nullable<MultiRenderTarget>): void {\r\n        if (!this._ownsRotMrt && rotMrt && this._rotMrt) {\r\n            this._rotMrt = rotMrt;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Relocates this hosted region to a new base splat offset in the shared atlas (used when the compound\r\n     * compacts its atlas and this region's rows move). Subsequent decode/render/readback and\r\n     * {@link restoreRegion} all address from the new base. Call between {@link backupRegion} (which read from\r\n     * the old base) and {@link restoreRegion} (which will write to the new base). No-op for a standalone\r\n     * work buffer, which owns its square MRT at base 0.\r\n     * @param baseOffset the region's new first splat index in the atlas\r\n     */\r\n    public setBaseOffset(baseOffset: number): void {\r\n        if (!this._ownsMrt) {\r\n            this._baseOffset = baseOffset;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * True once the backup/restore/relayout copy shaders are compiled, so {@link backupRegion} can preserve the\r\n     * region across an atlas rebuild. Callers that decode into a hosted region should await this before writing\r\n     * data, so a later grow/compaction can never race shader compilation and drop the region.\r\n     */\r\n    public get canBackup(): boolean {\r\n        return this._disposed || this._ownsMrt ? false : this.isRelayoutReady();\r\n    }\r\n\r\n    /**\r\n     * Copies this hosted region's four decoded textures out of the shared atlas into an internal backup MRT so\r\n     * they survive the compound recreating the atlas on a grow. Call immediately before the atlas is recreated,\r\n     * then {@link rebindAtlas} + {@link restoreRegion} after.\r\n     */\r\n    public backupRegion(): void {\r\n        if (this._disposed || this._ownsMrt) {\r\n            return;\r\n        }\r\n        if (!this.isRelayoutReady()) {\r\n            // The copy shaders should be compiled well before any grow (callers warm them before decoding), so this\r\n            // path means a grow raced compilation; warn rather than silently drop the region's GPU data on the restore.\r\n            Logger.Warn(\"GaussianSplattingWorkBuffer: backup skipped because the copy shaders are not ready; streamed region data may be lost on the atlas rebuild.\");\r\n            return;\r\n        }\r\n        const width = this._textureSize;\r\n        const regionRows = Math.max(1, Math.floor(this._capacity / width));\r\n        const baseRow = Math.floor(this._baseOffset / width);\r\n        if (!this._backupMrt) {\r\n            this._backupMrt = this._createMrt(\"gsAtlasBackup\", false, width, regionRows);\r\n        }\r\n        // Identity copy of the region out of the atlas: with useMap=0 and dstBaseRow=-baseRow the shader reads\r\n        // atlas texel ((p.y + baseRow) * width + p.x) — the region's global texel — into backup texel p.\r\n        this._renderRelayoutPass(this._backupMrt, this._mrt.textures, this._mrt.textures[0], 0, width, width, 0, -baseRow);\r\n        // Same for each baked SH texture (one integer copy pass per texture).\r\n        if (this._shMrts.length && this._shCopyMaterial) {\r\n            if (!this._backupShMrts) {\r\n                this._backupShMrts = this._shMrts.map((_, k) => this._createShMrt(`gsShAtlasBackup${k}`, false, width, regionRows));\r\n            }\r\n            for (let k = 0; k < this._shMrts.length; k++) {\r\n                this._renderShCopyPass(this._backupShMrts[k], this._shMrts[k].textures[0], this._mrt.textures[0], 0, width, width, 0, -baseRow);\r\n            }\r\n        }\r\n        // Same for the rotation/scale textures (one 3-out float copy pass).\r\n        if (this._rotMrt && this._rotCopyMaterial) {\r\n            if (!this._backupRotMrt) {\r\n                this._backupRotMrt = this._createRotMrt(\"gsRotAtlasBackup\", false, width, regionRows);\r\n            }\r\n            this._renderRotCopyPass(this._backupRotMrt, this._rotMrt.textures, this._mrt.textures[0], 0, width, width, 0, -baseRow);\r\n        }\r\n        this._quad.material = this._material;\r\n    }\r\n\r\n    /**\r\n     * Restores the backed-up region into the (new) atlas, confined by a scissor to the region's rows so no other\r\n     * part is touched. Call {@link rebindAtlas} to the new atlas first. Frees the backup afterwards.\r\n     */\r\n    public restoreRegion(): void {\r\n        if (this._disposed || this._ownsMrt || !this._backupMrt || !this._copyMaterial) {\r\n            return;\r\n        }\r\n        const width = this._textureSize;\r\n        const regionRows = Math.max(1, Math.floor(this._capacity / width));\r\n        const baseRow = Math.floor(this._baseOffset / width);\r\n        const engine = this._scene.getEngine();\r\n        engine.enableScissor(0, baseRow, width, regionRows);\r\n        try {\r\n            // useMap=0 identity with dstBaseRow=baseRow: atlas texel p reads backup texel ((p.y - baseRow)*width + p.x).\r\n            this._renderRelayoutPass(this._mrt, this._backupMrt.textures, this._backupMrt.textures[0], 0, width, width, 0, baseRow);\r\n            // Restore each baked SH texture the same way (scissored to the region's rows). The map placeholder must\r\n            // be a FLOAT texture (uMapTex is texture_2d<f32>) even though useMap=0 doesn't sample it — WebGPU still\r\n            // validates the bound texture's sample type against the layout. Use the atlas centers (F32).\r\n            if (this._backupShMrts && this._shMrts.length && this._shCopyMaterial) {\r\n                for (let k = 0; k < this._shMrts.length && k < this._backupShMrts.length; k++) {\r\n                    this._renderShCopyPass(this._shMrts[k], this._backupShMrts[k].textures[0], this._mrt.textures[0], 0, width, width, 0, baseRow);\r\n                }\r\n            }\r\n            // Restore the rotation/scale textures the same way (3-out float copy, scissored to the region's rows).\r\n            if (this._backupRotMrt && this._rotMrt && this._rotCopyMaterial) {\r\n                this._renderRotCopyPass(this._rotMrt, this._backupRotMrt.textures, this._mrt.textures[0], 0, width, width, 0, baseRow);\r\n            }\r\n        } finally {\r\n            engine.disableScissor();\r\n            this._quad.material = this._material;\r\n        }\r\n        this._backupMrt.dispose();\r\n        this._backupMrt = null;\r\n        if (this._backupShMrts) {\r\n            for (const mrt of this._backupShMrts) {\r\n                mrt.dispose();\r\n            }\r\n            this._backupShMrts = null;\r\n        }\r\n        this._backupRotMrt?.dispose();\r\n        this._backupRotMrt = null;\r\n    }\r\n\r\n    /**\r\n     * Creates a 4-attachment MRT (centers F32 / covA / covB / colors U8) sized to the work buffer. covA/covB\r\n     * use HALF_FLOAT when the engine can render to it, matching the precision the non-streamed\r\n     * GaussianSplattingMesh path already uses for these same two textures (see\r\n     * `gaussianSplattingMeshBase.pure.ts`'s `createTextureFromDataF16` covA/covB textures); centers stays F32\r\n     * and colors stays U8 in both paths.\r\n     * @param name MRT and attachment base name\r\n     * @param disableClear when true, clearing is suppressed so renders accumulate (the decode buffer); when\r\n     *   false the MRT clears to zero on each render (the temporary relayout buffer, so gaps stay zeroed)\r\n     * @param width texture width (defaults to the work-buffer size; the region row width for a scoped relayout)\r\n     * @param height texture height (defaults to the work-buffer size; the region row count for a scoped relayout)\r\n     * @returns the created MRT\r\n     */\r\n    private _createMrt(name: string, disableClear: boolean, width: number = this._textureSize, height: number = this._textureSize): MultiRenderTarget {\r\n        const covType = this._scene.getEngine()._caps.textureHalfFloatRender ? Constants.TEXTURETYPE_HALF_FLOAT : Constants.TEXTURETYPE_FLOAT;\r\n        const mrt = new MultiRenderTarget(\r\n            name,\r\n            { width, height },\r\n            4,\r\n            this._scene,\r\n            {\r\n                types: [Constants.TEXTURETYPE_FLOAT, covType, covType, Constants.TEXTURETYPE_UNSIGNED_BYTE],\r\n                samplingModes: [\r\n                    Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n                    Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n                    Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n                    Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n                ],\r\n                formats: [Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA],\r\n                generateDepthBuffer: false,\r\n                generateDepthTexture: false,\r\n                generateMipMaps: false,\r\n            },\r\n            [`${name}Centers`, `${name}CovA`, `${name}CovB`, `${name}Colors`]\r\n        );\r\n        mrt.clearColor = new Color4(0, 0, 0, 0);\r\n        mrt.renderList = [];\r\n        if (disableClear) {\r\n            mrt.onClearObservable.add(() => {});\r\n        }\r\n        return mrt;\r\n    }\r\n\r\n    /**\r\n     * Creates a single-attachment integer render target (RGBA_INTEGER / UNSIGNED_INTEGER) that holds one packed-u32\r\n     * baked-SH texture. One attachment per pass keeps within WebGPU's per-sample color-attachment byte budget and\r\n     * matches the format/type of the draw path's `shTexture0..N` samplers (`_GaussianSplattingBytesPerShTexel`).\r\n     * @param name attachment name\r\n     * @param disableClear when true, clearing is suppressed so SH decodes accumulate across files\r\n     * @param width texture width (defaults to the work-buffer size)\r\n     * @param height texture height (defaults to the work-buffer size)\r\n     * @returns the created single-attachment integer MRT\r\n     */\r\n    private _createShMrt(name: string, disableClear: boolean, width: number = this._textureSize, height: number = this._textureSize): MultiRenderTarget {\r\n        const mrt = new MultiRenderTarget(\r\n            name,\r\n            { width, height },\r\n            1,\r\n            this._scene,\r\n            {\r\n                types: [Constants.TEXTURETYPE_UNSIGNED_INTEGER],\r\n                formats: [Constants.TEXTUREFORMAT_RGBA_INTEGER],\r\n                samplingModes: [Constants.TEXTURE_NEAREST_SAMPLINGMODE],\r\n                generateDepthBuffer: false,\r\n                generateDepthTexture: false,\r\n                generateMipMaps: false,\r\n            },\r\n            [name]\r\n        );\r\n        mrt.clearColor = new Color4(0, 0, 0, 0);\r\n        mrt.renderList = [];\r\n        if (disableClear) {\r\n            mrt.onClearObservable.add(() => {});\r\n        }\r\n        return mrt;\r\n    }\r\n\r\n    /**\r\n     * Creates a 3-attachment half-float MRT ([rotA, rotB, rotScale]) holding the per-splat rotation matrix + scale\r\n     * consumed by voxel-IBL shadowing. RGBA half-float when the engine can render to it (matching the covariance\r\n     * precision), else full float. 3 attachments = 24 B/sample, within WebGPU's per-sample budget (its own pass).\r\n     * @param name MRT and attachment base name\r\n     * @param disableClear when true, clearing is suppressed so decodes accumulate (the decode buffer)\r\n     * @param width texture width (defaults to the work-buffer size; the region row width for a scoped relayout)\r\n     * @param height texture height (defaults to the work-buffer size; the region row count for a scoped relayout)\r\n     * @returns the created MRT\r\n     */\r\n    private _createRotMrt(name: string, disableClear: boolean, width: number = this._textureSize, height: number = this._textureSize): MultiRenderTarget {\r\n        const rotType = this._scene.getEngine()._caps.textureHalfFloatRender ? Constants.TEXTURETYPE_HALF_FLOAT : Constants.TEXTURETYPE_FLOAT;\r\n        const mrt = new MultiRenderTarget(\r\n            name,\r\n            { width, height },\r\n            3,\r\n            this._scene,\r\n            {\r\n                types: [rotType, rotType, rotType],\r\n                formats: [Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA],\r\n                samplingModes: [Constants.TEXTURE_NEAREST_SAMPLINGMODE, Constants.TEXTURE_NEAREST_SAMPLINGMODE, Constants.TEXTURE_NEAREST_SAMPLINGMODE],\r\n                generateDepthBuffer: false,\r\n                generateDepthTexture: false,\r\n                generateMipMaps: false,\r\n            },\r\n            [`${name}A`, `${name}B`, `${name}Scale`]\r\n        );\r\n        mrt.clearColor = new Color4(0, 0, 0, 0);\r\n        mrt.renderList = [];\r\n        if (disableClear) {\r\n            mrt.onClearObservable.add(() => {});\r\n        }\r\n        return mrt;\r\n    }\r\n\r\n    /**\r\n     * Decodes one SOG file into the work buffer at the given splat offset (accumulating; previously\r\n     * decoded files are preserved). Resolves once the GPU decode has been issued. The caller may\r\n     * dispose the source pack textures after this resolves.\r\n     * @param pack the SOG texture pack (GPU source textures + per-file decode parameters)\r\n     * @param offset first splat index (pixel offset) for this file in the work buffer\r\n     */\r\n    public async decodeAsync(pack: ISogTexturePack, offset: number): Promise<void> {\r\n        if (this._disposed) {\r\n            return;\r\n        }\r\n        this._applyPack(pack);\r\n        // When SH is enabled, bake EVERY file's region — even a file with no higher-order SH (a coarse LOD may drop\r\n        // it): those get uCoeffs=0 so the whole region neutral-fills (128), keeping mixed-degree files consistent.\r\n        const decodeSh = this._shMaterial !== null && this._shMrts.length > 0;\r\n        if (decodeSh) {\r\n            this._applyShPack(pack);\r\n        }\r\n        const decodeRot = this._rotMaterial !== null && this._rotMrt !== null;\r\n        if (decodeRot) {\r\n            this._applyRotPack(pack);\r\n        }\r\n        // Render the decode pass at the start of a frame (the safe point for custom render targets),\r\n        // once the shader is compiled — never re-entrantly from a promise/observable continuation.\r\n        await new Promise<void>((resolve) => {\r\n            const attempt = () => {\r\n                if (this._disposed) {\r\n                    resolve();\r\n                    return;\r\n                }\r\n                if (!this._material.isReady(this._quad) || (decodeSh && !this._shMaterial!.isReady(this._quad)) || (decodeRot && !this._rotMaterial!.isReady(this._quad))) {\r\n                    this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n                    return;\r\n                }\r\n                // Scissor every pass to just this file's atlas rows so the fullscreen triangle only shades the region\r\n                // it writes, not the whole (wide) atlas. Correct because the shaders already discard outside the exact\r\n                // splat range, and the row band is a superset of it.\r\n                const width = this._textureSize;\r\n                // Bind uOffset at render time from the live _baseOffset so it shares one value with the scissor below:\r\n                // compactAtlas() can relocate this region (via setBaseOffset) during the defer window.\r\n                const globalOffset = this._baseOffset + offset;\r\n                this._material.setInt(\"uOffset\", globalOffset);\r\n                if (decodeSh) {\r\n                    this._shMaterial!.setInt(\"uOffset\", globalOffset);\r\n                }\r\n                if (decodeRot) {\r\n                    this._rotMaterial!.setInt(\"uOffset\", globalOffset);\r\n                }\r\n                const firstRow = Math.floor(globalOffset / width);\r\n                const rowCount = Math.max(1, Math.ceil((globalOffset + pack.splatCount) / width) - firstRow);\r\n                const engine = this._scene.getEngine();\r\n                engine.enableScissor(0, firstRow, width, rowCount);\r\n                try {\r\n                    this._quad.material = this._material;\r\n                    this._mrt.renderList = [this._quad];\r\n                    this._mrt.render();\r\n                    // Bake this file's higher-order SH: one pass per packed-u32 SH texture (uShTextureIndex selects the\r\n                    // 16 SH scalars written this pass). Files with fewer coefficients neutral-fill (128) higher bands.\r\n                    if (decodeSh) {\r\n                        for (let k = 0; k < this._shMrts.length; k++) {\r\n                            this._shMaterial!.setInt(\"uShTextureIndex\", k);\r\n                            this._quad.material = this._shMaterial!;\r\n                            this._shMrts[k].renderList = [this._quad];\r\n                            this._shMrts[k].render();\r\n                        }\r\n                        this._quad.material = this._material;\r\n                    }\r\n                    // Bake this file's rotation/scale into the 3-attachment half-float rotation target (one pass).\r\n                    if (decodeRot) {\r\n                        this._quad.material = this._rotMaterial!;\r\n                        this._rotMrt!.renderList = [this._quad];\r\n                        this._rotMrt!.render();\r\n                        this._quad.material = this._material;\r\n                    }\r\n                } finally {\r\n                    engine.disableScissor();\r\n                }\r\n                resolve();\r\n            };\r\n            this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Whether the relayout copy shader is compiled and ready. Lazily creates the copy material on first call.\r\n     * Callers should poll this before {@link relayoutSync} (which must only run when ready).\r\n     * @returns true when {@link relayoutSync} can run this frame\r\n     */\r\n    public isRelayoutReady(): boolean {\r\n        if (this._disposed) {\r\n            return false;\r\n        }\r\n        if (!this._copyMaterial) {\r\n            this._copyMaterial = this._createCopyMaterial();\r\n        }\r\n        // When SH is in use, the integer copy shader must also be compiled before a backup/restore/relayout can run.\r\n        if (this._shMrts.length && !this._shCopyMaterial) {\r\n            this._shCopyMaterial = this._createShCopyMaterial();\r\n        }\r\n        // Same for the rotation/scale 3-out float copy shader when rotation is in use.\r\n        if (this._rotMrt && !this._rotCopyMaterial) {\r\n            this._rotCopyMaterial = this._createRotCopyMaterial();\r\n        }\r\n        // `isReady` reports \"not ready\" when a bound sampler points at a disposed texture (a previous backup/relayout\r\n        // binds its temp MRTs as sources, then frees them). The copy passes bind fresh textures every call, so re-point\r\n        // the materials at the live atlas textures first; the check then reflects only whether the shader compiled.\r\n        this._bindCopyMaterialsToAtlas();\r\n        const shReady = this._shMrts.length === 0 || (this._shCopyMaterial !== null && this._shCopyMaterial.isReady(this._quad));\r\n        const rotReady = !this._rotMrt || (this._rotCopyMaterial !== null && this._rotCopyMaterial.isReady(this._quad));\r\n        return this._copyMaterial.isReady(this._quad) && shReady && rotReady;\r\n    }\r\n\r\n    /**\r\n     * Re-points the relayout/backup copy materials' samplers at the live atlas textures (valid, never freed), so a\r\n     * later {@link isRelayoutReady} check isn't tripped by a stale binding to a disposed temp/backup MRT.\r\n     */\r\n    private _bindCopyMaterialsToAtlas(): void {\r\n        const t = this._mrt.textures;\r\n        if (this._copyMaterial) {\r\n            this._copyMaterial.setTexture(\"uMapTex\", t[0]);\r\n            this._copyMaterial.setTexture(\"uSrc0\", t[0]);\r\n            this._copyMaterial.setTexture(\"uSrc1\", t[1]);\r\n            this._copyMaterial.setTexture(\"uSrc2\", t[2]);\r\n            this._copyMaterial.setTexture(\"uSrc3\", t[3]);\r\n        }\r\n        if (this._shCopyMaterial && this._shMrts.length) {\r\n            this._shCopyMaterial.setTexture(\"uMapTex\", t[0]);\r\n            this._shCopyMaterial.setTexture(\"uSrcSh\", this._shMrts[0].textures[0]);\r\n        }\r\n        if (this._rotCopyMaterial && this._rotMrt) {\r\n            const r = this._rotMrt.textures;\r\n            this._rotCopyMaterial.setTexture(\"uMapTex\", t[0]);\r\n            this._rotCopyMaterial.setTexture(\"uSrc0\", r[0]);\r\n            this._rotCopyMaterial.setTexture(\"uSrc1\", r[1]);\r\n            this._rotCopyMaterial.setTexture(\"uSrc2\", r[2]);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Relayouts the decoded work-buffer textures to a new (defragmented) splat layout, keeping the same\r\n     * texture instances so the consuming mesh does not need to re-bind. `srcIndexByDst[d]` is the source splat\r\n     * index whose decoded data should end up at destination index `d`, or a negative value for a gap (left\r\n     * zeroed). Uses a temporary MRT ping-pong (old -> temp via the map, then temp -> old identity) so\r\n     * overlapping moves stay correct. Must be called at a frame-safe point (inside `onBeforeRender`) and only\r\n     * when {@link isRelayoutReady} returns true.\r\n     * @param srcIndexByDst per-destination source splat index (negative = gap)\r\n     */\r\n    public relayoutSync(srcIndexByDst: Float32Array): void {\r\n        if (this._disposed || !this._copyMaterial) {\r\n            return;\r\n        }\r\n        // Map dimensions: standalone maps the whole square buffer; hosted maps just the region's rows.\r\n        const width = this._textureSize;\r\n        const mapW = width;\r\n        const mapH = this._ownsMrt ? width : Math.max(1, Math.floor(this._capacity / width));\r\n        // Reuse the map buffer + its GPU texture across relayouts (dimensions are fixed for a work buffer).\r\n        if (!this._relayoutMapData) {\r\n            this._relayoutMapData = new Float32Array(mapW * mapH);\r\n        }\r\n        const mapData = this._relayoutMapData;\r\n        mapData.fill(-1);\r\n        mapData.set(srcIndexByDst.subarray(0, Math.min(srcIndexByDst.length, mapData.length)));\r\n        if (!this._relayoutMapTexture) {\r\n            this._relayoutMapTexture = new RawTexture(\r\n                mapData,\r\n                mapW,\r\n                mapH,\r\n                Constants.TEXTUREFORMAT_R,\r\n                this._scene,\r\n                false,\r\n                false,\r\n                Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n                Constants.TEXTURETYPE_FLOAT\r\n            );\r\n        } else {\r\n            this._relayoutMapTexture.update(mapData);\r\n        }\r\n        const mapTexture = this._relayoutMapTexture;\r\n\r\n        if (this._ownsMrt) {\r\n            // Standalone: the work buffer owns the whole square texture, so a full ping-pong is safe.\r\n            const temp = this._createMrt(\"gsRelayoutTemp\", false);\r\n            try {\r\n                this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1); // old -> temp via map (gaps cleared)\r\n                this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0); // temp -> old, identity full overwrite\r\n            } finally {\r\n                temp.dispose();\r\n            }\r\n            // Same ping-pong for each baked SH texture (integer copy, one temp per texture).\r\n            if (this._shMrts.length && this._shCopyMaterial) {\r\n                for (let k = 0; k < this._shMrts.length; k++) {\r\n                    const shTemp = this._createShMrt(\"gsShRelayoutTemp\", false);\r\n                    try {\r\n                        this._renderShCopyPass(shTemp, this._shMrts[k].textures[0], mapTexture, 1);\r\n                        this._renderShCopyPass(this._shMrts[k], shTemp.textures[0], mapTexture, 0);\r\n                    } finally {\r\n                        shTemp.dispose();\r\n                    }\r\n                }\r\n            }\r\n            // Same ping-pong for the rotation/scale textures (3-out float copy).\r\n            if (this._rotMrt && this._rotCopyMaterial) {\r\n                const rotTemp = this._createRotMrt(\"gsRotRelayoutTemp\", false);\r\n                try {\r\n                    this._renderRotCopyPass(rotTemp, this._rotMrt.textures, mapTexture, 1);\r\n                    this._renderRotCopyPass(this._rotMrt, rotTemp.textures, mapTexture, 0);\r\n                } finally {\r\n                    rotTemp.dispose();\r\n                }\r\n            }\r\n            this._quad.material = this._material;\r\n            return;\r\n        }\r\n\r\n        // Hosted (shared compound atlas): scope the ping-pong to THIS region's row band so other parts are never\r\n        // touched. `_baseOffset` and `_capacity` are row-aligned (reserveStreamingPart), so the band is exact.\r\n        const baseRow = Math.floor(this._baseOffset / width);\r\n        const regionRows = mapH;\r\n        const engine = this._scene.getEngine();\r\n        // Region-sized temp (width x regionRows) — memory stays proportional to the region, not the whole atlas.\r\n        const temp = this._createMrt(\"gsRelayoutTemp\", false, width, regionRows);\r\n        // One region-sized integer temp per baked SH texture (same ping-pong, integer format).\r\n        const shTemps = this._shMrts.length && this._shCopyMaterial ? this._shMrts.map((_, k) => this._createShMrt(`gsShRelayoutTemp${k}`, false, width, regionRows)) : [];\r\n        // One region-sized rotation temp (3-attachment float) when rotation is in use.\r\n        const rotTemp = this._rotMrt && this._rotCopyMaterial ? this._createRotMrt(\"gsRotRelayoutTemp\", false, width, regionRows) : null;\r\n        try {\r\n            // Pass 1: atlas region -> temp via map. The map is region-local; uSrcBaseOffset shifts each source\r\n            // index to its GLOBAL atlas texel (uSrcWidth = atlas width). Temp is exactly the band, so no scissor.\r\n            this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1, /*dstWidth*/ width, /*srcWidth*/ width, /*srcBaseOffset*/ this._baseOffset, /*dstBaseRow*/ 0);\r\n            for (let k = 0; k < shTemps.length; k++) {\r\n                this._renderShCopyPass(shTemps[k], this._shMrts[k].textures[0], mapTexture, 1, width, width, this._baseOffset, 0);\r\n            }\r\n            if (rotTemp) {\r\n                this._renderRotCopyPass(rotTemp, this._rotMrt!.textures, mapTexture, 1, width, width, this._baseOffset, 0);\r\n            }\r\n            // Pass 2: temp -> atlas region, identity within the band. uDstBaseRow maps the atlas destination row\r\n            // back into the region-local temp; the scissor confines writes to the band so static parts are safe.\r\n            engine.enableScissor(0, baseRow, width, regionRows);\r\n            try {\r\n                this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0, /*dstWidth*/ width, /*srcWidth*/ width, /*srcBaseOffset*/ 0, /*dstBaseRow*/ baseRow);\r\n                for (let k = 0; k < shTemps.length; k++) {\r\n                    this._renderShCopyPass(this._shMrts[k], shTemps[k].textures[0], mapTexture, 0, width, width, 0, baseRow);\r\n                }\r\n                if (rotTemp) {\r\n                    this._renderRotCopyPass(this._rotMrt!, rotTemp.textures, mapTexture, 0, width, width, 0, baseRow);\r\n                }\r\n            } finally {\r\n                engine.disableScissor();\r\n            }\r\n        } finally {\r\n            temp.dispose();\r\n            for (const t of shTemps) {\r\n                t.dispose();\r\n            }\r\n            rotTemp?.dispose();\r\n            this._quad.material = this._material;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Renders one relayout copy pass into the target MRT, sampling the given source textures.\r\n     * @param target destination MRT\r\n     * @param sources the four source work-buffer textures\r\n     * @param mapTexture the R32F destination-to-source index map (only sampled when `useMap` is 1; any bound texture otherwise)\r\n     * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n     * @param dstWidth destination width used to linearize the destination texel (defaults to the work-buffer size)\r\n     * @param srcWidth source width used to convert a linear source index to a texel (defaults to the work-buffer size)\r\n     * @param srcBaseOffset added to each mapped source index so a region-local map reads the correct global atlas texel (hosted relayout)\r\n     * @param dstBaseRow subtracted from the destination row so an identity copy reads the region-local temp (hosted relayout)\r\n     */\r\n    private _renderRelayoutPass(\r\n        target: MultiRenderTarget,\r\n        sources: Texture[],\r\n        mapTexture: BaseTexture,\r\n        useMap: number,\r\n        dstWidth: number = this._textureSize,\r\n        srcWidth: number = this._textureSize,\r\n        srcBaseOffset: number = 0,\r\n        dstBaseRow: number = 0\r\n    ): void {\r\n        const material = this._copyMaterial!;\r\n        material.setTexture(\"uMapTex\", mapTexture);\r\n        material.setTexture(\"uSrc0\", sources[0]);\r\n        material.setTexture(\"uSrc1\", sources[1]);\r\n        material.setTexture(\"uSrc2\", sources[2]);\r\n        material.setTexture(\"uSrc3\", sources[3]);\r\n        material.setInt(\"uDstWidth\", dstWidth);\r\n        material.setInt(\"uSrcWidth\", srcWidth);\r\n        material.setInt(\"uUseMap\", useMap);\r\n        material.setInt(\"uSrcBaseOffset\", srcBaseOffset);\r\n        material.setInt(\"uDstBaseRow\", dstBaseRow);\r\n        this._quad.material = material;\r\n        target.renderList = [this._quad];\r\n        target.render();\r\n    }\r\n\r\n    private _createCopyMaterial(): ShaderMaterial {\r\n        const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n        const material = new ShaderMaterial(\r\n            GaussianSplattingWorkBufferRelayoutShaderName,\r\n            this._scene,\r\n            {\r\n                vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n                fragmentSource: isWGSL ? GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL : GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL,\r\n            },\r\n            {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\", \"uSrcBaseOffset\", \"uDstBaseRow\"],\r\n                samplers: [\"uMapTex\", \"uSrc0\", \"uSrc1\", \"uSrc2\", \"uSrc3\"],\r\n                shaderLanguage: this._shaderLanguage,\r\n            }\r\n        );\r\n        material.backFaceCulling = false;\r\n        material.disableDepthWrite = true;\r\n        return material;\r\n    }\r\n\r\n    /**\r\n     * Renders one INTEGER SH copy pass (one packed-u32 SH texture) into the target, sampling one integer source.\r\n     * Same index/map/base math as {@link _renderRelayoutPass} but for the integer SH format.\r\n     * @param target destination single-attachment integer MRT\r\n     * @param srcSh the integer SH source texture\r\n     * @param mapTexture the R32F destination-to-source index map (sampled only when `useMap` is 1)\r\n     * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n     * @param dstWidth destination width used to linearize the destination texel\r\n     * @param srcWidth source width used to convert a linear source index to a texel\r\n     * @param srcBaseOffset added to each mapped source index (region-local map -> global atlas texel)\r\n     * @param dstBaseRow subtracted from the destination row for an identity copy of a region-local temp\r\n     */\r\n    private _renderShCopyPass(\r\n        target: MultiRenderTarget,\r\n        srcSh: Texture,\r\n        mapTexture: BaseTexture,\r\n        useMap: number,\r\n        dstWidth: number = this._textureSize,\r\n        srcWidth: number = this._textureSize,\r\n        srcBaseOffset: number = 0,\r\n        dstBaseRow: number = 0\r\n    ): void {\r\n        const material = this._shCopyMaterial!;\r\n        material.setTexture(\"uMapTex\", mapTexture);\r\n        material.setTexture(\"uSrcSh\", srcSh);\r\n        material.setInt(\"uDstWidth\", dstWidth);\r\n        material.setInt(\"uSrcWidth\", srcWidth);\r\n        material.setInt(\"uUseMap\", useMap);\r\n        material.setInt(\"uSrcBaseOffset\", srcBaseOffset);\r\n        material.setInt(\"uDstBaseRow\", dstBaseRow);\r\n        this._quad.material = material;\r\n        target.renderList = [this._quad];\r\n        target.render();\r\n    }\r\n\r\n    private _createShCopyMaterial(): ShaderMaterial {\r\n        const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n        const material = new ShaderMaterial(\r\n            GaussianSplattingWorkBufferShCopyShaderName,\r\n            this._scene,\r\n            {\r\n                vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n                fragmentSource: isWGSL ? GaussianSplattingWorkBufferShCopyFragmentShaderWGSL : GaussianSplattingWorkBufferShCopyFragmentShaderGLSL,\r\n            },\r\n            {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\", \"uSrcBaseOffset\", \"uDstBaseRow\"],\r\n                samplers: [\"uMapTex\", \"uSrcSh\"],\r\n                shaderLanguage: this._shaderLanguage,\r\n            }\r\n        );\r\n        material.backFaceCulling = false;\r\n        material.disableDepthWrite = true;\r\n        return material;\r\n    }\r\n\r\n    /**\r\n     * Renders one rotation/scale copy pass (the three half-float rotation textures) into the target. Same\r\n     * index/map/base math as {@link _renderRelayoutPass} but with three attachments.\r\n     * @param target destination 3-attachment MRT\r\n     * @param sources the three source rotation textures ([rotA, rotB, rotScale])\r\n     * @param mapTexture the R32F destination-to-source index map (sampled only when `useMap` is 1)\r\n     * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n     * @param dstWidth destination width used to linearize the destination texel\r\n     * @param srcWidth source width used to convert a linear source index to a texel\r\n     * @param srcBaseOffset added to each mapped source index (region-local map -> global atlas texel)\r\n     * @param dstBaseRow subtracted from the destination row for an identity copy of a region-local temp\r\n     */\r\n    private _renderRotCopyPass(\r\n        target: MultiRenderTarget,\r\n        sources: Texture[],\r\n        mapTexture: BaseTexture,\r\n        useMap: number,\r\n        dstWidth: number = this._textureSize,\r\n        srcWidth: number = this._textureSize,\r\n        srcBaseOffset: number = 0,\r\n        dstBaseRow: number = 0\r\n    ): void {\r\n        const material = this._rotCopyMaterial!;\r\n        material.setTexture(\"uMapTex\", mapTexture);\r\n        material.setTexture(\"uSrc0\", sources[0]);\r\n        material.setTexture(\"uSrc1\", sources[1]);\r\n        material.setTexture(\"uSrc2\", sources[2]);\r\n        material.setInt(\"uDstWidth\", dstWidth);\r\n        material.setInt(\"uSrcWidth\", srcWidth);\r\n        material.setInt(\"uUseMap\", useMap);\r\n        material.setInt(\"uSrcBaseOffset\", srcBaseOffset);\r\n        material.setInt(\"uDstBaseRow\", dstBaseRow);\r\n        this._quad.material = material;\r\n        target.renderList = [this._quad];\r\n        target.render();\r\n    }\r\n\r\n    private _createRotCopyMaterial(): ShaderMaterial {\r\n        const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n        const material = new ShaderMaterial(\r\n            GaussianSplattingWorkBufferRotCopyShaderName,\r\n            this._scene,\r\n            {\r\n                vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n                fragmentSource: isWGSL ? GaussianSplattingWorkBufferRotCopyFragmentShaderWGSL : GaussianSplattingWorkBufferRotCopyFragmentShaderGLSL,\r\n            },\r\n            {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\", \"uSrcBaseOffset\", \"uDstBaseRow\"],\r\n                samplers: [\"uMapTex\", \"uSrc0\", \"uSrc1\", \"uSrc2\"],\r\n                shaderLanguage: this._shaderLanguage,\r\n            }\r\n        );\r\n        material.backFaceCulling = false;\r\n        material.disableDepthWrite = true;\r\n        return material;\r\n    }\r\n\r\n    /**\r\n     * Asynchronously reads back the decoded splat centers (stride-4 xyzw, w=1) for a contiguous splat range\r\n     * from the work buffer's centers texture, using a non-blocking GPU readback (WebGL2 PBO + fence, or WebGPU\r\n     * copyTextureToBuffer + mapAsync) so it never stalls the frame the way a CPU image decode does. The centers\r\n     * texture already holds the GPU-decoded positions (identical to the CPU decode), so this replaces decoding\r\n     * positions on the CPU from the means images. Returns null when async readback is unsupported (caller should\r\n     * fall back to CPU decoding).\r\n     * @param splatOffset first splat index of the range\r\n     * @param splatCount number of splats in the range\r\n     * @returns a stride-4 Float32Array of length `splatCount * 4`, or null when unsupported/failed\r\n     */\r\n    public async readCentersRangeAsync(splatOffset: number, splatCount: number): Promise<Nullable<Float32Array>> {\r\n        if (this._disposed || splatCount <= 0 || !this.supportsAsyncCentersReadback) {\r\n            return null;\r\n        }\r\n\r\n        const width = this._textureSize;\r\n        // Shift the region-local offset by the atlas base so the readback targets the same global texels the\r\n        // decode wrote (0 base for a standalone work buffer).\r\n        const globalOffset = this._baseOffset + splatOffset;\r\n        // The range maps to whole texel rows [rowStart, rowEnd); read that rectangle and slice the exact range.\r\n        // Splat i lives at texel (i % width, floor(i / width)) in both decode and draw, so the readback (which\r\n        // indexes the same texture storage directly, with no UV/flip) yields splat i at buffer position\r\n        // i - rowStart * width on every backend.\r\n        const rowStart = Math.floor(globalOffset / width);\r\n        const rowEnd = Math.ceil((globalOffset + splatCount) / width);\r\n        const rowCount = rowEnd - rowStart;\r\n        const startInBuffer = (globalOffset - rowStart * width) * 4;\r\n        const sliceEnd = startInBuffer + splatCount * 4;\r\n        const centers = this._mrt.textures[0];\r\n\r\n        const engine = this._scene.getEngine();\r\n\r\n        if (engine.isWebGPU) {\r\n            // WebGPU: copyTextureToBuffer of the row span + mapAsync (genuinely non-blocking). noDataConversion\r\n            // returns the raw RGBA32F floats tightly packed (the 256-byte row alignment is removed internally).\r\n            const result = await centers.readPixels(0, 0, null, true, true, 0, rowStart, width, rowCount);\r\n            if (this._disposed || !result) {\r\n                return null;\r\n            }\r\n            const floats = result instanceof Float32Array ? result : new Float32Array(result.buffer, result.byteOffset, result.byteLength / 4);\r\n            return floats.length >= sliceEnd ? (floats.subarray(startInBuffer, sliceEnd) as Float32Array) : null;\r\n        }\r\n\r\n        // WebGL2: read directly from the centers texture via a reused FBO + async PBO readback.\r\n        const glEngine = engine as unknown as {\r\n            _gl: WebGL2RenderingContext;\r\n            _currentFramebuffer: Nullable<WebGLFramebuffer>;\r\n            _readPixelsAsync(x: number, y: number, w: number, h: number, format: number, type: number, o: ArrayBufferView): Nullable<Promise<ArrayBufferView>>;\r\n        };\r\n        const gl = glEngine._gl;\r\n        const hardware = centers.getInternalTexture()?._hardwareTexture?.underlyingResource as Nullable<WebGLTexture>;\r\n        if (!hardware) {\r\n            return null;\r\n        }\r\n        const buffer = new Float32Array(width * rowCount * 4);\r\n        if (!this._readFbo) {\r\n            this._readFbo = gl.createFramebuffer();\r\n        }\r\n        const previousFbo = glEngine._currentFramebuffer;\r\n        gl.bindFramebuffer(gl.FRAMEBUFFER, this._readFbo);\r\n        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, hardware, 0);\r\n        gl.readBuffer(gl.COLOR_ATTACHMENT0);\r\n\r\n        // _readPixelsAsync issues the readPixels into a PBO synchronously, then resolves once the GPU fence\r\n        // signals — so the framebuffer can be restored immediately while the transfer completes off-thread.\r\n        const promise = glEngine._readPixelsAsync(0, rowStart, width, rowCount, gl.RGBA, gl.FLOAT, buffer);\r\n        gl.bindFramebuffer(gl.FRAMEBUFFER, previousFbo);\r\n        // gl.readBuffer is global state: restore the default-framebuffer read source (BACK) so later\r\n        // readPixels on the default framebuffer aren't left pointing at COLOR_ATTACHMENT0. When restoring to\r\n        // another FBO, COLOR_ATTACHMENT0 is the correct default read buffer, so only reset for the default one.\r\n        if (!previousFbo) {\r\n            gl.readBuffer(gl.BACK);\r\n        }\r\n        if (!promise) {\r\n            return null;\r\n        }\r\n        await promise;\r\n        if (this._disposed || buffer.length < sliceEnd) {\r\n            return null;\r\n        }\r\n        return buffer.subarray(startInBuffer, sliceEnd) as Float32Array;\r\n    }\r\n\r\n    /**\r\n     * Disposes the work buffer and its decode resources.\r\n     */\r\n    public dispose(): void {\r\n        this._disposed = true;\r\n        if (this._readFbo) {\r\n            (this._scene.getEngine() as unknown as { _gl?: WebGL2RenderingContext })._gl?.deleteFramebuffer(this._readFbo);\r\n            this._readFbo = null;\r\n        }\r\n        this._quad.dispose();\r\n        this._material.dispose(true, false);\r\n        this._shMaterial?.dispose(true, false);\r\n        this._rotMaterial?.dispose(true, false);\r\n        this._copyMaterial?.dispose(true, false);\r\n        this._shCopyMaterial?.dispose(true, false);\r\n        this._rotCopyMaterial?.dispose(true, false);\r\n        this._relayoutMapTexture?.dispose();\r\n        this._backupMrt?.dispose();\r\n        this._backupMrt = null;\r\n        if (this._backupShMrts) {\r\n            for (const mrt of this._backupShMrts) {\r\n                mrt.dispose();\r\n            }\r\n            this._backupShMrts = null;\r\n        }\r\n        this._backupRotMrt?.dispose();\r\n        this._backupRotMrt = null;\r\n        // Only dispose the MRT when we own it; an external atlas belongs to the hosting compound mesh.\r\n        if (this._ownsMrt) {\r\n            this._mrt.dispose();\r\n        }\r\n        // Same ownership rule for the SH targets (standalone owns; hosted borrows the compound's shared SH atlas).\r\n        if (this._ownsShMrts) {\r\n            for (const mrt of this._shMrts) {\r\n                mrt.dispose();\r\n            }\r\n        }\r\n        this._shMrts = [];\r\n        // Same ownership rule for the rotation target.\r\n        if (this._ownsRotMrt) {\r\n            this._rotMrt?.dispose();\r\n        }\r\n        this._rotMrt = null;\r\n    }\r\n\r\n    private _createQuad(): Mesh {\r\n        const quad = new Mesh(\"gsWorkBufferQuad\", this._scene);\r\n        const vertexData = new VertexData();\r\n        // Fullscreen triangle in clip space (the vertex shader passes positions straight through).\r\n        vertexData.positions = [-1, -1, 0, 3, -1, 0, -1, 3, 0];\r\n        vertexData.indices = [0, 1, 2];\r\n        vertexData.applyToMesh(quad);\r\n        // Render only inside the work-buffer MRT, never in the main scene pass.\r\n        this._scene.removeMesh(quad);\r\n        return quad;\r\n    }\r\n\r\n    private _createMaterial(): ShaderMaterial {\r\n        const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n        const material = new ShaderMaterial(\r\n            \"gsSogDecode\",\r\n            this._scene,\r\n            {\r\n                vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n                fragmentSource: isWGSL ? GaussianSplattingWorkBufferFragmentShaderWGSL : GaussianSplattingWorkBufferFragmentShaderGLSL,\r\n            },\r\n            {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"sogMeansMin\", \"sogMeansMax\", \"sogScalesMin\", \"sogScalesMax\", \"sogSh0Min\", \"sogSh0Max\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\"],\r\n                samplers: [\"sogMeansLTex\", \"sogMeansUTex\", \"sogScalesTex\", \"sogQuatsTex\", \"sogSh0Tex\", \"sogCodebookTex\"],\r\n                shaderLanguage: this._shaderLanguage,\r\n            }\r\n        );\r\n        material.backFaceCulling = false;\r\n        material.disableDepthWrite = true;\r\n        return material;\r\n    }\r\n\r\n    private _applyPack(pack: ISogTexturePack): void {\r\n        const material = this._material;\r\n        const srcWidth = (pack.meansTextureL as Texture).getSize().width;\r\n\r\n        material.setTexture(\"sogMeansLTex\", pack.meansTextureL);\r\n        material.setTexture(\"sogMeansUTex\", pack.meansTextureU);\r\n        material.setTexture(\"sogScalesTex\", pack.scalesTexture);\r\n        material.setTexture(\"sogQuatsTex\", pack.quatsTexture);\r\n        material.setTexture(\"sogSh0Tex\", pack.sh0Texture);\r\n        // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n        material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? pack.sh0Texture);\r\n\r\n        material.setVector3(\"sogMeansMin\", new Vector3(pack.meansMin[0], pack.meansMin[1], pack.meansMin[2]));\r\n        material.setVector3(\"sogMeansMax\", new Vector3(pack.meansMax[0], pack.meansMax[1], pack.meansMax[2]));\r\n        const sMin = pack.scalesMin ?? [0, 0, 0];\r\n        const sMax = pack.scalesMax ?? [0, 0, 0];\r\n        material.setVector3(\"sogScalesMin\", new Vector3(sMin[0], sMin[1], sMin[2]));\r\n        material.setVector3(\"sogScalesMax\", new Vector3(sMax[0], sMax[1], sMax[2]));\r\n        const c0Min = pack.sh0Min ?? [0, 0, 0, 0];\r\n        const c0Max = pack.sh0Max ?? [0, 0, 0, 0];\r\n        material.setVector4(\"sogSh0Min\", new Vector4(c0Min[0], c0Min[1], c0Min[2], c0Min[3]));\r\n        material.setVector4(\"sogSh0Max\", new Vector4(c0Max[0], c0Max[1], c0Max[2], c0Max[3]));\r\n\r\n        material.setInt(\"uVersion\", pack.version);\r\n        // uOffset is bound at render time in decodeAsync (from the live _baseOffset).\r\n        material.setInt(\"uCount\", pack.splatCount);\r\n        material.setInt(\"uDestWidth\", this._textureSize);\r\n        material.setInt(\"uSrcWidth\", srcWidth);\r\n    }\r\n\r\n    private _createShMaterial(): ShaderMaterial {\r\n        const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n        const material = new ShaderMaterial(\r\n            GaussianSplattingWorkBufferShDecodeShaderName,\r\n            this._scene,\r\n            {\r\n                vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n                fragmentSource: isWGSL ? GaussianSplattingWorkBufferShDecodeFragmentShaderWGSL : GaussianSplattingWorkBufferShDecodeFragmentShaderGLSL,\r\n            },\r\n            {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"sogShnMin\", \"sogShnMax\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\", \"uCoeffs\", \"uShTextureIndex\"],\r\n                samplers: [\"sogShLabelsTex\", \"sogShCentroidsTex\", \"sogCodebookTex\"],\r\n                shaderLanguage: this._shaderLanguage,\r\n            }\r\n        );\r\n        material.backFaceCulling = false;\r\n        material.disableDepthWrite = true;\r\n        return material;\r\n    }\r\n\r\n    private _applyShPack(pack: ISogTexturePack): void {\r\n        const material = this._shMaterial!;\r\n        // A file may carry no higher-order SH (coarse LOD): fall back to sh0Texture as a harmless placeholder for the\r\n        // label/centroid samplers and set uCoeffs=0 so the shader neutral-fills every coefficient (128 -> 0 lighting).\r\n        const hasSh = !!pack.shLabelsTexture && !!pack.shCentroidsTexture;\r\n        const labels = pack.shLabelsTexture ?? pack.sh0Texture;\r\n        const centroids = pack.shCentroidsTexture ?? pack.sh0Texture;\r\n        material.setTexture(\"sogShLabelsTex\", labels);\r\n        material.setTexture(\"sogShCentroidsTex\", centroids);\r\n        // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n        material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? labels);\r\n        material.setFloat(\"sogShnMin\", pack.shnMin ?? 0);\r\n        material.setFloat(\"sogShnMax\", pack.shnMax ?? 0);\r\n        material.setInt(\"uVersion\", pack.version);\r\n        // uOffset is bound at render time in decodeAsync (from the live _baseOffset).\r\n        material.setInt(\"uCount\", pack.splatCount);\r\n        material.setInt(\"uDestWidth\", this._textureSize);\r\n        material.setInt(\"uSrcWidth\", (labels as Texture).getSize().width);\r\n        // Higher-order coefficient count for THIS file (bands=3 -> 15). 0 when the file has no SH -> full neutral fill.\r\n        material.setInt(\"uCoeffs\", hasSh ? pack.shCoeffCount : 0);\r\n    }\r\n\r\n    private _createRotMaterial(): ShaderMaterial {\r\n        const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n        const material = new ShaderMaterial(\r\n            GaussianSplattingWorkBufferRotationDecodeShaderName,\r\n            this._scene,\r\n            {\r\n                vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n                fragmentSource: isWGSL ? GaussianSplattingWorkBufferRotationDecodeFragmentShaderWGSL : GaussianSplattingWorkBufferRotationDecodeFragmentShaderGLSL,\r\n            },\r\n            {\r\n                attributes: [\"position\"],\r\n                uniforms: [\"sogScalesMin\", \"sogScalesMax\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\"],\r\n                samplers: [\"sogScalesTex\", \"sogQuatsTex\", \"sogCodebookTex\"],\r\n                shaderLanguage: this._shaderLanguage,\r\n            }\r\n        );\r\n        material.backFaceCulling = false;\r\n        material.disableDepthWrite = true;\r\n        return material;\r\n    }\r\n\r\n    private _applyRotPack(pack: ISogTexturePack): void {\r\n        const material = this._rotMaterial!;\r\n        const srcWidth = (pack.scalesTexture as Texture).getSize().width;\r\n        material.setTexture(\"sogScalesTex\", pack.scalesTexture);\r\n        material.setTexture(\"sogQuatsTex\", pack.quatsTexture);\r\n        // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n        material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? pack.scalesTexture);\r\n        const sMin = pack.scalesMin ?? [0, 0, 0];\r\n        const sMax = pack.scalesMax ?? [0, 0, 0];\r\n        material.setVector3(\"sogScalesMin\", new Vector3(sMin[0], sMin[1], sMin[2]));\r\n        material.setVector3(\"sogScalesMax\", new Vector3(sMax[0], sMax[1], sMax[2]));\r\n        material.setInt(\"uVersion\", pack.version);\r\n        // uOffset is bound at render time in decodeAsync (from the live _baseOffset).\r\n        material.setInt(\"uCount\", pack.splatCount);\r\n        material.setInt(\"uDestWidth\", this._textureSize);\r\n        material.setInt(\"uSrcWidth\", srcWidth);\r\n    }\r\n}\r\n","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","import { type Nullable } from \"core/types\";\r\n\r\n/**\r\n * A node in the {@link GaussianSplattingBlockAllocator}'s linked list, representing either an allocated\r\n * block or a free region. Callers receive {@link GaussianSplattingMemBlock} instances as handles from\r\n * {@link GaussianSplattingBlockAllocator.allocate} and must treat their {@link offset}/{@link size} as\r\n * read-only.\r\n *\r\n * Ported from the PlayCanvas engine (`src/core/block-allocator.js`).\r\n * @experimental\r\n */\r\nexport class GaussianSplattingMemBlock {\r\n    /** @internal Position in the address space. */\r\n    public _offset = 0;\r\n    /** @internal Size of this block. */\r\n    public _size = 0;\r\n    /** @internal True if this is a free region, false if allocated. */\r\n    public _free = true;\r\n    /** @internal Previous node in the main (all-nodes, offset-ordered) list. */\r\n    public _prev: Nullable<GaussianSplattingMemBlock> = null;\r\n    /** @internal Next node in the main (all-nodes, offset-ordered) list. */\r\n    public _next: Nullable<GaussianSplattingMemBlock> = null;\r\n    /** @internal Previous node in the bucket free-list. */\r\n    public _prevFree: Nullable<GaussianSplattingMemBlock> = null;\r\n    /** @internal Next node in the bucket free-list. */\r\n    public _nextFree: Nullable<GaussianSplattingMemBlock> = null;\r\n    /** @internal Index of the size bucket this free block belongs to, or -1 if not in any bucket. */\r\n    public _bucket = -1;\r\n\r\n    /**\r\n     * The offset of this block in the address space.\r\n     */\r\n    public get offset(): number {\r\n        return this._offset;\r\n    }\r\n\r\n    /**\r\n     * The size of this block.\r\n     */\r\n    public get size(): number {\r\n        return this._size;\r\n    }\r\n}\r\n\r\n/**\r\n * A general-purpose 1D block allocator backed by a doubly-linked list with segregated free-list buckets.\r\n * Manages a linear address space where contiguous blocks can be allocated and freed.\r\n *\r\n * Free blocks are organized into power-of-2 size buckets for best-fit allocation, which reduces\r\n * fragmentation compared to a single first-fit free list. Supports incremental defragmentation and\r\n * automatic growth. Used to place streamed Gaussian Splatting LOD files into the unified GPU work buffer.\r\n *\r\n * Ported from the PlayCanvas engine (`src/core/block-allocator.js`).\r\n * @experimental\r\n */\r\nexport class GaussianSplattingBlockAllocator {\r\n    // Head/tail of the main list (all blocks, offset-ordered).\r\n    private _headAll: Nullable<GaussianSplattingMemBlock> = null;\r\n    private _tailAll: Nullable<GaussianSplattingMemBlock> = null;\r\n    // Segregated free-list bucket heads. Bucket i covers sizes [2^i, 2^(i+1)). Grows as larger free blocks appear.\r\n    private readonly _freeBucketHeads: Array<Nullable<GaussianSplattingMemBlock>> = [];\r\n    // Pool of recycled MemBlock objects.\r\n    private readonly _pool: GaussianSplattingMemBlock[] = [];\r\n    private _capacity = 0;\r\n    private _usedSize = 0;\r\n    private _freeSize = 0;\r\n    // Number of free regions; maintained O(1) for the fragmentation metric.\r\n    private _freeRegionCount = 0;\r\n    // Multiplicative growth factor used by updateAllocation.\r\n    private readonly _growMultiplier: number;\r\n\r\n    /**\r\n     * Creates a new block allocator.\r\n     * @param capacity initial address space capacity (defaults to 0)\r\n     * @param growMultiplier multiplicative growth factor for auto-grow in {@link updateAllocation} (defaults to 1.1)\r\n     */\r\n    public constructor(capacity = 0, growMultiplier = 1.1) {\r\n        this._growMultiplier = growMultiplier;\r\n        if (capacity > 0) {\r\n            this._capacity = capacity;\r\n            this._freeSize = capacity;\r\n            const block = this._obtain(0, capacity, true);\r\n            this._headAll = block;\r\n            this._tailAll = block;\r\n            this._addToBucket(block);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Total address space capacity.\r\n     */\r\n    public get capacity(): number {\r\n        return this._capacity;\r\n    }\r\n\r\n    /**\r\n     * Total size of all allocated blocks.\r\n     */\r\n    public get usedSize(): number {\r\n        return this._usedSize;\r\n    }\r\n\r\n    /**\r\n     * Total size of all free regions.\r\n     */\r\n    public get freeSize(): number {\r\n        return this._freeSize;\r\n    }\r\n\r\n    /**\r\n     * Fragmentation ratio in the range [0, 1]. Returns 0 when all free space is one contiguous block\r\n     * (ideal), and approaches 1 when free space is split into many pieces. Computed O(1).\r\n     */\r\n    public get fragmentation(): number {\r\n        return this._freeSize > 0 ? 1 - 1 / this._freeRegionCount : 0;\r\n    }\r\n\r\n    /**\r\n     * Allocates a contiguous block of the given size.\r\n     * @param size the number of units to allocate (must be \\> 0)\r\n     * @returns a block handle, or null if no space is available\r\n     */\r\n    public allocate(size: number): Nullable<GaussianSplattingMemBlock> {\r\n        if (size <= 0) {\r\n            return null;\r\n        }\r\n\r\n        const gap = this._findFreeBlock(size);\r\n        if (!gap) {\r\n            return null;\r\n        }\r\n\r\n        this._usedSize += size;\r\n        this._freeSize -= size;\r\n\r\n        if (gap._size === size) {\r\n            // Perfect fit: convert free block to allocated.\r\n            gap._free = false;\r\n            this._removeFromBucket(gap);\r\n            return gap;\r\n        }\r\n\r\n        // Split: create allocated block at start of gap, shrink gap.\r\n        const alloc = this._obtain(gap._offset, size, false);\r\n        gap._offset += size;\r\n        gap._size -= size;\r\n        this._rebucket(gap);\r\n        this._insertAfterInMainList(alloc, gap._prev);\r\n        return alloc;\r\n    }\r\n\r\n    /**\r\n     * Frees a previously allocated block. Adjacent free regions are merged automatically.\r\n     * @param block the block to free (must have been returned by {@link allocate})\r\n     */\r\n    public free(block: GaussianSplattingMemBlock): void {\r\n        if (!block || block._free) {\r\n            return;\r\n        }\r\n\r\n        block._free = true;\r\n        this._usedSize -= block._size;\r\n        this._freeSize += block._size;\r\n\r\n        const prev = block._prev;\r\n        const next = block._next;\r\n        const prevFree = prev && prev._free;\r\n        const nextFree = next && next._free;\r\n\r\n        if (prevFree && nextFree) {\r\n            // Both neighbors free: merge all three into prev.\r\n            prev._size += block._size + next._size;\r\n            this._removeFromMainList(block);\r\n            this._removeFromMainList(next);\r\n            this._removeFromBucket(next);\r\n            this._release(block);\r\n            this._release(next);\r\n            this._rebucket(prev);\r\n        } else if (prevFree) {\r\n            // Left neighbor free: merge into prev.\r\n            prev._size += block._size;\r\n            this._removeFromMainList(block);\r\n            this._release(block);\r\n            this._rebucket(prev);\r\n        } else if (nextFree) {\r\n            // Right neighbor free: absorb right into block.\r\n            block._size += next._size;\r\n            this._removeFromMainList(next);\r\n            this._removeFromBucket(next);\r\n            this._release(next);\r\n            this._addToBucket(block);\r\n        } else {\r\n            // Neither neighbor free: insert into bucket.\r\n            this._addToBucket(block);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Grows the address space. Only increases capacity, never decreases.\r\n     * @param newCapacity the new capacity (must be \\> current capacity)\r\n     */\r\n    public grow(newCapacity: number): void {\r\n        if (newCapacity <= this._capacity) {\r\n            return;\r\n        }\r\n\r\n        const added = newCapacity - this._capacity;\r\n        this._capacity = newCapacity;\r\n        this._freeSize += added;\r\n\r\n        if (this._tailAll && this._tailAll._free) {\r\n            // Extend existing tail free block.\r\n            this._tailAll._size += added;\r\n            this._rebucket(this._tailAll);\r\n        } else {\r\n            // Append new free block.\r\n            const block = this._obtain(this._capacity - added, added, true);\r\n            this._insertAfterInMainList(block, this._tailAll);\r\n            this._addToBucket(block);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Defragments the allocator by moving allocated blocks to reduce fragmentation.\r\n     *\r\n     * When maxMoves is 0, performs a full compaction in a single O(n) pass: all allocated blocks are packed\r\n     * contiguously from offset 0 and a single free block is placed at the end. When maxMoves \\> 0, performs\r\n     * incremental defragmentation (relocate the last block into the first fitting gap, then slide blocks left).\r\n     *\r\n     * Moved blocks have their {@link GaussianSplattingMemBlock.offset} updated in place (handles stay valid),\r\n     * so callers must relocate the corresponding GPU data for every block in the returned set.\r\n     * @param maxMoves maximum number of block moves (0 = full compaction, the default)\r\n     * @param result optional set to receive the moved blocks (defaults to a new set)\r\n     * @returns the set of blocks that were moved\r\n     */\r\n    public defrag(maxMoves = 0, result: Set<GaussianSplattingMemBlock> = new Set()): Set<GaussianSplattingMemBlock> {\r\n        result.clear();\r\n\r\n        if (this._freeRegionCount === 0) {\r\n            return result;\r\n        }\r\n\r\n        if (maxMoves === 0) {\r\n            this._defragFull(result);\r\n        } else {\r\n            this._defragIncremental(maxMoves, result);\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * Batch update: frees a set of blocks and allocates new ones. Handles growth and compaction internally\r\n     * when allocations cannot be satisfied. The `toAllocate` array is modified in place: each numeric size\r\n     * entry is replaced with the allocated block.\r\n     * @param toFree blocks to release\r\n     * @param toAllocate sizes to allocate; modified in place (numbers are replaced with block handles)\r\n     * @returns true if a full defrag was performed (all existing blocks have new offsets and must be re-rendered)\r\n     */\r\n    public updateAllocation(toFree: GaussianSplattingMemBlock[], toAllocate: Array<number | GaussianSplattingMemBlock>): boolean {\r\n        // Phase 1: free old blocks.\r\n        for (let i = 0; i < toFree.length; i++) {\r\n            this.free(toFree[i]);\r\n        }\r\n\r\n        // Phase 2: try to allocate all new blocks.\r\n        for (let i = 0; i < toAllocate.length; i++) {\r\n            const size = toAllocate[i] as number;\r\n            const block = this.allocate(size);\r\n            if (block) {\r\n                toAllocate[i] = block;\r\n            } else {\r\n                // Allocation failed at index i; entries [0..i-1] are blocks, [i..n-1] are still numbers.\r\n                let totalRemaining = size;\r\n                for (let j = i + 1; j < toAllocate.length; j++) {\r\n                    totalRemaining += toAllocate[j] as number;\r\n                }\r\n\r\n                // Grow if the free space would be below the headroom threshold.\r\n                const neededCapacity = this._usedSize + totalRemaining;\r\n                const headroomCapacity = Math.ceil(neededCapacity * this._growMultiplier);\r\n                if (headroomCapacity > this._capacity) {\r\n                    this.grow(headroomCapacity);\r\n                }\r\n\r\n                // Full defrag: compact everything, then allocate the remainder (guaranteed to succeed).\r\n                this.defrag(0);\r\n                for (let j = i; j < toAllocate.length; j++) {\r\n                    toAllocate[j] = this.allocate(toAllocate[j] as number)!;\r\n                }\r\n\r\n                return true;\r\n            }\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Computes the bucket index for a given block size (= floor(log2(size))).\r\n     * @param size block size (must be \\> 0)\r\n     * @returns the bucket index\r\n     */\r\n    private _bucketFor(size: number): number {\r\n        return 31 - Math.clz32(size);\r\n    }\r\n\r\n    private _addToBucket(block: GaussianSplattingMemBlock): void {\r\n        const b = this._bucketFor(block._size);\r\n        block._bucket = b;\r\n        while (b >= this._freeBucketHeads.length) {\r\n            this._freeBucketHeads.push(null);\r\n        }\r\n        block._prevFree = null;\r\n        block._nextFree = this._freeBucketHeads[b];\r\n        if (this._freeBucketHeads[b]) {\r\n            this._freeBucketHeads[b]!._prevFree = block;\r\n        }\r\n        this._freeBucketHeads[b] = block;\r\n        this._freeRegionCount++;\r\n    }\r\n\r\n    private _removeFromBucket(block: GaussianSplattingMemBlock): void {\r\n        const b = block._bucket;\r\n        if (block._prevFree) {\r\n            block._prevFree._nextFree = block._nextFree;\r\n        } else {\r\n            this._freeBucketHeads[b] = block._nextFree;\r\n        }\r\n        if (block._nextFree) {\r\n            block._nextFree._prevFree = block._prevFree;\r\n        }\r\n        block._prevFree = null;\r\n        block._nextFree = null;\r\n        block._bucket = -1;\r\n        this._freeRegionCount--;\r\n    }\r\n\r\n    private _rebucket(block: GaussianSplattingMemBlock): void {\r\n        const newBucket = this._bucketFor(block._size);\r\n        if (newBucket !== block._bucket) {\r\n            this._removeFromBucket(block);\r\n            this._addToBucket(block);\r\n        }\r\n    }\r\n\r\n    private _obtain(offset: number, size: number, free: boolean): GaussianSplattingMemBlock {\r\n        const block = this._pool.length > 0 ? this._pool.pop()! : new GaussianSplattingMemBlock();\r\n        block._offset = offset;\r\n        block._size = size;\r\n        block._free = free;\r\n        block._prev = null;\r\n        block._next = null;\r\n        block._prevFree = null;\r\n        block._nextFree = null;\r\n        block._bucket = -1;\r\n        return block;\r\n    }\r\n\r\n    private _release(block: GaussianSplattingMemBlock): void {\r\n        block._prev = null;\r\n        block._next = null;\r\n        block._prevFree = null;\r\n        block._nextFree = null;\r\n        block._bucket = -1;\r\n        this._pool.push(block);\r\n    }\r\n\r\n    private _insertAfterInMainList(block: GaussianSplattingMemBlock, after: Nullable<GaussianSplattingMemBlock>): void {\r\n        if (after === null) {\r\n            block._prev = null;\r\n            block._next = this._headAll;\r\n            if (this._headAll) {\r\n                this._headAll._prev = block;\r\n            }\r\n            this._headAll = block;\r\n            if (!this._tailAll) {\r\n                this._tailAll = block;\r\n            }\r\n        } else {\r\n            block._prev = after;\r\n            block._next = after._next;\r\n            if (after._next) {\r\n                after._next._prev = block;\r\n            }\r\n            after._next = block;\r\n            if (this._tailAll === after) {\r\n                this._tailAll = block;\r\n            }\r\n        }\r\n    }\r\n\r\n    private _removeFromMainList(block: GaussianSplattingMemBlock): void {\r\n        if (block._prev) {\r\n            block._prev._next = block._next;\r\n        } else {\r\n            this._headAll = block._next;\r\n        }\r\n        if (block._next) {\r\n            block._next._prev = block._prev;\r\n        } else {\r\n            this._tailAll = block._prev;\r\n        }\r\n        block._prev = null;\r\n        block._next = null;\r\n    }\r\n\r\n    private _findFreeBlock(size: number): Nullable<GaussianSplattingMemBlock> {\r\n        const startBucket = this._bucketFor(size);\r\n        const len = this._freeBucketHeads.length;\r\n\r\n        // Target bucket: best-fit (smallest block >= size).\r\n        if (startBucket < len) {\r\n            let best: Nullable<GaussianSplattingMemBlock> = null;\r\n            let node = this._freeBucketHeads[startBucket];\r\n            while (node) {\r\n                if (node._size >= size) {\r\n                    if (!best || node._size < best._size) {\r\n                        best = node;\r\n                        if (node._size === size) {\r\n                            break;\r\n                        }\r\n                    }\r\n                }\r\n                node = node._nextFree;\r\n            }\r\n            if (best) {\r\n                return best;\r\n            }\r\n        }\r\n\r\n        // Higher buckets: first-fit (any block is large enough).\r\n        for (let b = startBucket + 1; b < len; b++) {\r\n            if (this._freeBucketHeads[b]) {\r\n                return this._freeBucketHeads[b];\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n    private _defragFull(result: Set<GaussianSplattingMemBlock>): void {\r\n        // Remove all free blocks from all buckets and pool them.\r\n        for (let b = 0; b < this._freeBucketHeads.length; b++) {\r\n            let node = this._freeBucketHeads[b];\r\n            while (node) {\r\n                const nextFree = node._nextFree;\r\n                this._removeFromMainList(node);\r\n                node._prevFree = null;\r\n                node._nextFree = null;\r\n                node._bucket = -1;\r\n                this._pool.push(node);\r\n                node = nextFree;\r\n            }\r\n            this._freeBucketHeads[b] = null;\r\n        }\r\n        this._freeRegionCount = 0;\r\n\r\n        // Walk remaining (all allocated) blocks, assigning sequential offsets.\r\n        let offset = 0;\r\n        let block = this._headAll;\r\n        while (block) {\r\n            if (block._offset !== offset) {\r\n                block._offset = offset;\r\n                result.add(block);\r\n            }\r\n            offset += block._size;\r\n            block = block._next;\r\n        }\r\n\r\n        // Create a single free block at the end if there is remaining capacity.\r\n        const remaining = this._capacity - offset;\r\n        if (remaining > 0) {\r\n            const freeBlock = this._obtain(offset, remaining, true);\r\n            this._insertAfterInMainList(freeBlock, this._tailAll);\r\n            this._addToBucket(freeBlock);\r\n        }\r\n    }\r\n\r\n    private _defragIncremental(maxMoves: number, result: Set<GaussianSplattingMemBlock>): void {\r\n        const phase1Moves = Math.ceil(maxMoves / 2);\r\n        const phase2Moves = maxMoves - phase1Moves;\r\n\r\n        // Phase 1: relocate the last allocated block to the first fitting gap (maximizes tail free space).\r\n        for (let i = 0; i < phase1Moves; i++) {\r\n            let lastAlloc = this._tailAll;\r\n            while (lastAlloc && lastAlloc._free) {\r\n                lastAlloc = lastAlloc._prev;\r\n            }\r\n            if (!lastAlloc) {\r\n                break;\r\n            }\r\n\r\n            const gap = this._findFreeBlock(lastAlloc._size);\r\n            if (!gap || gap._offset >= lastAlloc._offset) {\r\n                break;\r\n            }\r\n\r\n            this._moveBlock(lastAlloc, gap);\r\n            result.add(lastAlloc);\r\n        }\r\n\r\n        // Phase 2: slide allocated blocks left into adjacent free gaps (cleans up interior fragmentation).\r\n        let block = this._headAll;\r\n        for (let i = 0; i < phase2Moves && block;) {\r\n            const next = block._next;\r\n\r\n            if (block._free && next && !next._free) {\r\n                const allocBlock = next;\r\n                const freeBlock = block;\r\n\r\n                allocBlock._offset = freeBlock._offset;\r\n                freeBlock._offset = allocBlock._offset + allocBlock._size;\r\n\r\n                // Swap in the main list.\r\n                const a = freeBlock._prev;\r\n                const b = allocBlock._next;\r\n\r\n                allocBlock._prev = a;\r\n                allocBlock._next = freeBlock;\r\n                freeBlock._prev = allocBlock;\r\n                freeBlock._next = b;\r\n                if (a) {\r\n                    a._next = allocBlock;\r\n                } else {\r\n                    this._headAll = allocBlock;\r\n                }\r\n                if (b) {\r\n                    b._prev = freeBlock;\r\n                } else {\r\n                    this._tailAll = freeBlock;\r\n                }\r\n\r\n                // Merge the free block with its new right neighbor if also free.\r\n                if (freeBlock._next && freeBlock._next._free) {\r\n                    const right = freeBlock._next;\r\n                    freeBlock._size += right._size;\r\n                    this._removeFromMainList(right);\r\n                    this._removeFromBucket(right);\r\n                    this._release(right);\r\n                    this._rebucket(freeBlock);\r\n                }\r\n\r\n                result.add(allocBlock);\r\n                i++;\r\n\r\n                // Continue from the block after freeBlock to find more opportunities.\r\n                block = freeBlock._next;\r\n            } else {\r\n                block = next;\r\n            }\r\n        }\r\n    }\r\n\r\n    private _moveBlock(block: GaussianSplattingMemBlock, gap: GaussianSplattingMemBlock): void {\r\n        const blockSize = block._size;\r\n        const newOffset = gap._offset;\r\n\r\n        // 1. Remove the block from its current position, freeing that space.\r\n        const prev = block._prev;\r\n        this._removeFromMainList(block);\r\n\r\n        // Create a free region where the block was.\r\n        const freed = this._obtain(block._offset, blockSize, true);\r\n        this._insertAfterInMainList(freed, prev);\r\n        this._addToBucket(freed);\r\n\r\n        // Merge freed with its right neighbor.\r\n        if (freed._next && freed._next._free) {\r\n            const right = freed._next;\r\n            freed._size += right._size;\r\n            this._removeFromMainList(right);\r\n            this._removeFromBucket(right);\r\n            this._release(right);\r\n            this._rebucket(freed);\r\n        }\r\n        // Merge freed with its left neighbor.\r\n        if (freed._prev && freed._prev._free) {\r\n            const left = freed._prev;\r\n            left._size += freed._size;\r\n            this._removeFromMainList(freed);\r\n            this._removeFromBucket(freed);\r\n            this._release(freed);\r\n            this._rebucket(left);\r\n        }\r\n\r\n        // 2. Place the block at the gap.\r\n        block._offset = newOffset;\r\n\r\n        if (gap._size === blockSize) {\r\n            // Perfect fit: replace the gap with the block.\r\n            const gapPrev = gap._prev;\r\n            this._removeFromMainList(gap);\r\n            this._removeFromBucket(gap);\r\n            this._release(gap);\r\n            this._insertAfterInMainList(block, gapPrev);\r\n        } else {\r\n            // Partial fit: shrink the gap, insert the block before it.\r\n            gap._offset += blockSize;\r\n            gap._size -= blockSize;\r\n            this._rebucket(gap);\r\n            this._insertAfterInMainList(block, gap._prev);\r\n        }\r\n    }\r\n}\r\n","import { type Nullable } from \"core/types\";\r\nimport { GaussianSplattingBlockAllocator, type GaussianSplattingMemBlock } from \"./gaussianSplattingBlockAllocator\";\r\n\r\n/**\r\n * One resident block relocation produced by {@link GaussianSplattingResidencyController.compact}: the file's\r\n * splat data must be moved from `oldOffset` to `newOffset` (`count` splats) in the work buffer.\r\n */\r\nexport interface IResidencyMove {\r\n    /** File index whose splat data must move. */\r\n    file: number;\r\n    /** The file's previous splat offset in the work buffer. */\r\n    oldOffset: number;\r\n    /** The file's new splat offset after compaction. */\r\n    newOffset: number;\r\n    /** Number of splats in the file. */\r\n    count: number;\r\n}\r\n\r\n/**\r\n * Tracks which streamed Gaussian Splatting files are resident in the GPU work buffer and where, evicting\r\n * unreferenced files after a cooldown to keep the resident set within a fixed budget.\r\n *\r\n * Built on {@link GaussianSplattingBlockAllocator}: each resident file owns a contiguous block of the work\r\n * buffer's splat-index address space. A file with no remaining references is scheduled for eviction; after\r\n * `cooldownFrames` ticks (or sooner, if the space is needed by a new allocation — \"evict-to-fit\") its block\r\n * is freed and reused. Pinned files (e.g. the always-rendered environment and the padding splat) are never\r\n * evicted. The {@link onEvict} callback fires for every file the controller evicts so the owner can drop its\r\n * own bookkeeping (e.g. mark it no longer decoded).\r\n *\r\n * This controller owns only memory/residency bookkeeping — it has no knowledge of the scene, GPU, downloads,\r\n * or reference counting (the caller decides when a file's reference count reaches zero and calls\r\n * {@link scheduleEviction}).\r\n * @experimental\r\n */\r\nexport class GaussianSplattingResidencyController {\r\n    private readonly _allocator: GaussianSplattingBlockAllocator;\r\n    private readonly _blocks = new Map<number, GaussianSplattingMemBlock>();\r\n    // file -> frames remaining before eviction (only present for unreferenced, evictable files).\r\n    private readonly _cooldown = new Map<number, number>();\r\n    private readonly _pinned = new Set<number>();\r\n    private readonly _cooldownFrames: number;\r\n    private readonly _onEvict: (file: number) => void;\r\n\r\n    /**\r\n     * Creates a residency controller.\r\n     * @param capacity total splat-index capacity of the work buffer\r\n     * @param cooldownFrames number of ticks an unreferenced file stays resident before being evicted\r\n     * @param onEvict called with the file index whenever the controller evicts a file (via tick or evict-to-fit)\r\n     */\r\n    public constructor(capacity: number, cooldownFrames: number, onEvict: (file: number) => void) {\r\n        this._allocator = new GaussianSplattingBlockAllocator(capacity);\r\n        this._cooldownFrames = Math.max(0, cooldownFrames);\r\n        this._onEvict = onEvict;\r\n    }\r\n\r\n    /**\r\n     * Total splat-index capacity.\r\n     */\r\n    public get capacity(): number {\r\n        return this._allocator.capacity;\r\n    }\r\n\r\n    /**\r\n     * Number of files currently resident.\r\n     */\r\n    public get residentCount(): number {\r\n        return this._blocks.size;\r\n    }\r\n\r\n    /**\r\n     * Total free splat capacity (sum of all gaps, which may be fragmented). After {@link compact} an\r\n     * allocation of up to this size is guaranteed to fit.\r\n     */\r\n    public get freeSize(): number {\r\n        return this._allocator.freeSize;\r\n    }\r\n\r\n    /**\r\n     * Whether the given file currently has a block in the work buffer.\r\n     * @param file file index\r\n     * @returns true if resident\r\n     */\r\n    public has(file: number): boolean {\r\n        return this._blocks.has(file);\r\n    }\r\n\r\n    /**\r\n     * The work-buffer splat offset of a resident file, or undefined if not resident.\r\n     * @param file file index\r\n     * @returns the splat offset, or undefined\r\n     */\r\n    public offset(file: number): number | undefined {\r\n        return this._blocks.get(file)?.offset;\r\n    }\r\n\r\n    /**\r\n     * Allocates a contiguous block for a file about to be decoded. If there is no room, evicts files whose\r\n     * eviction cooldown is pending (they are unreferenced) and retries once. Returns the splat offset, or null\r\n     * if it still does not fit (the caller should refuse the decode and keep the node's current LOD).\r\n     * @param file file index\r\n     * @param count number of splats the file needs\r\n     * @returns the allocated splat offset, or null if it cannot fit\r\n     */\r\n    public allocate(file: number, count: number): Nullable<number> {\r\n        const existing = this._blocks.get(file);\r\n        if (existing) {\r\n            return existing.offset;\r\n        }\r\n        let block = this._allocator.allocate(count);\r\n        if (!block) {\r\n            // Evict-to-fit: reclaim every unreferenced (cooldown-scheduled) file, then retry once.\r\n            this._evictAllCooled();\r\n            block = this._allocator.allocate(count);\r\n            if (!block) {\r\n                return null;\r\n            }\r\n        }\r\n        this._blocks.set(file, block);\r\n        return block.offset;\r\n    }\r\n\r\n    /**\r\n     * Allocates a block for a file that must never be evicted (e.g. the environment or padding splat).\r\n     * @param file file index (use a sentinel that cannot collide with real file indices)\r\n     * @param count number of splats\r\n     * @returns the allocated splat offset, or null if it cannot fit\r\n     */\r\n    public pin(file: number, count: number): Nullable<number> {\r\n        const offset = this.allocate(file, count);\r\n        if (offset !== null) {\r\n            this._pinned.add(file);\r\n        }\r\n        return offset;\r\n    }\r\n\r\n    /**\r\n     * Frees a file's block immediately (e.g. when a decode was cancelled before completing). Does not fire\r\n     * {@link onEvict}. No-op for pinned or non-resident files.\r\n     * @param file file index\r\n     */\r\n    public free(file: number): void {\r\n        if (this._pinned.has(file)) {\r\n            return;\r\n        }\r\n        const block = this._blocks.get(file);\r\n        if (!block) {\r\n            return;\r\n        }\r\n        this._allocator.free(block);\r\n        this._blocks.delete(file);\r\n        this._cooldown.delete(file);\r\n    }\r\n\r\n    /**\r\n     * Compacts the resident blocks to defragment free space (capacity is unchanged), returning every block\r\n     * that moved so the caller can relocate the corresponding GPU/CPU splat data. Call when an allocation\r\n     * fails despite sufficient total free space ({@link freeSize}); afterwards that allocation will fit.\r\n     * @returns the relocations to apply (empty when nothing moved)\r\n     */\r\n    public compact(): IResidencyMove[] {\r\n        const before = new Map<number, number>();\r\n        for (const [file, block] of Array.from(this._blocks)) {\r\n            before.set(file, block.offset);\r\n        }\r\n        this._allocator.defrag(0);\r\n        const moves: IResidencyMove[] = [];\r\n        for (const [file, block] of Array.from(this._blocks)) {\r\n            const oldOffset = before.get(file)!;\r\n            if (oldOffset !== block.offset) {\r\n                moves.push({ file, oldOffset, newOffset: block.offset, count: block.size });\r\n            }\r\n        }\r\n        return moves;\r\n    }\r\n\r\n    /**\r\n     * Returns the current resident blocks (file index, splat offset, splat count). Used to relocate GPU/CPU\r\n     * data after {@link compact}.\r\n     * @returns one entry per resident file\r\n     */\r\n    public getResidentBlocks(): Array<{ file: number; offset: number; count: number }> {\r\n        const result: Array<{ file: number; offset: number; count: number }> = [];\r\n        for (const [file, block] of Array.from(this._blocks)) {\r\n            result.push({ file, offset: block.offset, count: block.size });\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * Schedules an unreferenced resident file for eviction after the cooldown. No-op for pinned or\r\n     * non-resident files.\r\n     * @param file file index\r\n     */\r\n    public scheduleEviction(file: number): void {\r\n        if (this._pinned.has(file) || !this._blocks.has(file)) {\r\n            return;\r\n        }\r\n        this._cooldown.set(file, this._cooldownFrames);\r\n    }\r\n\r\n    /**\r\n     * Cancels a pending eviction because the file was referenced again.\r\n     * @param file file index\r\n     */\r\n    public cancelEviction(file: number): void {\r\n        this._cooldown.delete(file);\r\n    }\r\n\r\n    /**\r\n     * Advances all eviction cooldowns by one frame, evicting any that expire. Each evicted file fires\r\n     * {@link onEvict}.\r\n     * @returns the file indices evicted this tick\r\n     */\r\n    public tick(): number[] {\r\n        if (this._cooldown.size === 0) {\r\n            return [];\r\n        }\r\n        const evicted: number[] = [];\r\n        for (const [file, frames] of Array.from(this._cooldown)) {\r\n            if (frames <= 1) {\r\n                evicted.push(file);\r\n            } else {\r\n                this._cooldown.set(file, frames - 1);\r\n            }\r\n        }\r\n        for (const file of evicted) {\r\n            this._evict(file);\r\n        }\r\n        return evicted;\r\n    }\r\n\r\n    /**\r\n     * Releases all bookkeeping. The allocator and maps are cleared.\r\n     */\r\n    public dispose(): void {\r\n        this._blocks.clear();\r\n        this._cooldown.clear();\r\n        this._pinned.clear();\r\n    }\r\n\r\n    private _evictAllCooled(): void {\r\n        const files = Array.from(this._cooldown.keys());\r\n        for (const file of files) {\r\n            this._evict(file);\r\n        }\r\n    }\r\n\r\n    private _evict(file: number): void {\r\n        const block = this._blocks.get(file);\r\n        if (block) {\r\n            this._allocator.free(block);\r\n            this._blocks.delete(file);\r\n        }\r\n        this._cooldown.delete(file);\r\n        this._onEvict(file);\r\n    }\r\n}\r\n","import { GaussianSplattingMesh, type IGaussianSplattingStreamingPart, type IGaussianSplattingLodBudgetParticipant } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh\";\r\nimport { type GaussianSplattingPartProxyMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh\";\r\nimport { type IGaussianSplattingSplatRange } from \"core/Meshes/GaussianSplatting/gaussianSplattingMeshBase\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport { Vector3, Matrix, Quaternion } from \"core/Maths/math.vector\";\r\nimport { Color4 } from \"core/Maths/math.color\";\r\nimport { Frustum } from \"core/Maths/math.frustum\";\r\nimport { Plane } from \"core/Maths/math.plane\";\r\nimport { Camera } from \"core/Cameras/camera\";\r\nimport { type Observer } from \"core/Misc/observable\";\r\nimport { BoundingInfo } from \"core/Culling/boundingInfo\";\r\nimport { CreateLineSystem } from \"core/Meshes/Builders/linesBuilder\";\r\nimport { type LinesMesh } from \"core/Meshes/linesMesh\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer\";\r\nimport { ParseSogMetaAsTextures, type SOGRootData } from \"./sog.pure\";\r\nimport { GaussianSplattingWorkBuffer } from \"./gaussianSplattingWorkBuffer\";\r\nimport { GaussianSplattingDownloadManager } from \"./gaussianSplattingDownloadManager\";\r\nimport { GaussianSplattingResidencyController } from \"./gaussianSplattingResidencyController\";\r\nimport { type ISogTexturePack } from \"./splatDefs\";\r\n\r\n/**\r\n * A single LOD variant of a tree node: a contiguous splat range inside one streamed SOG file.\r\n */\r\ninterface ISOGLODEntry {\r\n    /** Index into {@link ISOGLODMetadata.filenames}. */\r\n    file: number;\r\n    /** First splat index inside that file. */\r\n    offset: number;\r\n    /** Number of splats. */\r\n    count: number;\r\n}\r\n\r\n/**\r\n * A node of the PlayCanvas-style SOG LOD octree. Internal nodes have `children`; leaves have `lods`.\r\n */\r\ninterface ISOGLODNode {\r\n    bound: { min: number[]; max: number[] };\r\n    children?: ISOGLODNode[];\r\n    lods?: { [level: string]: ISOGLODEntry };\r\n    /** LOD level currently streamed/rendered for this node, or undefined until its base LOD is ready. */\r\n    activeLod?: number;\r\n    /** Distance-based ideal LOD level for this node, recomputed per frame. */\r\n    optimalLod?: number;\r\n    /** Projected screen size (pixels) of the node's AABB — the max across active cameras. Larger nodes keep finer\r\n     * detail under the splat budget. Only computed while the budget is enabled. */\r\n    pixelSize?: number;\r\n    /** Available LOD levels for this leaf, sorted ascending (0 = finest). Set during the tree walk. */\r\n    availableLevels?: number[];\r\n    /** Coarsest available level (= max key), always streamed as the permanent base layer. */\r\n    baseLod?: number;\r\n    /** Final LOD level the node should stream/render (distance optimal, capped by maxDetailLod). */\r\n    targetLevel?: number;\r\n    /** Frames remaining before this node may switch LOD again (oscillation damping). */\r\n    lodCooldown?: number;\r\n    /** True when the node's bounding box currently intersects the camera frustum. Drives the LOD bias that\r\n     * pushes off-screen nodes to the coarsest level (they stay rendered, not hidden). */\r\n    inFrustum?: boolean;\r\n    /** Cached local-space bounding info used for the per-node frustum test (created once per leaf). */\r\n    cullBounds?: BoundingInfo;\r\n    /** File index this node currently has an in-flight/queued decode request for (its not-yet-decoded target),\r\n     * or undefined when the node's target is already decoded. Drives pending-download reference counting. */\r\n    pendingFile?: number;\r\n    /** File index this node's current {@link activeLod} renders from, or undefined before any LOD is active.\r\n     * Drives the resident reference count that keeps a file in the work buffer. */\r\n    activeFile?: number;\r\n}\r\n\r\n/**\r\n * Parsed contents of a PlayCanvas-style `lod-meta.json` file.\r\n */\r\nexport interface ISOGLODMetadata {\r\n    /** Number of LOD levels (0 = highest detail). */\r\n    lodLevels: number;\r\n    /** SOG `meta.json` paths, relative to the metadata file, indexed by `ISOGLODEntry.file`. */\r\n    filenames: string[];\r\n    /** Optional always-on environment `.sog` bundle, relative to the metadata file. */\r\n    environment?: string;\r\n    /** Root of the LOD octree. */\r\n    tree: ISOGLODNode;\r\n}\r\n\r\n/**\r\n * Selects which LOD value drives the {@link GaussianSplattingStream} debug wireframe colors.\r\n */\r\nexport type GaussianSplattingStreamDebugLodSource = \"optimal\" | \"current\";\r\n\r\n/**\r\n * Immutable metadata-resolution state for a stream's total number of finest-LOD splats.\r\n * @experimental\r\n */\r\nexport type GaussianSplattingStreamLod0SplatCount = Readonly<{ status: \"pending\" }> | Readonly<{ status: \"available\"; count: number }> | Readonly<{ status: \"unavailable\" }>;\r\n\r\n/**\r\n * Options for {@link GaussianSplattingStream}.\r\n */\r\nexport interface IGaussianSplattingStreamOptions {\r\n    /** URL of the fflate UMD module used to unzip `.sog` environment bundles. */\r\n    deflateURL?: string;\r\n    /** Pre-loaded fflate module. */\r\n    fflate?: any;\r\n    /** When true, renders a wireframe box per LOD node, colored by the node's LOD level. */\r\n    debugDisplay?: boolean;\r\n    /** Which LOD value drives the debug wireframe colors. Defaults to `\"optimal\"`. */\r\n    debugLodSource?: GaussianSplattingStreamDebugLodSource;\r\n    /** Distance (in local units) of the first LOD transition. PlayCanvas default `5`. */\r\n    lodBaseDistance?: number;\r\n    /** Geometric ratio between successive LOD transition distances. PlayCanvas default `3`. */\r\n    lodMultiplier?: number;\r\n    /** Distance multiplier applied to nodes behind the camera (`1` = no penalty). PlayCanvas default `1`. */\r\n    lodBehindPenalty?: number;\r\n    /** Lowest LOD index the optimal-LOD heuristic may select. Defaults to `0`. */\r\n    lodRangeMin?: number;\r\n    /** Highest LOD index the optimal-LOD heuristic may select. Defaults to `lodLevels - 1`. */\r\n    lodRangeMax?: number;\r\n    /** Maximum number of LOD source files to GPU-decode per frame (spreads work to avoid hitches). Defaults to `1`. */\r\n    maxDecodesPerFrame?: number;\r\n    /** Frames a node must wait after switching LOD before it may switch again (oscillation damping). Defaults to `10`. */\r\n    lodCooldownFrames?: number;\r\n    /** Minimum number of frames between LOD re-evaluations (throttles per-frame work during motion). Defaults to `4`. */\r\n    lodUpdateInterval?: number;\r\n    /** Minimum camera movement (world units) required to re-evaluate LODs. Defaults to `0.5`. */\r\n    lodUpdateDistance?: number;\r\n    /**\r\n     * Finest (most detailed) LOD level any node is allowed to render. `0` allows full detail (level 0);\r\n     * `1` caps detail at the next-coarser level, and so on. Higher values force a coarser maximum detail.\r\n     */\r\n    maxDetailLod?: number;\r\n    /**\r\n     * When true (default), LOD nodes outside the camera frustum are biased to their coarsest LOD rather than\r\n     * rendered at full detail. They stay in the sort/render set so they appear instantly (at low detail) when\r\n     * the camera turns toward them, then refine. Set to `false` to render every node at its distance LOD.\r\n     */\r\n    frustumCulling?: boolean;\r\n    /** Maximum number of LOD file downloads allowed to run concurrently. PlayCanvas default `2`. */\r\n    maxConcurrentDownloads?: number;\r\n    /** Number of times a failed file download is retried before giving up. PlayCanvas default `2`. */\r\n    maxDownloadRetries?: number;\r\n    /**\r\n     * Initial GPU/CPU memory estimate (in megabytes) for resident splats. It is converted to a splat count\r\n     * using the per-splat cost (core data plus any baked SH and rotation/scale textures), combined with\r\n     * {@link maxResidentSplats} by taking the smaller limit, then raised when necessary to fit the complete\r\n     * coarse layer. The work buffer has a fixed lifetime capacity; construct a new stream to use another limit.\r\n     * Finite non-positive values leave this limit unset; non-finite values are rejected.\r\n     */\r\n    memoryBudgetMb?: number;\r\n    /**\r\n     * Initial maximum number of splats kept resident in the fixed-size work buffer. It is raised when necessary\r\n     * to fit the complete coarse layer. When unset and the complete source size is known, streams retain the complete\r\n     * source. Streams that defer finer metadata use a bounded device-tiered default with coarse-derived refinement\r\n     * headroom.\r\n     * Finite non-positive values leave this limit unset; non-finite or unsafe positive counts are rejected.\r\n     * Positive fractional counts are floored to at least one splat before applying the coarse minimum.\r\n     */\r\n    maxResidentSplats?: number;\r\n    /**\r\n     * Frames an unreferenced (no longer rendered) LOD file stays resident before it is evicted, so a quick\r\n     * return to it avoids a re-download. Only used when a budget enables eviction. PlayCanvas default `100`.\r\n     */\r\n    evictionCooldownFrames?: number;\r\n    /**\r\n     * Enables budget-driven LOD: caps the total rendered splats by converging a screen-space (size + distance)\r\n     * pixel-size threshold to the budget. Selection is view-direction-independent, so it is consistent across any\r\n     * number of active cameras (each node takes the finest level and largest projected size any camera demands).\r\n     * A number is an explicit splat cap; `\"auto\"` picks a device-tiered default (desktop 2.5M / iOS 1.5M /\r\n     * other mobile 1M; XR shares the mobile tier). **Undefined (default) disables the cap** — LOD is pure\r\n     * distance, identical to prior behavior. Runtime-mutable via the {@link splatBudget} accessor. When this stream\r\n     * is hosted in a compound, the compound's {@link GaussianSplattingMesh.splatBudget} (if set) overrides this and\r\n     * apportions a shared budget across all its streams.\r\n     */\r\n    splatBudget?: number | \"auto\";\r\n    /**\r\n     * When set, the stream does not render itself; instead it reserves a region of this compound mesh and\r\n     * decodes/sorts into it, so its splats are depth-sorted and drawn in ONE pass together with the compound's\r\n     * other (static) parts. Used by {@link AddGaussianSplattingStreamPart}. The stream mesh becomes a hidden\r\n     * controller; the SOG up-axis orientation is applied to the reserved part's proxy transform.\r\n     * @internal\r\n     */\r\n    hostCompound?: GaussianSplattingMesh;\r\n    /**\r\n     * When true, higher-order spherical-harmonics carried by the SOG files (`shN`) are GPU-decoded into baked\r\n     * packed-u32 SH textures so the streamed splats render with view-dependent lighting (matching the non-stream\r\n     * `.spz`/`.sog` path) instead of flat DC-only color. Streams with complete initial metadata use the maximum\r\n     * source SH degree. Streams that defer finer metadata reserve the supported degree-4 layout before it is known,\r\n     * even if the files ultimately carry no `shN`; lower-degree files neutral-fill the unused bands.\r\n     * Defaults to `true`; set to `false` to force flat DC-only color and avoid the SH decode cost/texture memory.\r\n     */\r\n    decodeSh?: boolean;\r\n    /**\r\n     * When true, each splat's rotation matrix + scale are GPU-decoded into half-float rotation/scale textures so the\r\n     * streamed splats participate in voxel-based IBL shadowing (matching the non-stream path). Standalone: the work\r\n     * buffer owns the rotation textures. Hosted: the compound's rotation textures become a shared render-target atlas\r\n     * the stream decodes into. Defaults to `false`.\r\n     */\r\n    needsRotationScale?: boolean;\r\n}\r\n\r\n// tan(22.5deg): reference half-FOV for a 45-degree vertical FOV, used for FOV compensation (matches PlayCanvas).\r\nconst RefTanHalfFov = Math.tan((22.5 * Math.PI) / 180);\r\n\r\n// Sentinel \"file\" ids for the residency controller's pinned (never-evicted) allocations.\r\nconst PaddingFileId = -2;\r\nconst EnvironmentFileId = -1;\r\n// Core bytes per resident splat: the four work-buffer textures cost 16+16+16+4 = 52 bytes on the GPU, plus ~32\r\n// bytes of CPU position/sort data. `_resolveResidentBudget` adds the SH and rotation/scale texture cost on top.\r\nconst BytesPerResidentSplat = 84;\r\nconst MaxSupportedShDegree = 4;\r\nconst MaxSupportedShTextureCount = 5;\r\nconst ProgressiveMetadataFileThreshold = 32;\r\nconst DesktopAutomaticResidentMemoryMb = 512;\r\nconst MobileAutomaticResidentMemoryMb = 256;\r\n\r\n// Scratch objects reused by the per-frame optimal-LOD evaluation (avoids per-call allocations).\r\nconst TmpInvWorld = new Matrix();\r\nconst TmpLocalCamera = new Vector3();\r\nconst TmpLocalForward = new Vector3();\r\nconst TmpWorldForward = new Vector3();\r\n// Camera-local forward axis (+Z) used to derive the world-space view direction.\r\nconst LocalForwardAxis = new Vector3(0, 0, 1);\r\n\r\n// The 12 edges of a box, as index pairs into its 8 corners. 12 edges x 2 endpoints = 24 vertices per box.\r\nconst BoxEdges = [\r\n    [0, 1],\r\n    [1, 2],\r\n    [2, 3],\r\n    [3, 0],\r\n    [4, 5],\r\n    [5, 6],\r\n    [6, 7],\r\n    [7, 4],\r\n    [0, 4],\r\n    [1, 5],\r\n    [2, 6],\r\n    [3, 7],\r\n];\r\n// Vertices generated per leaf box (BoxEdges.length * 2).\r\nconst VerticesPerBox = BoxEdges.length * 2;\r\n\r\n/**\r\n * Wireframe colors per LOD level (cycled by `node.activeLod`).\r\n */\r\nconst GsLodDebugColors = [\r\n    new Color4(1.0, 0.2, 0.2, 1.0), // LOD 0 - red\r\n    new Color4(1.0, 0.6, 0.1, 1.0), // LOD 1 - orange\r\n    new Color4(1.0, 1.0, 0.2, 1.0), // LOD 2 - yellow\r\n    new Color4(0.3, 1.0, 0.3, 1.0), // LOD 3 - green\r\n    new Color4(0.2, 1.0, 1.0, 1.0), // LOD 4 - cyan\r\n    new Color4(0.4, 0.5, 1.0, 1.0), // LOD 5 - blue\r\n    new Color4(0.9, 0.4, 1.0, 1.0), // LOD 6 - magenta\r\n    new Color4(1.0, 1.0, 1.0, 1.0), // LOD 7 - white\r\n];\r\n\r\n/**\r\n * Streams a PlayCanvas-style SOG LOD scene (`lod-meta.json`) into a single Gaussian Splatting mesh.\r\n *\r\n * Each selected SOG file (plus the environment) is loaded directly as GPU textures and decoded on the\r\n * GPU into one unified, PlayCanvas-style square work buffer (no CPU splat decode or `updateData`). Only\r\n * the splats of each node's currently-selected LOD are rendered/sorted via the mesh's interval filter.\r\n *\r\n * The coarsest (least-detail) LOD of every node is streamed first as a permanent base layer so the whole\r\n * scene is visible quickly with no holes. A distance-based \"optimal\" LOD is then computed per node (see\r\n * {@link evaluateOptimalLods}); finer LOD source files are streamed on demand and a node only switches to\r\n * a finer LOD once that file is decoded, so transitions never flash or leave gaps.\r\n *\r\n * @experimental\r\n */\r\nexport class GaussianSplattingStream extends GaussianSplattingMesh implements IGaussianSplattingLodBudgetParticipant {\r\n    private readonly _metadata: ISOGLODMetadata;\r\n    private readonly _rootUrl: string;\r\n    private readonly _streamOptions: IGaussianSplattingStreamOptions;\r\n\r\n    // Flat list of leaf nodes that carry renderable LOD entries (used by the LOD heuristic and debug).\r\n    private readonly _leafNodes: ISOGLODNode[] = [];\r\n\r\n    private _lod0SplatCount: GaussianSplattingStreamLod0SplatCount = Object.freeze({ status: \"pending\" as const });\r\n\r\n    // LOD heuristic parameters (PlayCanvas-aligned defaults).\r\n    private _lodBaseDistance = 5;\r\n    private _lodMultiplier = 3;\r\n    private _lodBehindPenalty = 1;\r\n    private _lodRangeMin = 0;\r\n    private _lodRangeMax: number;\r\n    private _maxDecodesPerFrame = 1;\r\n    private _lodCooldownFrames = 10;\r\n    // Minimum frames between LOD re-evaluations, and minimum camera movement (world units) to re-evaluate.\r\n    private _lodUpdateInterval = 4;\r\n    private _lodUpdateDistance = 0.5;\r\n    private _maxDetailLod = 0;\r\n\r\n    // Budget-driven LOD. The stream's own resolved cap lives in the inherited protected `_splatBudget`\r\n    // (0 = disabled; the option's \"auto\" is resolved to a device-tiered default in the constructor). `_lodPixelThreshold`\r\n    // is the converged pixel-size threshold that selects each node's level. `_hostBudgetAllocation` is\r\n    // the compound's apportioned slice when this stream is a coordinated budget participant (null = not coordinated,\r\n    // so the stream uses its own `_splatBudget`).\r\n    private _lodPixelThreshold = 1;\r\n    private _hostBudgetAllocation: Nullable<number> = null;\r\n\r\n    // Frustum LOD bias: when enabled, nodes outside the camera frustum are rendered at their coarsest LOD.\r\n    private _frustumCulling = true;\r\n    // Reused local-space frustum planes and local-to-clip scratch matrix (avoids per-frame allocation).\r\n    private readonly _frustumPlanes: Plane[] = [\r\n        new Plane(0, 0, 0, 0),\r\n        new Plane(0, 0, 0, 0),\r\n        new Plane(0, 0, 0, 0),\r\n        new Plane(0, 0, 0, 0),\r\n        new Plane(0, 0, 0, 0),\r\n        new Plane(0, 0, 0, 0),\r\n    ];\r\n    private readonly _cullCameraViewProj = new Matrix();\r\n    private readonly _cullViewProj = new Matrix();\r\n    // Reused per-leaf \"inside any active camera's frustum\" accumulator for the union frustum test (avoids per-frame allocation).\r\n    private readonly _frustumScratch: boolean[] = [];\r\n\r\n    // GPU work buffer holding all decoded splats; created once the total capacity is known.\r\n    private _workBuffer: Nullable<GaussianSplattingWorkBuffer> = null;\r\n    // Higher-order SH: exact maximum for small streams, supported maximum for progressive metadata.\r\n    // Degree 0 disables baking; progressive streams reserve SH even before source degrees are known.\r\n    private _decodeSh!: boolean;\r\n    private _streamShDegree = 0;\r\n    private _shTextureCount = 0;\r\n    // Rotation/scale for voxel-IBL shadows. Enabled via options.needsRotationScale.\r\n    private _needsRotationScale = false;\r\n    // True once GPU position readback has been validated against a CPU decode (see _probeReadbackAsync). While\r\n    // false, positions are decoded on the CPU from the means images; once validated, every SOG image uses the\r\n    // fast direct upload and positions are read back from the work buffer (non-blocking).\r\n    private _useGpuPositionReadback = false;\r\n    // Whether the engine reports GPU readback support (candidate to validate on the first decode).\r\n    private _readbackCandidate = false;\r\n    // Set once the one-time readback validation has run (success or failure).\r\n    private _readbackProbed = false;\r\n\r\n    // Residency controller: owns the work-buffer slot allocator, per-file blocks, and eviction cooldowns.\r\n    private _residency: Nullable<GaussianSplattingResidencyController> = null;\r\n    // Splat count of each source file (learned from its metadata before allocation).\r\n    private readonly _fileCounts = new Map<number, number>();\r\n    // Cached SOG metadata per file so on-demand decodes don't refetch the meta.json.\r\n    private readonly _fileMeta = new Map<number, { sogData: SOGRootData; subRootUrl: string }>();\r\n    // Unique source files required by the coarsest entry of at least one leaf.\r\n    private readonly _baseFileIds = new Set<number>();\r\n    // Files whose splats have been fully GPU-decoded into the work buffer (render-safe).\r\n    private readonly _decodedFiles = new Set<number>();\r\n    // Files whose decode is currently in flight (dedupes concurrent requests).\r\n    private readonly _loadingFiles = new Set<number>();\r\n    // FIFO of file ids waiting to be decoded (drained under a per-frame budget).\r\n    private readonly _decodeQueue: number[] = [];\r\n    // Per-file reference count: number of leaf nodes whose active LOD renders, or whose pending target points\r\n    // at, each file. At zero, a decoded file is scheduled for eviction and a still-downloading file is cancelled.\r\n    private readonly _fileRefs = new Map<number, number>();\r\n    // Files whose in-flight decode was cancelled; checked at decode checkpoints to bail out cooperatively.\r\n    private readonly _cancelledDecodes = new Set<number>();\r\n    // Eviction is enabled for progressive metadata or capacity below the complete source size.\r\n    private _evictionEnabled = false;\r\n    private _residentBudget = 0;\r\n    // Padding + environment + unique whole coarse source files. Zero until coarse metadata has resolved.\r\n    private _minimumResidentSplats = 0;\r\n    // Raw budget options; the final `_residentBudget` is resolved from these once the SH/rotation byte cost is known\r\n    // (after the metadata pre-pass), so the memory budget accounts for the extra baked SH and rotation textures.\r\n    private _maxResidentSplats = 0;\r\n    private _memoryBudgetMb = 0;\r\n    private _evictionCooldownFrames = 100;\r\n    // Serializes the allocate -> decode -> readback critical section so a defrag relayout (which runs inside it)\r\n    // never overlaps another file's decode writing the work buffer, which would corrupt the moved data.\r\n    private _decodeGate: Promise<void> = Promise.resolve();\r\n    // Reusable scratch for the (rare) defrag relayout, to avoid per-relayout allocations during streaming.\r\n    private readonly _relayoutOldOffsets = new Map<number, number>();\r\n    private _relayoutSrcIndex: Nullable<Float32Array> = null;\r\n\r\n    // Throttles and retries the SOG file/image downloads (PlayCanvas-style download manager).\r\n    private readonly _downloadManager: GaussianSplattingDownloadManager;\r\n\r\n    // Global range covered by the environment file (always rendered), or null until it loads.\r\n    private _environmentRange: Nullable<{ offset: number; count: number }> = null;\r\n    // Unzipped environment bundle contents, retained between count-gathering and decode.\r\n    private _environmentFiles: Nullable<Map<string, Uint8Array>> = null;\r\n\r\n    // Per-frame LOD streaming loop; installed once the base layer is ready.\r\n    private _lodObserver: Nullable<Observer<Scene>> = null;\r\n    private _baseLayerReady = false;\r\n    private _metadataReady = false;\r\n    // Throttling state for the per-frame LOD loop: each active camera's world position at the last LOD evaluation, so\r\n    // a re-eval is gated on the camera set changing or any camera translating past `_lodUpdateDistance`.\r\n    private _framesSinceLodUpdate = 0;\r\n    private readonly _lastLodCamPositions: Vector3[] = [];\r\n    // Signature of the discrete projected-size inputs (per-camera identity/FOV/FOV-mode/viewport + render size) at the\r\n    // last LOD evaluation. Camera translation is tracked separately (above); this catches the rest — a colocated\r\n    // camera swap, a viewport resize, or an FOV change — which would otherwise leave the budget LODs stale.\r\n    private _lastLodSignature = \"\";\r\n    // Forces the next LOD update to run regardless of the throttle (e.g. after a budget change).\r\n    private _forceLodUpdate = false;\r\n\r\n    // Running local-space bounds of all decoded splat centers (for frustum culling / picking).\r\n    private readonly _boundsMin = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);\r\n    private readonly _boundsMax = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);\r\n\r\n    // Debug LOD-node wireframe display.\r\n    private _debugDisplay = false;\r\n    private _debugLodSource: GaussianSplattingStreamDebugLodSource = \"optimal\";\r\n    private _debugMesh: Nullable<LinesMesh> = null;\r\n    private _debugObserver: Nullable<Observer<Scene>> = null;\r\n    // Per-vertex RGBA color buffer mirror, updated in place when LOD colors change (avoids mesh rebuild flicker).\r\n    private _debugColorData: Nullable<Float32Array> = null;\r\n    // Signature of the per-leaf displayed LOD levels, used to skip rebuilding unchanged debug geometry.\r\n    private _debugSignature = 0;\r\n\r\n    private _disposed = false;\r\n\r\n    // Hosted mode: when set, the stream decodes/sorts into a reserved region of a compound mesh instead of\r\n    // rendering itself. `_host` is the reserved-part handle (resolved once the total capacity is known),\r\n    // `_positionBase` is the region's first splat index in the compound's shared position buffer.\r\n    private readonly _hostCompound: Nullable<GaussianSplattingMesh> = null;\r\n    private _host: Nullable<IGaussianSplattingStreamingPart> = null;\r\n    private _positionBase = 0;\r\n    // Unsubscribe functions for the host's atlas-rebuild hooks (backup/restore the region across a grow).\r\n    private _unsubBeforeRebuild: Nullable<() => void> = null;\r\n    private _unsubAfterRebuild: Nullable<() => void> = null;\r\n    // Unsubscribe functions binding this controller's lifetime to its host compound: removing the part or disposing\r\n    // the compound disposes this stream, even mid-load. Registered at reservation so the window is never open.\r\n    private _hostUnsubRemove: Nullable<() => void> = null;\r\n    private _hostUnsubDispose: Nullable<() => void> = null;\r\n    // True once the host has released this stream's part (removePart, or the compound is being disposed), so dispose()\r\n    // must NOT call back into the compound to remove the part again.\r\n    private _partReleasedByHost = false;\r\n    // CPU snapshot of this region's shared `_splatPositions` taken before an atlas grow and restored after it —\r\n    // the grow rebuilds `_splatPositions` from CPU part sources, and a streamed region has none, so without this\r\n    // its sort-worker positions would be zeroed (the streamed splats would collapse to the origin).\r\n    private _positionSnapshot: Nullable<Float32Array> = null;\r\n    // Hosted mode: resolves once the reserved part exists AND its base layer has decoded (proxy bounds are\r\n    // real); rejects if streaming fails/disposes before that. Lets AddGaussianSplattingStreamPartAsync hand\r\n    // back a ready part proxy, replacing the standalone waitForEnabled/waitForStreamedBounds handshake.\r\n    private _partReadyPromise: Nullable<Promise<void>> = null;\r\n    private _partReadyResolve: Nullable<() => void> = null;\r\n    private _partReadyReject: Nullable<(reason: Error) => void> = null;\r\n    private _partReadySettled = false;\r\n\r\n    /**\r\n     * Returns true when the parsed JSON looks like a PlayCanvas-style `lod-meta.json` payload.\r\n     * @param data parsed JSON\r\n     * @returns whether the data is SOG LOD metadata\r\n     */\r\n    public static IsLODMetadata(data: unknown): data is ISOGLODMetadata {\r\n        if (typeof data !== \"object\" || data === null) {\r\n            return false;\r\n        }\r\n        const meta = data as Partial<ISOGLODMetadata>;\r\n        return typeof meta.lodLevels === \"number\" && Array.isArray(meta.filenames) && typeof meta.tree === \"object\" && meta.tree !== null;\r\n    }\r\n\r\n    /**\r\n     * Creates a new SOG LOD streaming mesh and immediately starts streaming (non-blocking).\r\n     * @param name mesh name\r\n     * @param metadata parsed `lod-meta.json`\r\n     * @param rootUrl base URL the metadata's relative paths resolve against\r\n     * @param scene hosting scene\r\n     * @param options streaming options\r\n     */\r\n    constructor(name: string, metadata: ISOGLODMetadata, rootUrl: string, scene: Scene, options: IGaussianSplattingStreamOptions = {}) {\r\n        // Validate before super registers the mesh with the scene, so invalid options leave no partial entity.\r\n        const maxResidentSplats = GaussianSplattingStream._NormalizeResidentLimit(options.maxResidentSplats ?? 0, \"maxResidentSplats\", true);\r\n        const memoryBudgetMb = GaussianSplattingStream._NormalizeResidentLimit(options.memoryBudgetMb ?? 0, \"memoryBudgetMb\", false);\r\n        super(name, null, scene, false);\r\n        this._metadata = metadata;\r\n        this._rootUrl = rootUrl;\r\n        this._streamOptions = options;\r\n        this._hostCompound = options.hostCompound ?? null;\r\n        this._decodeSh = options.decodeSh ?? true;\r\n        this._needsRotationScale = options.needsRotationScale ?? false;\r\n\r\n        // LOD heuristic parameters: take the provided values, otherwise keep the PlayCanvas-aligned defaults.\r\n        const maxLod = Math.max(0, metadata.lodLevels - 1);\r\n        this._lodRangeMax = maxLod;\r\n        if (options.lodBaseDistance !== undefined) {\r\n            this._lodBaseDistance = Math.max(0.1, options.lodBaseDistance);\r\n        }\r\n        if (options.lodMultiplier !== undefined) {\r\n            this._lodMultiplier = Math.max(1.2, options.lodMultiplier);\r\n        }\r\n        if (options.lodBehindPenalty !== undefined) {\r\n            this._lodBehindPenalty = Math.max(1, options.lodBehindPenalty);\r\n        }\r\n        if (options.lodRangeMin !== undefined) {\r\n            this._lodRangeMin = Math.max(0, Math.min(options.lodRangeMin, maxLod));\r\n        }\r\n        if (options.lodRangeMax !== undefined) {\r\n            this._lodRangeMax = Math.max(this._lodRangeMin, Math.min(options.lodRangeMax, maxLod));\r\n        }\r\n        if (options.maxDecodesPerFrame !== undefined) {\r\n            this._maxDecodesPerFrame = Math.max(1, options.maxDecodesPerFrame);\r\n        }\r\n        if (options.lodCooldownFrames !== undefined) {\r\n            this._lodCooldownFrames = Math.max(0, options.lodCooldownFrames);\r\n        }\r\n        if (options.lodUpdateInterval !== undefined) {\r\n            this._lodUpdateInterval = Math.max(1, options.lodUpdateInterval);\r\n        }\r\n        if (options.lodUpdateDistance !== undefined) {\r\n            this._lodUpdateDistance = Math.max(0, options.lodUpdateDistance);\r\n        }\r\n        if (options.maxDetailLod !== undefined) {\r\n            this._maxDetailLod = Math.max(0, Math.floor(options.maxDetailLod));\r\n        }\r\n        this._splatBudget = this._resolveSplatBudget(options.splatBudget);\r\n        if (options.frustumCulling !== undefined) {\r\n            this._frustumCulling = options.frustumCulling;\r\n        }\r\n        if (options.debugLodSource) {\r\n            this._debugLodSource = options.debugLodSource;\r\n        }\r\n        if (options.evictionCooldownFrames !== undefined) {\r\n            this._evictionCooldownFrames = Math.max(0, Math.floor(options.evictionCooldownFrames));\r\n        }\r\n        // Resolve the capacity after coarse metadata and the fixed SH/rotation layout are known.\r\n        this._maxResidentSplats = maxResidentSplats;\r\n        this._memoryBudgetMb = memoryBudgetMb;\r\n\r\n        this._downloadManager = new GaussianSplattingDownloadManager({\r\n            maxConcurrent: options.maxConcurrentDownloads,\r\n            maxRetries: options.maxDownloadRetries,\r\n        });\r\n\r\n        // PlayCanvas SOG data is authored with a flipped Y and Z-up. Standalone: bake the orientation into this\r\n        // mesh's transform. Hosted: this mesh does not render — the orientation is applied to the reserved part's\r\n        // proxy transform instead (see _streamAllAsync), so it composes with the compound's per-part world matrix.\r\n        if (!this._hostCompound) {\r\n            this.scaling.y *= -1;\r\n            this.rotation.x = -Math.PI / 2;\r\n        } else {\r\n            // Hidden controller: never rendered/picked/serialized; the compound renders the streamed splats.\r\n            this.setEnabled(false);\r\n            this.isPickable = false;\r\n            this.doNotSerialize = true;\r\n            // Created before _streamAllAsync is kicked off (below) so there is no resolve-before-await race.\r\n            this._partReadyPromise = new Promise<void>((resolve, reject) => {\r\n                this._partReadyResolve = resolve;\r\n                this._partReadyReject = reject;\r\n            });\r\n            // Attach a no-op rejection handler so a caller that never awaits whenPartReadyAsync() (e.g. the synchronous\r\n            // AddGaussianSplattingStreamPart) does not produce an unhandled promise rejection on failure; real\r\n            // consumers still observe the rejection through their own await.\r\n            // eslint-disable-next-line github/no-then\r\n            this._partReadyPromise.catch(() => {});\r\n            // Bind to the host's disposal FROM CONSTRUCTION (not just from reservation): the metadata pre-pass in\r\n            // _streamAllAsync runs before the region is reserved, so a compound disposed during that download would\r\n            // otherwise be missed and the controller would reserve into a disposed host. dispose() -> _disposed, so\r\n            // _streamAllAsync's post-download check bails before reserving.\r\n            const disposeObserver = this._hostCompound.onDisposeObservable.add(() => {\r\n                if (!this._disposed) {\r\n                    this._partReleasedByHost = true;\r\n                    this.dispose();\r\n                }\r\n            });\r\n            this._hostUnsubDispose = () => this._hostCompound!.onDisposeObservable.remove(disposeObserver);\r\n        }\r\n\r\n        this._collectLodEntries(metadata.tree);\r\n\r\n        if (options.debugDisplay) {\r\n            this.debugDisplay = true;\r\n        }\r\n\r\n        // Kick off streaming without blocking the caller or the render loop. In hosted mode settle the part-ready\r\n        // deferred: _streamAllAsync resolves it once the base layer has decoded. If it finishes WITHOUT the part ever\r\n        // becoming ready (empty stream) or throws, dispose the controller so a hosted stream doesn't leave its work\r\n        // buffer and reserved region allocated — the synchronous AddGaussianSplattingStreamPart never awaits, so it\r\n        // can't clean up itself. Standalone startup failures also dispose their partial resources.\r\n        // `_partReadySettled` distinguishes a genuine success (leave it running) from a\r\n        // finished-but-never-ready result (dispose).\r\n        // eslint-disable-next-line github/no-then\r\n        void this._streamAllAsync().then(\r\n            () => {\r\n                const becameReady = this._partReadySettled;\r\n                this._rejectPartReady(\"GaussianSplattingStream: stream produced no splats.\");\r\n                if (!becameReady && this._hostCompound && !this._disposed) {\r\n                    this._disposeAndReclaim();\r\n                }\r\n            },\r\n            (e) => {\r\n                this._lod0SplatCount = Object.freeze({ status: \"unavailable\" as const });\r\n                Logger.Error(\"GaussianSplattingStream: streaming failed: \" + (e?.message ?? e));\r\n                this._rejectPartReady(\"GaussianSplattingStream: streaming failed: \" + (e?.message ?? e));\r\n                if (!this._disposed) {\r\n                    this._disposeAndReclaim();\r\n                }\r\n            }\r\n        );\r\n    }\r\n\r\n    public override getClassName(): string {\r\n        return \"GaussianSplattingStream\";\r\n    }\r\n\r\n    /**\r\n     * When `_hostCompound` is set (i.e. this stream was created via {@link AddGaussianSplattingStreamPart}\r\n     * to drive a reserved region of another compound mesh, rather than rendering itself), this instance is\r\n     * disabled and never drawn — so it never runs its own depth-sort worker and the base class's readiness\r\n     * check (which waits for one) would never pass. Report ready unconditionally in that case; the host\r\n     * compound is the one actually rendering, and its own `isReady()` already covers real sort completion.\r\n     * @param completeCheck defines if a complete check (including materials and lights) has to be done (false by default)\r\n     * @returns true when ready\r\n     */\r\n    public override isReady(completeCheck = false): boolean {\r\n        if (this._hostCompound) {\r\n            return true;\r\n        }\r\n        return super.isReady(completeCheck);\r\n    }\r\n\r\n    /**\r\n     * Hosted mode only: the compound part proxy this stream drives (world transform + visibility of the\r\n     * reserved region), or null before the part has been reserved (or when running standalone).\r\n     */\r\n    public get streamingPartProxy(): Nullable<GaussianSplattingPartProxyMesh> {\r\n        return this._host?.proxy ?? null;\r\n    }\r\n\r\n    /**\r\n     * Hosted mode only: resolves once the reserved part exists and its base layer has decoded (so the proxy's\r\n     * bounds are real and the part is ready to be placed/framed), or rejects if streaming fails/disposes first.\r\n     * Resolves immediately for a standalone stream. Used by {@link AddGaussianSplattingStreamPartAsync}.\r\n     * @returns a promise that settles when the hosted part is ready to use\r\n     */\r\n    public async whenPartReadyAsync(): Promise<void> {\r\n        await (this._partReadyPromise ?? Promise.resolve());\r\n    }\r\n\r\n    /** Resolves the part-ready deferred (hosted mode); no-op if already settled or standalone. */\r\n    private _resolvePartReady(): void {\r\n        if (this._partReadySettled) {\r\n            return;\r\n        }\r\n        this._partReadySettled = true;\r\n        this._partReadyResolve?.();\r\n    }\r\n\r\n    /**\r\n     * Rejects the part-ready deferred (hosted mode); no-op if already settled or standalone.\r\n     * @param message failure reason surfaced to the awaiter\r\n     */\r\n    private _rejectPartReady(message: string): void {\r\n        if (this._partReadySettled) {\r\n            return;\r\n        }\r\n        this._partReadySettled = true;\r\n        this._partReadyReject?.(new Error(message));\r\n    }\r\n\r\n    /**\r\n     * Resolves once the scene is fully streamed and displayed for the current camera: a LOD re-evaluation has\r\n     * run for the current point of view, every reachable LOD file has finished downloading and decoding (no\r\n     * downloads, decodes, or queued work remain), and the depth sort for the resulting splats has been applied\r\n     * and rendered. Intended for deterministic automated testing and screenshot/image comparison.\r\n     *\r\n     * Streaming and settling require rendered frames. If an external render loop is already running, this waits\r\n     * on it passively; otherwise (e.g. when awaited inside an async `createScene` before the host starts its\r\n     * render loop) it drives `scene.render()` itself until settled, so it never deadlocks.\r\n     *\r\n     * Note: the promise only resolves while the camera is still — if the camera keeps moving, the target LODs\r\n     * (and the depth sort) keep changing and the stream never settles. Position the camera, then await this.\r\n     * @param stableFrames number of consecutive settled frames to require before resolving (defaults to 3), so\r\n     *   the final sorted frame is actually on screen\r\n     * @returns a promise that resolves when loading and rendering are complete for the current view\r\n     */\r\n    public async whenSettledAsync(stableFrames = 3): Promise<void> {\r\n        if (this._disposed) {\r\n            return;\r\n        }\r\n        // Re-evaluate LODs immediately so the target levels reflect the current camera before we wait.\r\n        this._forceLodUpdate = true;\r\n        const required = Math.max(1, stableFrames);\r\n        const scene = this._scene;\r\n        let stable = 0;\r\n        const isSettled = (): boolean => {\r\n            if (this._isLoadingIdle() && this._sinkIsDepthSortSettled) {\r\n                return ++stable >= required;\r\n            }\r\n            stable = 0;\r\n            return false;\r\n        };\r\n\r\n        // An external render loop is already driving frames: observe it passively.\r\n        if (scene.getEngine().activeRenderLoops.length > 0) {\r\n            await new Promise<void>((resolve) => {\r\n                let observer: Nullable<Observer<Scene>> = null;\r\n                observer = scene.onAfterRenderObservable.add(() => {\r\n                    if (this._disposed || isSettled()) {\r\n                        if (observer) {\r\n                            scene.onAfterRenderObservable.remove(observer);\r\n                            observer = null;\r\n                        }\r\n                        resolve();\r\n                    }\r\n                });\r\n            });\r\n            return;\r\n        }\r\n\r\n        // No render loop yet (e.g. awaited inside createScene): drive rendering ourselves so the streaming\r\n        // decodes and depth sort can progress, yielding between frames so async downloads/readbacks resolve.\r\n        // Wrap each render in beginFrame/endFrame exactly like the engine's own render loop: on WebGPU,\r\n        // endFrame submits the frame's command buffers and presents the swapchain, so a bare scene.render()\r\n        // would leave the acquired swapchain texture to be destroyed at the frame boundary before its command\r\n        // buffer is submitted (\"destroyed texture used in a submit\").\r\n        const engine = scene.getEngine();\r\n        const requestFrame = (globalThis as { requestAnimationFrame?: (cb: () => void) => void }).requestAnimationFrame;\r\n        while (!this._disposed) {\r\n            engine.beginFrame();\r\n            scene.render();\r\n            engine.endFrame();\r\n            if (isSettled()) {\r\n                return;\r\n            }\r\n            // eslint-disable-next-line no-await-in-loop\r\n            await new Promise<void>((resolve) => {\r\n                if (typeof requestFrame === \"function\") {\r\n                    requestFrame(() => resolve());\r\n                } else {\r\n                    setTimeout(resolve, 16);\r\n                }\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Whether the base layer is ready and there is no streaming work in flight (nothing queued for decode, no\r\n     * decode running, and no downloads pending).\r\n     * @returns true when no loading work remains\r\n     */\r\n    private _isLoadingIdle(): boolean {\r\n        return this._baseLayerReady && this._metadataReady && this._decodeQueue.length === 0 && this._loadingFiles.size === 0 && this._downloadManager.isIdle;\r\n    }\r\n\r\n    /**\r\n     * Finest (most detailed) LOD level any node is allowed to render. `0` allows full detail (level 0);\r\n     * `1` caps detail at the next-coarser level, and so on. Nodes already coarser than this cap (by\r\n     * distance) are unaffected. Changes take effect in real time.\r\n     */\r\n    public get maxDetailLod(): number {\r\n        return this._maxDetailLod;\r\n    }\r\n\r\n    public set maxDetailLod(value: number) {\r\n        const level = Math.max(0, Math.floor(value));\r\n        if (this._maxDetailLod === level) {\r\n            return;\r\n        }\r\n        this._maxDetailLod = level;\r\n        // Re-evaluate LODs on the next frame regardless of the movement throttle so the change is immediate.\r\n        this._forceLodUpdate = true;\r\n    }\r\n\r\n    /**\r\n     * This stream's own budget-driven LOD cap in splats (see {@link IGaussianSplattingStreamOptions.splatBudget}).\r\n     * `0` disables the budget (pure distance LOD). Setting it caps the rendered splat count, taking effect on the\r\n     * next frame. When this stream is hosted in a compound whose own budget is set, that shared budget overrides\r\n     * this value — read the actual runtime cap from {@link effectiveSplatBudget}, not this getter (which always\r\n     * reports the configured own cap).\r\n     * @experimental\r\n     */\r\n    public override get splatBudget(): number {\r\n        return this._splatBudget;\r\n    }\r\n\r\n    public override set splatBudget(value: number) {\r\n        const budget = value > 0 ? Math.floor(value) : 0;\r\n        if (budget === this._splatBudget) {\r\n            return;\r\n        }\r\n        this._splatBudget = budget;\r\n        // Re-evaluate LODs on the next frame regardless of the movement throttle so the change is immediate.\r\n        this._forceLodUpdate = true;\r\n    }\r\n\r\n    /**\r\n     * The splat cap actually in force this frame: a hosting compound's apportioned allocation when this stream is\r\n     * coordinated, otherwise this stream's own {@link splatBudget}, clamped to what can be kept resident. `0` means\r\n     * no cap (pure distance LOD). Unlike {@link splatBudget}, this reflects the compound override, so it is the value\r\n     * to display or reason about at runtime.\r\n     * @experimental\r\n     */\r\n    public get effectiveSplatBudget(): number {\r\n        return this._effectiveSplatBudget();\r\n    }\r\n\r\n    /**\r\n     * The resolved maximum number of splats kept resident in the work buffer. This combines\r\n     * {@link IGaussianSplattingStreamOptions.maxResidentSplats} and {@link IGaussianSplattingStreamOptions.memoryBudgetMb},\r\n     * taking the smaller positive limit and raising it to {@link minimumResidentSplats}. With neither limit set,\r\n     * the complete source size is retained when known; otherwise a bounded device-tiered default is used.\r\n     * The fixed capacity is capped at the device texture limit. `0` means initial capacity has not been resolved.\r\n     * @experimental\r\n     */\r\n    public get residentSplatBudget(): number {\r\n        return this._residentBudget;\r\n    }\r\n\r\n    /**\r\n     * Minimum fixed work-buffer capacity required for the complete coarse representation: one invisible padding\r\n     * splat, the included environment, and every unique whole coarse source file. It is `0` until the required\r\n     * coarse metadata has resolved. Initial residency options below this value are raised to it.\r\n     * @experimental\r\n     */\r\n    public get minimumResidentSplats(): number {\r\n        return this._minimumResidentSplats;\r\n    }\r\n\r\n    /**\r\n     * The total number of splats represented by valid level-0 leaf entries. This remains pending while source\r\n     * metadata is loading and is unavailable when no applicable level-0 entries exist or required metadata fails.\r\n     * @experimental\r\n     */\r\n    public get lod0SplatCount(): GaussianSplattingStreamLod0SplatCount {\r\n        return this._lod0SplatCount;\r\n    }\r\n\r\n    /**\r\n     * Resolves the raw {@link splatBudget} option to a concrete cap: `undefined` ⇒ 0 (disabled), `\"auto\"` ⇒ a\r\n     * device-tiered default, a positive number ⇒ itself (floored).\r\n     * @param option the raw option value\r\n     * @returns the resolved splat cap (0 = disabled)\r\n     */\r\n    private _resolveSplatBudget(option: number | \"auto\" | undefined): number {\r\n        if (option === undefined) {\r\n            return 0;\r\n        }\r\n        if (option === \"auto\") {\r\n            return this._computeDefaultSplatBudget();\r\n        }\r\n        return option > 0 ? Math.floor(option) : 0;\r\n    }\r\n\r\n    /**\r\n     * Device-tiered default splat budget for {@link splatBudget} `\"auto\"`: desktop 2.5M, iOS 1.5M, other mobile\r\n     * (incl. Android/XR) 1M. XR is folded into the mobile tier (no reliable at-construction detection).\r\n     * @returns the default splat cap for this device\r\n     */\r\n    private _computeDefaultSplatBudget(): number {\r\n        const isMobile = !!this._scene.getEngine().hostInformation?.isMobile;\r\n        if (!isMobile) {\r\n            return 2_500_000;\r\n        }\r\n        if (typeof navigator !== \"undefined\" && navigator.userAgent && /iPad|iPhone|iPod/.test(navigator.userAgent)) {\r\n            return 1_500_000;\r\n        }\r\n        return 1_000_000;\r\n    }\r\n\r\n    /**\r\n     * The splat budget this stream converges against this frame: the compound's apportioned allocation when hosted\r\n     * and coordinated, else this stream's own resolved budget. Clamped to the resident budget so the stream never\r\n     * targets more splats than can be kept resident. `0` means the budget is disabled.\r\n     * @returns the effective splat cap (0 = disabled)\r\n     */\r\n    private _effectiveSplatBudget(): number {\r\n        if (this._hostBudgetAllocation !== null) {\r\n            // Coordinated by the host: even a 0 allocation (static parts consumed the whole budget) keeps the budget\r\n            // path active so the stream converges to its coarsest level — it must never revert to unbounded LOD, or\r\n            // the compound total could exceed the cap.\r\n            const alloc = Math.max(1, this._hostBudgetAllocation);\r\n            return this._residentBudget > 0 ? Math.min(alloc, this._residentBudget) : alloc;\r\n        }\r\n        if (this._splatBudget <= 0) {\r\n            return 0;\r\n        }\r\n        return this._residentBudget > 0 ? Math.min(this._splatBudget, this._residentBudget) : this._splatBudget;\r\n    }\r\n\r\n    /**\r\n     * Whether budget-driven LOD is active this frame.\r\n     * @returns true when a positive effective budget is in force\r\n     */\r\n    private _splatBudgetEnabled(): boolean {\r\n        return this._effectiveSplatBudget() > 0;\r\n    }\r\n\r\n    /**\r\n     * {@link IGaussianSplattingLodBudgetParticipant}: the splats this stream would render at full (distance-optimal)\r\n     * detail — its demand on a host compound's shared budget. Computed from the current per-node distance-optimal\r\n     * levels (no pixel threshold), so it does not depend on the allocation it is helping to compute.\r\n     * @returns the full-detail rendered splat count (0 before the base layer is ready)\r\n     */\r\n    public getBudgetDemand(): number {\r\n        if (!this._baseLayerReady) {\r\n            return 0;\r\n        }\r\n        // Include the always-rendered environment as a fixed cost so the host allocates enough for it; the leaf\r\n        // convergence reserves the same amount (see _computeTargetLevels).\r\n        let sum = this._environmentSplatCount();\r\n        for (const node of this._leafNodes) {\r\n            const desired = node.optimalLod ?? node.baseLod!;\r\n            sum += this._countAtLevel(node, this._cappedLevelForNode(node, desired));\r\n        }\r\n        return sum;\r\n    }\r\n\r\n    /**\r\n     * {@link IGaussianSplattingLodBudgetParticipant}: sets the compound's apportioned share of the shared budget.\r\n     * `null` releases coordination (revert to this stream's own {@link splatBudget}); a number (incl. 0, meaning\r\n     * \"coordinated at the coarsest level\") drives the pixel-threshold convergence. Any change to the (already integer)\r\n     * allocation forces a next-frame re-eval: a decrease may put the current selection over the new cap, and even a\r\n     * small increase can unlock a finer level that a stationary camera would otherwise never re-evaluate to. The\r\n     * apportioned demand is allocation-independent, so this settles in one step and does not churn frame to frame.\r\n     * @param splats the apportioned allocation, or null to release coordination\r\n     */\r\n    public setBudgetAllocation(splats: Nullable<number>): void {\r\n        if (splats === null) {\r\n            if (this._hostBudgetAllocation !== null) {\r\n                this._hostBudgetAllocation = null;\r\n                this._forceLodUpdate = true;\r\n            }\r\n            return;\r\n        }\r\n        const prev = this._hostBudgetAllocation;\r\n        this._hostBudgetAllocation = splats;\r\n        if (prev === null || splats !== prev) {\r\n            this._forceLodUpdate = true;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Coarsest LOD level index in the scene (number of LOD levels minus one). Useful as the upper bound\r\n     * for {@link maxDetailLod}.\r\n     */\r\n    public get maxLodLevel(): number {\r\n        return Math.max(0, this._metadata.lodLevels - 1);\r\n    }\r\n\r\n    /**\r\n     * When true (default), nodes whose bounding box is outside the camera frustum are biased to the coarsest\r\n     * LOD instead of being hidden. They stay in the sort/render set (their off-screen splats are clipped), so\r\n     * turning the camera toward them shows low detail immediately with no invisible frames, then refines.\r\n     * Changes take effect in real time.\r\n     */\r\n    public get frustumCulling(): boolean {\r\n        return this._frustumCulling;\r\n    }\r\n\r\n    public set frustumCulling(value: boolean) {\r\n        if (this._frustumCulling === value) {\r\n            return;\r\n        }\r\n        this._frustumCulling = value;\r\n        // Re-evaluate LODs next frame so the off-screen bias is applied/removed immediately.\r\n        this._forceLodUpdate = true;\r\n    }\r\n\r\n    /**\r\n     * When true, renders a wireframe box per LOD node, colored by the LOD level selected by {@link debugLodSource}.\r\n     */\r\n    public get debugDisplay(): boolean {\r\n        return this._debugDisplay;\r\n    }\r\n\r\n    public set debugDisplay(value: boolean) {\r\n        if (this._debugDisplay === value) {\r\n            return;\r\n        }\r\n        this._debugDisplay = value;\r\n        if (value) {\r\n            this._refreshDebugDisplay();\r\n        } else {\r\n            this._clearDebugDisplay();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Selects which LOD value drives the debug wireframe colors: the distance-based `\"optimal\"` LOD\r\n     * (default, recomputed as the camera moves) or the `\"current\"` streamed/rendered LOD.\r\n     */\r\n    public get debugLodSource(): GaussianSplattingStreamDebugLodSource {\r\n        return this._debugLodSource;\r\n    }\r\n\r\n    public set debugLodSource(value: GaussianSplattingStreamDebugLodSource) {\r\n        if (this._debugLodSource === value) {\r\n            return;\r\n        }\r\n        this._debugLodSource = value;\r\n        if (this._debugDisplay) {\r\n            this._refreshDebugDisplay();\r\n        }\r\n    }\r\n\r\n    public override dispose(doNotRecurse?: boolean): void {\r\n        if (this._disposed) {\r\n            // Idempotent: a failed load disposes from its own _streamAllAsync handler, and the awaiter's catch may\r\n            // dispose again — don't re-fire cleanup/observables (and super.dispose) a second time.\r\n            return;\r\n        }\r\n        this._disposed = true;\r\n        this._rejectPartReady(\"GaussianSplattingStream: disposed before the part was ready.\");\r\n        this._unsubBeforeRebuild?.();\r\n        this._unsubAfterRebuild?.();\r\n        this._unsubBeforeRebuild = null;\r\n        this._unsubAfterRebuild = null;\r\n        this._hostUnsubRemove?.();\r\n        this._hostUnsubDispose?.();\r\n        this._hostUnsubRemove = null;\r\n        this._hostUnsubDispose = null;\r\n        // If this stream disposes on its own rather than because the host removed its part, release the reserved\r\n        // region (tombstone). Reclaiming the rows is a separate compaction — cheap disposal here so tearing down N\r\n        // parts doesn't trigger N atlas rebuilds; the caller/host reclaims when appropriate (a failed load compacts\r\n        // once, see the _streamAllAsync handler). Skipped when the host removed the part (it owns that policy).\r\n        if (this._hostCompound && !this._hostCompound.isDisposed()) {\r\n            this._hostCompound.unregisterLodBudgetParticipant(this);\r\n        }\r\n        if (this._host && this._hostCompound && !this._partReleasedByHost && !this._hostCompound.isDisposed()) {\r\n            this._hostCompound.removePart(this._host.partIndex);\r\n        }\r\n        this._host = null;\r\n        if (this._lodObserver) {\r\n            this._scene.onBeforeRenderObservable.remove(this._lodObserver);\r\n            this._lodObserver = null;\r\n        }\r\n        this._clearDebugDisplay();\r\n        this._downloadManager.dispose();\r\n        this._residency?.dispose();\r\n        this._residency = null;\r\n        this._workBuffer?.dispose();\r\n        this._workBuffer = null;\r\n        super.dispose(doNotRecurse);\r\n    }\r\n\r\n    /**\r\n     * Disposes this stream and, when hosted, compacts the host once to reclaim its tombstoned region's reserved\r\n     * rows. Used on a definitive load failure / empty result — a discrete, one-off reclaim, versus a bare\r\n     * {@link dispose} that only tombstones so tearing down several parts doesn't rebuild the atlas repeatedly.\r\n     */\r\n    private _disposeAndReclaim(): void {\r\n        const compound = this._hostCompound;\r\n        const hadPart = !!this._host && !this._partReleasedByHost;\r\n        this.dispose();\r\n        if (hadPart && compound && !compound.isDisposed()) {\r\n            compound.compactAtlas();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * The world matrix that actually places this stream's splats, used to map the camera into the space the\r\n     * node bounds live in (for LOD distance) and to build camera-local frusta (for frustum culling). Standalone:\r\n     * this controller mesh carries the transform. Hosted: this controller is a hidden, unplaced node — the splats\r\n     * are placed by the reserved part's proxy (SOG up-axis basis composed with the host's placement), so LOD and\r\n     * culling MUST use the proxy's world matrix or they compute distances/frustum tests in the wrong space\r\n     * (producing wrong per-chunk LODs, i.e. holes, whenever the host applies a non-identity transform).\r\n     * @param force when true, forces a full world-matrix recompute (else uses the renderId/sync fast-path)\r\n     * @returns the effective world matrix for LOD/culling\r\n     */\r\n    private _getEffectiveWorldMatrix(force: boolean): Matrix {\r\n        if (this._host) {\r\n            return this._host.proxy.computeWorldMatrix(force);\r\n        }\r\n        return this.computeWorldMatrix(force);\r\n    }\r\n\r\n    /**\r\n     * The cameras the LOD should serve: `scene.activeCameras` when set (split-view / multi-view), else the single\r\n     * `scene.activeCamera`. Mirrors the sort path's multi-camera handling.\r\n     * @returns the non-null active cameras (may be empty)\r\n     */\r\n    private _getActiveLodCameras(): Camera[] {\r\n        const cameras = this._scene.activeCameras?.length ? this._scene.activeCameras : this._scene.activeCamera ? [this._scene.activeCamera] : [];\r\n        return cameras.filter((camera): camera is Camera => !!camera);\r\n    }\r\n\r\n    /**\r\n     * Re-evaluates the optimal LOD for every node from the active cameras. Each node takes the finest level and the\r\n     * largest projected pixel size any active camera demands (so every pane of a split view is served), and the\r\n     * frustum bias uses the union of the frusta. Selection is view-direction-independent, so single- and multi-camera\r\n     * rendering are consistent. The results are stored in each node's `optimalLod` / `pixelSize`.\r\n     * @param camera when provided, evaluate against just this camera; otherwise use the active-camera set\r\n     */\r\n    public evaluateOptimalLods(camera: Nullable<Camera> = null): void {\r\n        const cameras = camera ? [camera] : this._getActiveLodCameras();\r\n        if (cameras.length === 0 || this._leafNodes.length === 0) {\r\n            return;\r\n        }\r\n\r\n        const maxLod = Math.max(0, this._metadata.lodLevels - 1);\r\n        const base = this._lodBaseDistance;\r\n        const mult = this._lodMultiplier;\r\n        const behindPenalty = this._lodBehindPenalty;\r\n        const rangeMin = this._lodRangeMin;\r\n        const rangeMax = this._lodRangeMax;\r\n        const budgetEnabled = this._splatBudgetEnabled();\r\n        const renderHeight = this._scene.getEngine().getRenderHeight() || 1;\r\n\r\n        // Precompute each camera in the mesh's local space (where the node bounds live). The local forward is only\r\n        // needed for the behind-camera penalty. FOV compensation uses min(tanHalfV, tanHalfH) (matches PlayCanvas).\r\n        const engine = this._scene.getEngine();\r\n        this._getEffectiveWorldMatrix(false).invertToRef(TmpInvWorld);\r\n        const camInfos = cameras.map((cam) => {\r\n            const aspect = engine.getAspectRatio(cam) || 1;\r\n            let tanHalfV = Math.tan(cam.fov * 0.5);\r\n            if (cam.fovMode === Camera.FOVMODE_HORIZONTAL_FIXED) {\r\n                tanHalfV /= aspect;\r\n            }\r\n            const tanHalfH = tanHalfV * aspect;\r\n            const fovScale = Math.min(tanHalfV, tanHalfH) / RefTanHalfFov;\r\n            // Vertical pixel extent of THIS camera's viewport (split-view panes render to a fraction of the canvas),\r\n            // so a node's projected size is measured against the pixels the camera actually draws into.\r\n            const pixelHeight = renderHeight * (cam.viewport ? cam.viewport.height : 1);\r\n            const localCamera = Vector3.TransformCoordinatesToRef(cam.globalPosition, TmpInvWorld, TmpLocalCamera);\r\n            const info = { px: localCamera.x, py: localCamera.y, pz: localCamera.z, fwx: 0, fwy: 0, fwz: 0, fovScale, tanHalfV, pixelHeight };\r\n            if (behindPenalty > 1) {\r\n                cam.getDirectionToRef(LocalForwardAxis, TmpWorldForward);\r\n                const localForward = Vector3.TransformNormalToRef(TmpWorldForward, TmpInvWorld, TmpLocalForward);\r\n                localForward.normalize();\r\n                info.fwx = localForward.x;\r\n                info.fwy = localForward.y;\r\n                info.fwz = localForward.z;\r\n            }\r\n            return info;\r\n        });\r\n\r\n        for (const node of this._leafNodes) {\r\n            const mn = node.bound.min;\r\n            const mx = node.bound.max;\r\n            const cx = (mn[0] + mx[0]) * 0.5;\r\n            const cy = (mn[1] + mx[1]) * 0.5;\r\n            const cz = (mn[2] + mx[2]) * 0.5;\r\n            const hx = mx[0] - mn[0];\r\n            const hy = mx[1] - mn[1];\r\n            const hz = mx[2] - mn[2];\r\n            const radius = 0.5 * Math.sqrt(hx * hx + hy * hy + hz * hz);\r\n\r\n            // Aggregate across cameras: the finest level and the largest projected size any active camera demands.\r\n            let optimalLod = Number.POSITIVE_INFINITY;\r\n            let pixelSize = 0;\r\n            for (const cam of camInfos) {\r\n                // Distance from the camera to the closest point on this node's AABB (local space).\r\n                const qx = cam.px < mn[0] ? mn[0] : cam.px > mx[0] ? mx[0] : cam.px;\r\n                const qy = cam.py < mn[1] ? mn[1] : cam.py > mx[1] ? mx[1] : cam.py;\r\n                const qz = cam.pz < mn[2] ? mn[2] : cam.pz > mx[2] ? mx[2] : cam.pz;\r\n                const dx = qx - cam.px;\r\n                const dy = qy - cam.py;\r\n                const dz = qz - cam.pz;\r\n                const actualDistance = Math.sqrt(dx * dx + dy * dy + dz * dz);\r\n\r\n                // Push nodes behind the camera toward coarser LODs when a penalty is configured.\r\n                let penalizedDistance = actualDistance;\r\n                if (behindPenalty > 1 && actualDistance > 0.01) {\r\n                    const dotOverDistance = (cam.fwx * dx + cam.fwy * dy + cam.fwz * dz) / actualDistance;\r\n                    if (dotOverDistance < 0) {\r\n                        penalizedDistance = actualDistance * (1 + -dotOverDistance * (behindPenalty - 1));\r\n                    }\r\n                }\r\n\r\n                // Geometric LOD bands: threshold[k] = base * mult^(k-1). Keep the finest (min) any camera wants.\r\n                const fovAdjustedDistance = penalizedDistance * cam.fovScale;\r\n                let lod: number;\r\n                if (maxLod === 0 || fovAdjustedDistance < base) {\r\n                    lod = 0;\r\n                } else {\r\n                    lod = maxLod;\r\n                    while (lod > 1 && fovAdjustedDistance < base * Math.pow(mult, lod - 1)) {\r\n                        lod--;\r\n                    }\r\n                }\r\n                if (lod < optimalLod) {\r\n                    optimalLod = lod;\r\n                }\r\n\r\n                // Budget-driven LOD: raw projected pixel size (node diameter in pixels), largest across cameras.\r\n                // Uses local radius/distance (invariant under uniform world scale); every camera weighs the same and\r\n                // view direction is ignored, so single- and multi-camera rendering stay consistent.\r\n                if (budgetEnabled) {\r\n                    const rdx = cx - cam.px;\r\n                    const rdy = cy - cam.py;\r\n                    const rdz = cz - cam.pz;\r\n                    const centerDist = Math.sqrt(rdx * rdx + rdy * rdy + rdz * rdz);\r\n                    const pixels = (radius * cam.pixelHeight) / (Math.max(centerDist, 1e-4) * cam.tanHalfV);\r\n                    if (pixels > pixelSize) {\r\n                        pixelSize = pixels;\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (optimalLod < rangeMin) {\r\n                optimalLod = rangeMin;\r\n            } else if (optimalLod > rangeMax) {\r\n                optimalLod = rangeMax;\r\n            }\r\n\r\n            // Frustum-based LOD bias: nodes outside EVERY active camera's frustum (see _updateNodeFrustum) are pushed\r\n            // to the coarsest allowed level instead of being hidden. They stay in the render/sort set (off-screen and\r\n            // clipped anyway), so turning a camera toward them shows low detail immediately, then refines.\r\n            if (this._frustumCulling && node.inFrustum === false) {\r\n                optimalLod = rangeMax;\r\n            }\r\n\r\n            node.optimalLod = optimalLod;\r\n            if (budgetEnabled) {\r\n                node.pixelSize = pixelSize;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * The LOD level used to color a node's debug box, per {@link debugLodSource}.\r\n     * @param node leaf node\r\n     * @returns the displayed LOD level\r\n     */\r\n    private _displayedLodLevel(node: ISOGLODNode): number {\r\n        if (this._debugLodSource === \"optimal\") {\r\n            return node.optimalLod ?? node.activeLod ?? 0;\r\n        }\r\n        return node.activeLod ?? 0;\r\n    }\r\n\r\n    /**\r\n     * Rebuilds the debug wireframe (evaluating the optimal LOD first when needed) and wires up the per-frame\r\n     * recolor observer. The observer runs for both LOD sources: \"optimal\" colors track the camera, and\r\n     * \"current\" colors track LOD levels as they stream in/out.\r\n     */\r\n    private _refreshDebugDisplay(): void {\r\n        if (this._debugLodSource === \"optimal\") {\r\n            this.evaluateOptimalLods();\r\n        }\r\n        this._buildDebugMesh();\r\n\r\n        const needsObserver = this._debugDisplay;\r\n        if (needsObserver && !this._debugObserver) {\r\n            this._debugObserver = this._scene.onBeforeRenderObservable.add(() => this._onDebugFrame());\r\n        } else if (!needsObserver && this._debugObserver) {\r\n            this._scene.onBeforeRenderObservable.remove(this._debugObserver);\r\n            this._debugObserver = null;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Per-frame debug update: recolors the existing wireframe in place whenever the displayed LOD levels\r\n     * change. For the \"optimal\" source the optimal LOD is recomputed first (it tracks the camera); for the\r\n     * \"current\" source the levels are driven by the streaming loop, so no recomputation is needed here. The\r\n     * geometry is never rebuilt, which avoids the dispose/recreate flicker while the camera moves.\r\n     */\r\n    private _onDebugFrame(): void {\r\n        if (this._debugLodSource === \"optimal\") {\r\n            this.evaluateOptimalLods();\r\n        }\r\n        if (this._computeDebugSignature() !== this._debugSignature) {\r\n            this._updateDebugColors();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Builds the LOD-node wireframe boxes once (one box per leaf node), colored by the displayed LOD level.\r\n     * The color vertex buffer is created updatable so subsequent recolors can happen in place.\r\n     */\r\n    private _buildDebugMesh(): void {\r\n        if (this._debugMesh) {\r\n            this._debugMesh.dispose();\r\n            this._debugMesh = null;\r\n        }\r\n        this._debugColorData = null;\r\n\r\n        const lines: Vector3[][] = [];\r\n        const colors: Color4[][] = [];\r\n        for (const node of this._leafNodes) {\r\n            const color = GsLodDebugColors[this._displayedLodLevel(node) % GsLodDebugColors.length];\r\n            const mn = node.bound.min;\r\n            const mx = node.bound.max;\r\n            const corners = [\r\n                new Vector3(mn[0], mn[1], mn[2]),\r\n                new Vector3(mx[0], mn[1], mn[2]),\r\n                new Vector3(mx[0], mx[1], mn[2]),\r\n                new Vector3(mn[0], mx[1], mn[2]),\r\n                new Vector3(mn[0], mn[1], mx[2]),\r\n                new Vector3(mx[0], mn[1], mx[2]),\r\n                new Vector3(mx[0], mx[1], mx[2]),\r\n                new Vector3(mn[0], mx[1], mx[2]),\r\n            ];\r\n            for (const edge of BoxEdges) {\r\n                lines.push([corners[edge[0]], corners[edge[1]]]);\r\n                colors.push([color, color]);\r\n            }\r\n        }\r\n\r\n        this._debugSignature = this._computeDebugSignature();\r\n        if (lines.length === 0) {\r\n            return;\r\n        }\r\n\r\n        const mesh = CreateLineSystem(this.name + \"_lodDebug\", { lines, colors, updatable: true, useVertexAlpha: false }, this._scene);\r\n        mesh.parent = this;\r\n        mesh.isPickable = false;\r\n        mesh.doNotSerialize = true;\r\n        mesh.reservedDataStore = { hidden: true };\r\n        this._debugMesh = mesh;\r\n        this._debugColorData = new Float32Array(this._leafNodes.length * VerticesPerBox * 4);\r\n    }\r\n\r\n    /**\r\n     * Recolors the existing wireframe in place from the current displayed LOD levels, without rebuilding geometry.\r\n     */\r\n    private _updateDebugColors(): void {\r\n        if (!this._debugMesh || !this._debugColorData) {\r\n            return;\r\n        }\r\n        const data = this._debugColorData;\r\n        let offset = 0;\r\n        for (const node of this._leafNodes) {\r\n            const color = GsLodDebugColors[this._displayedLodLevel(node) % GsLodDebugColors.length];\r\n            for (let v = 0; v < VerticesPerBox; v++) {\r\n                data[offset++] = color.r;\r\n                data[offset++] = color.g;\r\n                data[offset++] = color.b;\r\n                data[offset++] = color.a;\r\n            }\r\n        }\r\n        this._debugMesh.updateVerticesData(VertexBuffer.ColorKind, data);\r\n        this._debugSignature = this._computeDebugSignature();\r\n    }\r\n\r\n    /**\r\n     * Computes a cheap 32-bit rolling hash of every leaf's displayed LOD level, used to detect when the\r\n     * debug wireframe needs recoloring. Avoids per-frame string allocation in the render loop.\r\n     * @returns a numeric signature of the current displayed LOD levels\r\n     */\r\n    private _computeDebugSignature(): number {\r\n        let hash = 0;\r\n        for (const node of this._leafNodes) {\r\n            hash = (hash * 31 + this._displayedLodLevel(node)) | 0;\r\n        }\r\n        return hash;\r\n    }\r\n\r\n    /**\r\n     * Disposes the LOD-node wireframe boxes and stops live debug updates.\r\n     */\r\n    private _clearDebugDisplay(): void {\r\n        if (this._debugObserver) {\r\n            this._scene.onBeforeRenderObservable.remove(this._debugObserver);\r\n            this._debugObserver = null;\r\n        }\r\n        if (this._debugMesh) {\r\n            this._debugMesh.dispose();\r\n            this._debugMesh = null;\r\n        }\r\n        this._debugColorData = null;\r\n        this._debugSignature = 0;\r\n    }\r\n\r\n    /**\r\n     * Walks the LOD tree and records every leaf that carries renderable LOD entries, capturing the set of\r\n     * available levels and the coarsest (base) level for each.\r\n     * @param node current tree node\r\n     */\r\n    private _collectLodEntries(node: ISOGLODNode): void {\r\n        if (node.children) {\r\n            for (const child of node.children) {\r\n                this._collectLodEntries(child);\r\n            }\r\n            return;\r\n        }\r\n\r\n        if (!node.lods) {\r\n            return;\r\n        }\r\n\r\n        // Malformed bounds break distance, projected-size, and frustum math. Check the coordinates are present and\r\n        // finite, then the DERIVED diagonal is finite and positive: finite-but-huge coordinates (e.g. ±1e308) yield an\r\n        // infinite span/radius/pixel-size and thus an infinite budget threshold that defeats the cap, while a zero\r\n        // (degenerate) span projects to zero pixels and never coarsens. Either way, skip such a node entirely.\r\n        const bmin = node.bound?.min;\r\n        const bmax = node.bound?.max;\r\n        if (!bmin || !bmax || bmin.length < 3 || bmax.length < 3 || !bmin.every((v) => Number.isFinite(v)) || !bmax.every((v) => Number.isFinite(v))) {\r\n            return;\r\n        }\r\n        const spanX = bmax[0] - bmin[0];\r\n        const spanY = bmax[1] - bmin[1];\r\n        const spanZ = bmax[2] - bmin[2];\r\n        const diagonal = Math.sqrt(spanX * spanX + spanY * spanY + spanZ * spanZ);\r\n        if (!Number.isFinite(diagonal) || diagonal <= 0) {\r\n            return;\r\n        }\r\n\r\n        // Declared LOD range: keys must resolve to a canonical, in-range, integer level so later `node.lods[String(level)]`\r\n        // lookups always hit and an out-of-range fine level can't slip past the convergence (which only coarsens within\r\n        // the declared level count) and defeat the cap.\r\n        const declaredLevels = Math.floor(Number(this._metadata.lodLevels));\r\n        const maxLevel = Number.isFinite(declaredLevels) && declaredLevels > 0 ? declaredLevels - 1 : 0;\r\n\r\n        // Collect all levels that hold splats (PlayCanvas convention: level 0 is the finest, higher = coarser).\r\n        // Normalize each entry's count to a finite positive integer HERE (metadata is untrusted and only shallowly\r\n        // validated, so `count` may be a string): all downstream arithmetic — budget demand/convergence — then adds\r\n        // numbers instead of concatenating strings. Require `String(level) === key` so a non-canonical key like \"01\"\r\n        // (which `Number` maps to 1, but `String(1)` can't retrieve) is rejected rather than crashing a later lookup.\r\n        const levels: number[] = [];\r\n        for (const key of Object.keys(node.lods)) {\r\n            const level = Number(key);\r\n            const entry = node.lods[key];\r\n            const count = entry ? Math.floor(Number(entry.count)) : NaN;\r\n            if (Number.isInteger(level) && String(level) === key && level >= 0 && level <= maxLevel && entry && Number.isFinite(count) && count > 0) {\r\n                entry.count = count;\r\n                levels.push(level);\r\n            }\r\n        }\r\n        if (levels.length === 0) {\r\n            return;\r\n        }\r\n        levels.sort((a, b) => a - b);\r\n\r\n        // Enforce non-increasing count as the level index increases (a coarser level must not cost MORE than a finer\r\n        // one). Keep every level whose count is at or below the running minimum: equal-count adjacent levels are valid\r\n        // (same splat count, different geometry) and preserved, while a malformed \"coarser but larger\" level is dropped\r\n        // so the budget can never pick more splats than a cheaper available level and the coarsest kept level (the base)\r\n        // is the true minimum — which the convergence relies on for its guaranteed cap.\r\n        const usable: number[] = [];\r\n        let minCount = Infinity;\r\n        for (const level of levels) {\r\n            const count = node.lods[String(level)].count;\r\n            if (count <= minCount) {\r\n                usable.push(level);\r\n                minCount = count;\r\n            }\r\n        }\r\n\r\n        node.availableLevels = usable;\r\n        node.baseLod = usable[usable.length - 1];\r\n        node.activeLod = undefined;\r\n        node.lodCooldown = 0;\r\n        node.inFrustum = true;\r\n        // Static local bounds; each camera's frustum is transformed into this space for evaluation.\r\n        node.cullBounds = new BoundingInfo(Vector3.FromArray(bmin), Vector3.FromArray(bmax));\r\n        this._leafNodes.push(node);\r\n    }\r\n\r\n    /**\r\n     * Streams the scene. Large streams fetch only required coarse metadata before allocating and decoding the\r\n     * complete coarse layer; finer metadata starts afterwards so it cannot occupy the download queue ahead of\r\n     * visible geometry. Small streams and streams containing only coarse files retain an exact all-file capacity upper bound.\r\n     */\r\n    private async _streamAllAsync(): Promise<void> {\r\n        const fileIds = this._collectAllFileIds();\r\n        const baseFileIds = this._collectBaseFileIds();\r\n        this._baseFileIds.clear();\r\n        for (const fileId of baseFileIds) {\r\n            this._baseFileIds.add(fileId);\r\n        }\r\n        if (this._leafNodes.length > 0 && baseFileIds.length === 0) {\r\n            throw new Error(\"GaussianSplattingStream: no valid coarse source files were referenced.\");\r\n        }\r\n\r\n        const progressiveMetadata = fileIds.length > ProgressiveMetadataFileThreshold && baseFileIds.length < fileIds.length;\r\n        if (progressiveMetadata && this._decodeSh) {\r\n            // Finer metadata is deliberately unknown during allocation. Reserve the renderer's complete supported\r\n            // degree-4 layout so a later file can never require a fixed-atlas resize or silently lose its SH.\r\n            this._streamShDegree = MaxSupportedShDegree;\r\n            this._shTextureCount = MaxSupportedShTextureCount;\r\n        }\r\n\r\n        // The environment keeps its existing initial ordering. On large streams only coarse source metadata follows\r\n        // it, leaving the FIFO download manager free for coarse textures before the hundreds of finer metadata files.\r\n        const initialFileIds = progressiveMetadata ? baseFileIds : fileIds;\r\n        const envCount = await this._gatherCountsAsync(initialFileIds);\r\n        if (this._disposed) {\r\n            return;\r\n        }\r\n        for (const fileId of baseFileIds) {\r\n            const count = this._fileCounts.get(fileId);\r\n            if (!this._fileMeta.has(fileId) || count === undefined || count <= 0) {\r\n                throw new Error(`GaussianSplattingStream: required coarse metadata for file ${fileId} is unavailable or invalid.`);\r\n            }\r\n        }\r\n        this._resolveMinimumResidentSplats(baseFileIds, envCount);\r\n        if (!progressiveMetadata) {\r\n            this._resolveLod0SplatCount();\r\n            this._metadataReady = true;\r\n        }\r\n\r\n        // Index 0 is reserved as a never-decoded padding splat: the sort worker and index buffer pad unused\r\n        // slots with index 0, and leaving that slot zeroed (center.w = 0 => zero covariance, alpha 0) makes\r\n        // the padding invisible instead of ghosting a copy of the first real splat.\r\n        let fullCapacity: Nullable<number> = null;\r\n        if (!progressiveMetadata) {\r\n            fullCapacity = 1 + envCount;\r\n            for (const fileId of fileIds) {\r\n                const count = this._fileCounts.get(fileId);\r\n                if (count !== undefined && count > 0) {\r\n                    fullCapacity = GaussianSplattingStream._SafeAddCounts(fullCapacity, count, \"stream capacity\");\r\n                }\r\n            }\r\n        }\r\n        if (this._minimumResidentSplats <= 1) {\r\n            throw new Error(\"GaussianSplattingStream: stream produced no splats.\");\r\n        }\r\n\r\n        let largestBaseFileCount = 0;\r\n        for (const fileId of baseFileIds) {\r\n            largestBaseFileCount = Math.max(largestBaseFileCount, this._fileCounts.get(fileId)!);\r\n        }\r\n        const capacity = this._resolveResidentBudget(fullCapacity, largestBaseFileCount);\r\n        // Progressive metadata always implies that additional source files may need to replace one another. For an\r\n        // exact small stream, eviction is necessary only when its chosen capacity is below the full source set.\r\n        this._evictionEnabled = progressiveMetadata || (fullCapacity !== null && capacity < fullCapacity);\r\n\r\n        this._residency = new GaussianSplattingResidencyController(capacity, this._evictionCooldownFrames, (file) => this._onFileEvicted(file));\r\n        // Padding is always pinned. Reserve the environment now, but pin it only after a successful decode so\r\n        // failed environment data can release its allocation before coarse/fine files need that space.\r\n        this._residency.pin(PaddingFileId, 1);\r\n        if (envCount > 0) {\r\n            const envOffset = this._residency.allocate(EnvironmentFileId, envCount);\r\n            if (envOffset !== null) {\r\n                this._environmentRange = { offset: envOffset, count: envCount };\r\n            } else {\r\n                Logger.Warn(\"GaussianSplattingStream: environment does not fit the memory budget; skipping it.\");\r\n                this._environmentFiles = null;\r\n            }\r\n        }\r\n\r\n        if (this._hostCompound) {\r\n            // Hosted: reserve a region of the compound sized to the work buffer, orient the part's proxy for the\r\n            // SOG up-axis, and decode straight into the compound's shared atlas so the streamed splats sort/draw\r\n            // in one pass with the compound's other parts. The compound owns the worker/render; this mesh stays\r\n            // a hidden controller.\r\n            const sogWorld = Matrix.Compose(new Vector3(1, -1, 1), Quaternion.RotationYawPitchRoll(0, -Math.PI / 2, 0), Vector3.ZeroReadOnly);\r\n            // Reserve with SH so the compound converts its SH textures to shared render-targetable integer MRTs and\r\n            // sets its SH degree; the hosted work buffer bakes into those shared targets at the region base offset.\r\n            const host = this._hostCompound.reserveStreamingPart(capacity, sogWorld, this.name + \"_part\", this._shTextureCount, this._streamShDegree, this._needsRotationScale);\r\n            this._host = host;\r\n            this._positionBase = host.base;\r\n            // Join the compound's shared splat budget (if any): the compound apportions its cap across all hosted\r\n            // streams. Harmless when the compound has no budget set (registration just tracks the participant).\r\n            this._hostCompound.registerLodBudgetParticipant(this);\r\n            // Bind this controller's lifetime to its part FROM RESERVATION (not after readiness): removing the part or\r\n            // disposing the compound — even while still downloading/decoding — disposes this stream so it stops writing\r\n            // into the compound's borrowed textures. `_partReleasedByHost` stops dispose() from removing the part again.\r\n            const compound = this._hostCompound;\r\n            // The remove observer needs the assigned part index, so it is registered here (at reservation); the\r\n            // compound-disposal observer was already registered at construction (see the ctor) to cover the pre-pass.\r\n            const removeObserver = compound.onPartRemovedObservable.add((removedIndex) => {\r\n                if (!this._disposed && this._host && removedIndex === this._host.partIndex) {\r\n                    this._partReleasedByHost = true;\r\n                    this.dispose();\r\n                }\r\n            });\r\n            this._hostUnsubRemove = () => compound.onPartRemovedObservable.remove(removeObserver);\r\n            const shExternal = this._shTextureCount > 0 && host.shMrtAtlas ? { textureCount: this._shTextureCount, externalMrts: host.shMrtAtlas } : undefined;\r\n            const rotExternal = this._needsRotationScale && host.rotMrtAtlas ? { externalMrt: host.rotMrtAtlas } : undefined;\r\n            // Use the region's ROW-ALIGNED capacity (host.capacity), not the raw stream capacity: backup/restore/\r\n            // relayout scope to whole atlas rows, so an unaligned capacity would drop the region's partial final row.\r\n            this._workBuffer = new GaussianSplattingWorkBuffer(\r\n                this._scene,\r\n                host.capacity,\r\n                {\r\n                    mrt: host.mrtAtlas!,\r\n                    width: host.atlasWidth,\r\n                    baseOffset: host.base,\r\n                },\r\n                shExternal,\r\n                rotExternal\r\n            );\r\n            this._readbackCandidate = this._workBuffer.supportsAsyncCentersReadback;\r\n            // Write decoded centers directly into the compound's shared position buffer (offset by the region base).\r\n            this._splatPositions = host.splatPositions;\r\n            this._vertexCount = capacity;\r\n            // Preserve this region's GPU-only data when the compound grows its atlas (adding a part / another\r\n            // stream): back it up before the old atlas is disposed, then rebind + restore into the new atlas.\r\n            const wb = this._workBuffer;\r\n            this._unsubBeforeRebuild = host.onBeforeAtlasRebuild(() => {\r\n                // Back up the region's atlas texels, and snapshot its CPU positions: the grow reallocates the shared\r\n                // `_splatPositions` and rebuilds it from CPU part sources, but this region has none, so its positions\r\n                // would be lost. `this._splatPositions` is still the pre-grow array and holds the real positions.\r\n                wb.backupRegion();\r\n                this._positionSnapshot = this._splatPositions ? this._splatPositions.slice(this._positionBase * 4, (this._positionBase + this._vertexCount) * 4) : null;\r\n            });\r\n            this._unsubAfterRebuild = host.onAfterAtlasRebuild(() => {\r\n                if (host.mrtAtlas) {\r\n                    wb.rebindAtlas(host.mrtAtlas);\r\n                }\r\n                // Rebind to the recreated shared SH and rotation atlases; restoreRegion() writes the backups into them.\r\n                wb.rebindShAtlas(host.shMrtAtlas);\r\n                wb.rebindRotAtlas(host.rotMrtAtlas);\r\n                // A plain grow keeps `host.base`; a compaction relocates the region to a new base. Update the base\r\n                // before restoring so the region's texels and positions land there.\r\n                this._positionBase = host.base;\r\n                wb.setBaseOffset(host.base);\r\n                wb.restoreRegion();\r\n                // Re-cache the reallocated shared array and restore the region's CPU positions at the (new) base.\r\n                this._splatPositions = host.splatPositions;\r\n                if (this._positionSnapshot && this._splatPositions) {\r\n                    this._splatPositions.set(this._positionSnapshot, this._positionBase * 4);\r\n                    this._positionSnapshot = null;\r\n                }\r\n            });\r\n            // Nothing active until a resource is decoded (as a range on the reserved part).\r\n            host.setActiveRanges([]);\r\n        } else {\r\n            // Bake higher-order SH when requested and present: the work buffer owns `_shTextureCount` integer SH\r\n            // targets and the draw path lights the decoded splats with them (SH degree = max across files).\r\n            const sh = this._shTextureCount > 0 ? { textureCount: this._shTextureCount } : undefined;\r\n            // Decode rotation/scale into an owned 3-attachment half-float target when voxel-IBL shadows are requested.\r\n            const rot = this._needsRotationScale ? {} : undefined;\r\n            this._workBuffer = new GaussianSplattingWorkBuffer(this._scene, capacity, undefined, sh, rot);\r\n            // GPU readback is only enabled after it is validated against a CPU decode on the first file (see\r\n            // _probeReadbackAsync); until then positions are decoded on the CPU so there is always a correct result.\r\n            this._readbackCandidate = this._workBuffer.supportsAsyncCentersReadback;\r\n            const splatPositions = new Float32Array(capacity * 4);\r\n            const textures = this._workBuffer.textures;\r\n            const shTextures = sh ? this._workBuffer.shTextures : undefined;\r\n            const rotTextures = rot ? this._workBuffer.rotationTextures : undefined;\r\n            this._setExternalWorkBuffer(textures[0], textures[1], textures[2], textures[3], splatPositions, capacity, shTextures, this._streamShDegree, rotTextures);\r\n            // Nothing is active until at least one resource has been decoded.\r\n            this.setSplatIndexRanges([]);\r\n            this.setEnabled(true);\r\n        }\r\n\r\n        // Hosted only: compile the region's backup/restore copy shaders BEFORE decoding any data, so a later\r\n        // grow/compaction (which synchronously backs this region up) can never race shader compilation and lose it.\r\n        if (this._host && this._workBuffer) {\r\n            await this._waitForCanBackupAsync(this._workBuffer);\r\n            if (this._disposed) {\r\n                return;\r\n            }\r\n        }\r\n\r\n        // Decode the environment, then every unique coarse source. Each completed coarse file immediately\r\n        // promotes its leaves and publishes their ranges; incomplete essential coarse data fails the stream.\r\n        if (this._environmentRange && this._environmentFiles) {\r\n            await this._decodeEnvironmentAsync();\r\n        }\r\n        this._environmentFiles = null;\r\n\r\n        for (const fileId of baseFileIds) {\r\n            if (this._disposed) {\r\n                return;\r\n            }\r\n            // eslint-disable-next-line no-await-in-loop\r\n            const decoded = await this._decodeFileAsync(fileId);\r\n            if (!decoded) {\r\n                throw new Error(`GaussianSplattingStream: required coarse file ${fileId} failed to decode.`);\r\n            }\r\n        }\r\n\r\n        if (this._disposed) {\r\n            return;\r\n        }\r\n        for (const node of this._leafNodes) {\r\n            if (node.activeLod !== node.baseLod || node.activeFile === undefined) {\r\n                throw new Error(\"GaussianSplattingStream: the complete coarse layer could not be activated.\");\r\n            }\r\n        }\r\n\r\n        // Coarse data is now complete and visible. Hosted callers can place/frame the real bounds immediately,\r\n        // while large streams fetch finer metadata in the background.\r\n        this._baseLayerReady = true;\r\n        this._resolvePartReady();\r\n\r\n        if (progressiveMetadata) {\r\n            const fineFileIds = fileIds.filter((fileId) => !this._baseFileIds.has(fileId));\r\n            await this._gatherCountsAsync(fineFileIds, false);\r\n            this._resolveLod0SplatCount();\r\n            this._metadataReady = true;\r\n            if (this._disposed) {\r\n                return;\r\n            }\r\n        }\r\n\r\n        // Only after complete coarse coverage and the finer metadata phase may the per-frame loop request fine\r\n        // geometry. The fixed work buffer continues to retain every pinned coarse source as fallback.\r\n        if (!this._lodObserver) {\r\n            this._lodObserver = this._scene.onBeforeRenderObservable.add(() => this._onLodFrame());\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Waits (up to a frame cap) until the work buffer's backup/restore copy shaders are compiled, so a later\r\n     * grow/compaction can preserve this hosted region (see {@link GaussianSplattingWorkBuffer.backupRegion}).\r\n     * Polls per rendered frame: shader readiness here depends on the render loop (and the shared atlas can be\r\n     * rebuilt concurrently), so this stays synchronized with the render-driven decode and always makes progress.\r\n     * On timeout it proceeds best-effort — a subsequent grow/compaction then warns rather than blocking decode.\r\n     * @param wb the hosted work buffer to wait on\r\n     */\r\n    private async _waitForCanBackupAsync(wb: GaussianSplattingWorkBuffer): Promise<void> {\r\n        for (let frame = 0; frame < 600 && !this._disposed; frame++) {\r\n            if (wb.canBackup) {\r\n                return;\r\n            }\r\n            // eslint-disable-next-line no-await-in-loop\r\n            await new Promise<void>((resolve) => this._scene.onBeforeRenderObservable.addOnce(() => resolve()));\r\n        }\r\n        if (!this._disposed && !wb.canBackup) {\r\n            Logger.Warn(\"GaussianSplattingStream: backup/restore copy shaders did not compile in time; a grow/compaction before they are ready may drop streamed data.\");\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Resolves the fixed initial work-buffer capacity. Explicit count/MB limits are combined by taking the smaller\r\n     * and then raised to the complete coarse minimum. Without an explicit limit, a known complete source retains\r\n     * legacy full residency. When finer metadata is deferred and the complete size is unknown, the device-tiered\r\n     * memory estimate is given at least one largest-coarse-file of headroom so one replacement file can refine\r\n     * while all coarse fallback files remain pinned.\r\n     * @param fullCapacity exact complete source capacity, or null when unavailable\r\n     * @param largestBaseFileCount largest whole coarse source file, used as modest replacement headroom\r\n     * @returns the fixed initial work-buffer capacity\r\n     */\r\n    private _resolveResidentBudget(fullCapacity: Nullable<number> = null, largestBaseFileCount = 0): number {\r\n        const hasExplicitLimit = this._maxResidentSplats > 0 || this._memoryBudgetMb > 0;\r\n        let budget = this._maxResidentSplats > 0 ? this._maxResidentSplats : Number.POSITIVE_INFINITY;\r\n        const bytesPerSplat = this._bytesPerResidentSplat();\r\n        if (this._memoryBudgetMb > 0) {\r\n            const fromMB = Math.floor((this._memoryBudgetMb * 1024 * 1024) / bytesPerSplat);\r\n            budget = Math.min(budget, fromMB);\r\n        }\r\n        if (!hasExplicitLimit && fullCapacity !== null) {\r\n            budget = fullCapacity;\r\n        } else if (!hasExplicitLimit) {\r\n            const automaticMb = this._scene.getEngine().hostInformation?.isMobile ? MobileAutomaticResidentMemoryMb : DesktopAutomaticResidentMemoryMb;\r\n            const automaticCount = Math.floor((automaticMb * 1024 * 1024) / bytesPerSplat);\r\n            const refinementHeadroom = Math.max(0, Math.floor(largestBaseFileCount));\r\n            const coarseWithHeadroom = GaussianSplattingStream._SafeAddCounts(this._minimumResidentSplats, refinementHeadroom, \"automatic resident capacity\");\r\n            budget = Math.max(automaticCount, coarseWithHeadroom);\r\n        } else if (budget < this._minimumResidentSplats) {\r\n            Logger.Warn(\r\n                `GaussianSplattingStream: the requested initial residency (${budget} splats) is below the complete coarse minimum (${this._minimumResidentSplats}); using the minimum.`\r\n            );\r\n        }\r\n\r\n        budget = Math.max(this._minimumResidentSplats, Math.floor(budget));\r\n        if (fullCapacity !== null) {\r\n            budget = Math.min(budget, fullCapacity);\r\n        }\r\n        if (fullCapacity !== null || this._minimumResidentSplats > 0) {\r\n            const maxTextureSize = Math.floor(this._scene.getEngine().getCaps().maxTextureSize);\r\n            const maxCapacity = maxTextureSize * maxTextureSize;\r\n            if (!Number.isSafeInteger(maxCapacity) || this._minimumResidentSplats > maxCapacity) {\r\n                throw new Error(`GaussianSplattingStream: minimum resident splat count ${this._minimumResidentSplats} exceeds the device texture capacity ${maxCapacity}.`);\r\n            }\r\n            if (budget > maxCapacity) {\r\n                budget = maxCapacity;\r\n            }\r\n            if (budget < this._minimumResidentSplats) {\r\n                throw new Error(`GaussianSplattingStream: minimum resident splat count ${this._minimumResidentSplats} exceeds the device texture capacity ${maxCapacity}.`);\r\n            }\r\n        }\r\n        if (!Number.isSafeInteger(budget) || budget < this._minimumResidentSplats || budget < 1) {\r\n            throw new Error(\"GaussianSplattingStream: resolved resident capacity is invalid.\");\r\n        }\r\n        this._residentBudget = budget;\r\n        return budget;\r\n    }\r\n\r\n    /**\r\n     * Returns the estimated combined GPU/CPU bytes occupied by one resident splat.\r\n     * @returns estimated bytes per resident splat\r\n     */\r\n    private _bytesPerResidentSplat(): number {\r\n        // The three rotation textures use half floats (8 B each) when supported, otherwise full floats (16 B each).\r\n        const rotBytes = this._scene.getEngine().getCaps().textureHalfFloatRender ? 24 : 48;\r\n        return BytesPerResidentSplat + this._shTextureCount * 16 + (this._needsRotationScale ? rotBytes : 0);\r\n    }\r\n\r\n    /**\r\n     * Collects the unique set of source file indices referenced by any LOD of any leaf, sorted ascending.\r\n     * @returns sorted unique file indices\r\n     */\r\n    private _collectAllFileIds(): number[] {\r\n        const ids = new Set<number>();\r\n        for (const node of this._leafNodes) {\r\n            for (const level of node.availableLevels!) {\r\n                const entry = node.lods![String(level)];\r\n                if (entry) {\r\n                    ids.add(entry.file);\r\n                }\r\n            }\r\n        }\r\n        return Array.from(ids).sort((a, b) => a - b);\r\n    }\r\n\r\n    /**\r\n     * Collects unique whole source files required by the coarsest entry of every valid leaf.\r\n     * @returns sorted unique coarse file indices\r\n     */\r\n    private _collectBaseFileIds(): number[] {\r\n        const ids = new Set<number>();\r\n        for (const node of this._leafNodes) {\r\n            const entry = node.lods?.[String(node.baseLod)];\r\n            if (entry) {\r\n                ids.add(entry.file);\r\n            }\r\n        }\r\n        return Array.from(ids).sort((a, b) => a - b);\r\n    }\r\n\r\n    /**\r\n     * Resolves the immutable minimum initial capacity from padding, environment, and unique whole coarse files.\r\n     * @param baseFileIds unique coarse source file indices\r\n     * @param environmentCount included environment splat count\r\n     */\r\n    private _resolveMinimumResidentSplats(baseFileIds: number[], environmentCount: number): void {\r\n        let minimum = GaussianSplattingStream._SafeAddCounts(1, Math.max(0, Math.floor(environmentCount)), \"minimum resident splats\");\r\n        for (const fileId of baseFileIds) {\r\n            const count = this._fileCounts.get(fileId);\r\n            if (count === undefined || !Number.isSafeInteger(count) || count <= 0) {\r\n                throw new Error(`GaussianSplattingStream: required coarse metadata for file ${fileId} is unavailable or invalid.`);\r\n            }\r\n            minimum = GaussianSplattingStream._SafeAddCounts(minimum, count, \"minimum resident splats\");\r\n        }\r\n        this._minimumResidentSplats = minimum;\r\n    }\r\n\r\n    /**\r\n     * Settles the level-0 diagnostic from normalized renderable leaf entries after their source metadata resolves.\r\n     * A file may back several leaf ranges, so its source count is deliberately not used in the total.\r\n     */\r\n    private _resolveLod0SplatCount(): void {\r\n        let total = 0;\r\n        let hasLod0Entry = false;\r\n        for (const node of this._leafNodes) {\r\n            if (node.availableLevels?.[0] !== 0) {\r\n                continue;\r\n            }\r\n            const entry = node.lods?.[\"0\"];\r\n            if (!entry) {\r\n                this._lod0SplatCount = Object.freeze({ status: \"unavailable\" as const });\r\n                return;\r\n            }\r\n            hasLod0Entry = true;\r\n            if (!this._fileCounts.has(entry.file) || !this._fileMeta.has(entry.file)) {\r\n                this._lod0SplatCount = Object.freeze({ status: \"unavailable\" as const });\r\n                return;\r\n            }\r\n            total += entry.count;\r\n            if (!Number.isSafeInteger(total)) {\r\n                this._lod0SplatCount = Object.freeze({ status: \"unavailable\" as const });\r\n                return;\r\n            }\r\n        }\r\n        this._lod0SplatCount = hasLod0Entry ? Object.freeze({ status: \"available\" as const, count: total }) : Object.freeze({ status: \"unavailable\" as const });\r\n    }\r\n\r\n    /**\r\n     * Fetches the environment bundle and the supplied referenced files' metadata to learn splat counts, caching\r\n     * each file's parsed metadata for the later on-demand decode. File metadata fetches run in parallel.\r\n     * @param fileIds file indices to fetch metadata for\r\n     * @param includeEnvironment whether to fetch the optional environment bundle in this phase\r\n     * @returns the environment splat count (0 when there is no environment)\r\n     */\r\n    private async _gatherCountsAsync(fileIds: number[], includeEnvironment = true): Promise<number> {\r\n        let envCount = 0;\r\n        // Track the max SH degree/coeffs across every streamed file (+ environment): the baked SH atlas is sized\r\n        // for the max once, up front, so no mid-stream resize — lower-degree files neutral-fill their higher bands.\r\n        let maxShDegree = 0;\r\n        let maxCoeffs = 0;\r\n        const foldSh = (data: SOGRootData) => {\r\n            const info = GaussianSplattingStream._GetShInfo(data);\r\n            if (info.degree > maxShDegree) {\r\n                maxShDegree = info.degree;\r\n            }\r\n            if (info.coeffs > maxCoeffs) {\r\n                maxCoeffs = info.coeffs;\r\n            }\r\n        };\r\n        if (includeEnvironment && this._metadata.environment) {\r\n            try {\r\n                const url = this._rootUrl + this._metadata.environment;\r\n                const buffer = await this._downloadManager.loadFileAsync(url);\r\n                const files = await this._unzipAsync(new Uint8Array(buffer));\r\n                const metaBytes = files.get(\"meta.json\");\r\n                if (metaBytes) {\r\n                    const meta = JSON.parse(new TextDecoder().decode(metaBytes)) as SOGRootData;\r\n                    envCount = GaussianSplattingStream._GetSplatCount(meta);\r\n                    foldSh(meta);\r\n                    this._environmentFiles = files;\r\n                }\r\n            } catch (e: any) {\r\n                // The environment is non-essential — keep streaming the LOD tree even if it fails.\r\n                Logger.Warn(\"GaussianSplattingStream: failed to load environment: \" + (e?.message ?? e));\r\n            }\r\n        }\r\n\r\n        await Promise.all(\r\n            fileIds.map(async (fileId) => {\r\n                const relativePath = this._metadata.filenames[fileId];\r\n                if (!relativePath) {\r\n                    Logger.Warn(`GaussianSplattingStream: missing filename for file index ${fileId}.`);\r\n                    return;\r\n                }\r\n                try {\r\n                    const metaUrl = this._rootUrl + relativePath;\r\n                    const subRootUrl = metaUrl.substring(0, metaUrl.lastIndexOf(\"/\") + 1);\r\n                    const metaBuffer = await this._downloadManager.loadFileAsync(metaUrl);\r\n                    const sogData = JSON.parse(new TextDecoder().decode(new Uint8Array(metaBuffer))) as SOGRootData;\r\n                    this._fileCounts.set(fileId, GaussianSplattingStream._GetSplatCount(sogData));\r\n                    this._fileMeta.set(fileId, { sogData, subRootUrl });\r\n                } catch (e: any) {\r\n                    Logger.Warn(`GaussianSplattingStream: failed to load metadata for ${relativePath}: ${e?.message ?? e}`);\r\n                }\r\n            })\r\n        );\r\n\r\n        // Fold in every file's SH (done after the parallel fetch so _fileMeta is fully populated).\r\n        for (const { sogData } of this._fileMeta.values()) {\r\n            foldSh(sogData);\r\n        }\r\n\r\n        // Resolve the stream's baked-SH configuration: enabled only when requested AND the data carries shN.\r\n        if (this._decodeSh && maxShDegree > 0 && maxCoeffs > 0) {\r\n            this._streamShDegree = Math.max(this._streamShDegree, maxShDegree);\r\n            // Packed-u32 SH textures: 16 SH scalar-bytes per texel, 3 channels per coefficient (matches ParseSogDatas).\r\n            this._shTextureCount = Math.max(this._shTextureCount, Math.ceil((maxCoeffs * 3) / 16));\r\n        }\r\n\r\n        return envCount;\r\n    }\r\n\r\n    /**\r\n     * Queues a file for on-demand decode if it isn't already decoded, in flight, or already queued.\r\n     * @param fileId file index to decode\r\n     */\r\n    private _enqueueDecode(fileId: number): void {\r\n        if (this._decodedFiles.has(fileId) || this._loadingFiles.has(fileId) || !this._fileMeta.has(fileId)) {\r\n            return;\r\n        }\r\n        if (this._decodeQueue.indexOf(fileId) === -1) {\r\n            this._decodeQueue.push(fileId);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Starts up to {@link _maxDecodesPerFrame} queued decodes for this frame. Decodes run asynchronously\r\n     * and promote any waiting nodes once they complete.\r\n     */\r\n    private _pumpDecodeQueue(): void {\r\n        let started = 0;\r\n        while (this._decodeQueue.length > 0 && started < this._maxDecodesPerFrame) {\r\n            const fileId = this._decodeQueue.shift()!;\r\n            if (this._decodedFiles.has(fileId) || this._loadingFiles.has(fileId)) {\r\n                continue;\r\n            }\r\n            started++;\r\n            // eslint-disable-next-line github/no-then\r\n            this._decodeFileAsync(fileId).catch((e) => {\r\n                Logger.Warn(\"GaussianSplattingStream: decode failed: \" + (e?.message ?? e));\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Writes a decoded splat range's positions into the shared buffer, expands the bounds, and incrementally\r\n     * patches the sort worker.\r\n     * @param positions stride-4 positions for the range\r\n     * @param base first splat index of the range in the work buffer\r\n     * @param count number of splats in the range\r\n     */\r\n    private _applyPositions(positions: Float32Array, base: number, count: number): void {\r\n        // In hosted mode _splatPositions is the compound's shared buffer; the region starts at _positionBase.\r\n        this._splatPositions!.set(positions, (this._positionBase + base) * 4);\r\n        this._updateBounds(positions, count);\r\n        // Incrementally patch only this range in the sort worker (avoids the full position-buffer re-copy).\r\n        this._sinkPostPositionsRange(base, count);\r\n    }\r\n\r\n    // ---- Sink routing: standalone drives this mesh; hosted drives the compound's reserved-part handle. ----\r\n\r\n    /**\r\n     * Sets the active source ranges (local to the stream's buffer) on the render sink.\r\n     * @param localRanges active ranges in the stream's local index space\r\n     */\r\n    private _sinkSetActiveRanges(localRanges: readonly IGaussianSplattingSplatRange[]): void {\r\n        if (this._host) {\r\n            this._host.setActiveRanges(localRanges);\r\n        } else {\r\n            this.setSplatIndexRanges(localRanges);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Patches a decoded position range (local offset) into the render sink's sort worker.\r\n     * @param base first splat index of the range, local to the stream's buffer\r\n     * @param count number of splats in the range\r\n     */\r\n    private _sinkPostPositionsRange(base: number, count: number): void {\r\n        if (this._host) {\r\n            this._host.postPositionsRange(base, count);\r\n        } else {\r\n            this._postWorkerPositionsRange(base, count);\r\n        }\r\n    }\r\n\r\n    /** Re-posts the full position/part set to the render sink's worker (after a relayout moved the region). */\r\n    private _sinkNotifyDataChanged(): void {\r\n        if (this._host) {\r\n            this._host.notifyDataChanged();\r\n        } else {\r\n            this._notifyWorkerNewData();\r\n        }\r\n    }\r\n\r\n    /** Whether the render sink's depth sort is settled. */\r\n    private get _sinkIsDepthSortSettled(): boolean {\r\n        return this._host ? this._host.isDepthSortSettled : this._isDepthSortSettled;\r\n    }\r\n\r\n    /**\r\n     * One-time validation of GPU position readback: reads a sample of the just-decoded range back from the work\r\n     * buffer and compares it to the CPU-decoded positions. Enables {@link _useGpuPositionReadback} only on an\r\n     * exact (within float tolerance) match, so an unsupported or incorrect readback (e.g. a backend without the\r\n     * required texture usage, or an orientation mismatch) safely keeps the CPU decode path.\r\n     * @param base first splat index of the validated range\r\n     * @param count number of splats in the range\r\n     * @param cpuPositions the CPU-decoded stride-4 positions for the range (ground truth)\r\n     */\r\n    private async _probeReadbackAsync(base: number, count: number, cpuPositions: Float32Array): Promise<void> {\r\n        this._readbackProbed = true;\r\n        if (!this._workBuffer) {\r\n            return;\r\n        }\r\n        const sampleCount = Math.min(count, 1024);\r\n        let ok = false;\r\n        try {\r\n            const gpu = await this._workBuffer.readCentersRangeAsync(base, sampleCount);\r\n            if (this._disposed) {\r\n                return;\r\n            }\r\n            if (gpu && gpu.length >= sampleCount * 4) {\r\n                ok = true;\r\n                for (let i = 0; i < sampleCount && ok; i++) {\r\n                    for (let j = 0; j < 3; j++) {\r\n                        const a = gpu[i * 4 + j];\r\n                        const b = cpuPositions[i * 4 + j];\r\n                        if (Math.abs(a - b) > 1e-2 * (1 + Math.abs(b))) {\r\n                            ok = false;\r\n                            break;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        } catch {\r\n            ok = false;\r\n        }\r\n        this._useGpuPositionReadback = ok;\r\n        Logger.Log(\r\n            ok\r\n                ? \"GaussianSplattingStream: GPU position readback validated; streamed LOD positions are read back from the GPU.\"\r\n                : \"GaussianSplattingStream: GPU position readback unavailable; decoding LOD positions on the CPU.\"\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Resolves the decoded positions for a splat range and applies them. Once GPU readback has been validated,\r\n     * positions are read back from the work buffer (non-blocking) and `pack.positions` is empty; otherwise the\r\n     * CPU-decoded `pack.positions` are used, and — on the first such decode — the GPU readback is validated\r\n     * against them so subsequent decodes can use the fast path.\r\n     * @param pack the parsed SOG pack (its `positions` is populated only on the CPU path)\r\n     * @param base first splat index of the range in the work buffer\r\n     * @param count number of splats in the range\r\n     * @returns whether positions were applied\r\n     */\r\n    private async _applyDecodedPositionsAsync(pack: ISogTexturePack, base: number, count: number): Promise<boolean> {\r\n        if (this._useGpuPositionReadback && this._workBuffer) {\r\n            const positions = await this._workBuffer.readCentersRangeAsync(base, count);\r\n            if (this._disposed) {\r\n                return false;\r\n            }\r\n            if (positions && this._splatPositions) {\r\n                this._applyPositions(positions, base, count);\r\n                return true;\r\n            }\r\n            // Validated readback unexpectedly returned nothing; fall through to the (likely empty) CPU positions.\r\n        }\r\n\r\n        const cpu = pack.positions.length >= count * 4 ? (pack.positions.subarray(0, count * 4) as Float32Array) : null;\r\n        if (!cpu || !this._splatPositions) {\r\n            return false;\r\n        }\r\n        this._applyPositions(cpu, base, count);\r\n        // First CPU decode while readback is a candidate: validate it so later decodes can use the fast path.\r\n        if (!this._readbackProbed && this._readbackCandidate) {\r\n            await this._probeReadbackAsync(base, count, cpu);\r\n        }\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * Decodes the always-on environment bundle into its work-buffer block and activates its range.\r\n     */\r\n    private async _decodeEnvironmentAsync(): Promise<void> {\r\n        if (!this._environmentRange || !this._environmentFiles || !this._workBuffer) {\r\n            return;\r\n        }\r\n        const range = this._environmentRange;\r\n        let decoded = false;\r\n        try {\r\n            const parsed = await ParseSogMetaAsTextures(this._environmentFiles, \"\", this._scene, !this._useGpuPositionReadback, this._downloadManager);\r\n            const pack = parsed.sogTextures;\r\n            if (!pack) {\r\n                Logger.Warn(\"GaussianSplattingStream: environment decoding produced no texture data.\");\r\n                return;\r\n            }\r\n            try {\r\n                if (this._disposed || !this._workBuffer) {\r\n                    return;\r\n                }\r\n                await this._workBuffer.decodeAsync(pack, range.offset);\r\n                if (this._disposed) {\r\n                    return;\r\n                }\r\n                const positionsApplied = await this._applyDecodedPositionsAsync(pack, range.offset, range.count);\r\n                if (this._disposed) {\r\n                    return;\r\n                }\r\n                if (!positionsApplied) {\r\n                    Logger.Warn(\"GaussianSplattingStream: decoded positions could not be applied for the environment.\");\r\n                    return;\r\n                }\r\n                if (this._residency?.pin(EnvironmentFileId, range.count) !== range.offset) {\r\n                    throw new Error(\"GaussianSplattingStream: decoded environment could not be pinned.\");\r\n                }\r\n                decoded = true;\r\n                this._refreshActiveRanges();\r\n            } finally {\r\n                // Always release the GPU source textures (the decode pass is the only consumer).\r\n                GaussianSplattingStream._DisposePack(pack);\r\n            }\r\n        } catch (e: any) {\r\n            Logger.Warn(\"GaussianSplattingStream: failed to decode environment: \" + (e?.message ?? e));\r\n        } finally {\r\n            if (!decoded) {\r\n                this._residency?.free(EnvironmentFileId);\r\n                this._environmentRange = null;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Loads one LOD source file as GPU textures, decodes it into its fixed work-buffer block, records its\r\n     * CPU centers for sorting, frees the source textures, then promotes any nodes that were waiting for it.\r\n     * Concurrent or repeat requests for the same file are ignored. If the file is cancelled mid-flight\r\n     * (because every node that wanted it retargeted), the decode bails cooperatively at the next checkpoint.\r\n     * @param fileId file index to decode\r\n     * @returns whether the file was decoded and published successfully\r\n     */\r\n    private async _decodeFileAsync(fileId: number): Promise<boolean> {\r\n        if (this._decodedFiles.has(fileId)) {\r\n            return true;\r\n        }\r\n        if (this._loadingFiles.has(fileId) || !this._residency) {\r\n            return false;\r\n        }\r\n        const meta = this._fileMeta.get(fileId);\r\n        const count = this._fileCounts.get(fileId);\r\n        if (!meta || count === undefined) {\r\n            return false;\r\n        }\r\n        this._loadingFiles.add(fileId);\r\n        this._cancelledDecodes.delete(fileId);\r\n        let allocated = false;\r\n        try {\r\n            const parsed = await ParseSogMetaAsTextures(meta.sogData, meta.subRootUrl, this._scene, !this._useGpuPositionReadback, this._downloadManager, fileId);\r\n            const pack = parsed.sogTextures;\r\n            if (!pack) {\r\n                return false;\r\n            }\r\n            // Serialize the allocate -> decode -> readback section: a relayout runs only inside it (see\r\n            // _relayoutAndAllocateAsync), so it never moves a file whose decode has not finished writing.\r\n            const release = await this._acquireDecodeGateAsync();\r\n            try {\r\n                if (this._disposed || !this._workBuffer || this._cancelledDecodes.has(fileId)) {\r\n                    return false;\r\n                }\r\n                const residency = this._residency;\r\n                if (!residency) {\r\n                    return false;\r\n                }\r\n                let base = residency.allocate(fileId, count);\r\n                if (base === null) {\r\n                    // Defragment the work buffer to reclaim fragmented free space, then retry.\r\n                    base = await this._relayoutAndAllocateAsync(fileId, count);\r\n                }\r\n                if (base === null) {\r\n                    // No room even after evicting and compacting: refuse and keep nodes on their current LOD.\r\n                    // A file cancelled mid-flight isn't a budget problem, so don't warn for it.\r\n                    if (!this._cancelledDecodes.has(fileId)) {\r\n                        Logger.Warn(`GaussianSplattingStream: resident memory budget full; skipping LOD file ${fileId}.`);\r\n                    }\r\n                    return false;\r\n                }\r\n                allocated = true;\r\n                if (this._disposed || !this._workBuffer || this._cancelledDecodes.has(fileId)) {\r\n                    return false;\r\n                }\r\n                await this._workBuffer.decodeAsync(pack, base);\r\n                if (this._disposed || this._cancelledDecodes.has(fileId)) {\r\n                    return false;\r\n                }\r\n                const positionsApplied = await this._applyDecodedPositionsAsync(pack, base, count);\r\n                if (this._disposed) {\r\n                    return false;\r\n                }\r\n                if (!positionsApplied) {\r\n                    Logger.Warn(`GaussianSplattingStream: decoded positions could not be applied for LOD file ${fileId}.`);\r\n                    return false;\r\n                }\r\n                if (this._baseFileIds.has(fileId)) {\r\n                    if (residency.pin(fileId, count) !== base) {\r\n                        throw new Error(`GaussianSplattingStream: required coarse file ${fileId} could not be pinned.`);\r\n                    }\r\n                }\r\n                this._decodedFiles.add(fileId);\r\n                // Promote any nodes that can now reach their desired LOD via this newly decoded file.\r\n                if (this._applyDesiredLods()) {\r\n                    this._refreshActiveRanges();\r\n                }\r\n                return true;\r\n            } finally {\r\n                GaussianSplattingStream._DisposePack(pack);\r\n                release();\r\n            }\r\n        } catch (e) {\r\n            // A cancelled file rejects its downloads on purpose — swallow that; re-throw genuine failures.\r\n            if (!this._cancelledDecodes.has(fileId)) {\r\n                throw e;\r\n            }\r\n            return false;\r\n        } finally {\r\n            // If a slot was allocated but the decode did not complete (cancelled/disposed), release it.\r\n            if (allocated && !this._decodedFiles.has(fileId)) {\r\n                this._residency?.free(fileId);\r\n            }\r\n            this._loadingFiles.delete(fileId);\r\n            this._cancelledDecodes.delete(fileId);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Acquires the decode gate (a simple async mutex). Resolves once any prior holder releases, returning a\r\n     * release function the caller must invoke in a `finally`.\r\n     * @returns the release function\r\n     */\r\n    private async _acquireDecodeGateAsync(): Promise<() => void> {\r\n        const previous = this._decodeGate;\r\n        let release!: () => void;\r\n        this._decodeGate = new Promise<void>((resolve) => {\r\n            release = resolve;\r\n        });\r\n        await previous;\r\n        return release;\r\n    }\r\n\r\n    /**\r\n     * Defragments the work buffer to make room for a file that did not fit, then allocates its slot. Runs the\r\n     * compaction + GPU relayout atomically inside a single `onBeforeRender` so no inconsistent CPU/GPU layout\r\n     * is ever rendered. Returns the new slot offset, or null if even compaction cannot free enough contiguous\r\n     * space (the caller refuses the upgrade).\r\n     * @param fileId file to allocate after compaction\r\n     * @param count splats the file needs\r\n     * @returns the allocated offset, or null\r\n     */\r\n    private async _relayoutAndAllocateAsync(fileId: number, count: number): Promise<Nullable<number>> {\r\n        if (!this._residency || !this._workBuffer) {\r\n            return null;\r\n        }\r\n        // Even a perfect compaction cannot help if the total free space is below what is needed.\r\n        if (this._residency.freeSize < count) {\r\n            return null;\r\n        }\r\n        return await new Promise<Nullable<number>>((resolve) => {\r\n            const attempt = () => {\r\n                // Bail out (no relayout) if the file was cancelled while we waited for the shader to be ready,\r\n                // so rapidly-changing targets don't trigger an expensive compaction for a file no longer needed.\r\n                if (this._disposed || !this._residency || !this._workBuffer || this._cancelledDecodes.has(fileId)) {\r\n                    resolve(null);\r\n                    return;\r\n                }\r\n                if (!this._workBuffer.isRelayoutReady()) {\r\n                    this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n                    return;\r\n                }\r\n                this._performRelayout();\r\n                resolve(this._residency.allocate(fileId, count));\r\n            };\r\n            this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Compacts the resident set and relocates the corresponding GPU textures and CPU positions to the new\r\n     * layout. Must run at a frame-safe point with the work buffer's relayout shader ready.\r\n     */\r\n    private _performRelayout(): void {\r\n        if (!this._residency || !this._workBuffer || !this._splatPositions) {\r\n            return;\r\n        }\r\n        const oldOffsets = this._relayoutOldOffsets;\r\n        oldOffsets.clear();\r\n        for (const block of this._residency.getResidentBlocks()) {\r\n            oldOffsets.set(block.file, block.offset);\r\n        }\r\n        const moves = this._residency.compact();\r\n        if (moves.length === 0) {\r\n            return;\r\n        }\r\n\r\n        const capacity = this._residency.capacity;\r\n        if (!this._relayoutSrcIndex || this._relayoutSrcIndex.length !== capacity) {\r\n            this._relayoutSrcIndex = new Float32Array(capacity);\r\n        }\r\n        const srcIndexByDst = this._relayoutSrcIndex;\r\n        srcIndexByDst.fill(-1);\r\n\r\n        const resident = this._residency.getResidentBlocks();\r\n        // Destination->source splat index map for the GPU relayout pass.\r\n        for (const block of resident) {\r\n            const oldOffset = oldOffsets.get(block.file)!;\r\n            for (let k = 0; k < block.count; k++) {\r\n                srcIndexByDst[block.offset + k] = oldOffset + k;\r\n            }\r\n        }\r\n        // GPU: relocate the decoded textures in place (same texture instances).\r\n        this._workBuffer.relayoutSync(srcIndexByDst);\r\n\r\n        // CPU positions: compaction only ever moves a block to a lower offset, so copying in place in ascending\r\n        // new-offset order is safe (a block's source is never overwritten by an earlier move). This avoids a\r\n        // full capacity*4 scratch buffer. Block offsets are region-local; in hosted mode `_splatPositions` is the\r\n        // compound-wide buffer, so shift both source and destination by the region base (`_positionBase`, 0 standalone).\r\n        const positions = this._splatPositions;\r\n        const base = this._positionBase;\r\n        resident.sort((a, b) => a.offset - b.offset);\r\n        for (const block of resident) {\r\n            const oldOffset = oldOffsets.get(block.file)!;\r\n            if (oldOffset !== block.offset) {\r\n                positions.copyWithin((base + block.offset) * 4, (base + oldOffset) * 4, (base + oldOffset + block.count) * 4);\r\n            }\r\n        }\r\n\r\n        // Update the environment offset (it may have moved), re-post to the sort worker, and refresh ranges.\r\n        if (this._environmentRange) {\r\n            const envOffset = this._residency.offset(EnvironmentFileId);\r\n            if (envOffset !== undefined) {\r\n                this._environmentRange.offset = envOffset;\r\n            }\r\n        }\r\n        this._sinkNotifyDataChanged();\r\n        this._refreshActiveRanges();\r\n    }\r\n\r\n    /**\r\n     * Drops a file evicted by the residency controller from the decoded set so it will be re-decoded on demand.\r\n     * The file had no remaining references, so no node was rendering or downloading it.\r\n     * @param fileId evicted file index\r\n     */\r\n    private _onFileEvicted(fileId: number): void {\r\n        this._decodedFiles.delete(fileId);\r\n    }\r\n\r\n    /**\r\n     * Snaps a desired LOD level to the nearest level the node provides, while never selecting a level finer\r\n     * than {@link maxDetailLod} (i.e. with an index below the cap). Ties prefer the finer allowed level. If\r\n     * the node has no level at or coarser than the cap, its coarsest available level is used.\r\n     * @param node leaf node\r\n     * @param desired desired LOD level\r\n     * @returns the chosen available level\r\n     */\r\n    private _cappedLevelForNode(node: ISOGLODNode, desired: number): number {\r\n        const levels = node.availableLevels!;\r\n        const floor = this._maxDetailLod;\r\n        let best = -1;\r\n        let bestDiff = Number.POSITIVE_INFINITY;\r\n        for (const level of levels) {\r\n            if (level < floor) {\r\n                continue;\r\n            }\r\n            const diff = Math.abs(level - desired);\r\n            if (diff < bestDiff) {\r\n                best = level;\r\n                bestDiff = diff;\r\n            }\r\n        }\r\n        // No level is coarse enough to satisfy the cap: fall back to the coarsest the node has.\r\n        return best < 0 ? node.baseLod! : best;\r\n    }\r\n\r\n    /**\r\n     * Computes each node's {@link ISOGLODNode.targetLevel}. With the splat budget disabled this is the\r\n     * distance-optimal level snapped to an available level (capped by {@link maxDetailLod}) — unchanged prior\r\n     * behavior. With the budget enabled it converges a global pixel-size threshold to the budget and coarsens each\r\n     * node from its distance-optimal ceiling by how far its projected size falls below that threshold.\r\n     */\r\n    private _computeTargetLevels(): void {\r\n        const budget = this._effectiveSplatBudget();\r\n        if (budget <= 0) {\r\n            for (const node of this._leafNodes) {\r\n                const desired = node.optimalLod ?? node.baseLod!;\r\n                node.targetLevel = this._cappedLevelForNode(node, desired);\r\n            }\r\n            return;\r\n        }\r\n        // The environment is always rendered on top of the leaves, so reserve it as a fixed cost: the leaves\r\n        // converge against the remainder, keeping the stream's total (env + leaves) within the budget.\r\n        const leafBudget = Math.max(0, budget - this._environmentSplatCount());\r\n        this._convergePixelThreshold(leafBudget);\r\n        const t = this._lodPixelThreshold;\r\n        for (const node of this._leafNodes) {\r\n            node.targetLevel = this._budgetedLevel(node, t);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Splat count of the always-rendered environment layer (0 when none), coerced to a finite non-negative integer.\r\n     * Counted as a fixed cost in both the budget demand and the leaf convergence so it is never over-drawn.\r\n     * @returns the environment's rendered splat count\r\n     */\r\n    private _environmentSplatCount(): number {\r\n        const count = this._environmentRange ? Math.floor(Number(this._environmentRange.count)) : 0;\r\n        return Number.isFinite(count) && count > 0 ? count : 0;\r\n    }\r\n\r\n    /**\r\n     * The level a node renders at for a given pixel-size threshold `t`: its distance-optimal ceiling, coarsened by\r\n     * `round(log_mult(t / pixelSize))` geometric steps when its projected size is below `t`. Snapped to\r\n     * an available level honoring {@link maxDetailLod}.\r\n     * @param node leaf node\r\n     * @param t pixel-size threshold (pixels)\r\n     * @returns the chosen available LOD level\r\n     */\r\n    private _budgetedLevel(node: ISOGLODNode, t: number): number {\r\n        const ceiling = node.optimalLod ?? node.baseLod!;\r\n        const ps = node.pixelSize ?? 0;\r\n        let steps = 0;\r\n        if (ps > 0 && t > ps) {\r\n            steps = Math.max(0, Math.round(Math.log(t / ps) / Math.log(this._lodMultiplier)));\r\n        }\r\n        return this._cappedLevelForNode(node, ceiling + steps);\r\n    }\r\n\r\n    /**\r\n     * Splat count of a node's file at a given (already snapped) available level.\r\n     * @param node leaf node\r\n     * @param level available LOD level\r\n     * @returns the level's splat count (0 if absent)\r\n     */\r\n    private _countAtLevel(node: ISOGLODNode, level: number): number {\r\n        const entry = node.lods![String(level)];\r\n        return entry ? entry.count : 0;\r\n    }\r\n\r\n    /**\r\n     * Sum of every leaf's rendered splat count at pixel-size threshold `t`.\r\n     * @param t pixel-size threshold (pixels)\r\n     * @returns total rendered splats\r\n     */\r\n    private _totalSplatsAtThreshold(t: number): number {\r\n        let sum = 0;\r\n        for (const node of this._leafNodes) {\r\n            sum += this._countAtLevel(node, this._budgetedLevel(node, t));\r\n        }\r\n        return sum;\r\n    }\r\n\r\n    /**\r\n     * Converges the global pixel-size threshold {@link _lodPixelThreshold} to the largest detail whose total rendered\r\n     * splats is still within `budget` (the pixel-scale cut, floored at the true sub-pixel limit of 1 px). The\r\n     * total is monotonically non-increasing in the threshold, so a bisection on `[floorT, ceilT]` — where `ceilT`\r\n     * coarsens every node to its coarsest available level — gives a GUARANTEED result at or under the cap. When even\r\n     * that coarsest state exceeds the budget (the budget is below the pinned minimum detail), the threshold is set to\r\n     * `ceilT` so every node renders at minimum detail — the best achievable; the cap is then unavoidable. O(leaves)\r\n     * per iteration; no decode.\r\n     * @param budget target maximum rendered splat count\r\n     */\r\n    private _convergePixelThreshold(budget: number): void {\r\n        const floorT = 1; // sub-pixel limit, in pixels\r\n        // At the finest allowed (threshold floor) we are already within budget: no coarsening needed.\r\n        if (this._totalSplatsAtThreshold(floorT) <= budget) {\r\n            this._lodPixelThreshold = floorT;\r\n            return;\r\n        }\r\n        // A threshold large enough to coarsen every node to its coarsest available level: a node coarsens by\r\n        // round(log_mult(t / pixelSize)) steps, so t >= maxPixelSize · mult^(lodLevels + 1) saturates them all.\r\n        let maxPixelSize = floorT;\r\n        for (const node of this._leafNodes) {\r\n            if (node.pixelSize && node.pixelSize > maxPixelSize) {\r\n                maxPixelSize = node.pixelSize;\r\n            }\r\n        }\r\n        // Cap the exponent (real LOD trees are shallow) so untrusted metadata can't push ceilT to Infinity, which\r\n        // would skip the bisection below and force every node to minimum detail.\r\n        const lodLevels = Math.min(32, Math.max(1, this._metadata.lodLevels));\r\n        const ceilT = maxPixelSize * Math.pow(this._lodMultiplier, lodLevels + 1);\r\n        if (this._totalSplatsAtThreshold(ceilT) > budget) {\r\n            // Even the coarsest level exceeds the budget (pinned base layers alone are over): render minimum detail.\r\n            this._lodPixelThreshold = ceilT;\r\n            return;\r\n        }\r\n        // Bisection: `hi` always satisfies the cap (starts at ceilT), `lo` never does, so the result is guaranteed\r\n        // within budget while keeping the finest detail the budget allows. Deterministic => temporally stable.\r\n        let lo = floorT;\r\n        let hi = ceilT;\r\n        for (let i = 0; i < 40 && hi - lo > 1e-3 * hi; i++) {\r\n            const mid = 0.5 * (lo + hi);\r\n            if (this._totalSplatsAtThreshold(mid) <= budget) {\r\n                hi = mid;\r\n            } else {\r\n                lo = mid;\r\n            }\r\n        }\r\n        this._lodPixelThreshold = hi;\r\n    }\r\n\r\n    /**\r\n     * The finest already-decoded level of a node that is at least as coarse as `level` (index >= level). Used to\r\n     * enforce the budget cap immediately without waiting for a download. Returns `null` when no such level is resident\r\n     * — including when eviction has freed the base layer — so the caller keeps the currently-visible (resident) file\r\n     * rather than switching to a non-resident one, which would render a hole.\r\n     * @param node leaf node\r\n     * @param level the minimum coarseness (level index) required\r\n     * @returns a resident level index >= level, or null when none is resident\r\n     */\r\n    private _residentLevelAtLeast(node: ISOGLODNode, level: number): Nullable<number> {\r\n        for (const lvl of node.availableLevels!) {\r\n            if (lvl >= level && this._decodedFiles.has(node.lods![String(lvl)].file)) {\r\n                return lvl;\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n    /**\r\n     * Applies each node's {@link ISOGLODNode.targetLevel}: switches a node to its target level when that\r\n     * level's file is already decoded, otherwise records a pending download request for the file and leaves\r\n     * the node on its current LOD (so nothing ever disappears). Nodes within their post-switch cooldown are\r\n     * left untouched to damp oscillation (and keep their existing pending request).\r\n     *\r\n     * Each node tracks the single file it currently needs but lacks ({@link ISOGLODNode.pendingFile}). When a\r\n     * node's target changes before that file finished downloading, the old file's reference is released; if no\r\n     * other node still needs it, its queued/in-flight download is cancelled (see {@link _releaseFileRef}).\r\n     * @returns true when at least one node changed LOD (callers should refresh the active ranges)\r\n     */\r\n    private _applyDesiredLods(): boolean {\r\n        let dirty = false;\r\n        for (const node of this._leafNodes) {\r\n            const desired = node.targetLevel ?? node.baseLod!;\r\n\r\n            // Budget cap enforcement (only when a budget is in force — otherwise ordinary distance/frustum coarsening\r\n            // must keep going through the cooldown path below, unchanged from pre-budget behavior). If the node renders\r\n            // FINER than its target (activeLod index < target) it exceeds the cap, so coarsen immediately — bypassing\r\n            // the oscillation cooldown and any not-yet-downloaded finer target — to the finest already-resident level at\r\n            // least as coarse as the target. When nothing coarser is resident (e.g. eviction freed the base layer) keep\r\n            // the current visible file and let the normal path below queue the coarse download, so nothing disappears.\r\n            if (this._splatBudgetEnabled() && node.activeLod !== undefined && node.activeLod < desired) {\r\n                const coarse = this._residentLevelAtLeast(node, desired);\r\n                if (coarse !== null && coarse !== node.activeLod) {\r\n                    this._switchActiveFile(node, node.lods![String(coarse)].file);\r\n                    node.activeLod = coarse;\r\n                    node.lodCooldown = this._lodCooldownFrames;\r\n                    dirty = true;\r\n                }\r\n            }\r\n\r\n            // Nodes in cooldown keep their current LOD and their existing pending request untouched (the cap\r\n            // coarsening above already ran, so this only gates refinement toward the target).\r\n            if (node.lodCooldown && node.lodCooldown > 0) {\r\n                continue;\r\n            }\r\n            let newPending: number | undefined;\r\n            if (desired !== node.activeLod) {\r\n                const entry = node.lods![String(desired)];\r\n                if (entry) {\r\n                    if (this._decodedFiles.has(entry.file)) {\r\n                        this._switchActiveFile(node, entry.file);\r\n                        node.activeLod = desired;\r\n                        node.lodCooldown = this._lodCooldownFrames;\r\n                        dirty = true;\r\n                    } else {\r\n                        newPending = entry.file;\r\n                    }\r\n                }\r\n            }\r\n            // Reconcile this node's pending-download reference against its (possibly changed) target.\r\n            if (node.pendingFile !== newPending) {\r\n                if (node.pendingFile !== undefined) {\r\n                    this._releaseFileRef(node.pendingFile);\r\n                }\r\n                if (newPending !== undefined) {\r\n                    this._acquirePendingFile(newPending);\r\n                }\r\n                node.pendingFile = newPending;\r\n            }\r\n        }\r\n        return dirty;\r\n    }\r\n\r\n    /**\r\n     * Moves a node's resident reference from its previous active file to the one it now renders, so the file\r\n     * count that keeps a block in the work buffer stays accurate (and cancels any pending eviction of the new\r\n     * file). The new file is already decoded.\r\n     * @param node leaf node switching its rendered file\r\n     * @param file the file the node now renders from\r\n     */\r\n    private _switchActiveFile(node: ISOGLODNode, file: number): void {\r\n        if (node.activeFile === file) {\r\n            return;\r\n        }\r\n        if (node.activeFile !== undefined) {\r\n            this._releaseFileRef(node.activeFile);\r\n        }\r\n        this._acquireFileRef(file);\r\n        node.activeFile = file;\r\n    }\r\n\r\n    /**\r\n     * Adds a reference to a file (active render or pending download), cancelling any scheduled eviction.\r\n     * @param fileId file index\r\n     */\r\n    private _acquireFileRef(fileId: number): void {\r\n        const refs = (this._fileRefs.get(fileId) ?? 0) + 1;\r\n        this._fileRefs.set(fileId, refs);\r\n        if (refs === 1) {\r\n            // Referenced again before its eviction cooldown elapsed: keep it resident.\r\n            this._residency?.cancelEviction(fileId);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Records that a node needs a not-yet-decoded file, bumping its reference count and queueing the decode.\r\n     * @param fileId file index the node now targets\r\n     */\r\n    private _acquirePendingFile(fileId: number): void {\r\n        this._acquireFileRef(fileId);\r\n        this._enqueueDecode(fileId);\r\n    }\r\n\r\n    /**\r\n     * Releases a node's reference to a file. When the last reference is dropped: a decoded file is scheduled\r\n     * for eviction (when streaming under a budget), and a still-downloading file has its queued decode dropped\r\n     * and any in-flight download cancelled.\r\n     * @param fileId file index the node no longer references\r\n     */\r\n    private _releaseFileRef(fileId: number): void {\r\n        const refs = (this._fileRefs.get(fileId) ?? 0) - 1;\r\n        if (refs > 0) {\r\n            this._fileRefs.set(fileId, refs);\r\n            return;\r\n        }\r\n        this._fileRefs.delete(fileId);\r\n        if (this._decodedFiles.has(fileId)) {\r\n            // No node renders it anymore: schedule eviction (only when streaming under a budget).\r\n            if (this._evictionEnabled) {\r\n                this._residency?.scheduleEviction(fileId);\r\n            }\r\n            return;\r\n        }\r\n        // Still downloading/queued: drop the queued decode and cancel any in-flight download.\r\n        const queueIndex = this._decodeQueue.indexOf(fileId);\r\n        if (queueIndex !== -1) {\r\n            this._decodeQueue.splice(queueIndex, 1);\r\n        }\r\n        if (this._loadingFiles.has(fileId)) {\r\n            // Flag the in-flight decode to bail at its next checkpoint and cancel its image downloads.\r\n            this._cancelledDecodes.add(fileId);\r\n            this._downloadManager.cancelGroup(fileId);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Per-frame LOD streaming loop. Ticks cooldowns and pumps the decode queue every frame, and runs the\r\n     * cheap per-node frustum test every frame so the off-screen LOD bias tracks camera rotation. The LOD\r\n     * re-evaluation is throttled to at most every {@link _lodUpdateInterval} frames once the camera has\r\n     * translated far enough, but also runs immediately whenever a node enters/leaves the frustum (so its\r\n     * detail upgrades/downgrades promptly), a node whose cooldown just expired still needs to switch LOD,\r\n     * or a cap change forces it. Active ranges rebuild on any LOD change.\r\n     *\r\n     * The cooldown-expiry trigger lets a node reach its already-computed target level as soon as its\r\n     * cooldown clears, rather than waiting for the camera to move. This matters right from load: a\r\n     * node's base-layer decode is itself applied as a switch (from no active level to the base one), so\r\n     * it starts the same cooldown a later switch would — this trigger is what lets the node progress past\r\n     * that base level promptly once it expires, even at a fixed camera pose.\r\n     */\r\n    private _onLodFrame(): void {\r\n        if (this._disposed || !this._baseLayerReady) {\r\n            return;\r\n        }\r\n        let cooldownExpiredWithPendingSwitch = false;\r\n        for (const node of this._leafNodes) {\r\n            if (node.lodCooldown && node.lodCooldown > 0) {\r\n                node.lodCooldown--;\r\n                if (node.lodCooldown === 0 && node.targetLevel !== undefined && node.targetLevel !== node.activeLod) {\r\n                    cooldownExpiredWithPendingSwitch = true;\r\n                }\r\n            }\r\n        }\r\n        // Tick eviction cooldowns: unreferenced files are freed once their cooldown elapses (budgeted streaming).\r\n        if (this._evictionEnabled) {\r\n            this._residency?.tick();\r\n        }\r\n        // In-flight/queued decodes still progress every frame.\r\n        this._pumpDecodeQueue();\r\n\r\n        // Per-node frustum test runs every frame (cheap) so the off-screen LOD bias tracks camera rotation,\r\n        // not just the translation that gates the throttled LOD re-evaluation below.\r\n        const frustumChanged = this._updateNodeFrustum();\r\n\r\n        let runLodEval = this._forceLodUpdate || frustumChanged || cooldownExpiredWithPendingSwitch;\r\n        if (!runLodEval && ++this._framesSinceLodUpdate >= this._lodUpdateInterval) {\r\n            const cameras = this._getActiveLodCameras();\r\n            const threshold = this._lodUpdateDistance;\r\n            // Re-evaluate when the active-camera set changes, when ANY active camera translated past the threshold, or\r\n            // when a discrete projected-size input changed (identity / FOV / viewport / render size). LOD selection is\r\n            // view-direction-independent, so rotation alone doesn't need a re-eval (the frustum test above tracks it).\r\n            if (cameras.length !== this._lastLodCamPositions.length || this._computeLodSignature(cameras) !== this._lastLodSignature) {\r\n                runLodEval = true;\r\n            } else {\r\n                for (let i = 0; i < cameras.length; i++) {\r\n                    if (Vector3.DistanceSquared(cameras[i].globalPosition, this._lastLodCamPositions[i]) >= threshold * threshold) {\r\n                        runLodEval = true;\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        if (runLodEval) {\r\n            this._forceLodUpdate = false;\r\n            this._framesSinceLodUpdate = 0;\r\n            // Snapshot each active camera's position and the projected-size signature so the next throttled check\r\n            // measures movement/input changes against them.\r\n            const cameras = this._getActiveLodCameras();\r\n            this._lastLodCamPositions.length = 0;\r\n            for (const cam of cameras) {\r\n                this._lastLodCamPositions.push(cam.globalPosition.clone());\r\n            }\r\n            this._lastLodSignature = this._computeLodSignature(cameras);\r\n            this.evaluateOptimalLods();\r\n            this._computeTargetLevels();\r\n            if (this._applyDesiredLods()) {\r\n                this._refreshActiveRanges();\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * A cheap signature of the discrete inputs (besides camera translation, tracked separately) that affect projected\r\n     * pixel size: each camera's identity, FOV, FOV mode and viewport, plus the engine render size and the effective\r\n     * world matrix revision. A change invalidates the throttled budget LOD so a colocated camera swap / viewport\r\n     * resize / FOV change — or the stream (or its hosted proxy) being moved or scaled while still in frustum, which\r\n     * shifts every node's distance and projected size — can't leave it stale.\r\n     * @param cameras the active cameras\r\n     * @returns the signature string\r\n     */\r\n    private _computeLodSignature(cameras: Camera[]): string {\r\n        const engine = this._scene.getEngine();\r\n        let sig = `${engine.getRenderWidth()}x${engine.getRenderHeight()}#${this._getEffectiveWorldMatrix(false).updateFlag}`;\r\n        for (const cam of cameras) {\r\n            const vp = cam.viewport;\r\n            sig += `|${cam.uniqueId}:${cam.fov}:${cam.fovMode}:${vp.x},${vp.y},${vp.width},${vp.height}`;\r\n        }\r\n        return sig;\r\n    }\r\n\r\n    /**\r\n     * Updates each leaf node's {@link ISOGLODNode.inFrustum} flag: a node is in-frustum if it is inside ANY\r\n     * active camera's frustum (the union). When {@link frustumCulling} is disabled (or there are no cameras)\r\n     * every node is marked in-frustum. Bounds are static (from the LOD tree), so flags are valid for all nodes\r\n     * regardless of decode state. Returns true when any node's in-frustum state changed (so the LOD bias must be re-applied).\r\n     * @returns whether any node's in-frustum state changed\r\n     */\r\n    private _updateNodeFrustum(): boolean {\r\n        const cameras = this._getActiveLodCameras();\r\n        let changed = false;\r\n\r\n        if (!this._frustumCulling || cameras.length === 0) {\r\n            for (const node of this._leafNodes) {\r\n                if (node.inFrustum === false) {\r\n                    node.inFrustum = true;\r\n                    changed = true;\r\n                }\r\n            }\r\n            return changed;\r\n        }\r\n\r\n        const nodes = this._leafNodes;\r\n        const inAny = this._frustumScratch;\r\n        // Node bounds remain immutable in stream-local space. Compose that space to clip once per camera instead\r\n        // of transforming every leaf's box and sphere into world space every frame.\r\n        const world = this._getEffectiveWorldMatrix(false);\r\n        for (let i = 0; i < nodes.length; i++) {\r\n            inAny[i] = false;\r\n        }\r\n        // A node is in-frustum if inside ANY active camera's frustum: OR each camera's test into the accumulator.\r\n        for (const cam of cameras) {\r\n            cam.getViewMatrix().multiplyToRef(cam.getProjectionMatrix(), this._cullCameraViewProj);\r\n            world.multiplyToRef(this._cullCameraViewProj, this._cullViewProj);\r\n            Frustum.GetPlanesToRef(this._cullViewProj, this._frustumPlanes);\r\n            let validFrustum = true;\r\n            for (const plane of this._frustumPlanes) {\r\n                if (\r\n                    !Number.isFinite(plane.normal.x) ||\r\n                    !Number.isFinite(plane.normal.y) ||\r\n                    !Number.isFinite(plane.normal.z) ||\r\n                    !Number.isFinite(plane.d) ||\r\n                    plane.normal.lengthSquared() === 0\r\n                ) {\r\n                    validFrustum = false;\r\n                    break;\r\n                }\r\n            }\r\n            if (!validFrustum) {\r\n                // Degenerate transforms/projections cannot safely reject local volumes. Treat this camera as seeing\r\n                // every node, preserving conservative rendering rather than turning malformed planes into holes.\r\n                for (let i = 0; i < nodes.length; i++) {\r\n                    inAny[i] = true;\r\n                }\r\n                continue;\r\n            }\r\n            for (let i = 0; i < nodes.length; i++) {\r\n                if (!inAny[i] && nodes[i].cullBounds!.isInFrustum(this._frustumPlanes)) {\r\n                    inAny[i] = true;\r\n                }\r\n            }\r\n        }\r\n        for (let i = 0; i < nodes.length; i++) {\r\n            if (inAny[i] !== nodes[i].inFrustum) {\r\n                nodes[i].inFrustum = inAny[i];\r\n                changed = true;\r\n            }\r\n        }\r\n        return changed;\r\n    }\r\n\r\n    /**\r\n     * Normalizes an initial residency option, preserving finite non-positive values as an unset limit.\r\n     * @param value option value\r\n     * @param name option name used in errors\r\n     * @param integer whether the normalized value must be an integer splat count\r\n     * @returns normalized value\r\n     */\r\n    private static _NormalizeResidentLimit(value: number, name: string, integer: boolean): number {\r\n        if (!Number.isFinite(value)) {\r\n            throw new RangeError(`GaussianSplattingStream: ${name} must be finite.`);\r\n        }\r\n        if (value <= 0) {\r\n            return 0;\r\n        }\r\n        const normalized = integer ? Math.max(1, Math.floor(value)) : value;\r\n        if (normalized > Number.MAX_SAFE_INTEGER) {\r\n            throw new RangeError(`GaussianSplattingStream: ${name} is outside the supported range.`);\r\n        }\r\n        return normalized;\r\n    }\r\n\r\n    /**\r\n     * Adds trusted non-negative integer counts without allowing unsafe capacity arithmetic.\r\n     * @param left first count\r\n     * @param right second count\r\n     * @param label capacity name used in errors\r\n     * @returns the safe integer sum\r\n     */\r\n    private static _SafeAddCounts(left: number, right: number, label: string): number {\r\n        const sum = left + right;\r\n        if (!Number.isSafeInteger(left) || left < 0 || !Number.isSafeInteger(right) || right < 0 || !Number.isSafeInteger(sum)) {\r\n            throw new Error(`GaussianSplattingStream: ${label} exceeds the supported integer range.`);\r\n        }\r\n        return sum;\r\n    }\r\n\r\n    /**\r\n     * Reads the splat count from SOG metadata, coerced to a finite non-negative integer (metadata is untrusted, so\r\n     * `count` / `shape[0]` may be a string or malformed — a non-numeric value must not leak into count arithmetic).\r\n     * @param data SOG metadata\r\n     * @returns the splat count (0 when absent/invalid)\r\n     */\r\n    private static _GetSplatCount(data: SOGRootData): number {\r\n        const raw = data.count ?? (Array.isArray(data.means.shape) ? data.means.shape[0] : 0);\r\n        const count = Math.floor(Number(raw));\r\n        return Number.isFinite(count) && count > 0 ? count : 0;\r\n    }\r\n\r\n    /**\r\n     * Reads a SOG file's higher-order SH degree and coefficient count from its metadata, mirroring\r\n     * {@link ParseSogDatas}'s `coeffs`/`shDegree` derivation. Returns zeros when the file carries no `shN`.\r\n     * @param data parsed SOG root metadata\r\n     * @returns the SH degree and higher-order coefficient count (excludes the DC/SH0 term)\r\n     */\r\n    private static _GetShInfo(data: SOGRootData): { degree: number; coeffs: number } {\r\n        if (!data.shN) {\r\n            return { degree: 0, coeffs: 0 };\r\n        }\r\n        // Derive the SH degree from remote (untrusted) metadata, then validate/clamp it: the degree drives the SH\r\n        // render-target count and decode-pass count, so a bogus (huge / non-finite / negative) `bands` or `shape`\r\n        // must not be able to demand unbounded allocation. The draw path supports shTexture0..4, i.e. degree <= 4.\r\n        let degree = 0;\r\n        const bands = data.shN.bands;\r\n        if (typeof bands === \"number\" && Number.isFinite(bands) && bands > 0) {\r\n            degree = Math.floor(bands);\r\n        } else if (Array.isArray(data.shN.shape) && Number.isFinite(data.shN.shape[1]) && data.shN.shape[1] > 0) {\r\n            const shapeCoeffs = Math.floor(data.shN.shape[1] / 3);\r\n            degree = shapeCoeffs > 0 ? Math.round(Math.sqrt(shapeCoeffs + 1) - 1) : 0;\r\n        }\r\n        if (!(degree > 0)) {\r\n            return { degree: 0, coeffs: 0 };\r\n        }\r\n        if (degree > MaxSupportedShDegree) {\r\n            Logger.Warn(`GaussianSplattingStream: SH degree ${degree} exceeds the maximum supported (${MaxSupportedShDegree}); clamping.`);\r\n            degree = MaxSupportedShDegree;\r\n        }\r\n        return { degree, coeffs: (degree + 1) ** 2 - 1 };\r\n    }\r\n\r\n    /**\r\n     * Disposes all GPU source textures of a SOG pack (they are only needed for the one decode pass).\r\n     * @param pack the SOG texture pack\r\n     */\r\n    private static _DisposePack(pack: ISogTexturePack): void {\r\n        pack.meansTextureL.dispose();\r\n        pack.meansTextureU.dispose();\r\n        pack.scalesTexture.dispose();\r\n        pack.quatsTexture.dispose();\r\n        pack.sh0Texture.dispose();\r\n        pack.shCentroidsTexture?.dispose();\r\n        pack.shLabelsTexture?.dispose();\r\n        pack.codebookTexture?.dispose();\r\n    }\r\n\r\n    /**\r\n     * Expands the running splat-center bounds with a newly decoded file's centers and updates the\r\n     * mesh bounding info so the GS is correctly frustum-culled and pickable.\r\n     * @param positions stride-4 splat centers for the new file\r\n     * @param count number of splats\r\n     */\r\n    private _updateBounds(positions: Float32Array, count: number): void {\r\n        const min = this._boundsMin;\r\n        const max = this._boundsMax;\r\n        for (let i = 0; i < count; i++) {\r\n            const x = positions[i * 4 + 0];\r\n            const y = positions[i * 4 + 1];\r\n            const z = positions[i * 4 + 2];\r\n            min.minimizeInPlaceFromFloats(x, y, z);\r\n            max.maximizeInPlaceFromFloats(x, y, z);\r\n        }\r\n        // Hosted: grow the reserved part's (and compound's) bounds. Standalone: set this mesh's bounds.\r\n        if (this._host) {\r\n            this._host.expandBounds(min, max);\r\n        } else {\r\n            this.setBoundingInfo(new BoundingInfo(min, max));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Rebuilds the active interval set from the environment plus each node's currently-selected LOD entry,\r\n     * coalesces adjacent ranges, and pushes the result to the sort worker.\r\n     */\r\n    private _refreshActiveRanges(): void {\r\n        const ranges: IGaussianSplattingSplatRange[] = [];\r\n\r\n        if (this._environmentRange) {\r\n            ranges.push({ offset: this._environmentRange.offset, count: this._environmentRange.count });\r\n        }\r\n\r\n        for (const node of this._leafNodes) {\r\n            if (node.activeLod === undefined) {\r\n                continue;\r\n            }\r\n            const entry = node.lods![String(node.activeLod)];\r\n            if (!entry) {\r\n                continue;\r\n            }\r\n            const base = this._residency?.offset(entry.file);\r\n            if (base === undefined) {\r\n                continue;\r\n            }\r\n            ranges.push({ offset: base + entry.offset, count: entry.count });\r\n        }\r\n\r\n        // Ranges are local to the stream's buffer; the sink (compound handle) offsets them by the region base.\r\n        this._sinkSetActiveRanges(GaussianSplattingStream._CoalesceRanges(ranges));\r\n    }\r\n\r\n    /**\r\n     * Sorts and merges adjacent/overlapping ranges to keep the interval list compact.\r\n     * @param ranges raw ranges\r\n     * @returns coalesced ranges\r\n     */\r\n    private static _CoalesceRanges(ranges: IGaussianSplattingSplatRange[]): IGaussianSplattingSplatRange[] {\r\n        if (ranges.length <= 1) {\r\n            return ranges;\r\n        }\r\n        const sorted = ranges.slice().sort((a, b) => a.offset - b.offset);\r\n        const merged: IGaussianSplattingSplatRange[] = [{ offset: sorted[0].offset, count: sorted[0].count }];\r\n        for (let i = 1; i < sorted.length; i++) {\r\n            const last = merged[merged.length - 1];\r\n            const range = sorted[i];\r\n            const lastEnd = last.offset + last.count;\r\n            if (range.offset <= lastEnd) {\r\n                const end = Math.max(lastEnd, range.offset + range.count);\r\n                last.count = end - last.offset;\r\n            } else {\r\n                merged.push({ offset: range.offset, count: range.count });\r\n            }\r\n        }\r\n        return merged;\r\n    }\r\n\r\n    /**\r\n     * Unzips a `.sog` bundle into a name -> bytes map, loading fflate on demand.\r\n     * @param data zipped bytes\r\n     * @returns map of entry name to bytes\r\n     */\r\n    private async _unzipAsync(data: Uint8Array): Promise<Map<string, Uint8Array>> {\r\n        let fflateModule = this._streamOptions.fflate;\r\n        if (!fflateModule) {\r\n            if (typeof (window as any).fflate === \"undefined\") {\r\n                await Tools.LoadScriptAsync(this._streamOptions.deflateURL ?? \"https://unpkg.com/fflate/umd/index.js\");\r\n            }\r\n            fflateModule = (window as any).fflate;\r\n        }\r\n\r\n        const unzipped = fflateModule.unzipSync(data) as Record<string, Uint8Array>;\r\n        const files = new Map<string, Uint8Array>();\r\n        for (const [name, content] of Object.entries(unzipped)) {\r\n            files.set(name, content);\r\n        }\r\n        return files;\r\n    }\r\n}\r\n\r\n/**\r\n * Adds a PlayCanvas-style SOG LOD stream as a part of a compound Gaussian Splatting mesh, so the streamed\r\n * splats are depth-sorted and rendered in ONE pass together with the compound's other (static) parts.\r\n *\r\n * The returned mesh is a hidden controller: it streams SOG LOD files, GPU-decodes them into a reserved region\r\n * of the compound's shared atlas, and drives which of its splats are active (LOD) — the compound owns the sort\r\n * and the single instanced draw. The SOG up-axis orientation is applied to the reserved part's proxy transform;\r\n * move/hide the part via the proxy (`streamController` exposes it once streaming has started).\r\n * @param compound the compound mesh to add the streamed part to\r\n * @param name name for the streaming controller / part\r\n * @param metadata parsed `lod-meta.json`\r\n * @param rootUrl base URL the metadata's relative paths resolve against\r\n * @param options streaming options\r\n * @returns the streaming controller mesh (hidden; drives the reserved compound part)\r\n * @experimental\r\n */\r\nexport function AddGaussianSplattingStreamPart(\r\n    compound: GaussianSplattingMesh,\r\n    name: string,\r\n    metadata: ISOGLODMetadata,\r\n    rootUrl: string,\r\n    options: IGaussianSplattingStreamOptions = {}\r\n): GaussianSplattingStream {\r\n    return new GaussianSplattingStream(name, metadata, rootUrl, compound.getScene(), { ...options, hostCompound: compound });\r\n}\r\n\r\n/**\r\n * Adds a PlayCanvas-style SOG LOD stream as a part of a compound Gaussian Splatting mesh and resolves once the\r\n * part is ready to use, returning its {@link GaussianSplattingPartProxyMesh} — the same handle\r\n * `GaussianSplattingCompoundMesh.addPart` returns for a static part. This lets a host application treat a\r\n * streamed splat exactly like any other compound part (place/frame/gizmo via the proxy, remove via\r\n * `compound.removePart(proxy.partIndex)`); the streaming controller lives behind the proxy and is disposed\r\n * automatically when the part is removed.\r\n *\r\n * Resolves after the reserved region exists and its base layer has decoded (so the proxy's bounds are real),\r\n * and rejects if streaming fails before that (the partially-constructed stream is disposed on rejection).\r\n *\r\n * NOTE: the base-layer decode runs on the GPU inside the scene's render loop, so this promise only resolves once\r\n * the scene is rendering. Do not `await` it before the render loop has started (it would never resolve) — start\r\n * rendering (e.g. `engine.runRenderLoop`) first, or `await` it concurrently with the first frames.\r\n * @param compound the compound mesh to add the streamed part to\r\n * @param name name for the streaming controller / part\r\n * @param metadata parsed `lod-meta.json`\r\n * @param rootUrl base URL the metadata's relative paths resolve against\r\n * @param options streaming options\r\n * @returns the part proxy driving the streamed region, ready to place/frame\r\n * @experimental\r\n */\r\nexport async function AddGaussianSplattingStreamPartAsync(\r\n    compound: GaussianSplattingMesh,\r\n    name: string,\r\n    metadata: ISOGLODMetadata,\r\n    rootUrl: string,\r\n    options: IGaussianSplattingStreamOptions = {}\r\n): Promise<GaussianSplattingPartProxyMesh> {\r\n    const stream = new GaussianSplattingStream(name, metadata, rootUrl, compound.getScene(), { ...options, hostCompound: compound });\r\n    try {\r\n        await stream.whenPartReadyAsync();\r\n    } catch (e) {\r\n        stream.dispose();\r\n        throw e;\r\n    }\r\n    const proxy = stream.streamingPartProxy;\r\n    if (!proxy) {\r\n        stream.dispose();\r\n        throw new Error(\"GaussianSplattingStream: streaming part was not reserved.\");\r\n    }\r\n    // The controller already binds its own lifetime to the part (removePart / compound disposal dispose the stream,\r\n    // and stream disposal releases the reserved part) — wired at reservation inside the stream, so it also covers the\r\n    // download/decode window before this promise resolves. Nothing to register here.\r\n    return proxy;\r\n}\r\n","/* eslint-disable @typescript-eslint/promise-function-async */\r\nimport { Scalar } from \"core/Maths/math.scalar\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { runCoroutineAsync, createYieldingScheduler, type Coroutine } from \"core/Misc/coroutine\";\r\nimport { _LoadScriptModuleAsync } from \"core/Misc/tools.internals\";\r\nimport { type SPLATLoadingOptions } from \"./splatLoadingOptions\";\r\nimport { Mode, type IParsedSplat } from \"./splatDefs\";\r\nimport { AllocateShBuffers } from \"core/Meshes/GaussianSplatting/gaussianSplattingMeshBase\";\r\nimport { type GaussianCloud, type SpzModule, type SpzExtensionSafeOrbitCameraAdobe } from \"@adobe/spz\";\r\n\r\nconst _SpzConversionBatchSize = 32768;\r\nconst _SH_C0 = 0.28209479177387814;\r\n\r\n// Cached WASM module promise — initialized once, reused across all SPZ loads.\r\nlet _SpzModulePromise: Promise<SpzModule> | null = null;\r\nlet _SpzModuleUrl: string | null = null;\r\n\r\n/**\r\n * Parses SPZ data and returns a promise resolving to an IParsedSplat object.\r\n * @param data The ArrayBuffer containing SPZ data.\r\n * @param scene The Babylon.js scene.\r\n * @param _loadingOptions Options for loading Gaussian Splatting files.\r\n * @returns A promise resolving to the parsed SPZ data.\r\n */\r\nexport function ParseSpz(data: ArrayBuffer, scene: Scene, _loadingOptions: SPLATLoadingOptions): Promise<IParsedSplat> {\r\n    const ubuf = new Uint8Array(data);\r\n    const ubufu32 = new Uint32Array(data.slice(0, 12)); // Only need ubufu32[0] to [2]\r\n    // debug infos\r\n    const splatCount = ubufu32[2];\r\n\r\n    const shDegree = ubuf[12];\r\n    const fractionalBits = ubuf[13];\r\n    const flags = ubuf[14];\r\n    const reserved = ubuf[15];\r\n    const version = ubufu32[1];\r\n\r\n    // check magic and version\r\n    if (reserved || ubufu32[0] != 0x5053474e || version < 2 || version > 4) {\r\n        // reserved must be 0\r\n        return new Promise((resolve) => {\r\n            resolve({ mode: Mode.Reject, data: new ArrayBuffer(0), hasVertexColors: false });\r\n        });\r\n    }\r\n\r\n    const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32\r\n    const buffer = new ArrayBuffer(rowOutputLength * splatCount);\r\n\r\n    const positionScale = 1.0 / (1 << fractionalBits);\r\n\r\n    const int32View = new Int32Array(1);\r\n    const uint8View = new Uint8Array(int32View.buffer);\r\n    const read24bComponent = function (u8: Uint8Array, offset: number) {\r\n        uint8View[0] = u8[offset + 0];\r\n        uint8View[1] = u8[offset + 1];\r\n        uint8View[2] = u8[offset + 2];\r\n        uint8View[3] = u8[offset + 2] & 0x80 ? 0xff : 0x00;\r\n        return int32View[0] * positionScale;\r\n    };\r\n\r\n    let byteOffset = 16;\r\n\r\n    const position = new Float32Array(buffer);\r\n    const scale = new Float32Array(buffer);\r\n    const rgba = new Uint8ClampedArray(buffer);\r\n    const rot = new Uint8ClampedArray(buffer);\r\n\r\n    // positions\r\n    for (let i = 0; i < splatCount; i++) {\r\n        position[i * 8 + 0] = read24bComponent(ubuf, byteOffset + 0);\r\n        position[i * 8 + 1] = read24bComponent(ubuf, byteOffset + 3);\r\n        position[i * 8 + 2] = read24bComponent(ubuf, byteOffset + 6);\r\n        byteOffset += 9;\r\n    }\r\n\r\n    // colors\r\n    for (let i = 0; i < splatCount; i++) {\r\n        for (let component = 0; component < 3; component++) {\r\n            const byteValue = ubuf[byteOffset + splatCount + i * 3 + component];\r\n            // 0.15 is hard coded value from spz\r\n            // Scale factor for DC color components. To convert to RGB, we should multiply by 0.282, but it can\r\n            // be useful to represent base colors that are out of range if the higher spherical harmonics bands\r\n            // bring them back into range so we multiply by a smaller value.\r\n            const value = (byteValue - 127.5) / (0.15 * 255);\r\n            rgba[i * 32 + 24 + component] = Scalar.Clamp((0.5 + _SH_C0 * value) * 255, 0, 255);\r\n        }\r\n\r\n        rgba[i * 32 + 24 + 3] = ubuf[byteOffset + i];\r\n    }\r\n    byteOffset += splatCount * 4;\r\n\r\n    // scales\r\n    for (let i = 0; i < splatCount; i++) {\r\n        scale[i * 8 + 3 + 0] = Math.exp(ubuf[byteOffset + 0] / 16.0 - 10.0);\r\n        scale[i * 8 + 3 + 1] = Math.exp(ubuf[byteOffset + 1] / 16.0 - 10.0);\r\n        scale[i * 8 + 3 + 2] = Math.exp(ubuf[byteOffset + 2] / 16.0 - 10.0);\r\n        byteOffset += 3;\r\n    }\r\n\r\n    // convert quaternion\r\n    if (version >= 3) {\r\n        /*\r\n            In version 3, rotations are represented as the smallest three components of the normalized rotation quaternion, for optimal rotation accuracy.\r\n            The largest component can be derived from the others and is not stored. Its index is stored on 2 bits\r\n            and each of the smallest three components is encoded as a 10-bit signed integer.\r\n        */\r\n        const sqrt12 = Math.SQRT1_2;\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const r = [ubuf[byteOffset + 0], ubuf[byteOffset + 1], ubuf[byteOffset + 2], ubuf[byteOffset + 3]];\r\n\r\n            const comp = r[0] + (r[1] << 8) + (r[2] << 16) + (r[3] << 24);\r\n\r\n            const cmask = (1 << 9) - 1;\r\n            const rotation = [];\r\n            const iLargest = comp >>> 30;\r\n            let remaining = comp;\r\n            let sumSquares = 0;\r\n\r\n            for (let i = 3; i >= 0; --i) {\r\n                if (i !== iLargest) {\r\n                    const mag = remaining & cmask;\r\n                    const negbit = (remaining >>> 9) & 0x1;\r\n                    remaining = remaining >>> 10;\r\n\r\n                    rotation[i] = sqrt12 * (mag / cmask);\r\n                    if (negbit === 1) {\r\n                        rotation[i] = -rotation[i];\r\n                    }\r\n\r\n                    // accumulate the sum of squares\r\n                    sumSquares += rotation[i] * rotation[i];\r\n                }\r\n            }\r\n\r\n            const square = 1 - sumSquares;\r\n            rotation[iLargest] = Math.sqrt(Math.max(square, 0));\r\n\r\n            const shuffle = [3, 0, 1, 2]; // shuffle to match the order of the quaternion components in the splat file\r\n            for (let j = 0; j < 4; j++) {\r\n                rot[i * 32 + 28 + j] = Math.round(127.5 + rotation[shuffle[j]] * 127.5);\r\n            }\r\n\r\n            byteOffset += 4;\r\n        }\r\n    } else {\r\n        /*\r\n            In version 2, rotations are represented as the `(x, y, z)` components of the normalized rotation quaternion. The\r\n            `w` component can be derived from the others and is not stored. Each component is encoded as an\r\n            8-bit signed integer.\r\n        */\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const x = ubuf[byteOffset + 0];\r\n            const y = ubuf[byteOffset + 1];\r\n            const z = ubuf[byteOffset + 2];\r\n            const nx = x / 127.5 - 1;\r\n            const ny = y / 127.5 - 1;\r\n            const nz = z / 127.5 - 1;\r\n            rot[i * 32 + 28 + 1] = x;\r\n            rot[i * 32 + 28 + 2] = y;\r\n            rot[i * 32 + 28 + 3] = z;\r\n            const v = 1 - (nx * nx + ny * ny + nz * nz);\r\n            rot[i * 32 + 28 + 0] = 127.5 + Math.sqrt(v < 0 ? 0 : v) * 127.5;\r\n\r\n            byteOffset += 3;\r\n        }\r\n    }\r\n\r\n    // SH\r\n    if (shDegree) {\r\n        // shVectorCount is : 3 for degree 1, 8 for degree 2, 15 for degree 3, 24 for degree 4\r\n        // number of vec3 vectors needed per splat\r\n        const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1; // minus 1 because sh0 is color\r\n        // number of scalar component values: 3 per vec3\r\n        const shComponentCount = shVectorCount * 3;\r\n\r\n        const textureCount = Math.ceil(shComponentCount / 16); // 4 components can be stored per texture, 4 sh per component\r\n        let shIndexRead = byteOffset;\r\n\r\n        const engine = scene.getEngine();\r\n        const width = engine.getCaps().maxTextureSize;\r\n        const height = Math.ceil(splatCount / width);\r\n\r\n        // sh is an array of uint8array that will be used to create sh textures\r\n        const sh = AllocateShBuffers(textureCount, height * width * 4 * 4);\r\n\r\n        for (let i = 0; i < splatCount; i++) {\r\n            for (let shIndexWrite = 0; shIndexWrite < shComponentCount; shIndexWrite++) {\r\n                const shValue = ubuf[shIndexRead++];\r\n\r\n                const textureIndex = Math.floor(shIndexWrite / 16);\r\n                const shArray = sh[textureIndex];\r\n\r\n                const byteIndexInTexture = shIndexWrite % 16; // [0..15]\r\n                const offsetPerSplat = i * 16; // 16 sh values per texture per splat.\r\n                shArray[byteIndexInTexture + offsetPerSplat] = shValue;\r\n            }\r\n        }\r\n\r\n        return new Promise((resolve) => {\r\n            resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false, sh: sh, shDegree: shDegree, trainedWithAntialiasing: !!flags });\r\n        });\r\n    }\r\n\r\n    return new Promise((resolve) => {\r\n        resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false, trainedWithAntialiasing: !!flags });\r\n    });\r\n}\r\n\r\n/**\r\n * Returns the initialized spz WASM module loaded from the given URL, loading it on first call.\r\n * @param url URL to the spz WASM ES module (its default export should be a factory function)\r\n * @returns A promise resolving to the initialized spz WASM module\r\n */\r\nexport async function GetSpzModule(url: string): Promise<SpzModule> {\r\n    if (_SpzModulePromise && _SpzModuleUrl === url) {\r\n        return await _SpzModulePromise;\r\n    }\r\n\r\n    const spzModulePromise = _LoadScriptModuleAsync(\r\n        `import createSpzModule from '${url}';\r\n         const module = await createSpzModule();\r\n         const returnedValue = module;`\r\n    );\r\n\r\n    _SpzModuleUrl = url;\r\n    _SpzModulePromise = spzModulePromise;\r\n\r\n    return await spzModulePromise;\r\n}\r\n\r\n/**\r\n * Converts a GaussianCloud object (from the spz WASM module) into the packed 32-byte-per-splat\r\n * ArrayBuffer and SH texture arrays expected by GaussianSplattingMeshBase.updateData.\r\n *\r\n * Packed layout per splat (32 bytes):\r\n *   [0-11]  position xyz   (float32 x3)\r\n *   [12-23] scale xyz      (float32 x3)\r\n *   [24-27] color RGBA     (uint8 x4, colors in [0,255], alpha in [0,255])\r\n *   [28-31] quaternion wxyz (uint8 x4, encoded as q * 127.5 + 127.5)\r\n *\r\n * SH coefficients from the cloud (Float32, range ~[-1,1]) are encoded to bytes\r\n * using the SPZ convention (load-spz.cc unquantizeSH): byte = coeff * 128 + 128.\r\n *\r\n * @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer\r\n * @param scene The Babylon.js scene (used to query maxTextureSize for SH textures)\r\n * @param useCoroutine If true, yields periodically to avoid blocking the main thread\r\n * @returns A coroutine returning an IParsedSplat ready to be passed to updateData\r\n */\r\nexport function* ConvertSpzToSplat(cloud: GaussianCloud, scene: Scene, useCoroutine = false): Coroutine<IParsedSplat> {\r\n    const splatCount: number = cloud.numPoints;\r\n    const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32 bytes\r\n    const buffer = new ArrayBuffer(rowOutputLength * splatCount);\r\n    const fBuffer = new Float32Array(buffer);\r\n    const uBuffer = new Uint8Array(buffer);\r\n\r\n    const positions: Float32Array = cloud.positions;\r\n    const scales: Float32Array = cloud.scales;\r\n    const colors: Float32Array = cloud.colors;\r\n    const alphas: Float32Array = cloud.alphas;\r\n    const rotations: Float32Array = cloud.rotations;\r\n\r\n    // Build SH texture arrays upfront so both main and SH data can be written in a single pass\r\n    let sh: Uint8Array[] | null = null;\r\n    const shDegree: number = cloud.shDegree;\r\n    let cloudSh: Float32Array | null = null;\r\n    let shComponentCount = 0;\r\n    let chunkStarts: Int32Array | null = null;\r\n    let chunkEnds: Int32Array | null = null;\r\n    let shArrays: Uint8Array[] | null = null;\r\n\r\n    if (shDegree > 0 && cloud.sh.length > 0) {\r\n        const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\r\n        shComponentCount = shVectorCount * 3;\r\n        const textureCount = Math.ceil(shComponentCount / 16);\r\n\r\n        const engine = scene.getEngine();\r\n        const width = engine.getCaps().maxTextureSize;\r\n        const height = Math.ceil(splatCount / width);\r\n        sh = AllocateShBuffers(textureCount, height * width * 4 * 4);\r\n\r\n        // Precompute chunk start/end and hoist texture references out of the per-splat loop\r\n        chunkStarts = new Int32Array(textureCount);\r\n        chunkEnds = new Int32Array(textureCount);\r\n        for (let t = 0; t < textureCount; t++) {\r\n            chunkStarts[t] = t * 16;\r\n            chunkEnds[t] = Math.min((t + 1) * 16, shComponentCount);\r\n        }\r\n        shArrays = sh;\r\n        cloudSh = cloud.sh;\r\n    }\r\n\r\n    // Single pass: write packed splat data and SH textures together to halve iteration count\r\n    for (let i = 0; i < splatCount; i++) {\r\n        const fBase = i * 8;\r\n        const uBase = i * 32;\r\n        const p = i * 3;\r\n        const r = i * 4;\r\n\r\n        // Position (float32 x3, bytes 0-11)\r\n        fBuffer[fBase + 0] = positions[p + 0];\r\n        fBuffer[fBase + 1] = positions[p + 1];\r\n        fBuffer[fBase + 2] = positions[p + 2];\r\n\r\n        // Scale (float32 x3, bytes 12-23) — cloud scales are in log space, convert to linear\r\n        fBuffer[fBase + 3] = Math.exp(scales[p + 0]);\r\n        fBuffer[fBase + 4] = Math.exp(scales[p + 1]);\r\n        fBuffer[fBase + 5] = Math.exp(scales[p + 2]);\r\n\r\n        // Color RGB: cloud gives raw SH DC coefficients, convert to [0,255] display value\r\n        const c0 = (0.5 + _SH_C0 * colors[p + 0]) * 255;\r\n        const c1 = (0.5 + _SH_C0 * colors[p + 1]) * 255;\r\n        const c2 = (0.5 + _SH_C0 * colors[p + 2]) * 255;\r\n        uBuffer[uBase + 24] = c0 <= 0 ? 0 : c0 >= 255 ? 255 : (c0 + 0.5) | 0;\r\n        uBuffer[uBase + 25] = c1 <= 0 ? 0 : c1 >= 255 ? 255 : (c1 + 0.5) | 0;\r\n        uBuffer[uBase + 26] = c2 <= 0 ? 0 : c2 >= 255 ? 255 : (c2 + 0.5) | 0;\r\n        // Alpha: cloud gives raw logit opacity, apply sigmoid to get [0,255]\r\n        uBuffer[uBase + 27] = ((1.0 / (1.0 + Math.exp(-alphas[i]))) * 255 + 0.5) | 0;\r\n\r\n        // Rotation: cloud is xyzw, packed buffer expects wxyz\r\n        const rw = rotations[r + 3] * 127.5 + 127.5;\r\n        const rx = rotations[r + 0] * 127.5 + 127.5;\r\n        const ry = rotations[r + 1] * 127.5 + 127.5;\r\n        const rz = rotations[r + 2] * 127.5 + 127.5;\r\n        uBuffer[uBase + 28] = rw <= 0 ? 0 : rw >= 255 ? 255 : (rw + 0.5) | 0; // w\r\n        uBuffer[uBase + 29] = rx <= 0 ? 0 : rx >= 255 ? 255 : (rx + 0.5) | 0; // x\r\n        uBuffer[uBase + 30] = ry <= 0 ? 0 : ry >= 255 ? 255 : (ry + 0.5) | 0; // y\r\n        uBuffer[uBase + 31] = rz <= 0 ? 0 : rz >= 255 ? 255 : (rz + 0.5) | 0; // z\r\n\r\n        // SH: process all texture chunks for this splat in the same iteration\r\n        if (cloudSh && shArrays && chunkStarts && chunkEnds) {\r\n            const shSplatBase = i * shComponentCount;\r\n            const offsetPerSplat = i * 16;\r\n            for (let t = 0; t < shArrays.length; t++) {\r\n                const shT = shArrays[t];\r\n                const chunkStart = chunkStarts[t];\r\n                const chunkEnd = chunkEnds[t];\r\n                for (let j = chunkStart; j < chunkEnd; j++) {\r\n                    const v = cloudSh[shSplatBase + j] * 128.0 + 128.0;\r\n                    shT[offsetPerSplat + j - chunkStart] = v <= 0 ? 0 : v >= 255 ? 255 : (v + 0.5) | 0;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (i % _SpzConversionBatchSize === 0 && useCoroutine) {\r\n            yield;\r\n        }\r\n    }\r\n\r\n    // Extract safe-orbit-camera extension if present\r\n    let safeOrbitCameraRadiusMin: number | undefined;\r\n    let safeOrbitCameraElevationMinMax: [number, number] | undefined;\r\n    if (cloud.extensions) {\r\n        for (const ext of cloud.extensions) {\r\n            const safeOrbitExt = ext as SpzExtensionSafeOrbitCameraAdobe;\r\n            if (safeOrbitExt.safeOrbitRadiusMin !== undefined) {\r\n                safeOrbitCameraRadiusMin = safeOrbitExt.safeOrbitRadiusMin;\r\n                safeOrbitCameraElevationMinMax = [safeOrbitExt.safeOrbitElevationMin, safeOrbitExt.safeOrbitElevationMax];\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    return {\r\n        mode: Mode.Splat,\r\n        data: buffer,\r\n        hasVertexColors: false,\r\n        sh: sh !== null ? sh : undefined,\r\n        shDegree: shDegree > 0 ? shDegree : undefined,\r\n        trainedWithAntialiasing: !!cloud.antialiased,\r\n        safeOrbitCameraRadiusMin,\r\n        safeOrbitCameraElevationMinMax,\r\n    };\r\n}\r\n\r\n/**\r\n * Async version of ConvertSpzToSplat that yields periodically to avoid blocking the main thread.\r\n * @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer\r\n * @param scene The Babylon.js scene\r\n * @returns A promise resolving to an IParsedSplat\r\n */\r\nexport async function ConvertSpzToSplatAsync(cloud: any, scene: Scene): Promise<IParsedSplat> {\r\n    return await runCoroutineAsync(ConvertSpzToSplat(cloud, scene, true), createYieldingScheduler());\r\n}\r\n","/* eslint-disable @typescript-eslint/promise-function-async*/\r\n/* eslint-disable @typescript-eslint/naming-convention */\r\nimport {\r\n    type ISceneLoaderPluginAsync,\r\n    type ISceneLoaderPluginFactory,\r\n    type ISceneLoaderAsyncResult,\r\n    type ISceneLoaderProgressEvent,\r\n    type SceneLoaderPluginOptions,\r\n    RegisterSceneLoaderPlugin,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { SPLATFileLoaderMetadata } from \"./splatFileLoader.metadata\";\r\nimport { GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh.pure\";\r\nimport { type ISafeOrbitCameraLimits } from \"core/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure\";\r\nimport { GaussianSplattingStream } from \"./gaussianSplattingStream\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { Mesh } from \"core/Meshes/mesh.pure\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { Vector3 } from \"core/Maths/math.vector.pure\";\r\nimport { PointsCloudSystem } from \"core/Particles/pointsCloudSystem\";\r\nimport { Color4 } from \"core/Maths/math.color.pure\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { type SPLATLoadingOptions } from \"./splatLoadingOptions\";\r\nimport { type GaussianSplattingMaterial } from \"core/Materials/GaussianSplatting/gaussianSplattingMaterial\";\r\nimport { ConvertSpzToSplatAsync, GetSpzModule, ParseSpz } from \"./spz\";\r\nimport { Mode, type IParsedSplat } from \"./splatDefs\";\r\nimport { ParseSogMeta, ParseSogMetaAsTextures, type SOGRootData } from \"./sog.pure\";\r\nimport { Tools } from \"core/Misc/tools.pure\";\r\nimport { type ArcRotateCamera } from \"core/Cameras/arcRotateCamera\";\r\n\r\n// FFlate access\r\ndeclare const fflate: any;\r\n\r\n/**\r\n * @experimental\r\n * SPLAT file type loader.\r\n * This is a babylon scene loader plugin.\r\n */\r\nexport class SPLATFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\r\n    /**\r\n     * Defines the name of the plugin.\r\n     */\r\n    public readonly name = SPLATFileLoaderMetadata.name;\r\n\r\n    private _assetContainer: Nullable<AssetContainer> = null;\r\n\r\n    private readonly _loadingOptions: Readonly<SPLATLoadingOptions>;\r\n    /**\r\n     * Defines the extensions the splat loader is able to load.\r\n     * force data to come in as an ArrayBuffer\r\n     */\r\n    public readonly extensions = SPLATFileLoaderMetadata.extensions;\r\n\r\n    /**\r\n     * Creates loader for gaussian splatting files\r\n     * @param loadingOptions options for loading and parsing splat and PLY files.\r\n     */\r\n    constructor(loadingOptions: Partial<Readonly<SPLATLoadingOptions>> = {}) {\r\n        this._loadingOptions = { ...SPLATFileLoader._DefaultLoadingOptions, ...loadingOptions };\r\n    }\r\n\r\n    private static readonly _DefaultLoadingOptions = {\r\n        keepInRam: false,\r\n        flipY: false,\r\n        needsRotationScaleTextures: false,\r\n        spzLibraryUrl: typeof WebAssembly === \"object\" ? \"https://unpkg.com/@adobe/spz@0.2.2/dist/spz.js\" : undefined,\r\n    } as const satisfies SPLATLoadingOptions;\r\n\r\n    /** @internal */\r\n    createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\r\n        return new SPLATFileLoader(options[SPLATFileLoaderMetadata.name]);\r\n    }\r\n\r\n    /**\r\n     * Imports  from the loaded gaussian splatting data and adds them to the scene\r\n     * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file\r\n     * @param scene the scene the meshes should be added to\r\n     * @param data the gaussian splatting data to load\r\n     * @param rootUrl root url to load from\r\n     * @param _onProgress callback called while file is loading\r\n     * @param _fileName Defines the name of the file to load\r\n     * @returns a promise containing the loaded meshes, particles, skeletons and animations\r\n     */\r\n    public async importMeshAsync(\r\n        meshesNames: any,\r\n        scene: Scene,\r\n        data: any,\r\n        rootUrl: string,\r\n        _onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n        _fileName?: string\r\n    ): Promise<ISceneLoaderAsyncResult> {\r\n        const lodStream = this._tryCreateLODStream(scene, data, rootUrl);\r\n        if (lodStream) {\r\n            return {\r\n                meshes: [lodStream],\r\n                particleSystems: [],\r\n                skeletons: [],\r\n                animationGroups: [],\r\n                transformNodes: [],\r\n                geometries: [],\r\n                lights: [],\r\n                spriteManagers: [],\r\n            };\r\n        }\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return await this._parseAsync(meshesNames, scene, data, rootUrl).then((meshes) => {\r\n            return {\r\n                meshes: meshes,\r\n                particleSystems: [],\r\n                skeletons: [],\r\n                animationGroups: [],\r\n                transformNodes: [],\r\n                geometries: [],\r\n                lights: [],\r\n                spriteManagers: [],\r\n            };\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Detects a PlayCanvas-style `lod-meta.json` payload and, if found, creates a streaming mesh for it.\r\n     * @param scene hosting scene\r\n     * @param data loaded file data\r\n     * @param rootUrl root url the metadata's relative paths resolve against\r\n     * @returns the streaming mesh, or null when the data is not SOG LOD metadata\r\n     */\r\n    private _tryCreateLODStream(scene: Scene, data: any, rootUrl: string): Nullable<GaussianSplattingStream> {\r\n        if (typeof data !== \"string\") {\r\n            return null;\r\n        }\r\n        let parsed: unknown;\r\n        try {\r\n            parsed = JSON.parse(data);\r\n        } catch {\r\n            return null;\r\n        }\r\n        if (!GaussianSplattingStream.IsLODMetadata(parsed)) {\r\n            return null;\r\n        }\r\n\r\n        const previousBlockEntityCollection = scene._blockEntityCollection;\r\n        scene._blockEntityCollection = !!this._assetContainer;\r\n        try {\r\n            const stream = new GaussianSplattingStream(\"GaussianSplattingStream\", parsed, rootUrl, scene, {\r\n                deflateURL: this._loadingOptions.deflateURL,\r\n                fflate: this._loadingOptions.fflate,\r\n            });\r\n            stream._parentContainer = this._assetContainer;\r\n            return stream;\r\n        } finally {\r\n            scene._blockEntityCollection = previousBlockEntityCollection;\r\n        }\r\n    }\r\n\r\n    private static _BuildPointCloud(pointcloud: PointsCloudSystem, data: ArrayBuffer): boolean {\r\n        if (!data.byteLength) {\r\n            return false;\r\n        }\r\n        const uBuffer = new Uint8Array(data);\r\n        const fBuffer = new Float32Array(data);\r\n\r\n        // parsed array contains room for position(3floats), normal(3floats), color (4b), quantized quaternion (4b)\r\n        const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n        const vertexCount = uBuffer.length / rowLength;\r\n\r\n        const pointcloudfunc = function (particle: any, i: number) {\r\n            const x = fBuffer[8 * i + 0];\r\n            const y = fBuffer[8 * i + 1];\r\n            const z = fBuffer[8 * i + 2];\r\n            particle.position = new Vector3(x, y, z);\r\n\r\n            const r = uBuffer[rowLength * i + 24 + 0] / 255;\r\n            const g = uBuffer[rowLength * i + 24 + 1] / 255;\r\n            const b = uBuffer[rowLength * i + 24 + 2] / 255;\r\n            particle.color = new Color4(r, g, b, 1);\r\n        };\r\n\r\n        pointcloud.addPoints(vertexCount, pointcloudfunc);\r\n        return true;\r\n    }\r\n\r\n    private static _BuildMesh(scene: Scene, parsedPLY: IParsedSplat): Mesh {\r\n        const mesh = new Mesh(\"PLYMesh\", scene);\r\n\r\n        const uBuffer = new Uint8Array(parsedPLY.data);\r\n        const fBuffer = new Float32Array(parsedPLY.data);\r\n\r\n        const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n        const vertexCount = uBuffer.length / rowLength;\r\n\r\n        const positions = [];\r\n\r\n        const vertexData = new VertexData();\r\n        for (let i = 0; i < vertexCount; i++) {\r\n            const x = fBuffer[8 * i + 0];\r\n            const y = fBuffer[8 * i + 1];\r\n            const z = fBuffer[8 * i + 2];\r\n            positions.push(x, y, z);\r\n        }\r\n\r\n        if (parsedPLY.hasVertexColors) {\r\n            const colors = new Float32Array(vertexCount * 4);\r\n            for (let i = 0; i < vertexCount; i++) {\r\n                const r = uBuffer[rowLength * i + 24 + 0] / 255;\r\n                const g = uBuffer[rowLength * i + 24 + 1] / 255;\r\n                const b = uBuffer[rowLength * i + 24 + 2] / 255;\r\n                colors[i * 4 + 0] = r;\r\n                colors[i * 4 + 1] = g;\r\n                colors[i * 4 + 2] = b;\r\n                colors[i * 4 + 3] = 1;\r\n            }\r\n            vertexData.colors = colors;\r\n        }\r\n\r\n        vertexData.positions = positions;\r\n        vertexData.indices = parsedPLY.faces!;\r\n\r\n        vertexData.applyToMesh(mesh);\r\n        return mesh;\r\n    }\r\n\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax, @typescript-eslint/naming-convention\r\n    private async _unzipWithFFlateAsync(data: Uint8Array): Promise<Map<string, Uint8Array>> {\r\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n        // @ts-ignore\r\n        let fflate = this._loadingOptions.fflate as typeof import(\"fflate\");\r\n        // ensure fflate is loaded\r\n        if (!fflate) {\r\n            if (typeof (window as any).fflate === \"undefined\") {\r\n                await Tools.LoadScriptAsync(this._loadingOptions.deflateURL ?? \"https://unpkg.com/fflate/umd/index.js\");\r\n            }\r\n            fflate = (window as any).fflate as typeof fflate;\r\n        }\r\n\r\n        const { unzipSync } = fflate;\r\n\r\n        const unzipped = unzipSync(data) as Record<string, Uint8Array>; // { [filename: string]: Uint8Array }\r\n\r\n        const files = new Map<string, Uint8Array>();\r\n        for (const [name, content] of Object.entries(unzipped)) {\r\n            files.set(name, content);\r\n        }\r\n        return files;\r\n    }\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    private _parseAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string): Promise<Array<AbstractMesh>> {\r\n        const babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon\r\n\r\n        const makeGSFromParsedSOG = (parsedSOG: IParsedSplat) => {\r\n            scene._blockEntityCollection = !!this._assetContainer;\r\n            const gaussianSplatting =\r\n                this._loadingOptions.gaussianSplattingMesh ??\r\n                new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam, this._loadingOptions.needsRotationScaleTextures);\r\n            gaussianSplatting._parentContainer = this._assetContainer;\r\n            babylonMeshesArray.push(gaussianSplatting);\r\n            if (parsedSOG.sogTextures) {\r\n                gaussianSplatting.setSogTextureData(parsedSOG.sogTextures);\r\n            } else {\r\n                gaussianSplatting.updateData(parsedSOG.data, parsedSOG.sh, { flipY: false }, undefined, parsedSOG.shDegree);\r\n            }\r\n            gaussianSplatting.scaling.y *= -1;\r\n            gaussianSplatting.computeWorldMatrix(true);\r\n            // Expose any parsed safe-orbit limits (SOG does not auto-apply them to the camera).\r\n            gaussianSplatting.safeOrbitCameraLimits = SPLATFileLoader._ExtractSafeOrbitLimits(parsedSOG);\r\n            scene._blockEntityCollection = false;\r\n        };\r\n\r\n        const engine = scene.getEngine();\r\n        let useSogTextures = this._loadingOptions.useSogTextures;\r\n        if (useSogTextures && !engine.isWebGPU && engine.version < 2) {\r\n            Logger.Warn(\"SPLATFileLoader: useSogTextures requires WebGL2 or WebGPU. Falling back to CPU path.\");\r\n            useSogTextures = false;\r\n        }\r\n        const sogParser = useSogTextures ? ParseSogMetaAsTextures : ParseSogMeta;\r\n\r\n        // check if data is json string\r\n        if (typeof data === \"string\") {\r\n            const dataSOG = JSON.parse(data) as SOGRootData;\r\n            if (dataSOG && dataSOG.means && dataSOG.scales && dataSOG.quats && dataSOG.sh0) {\r\n                return new Promise((resolve, reject) => {\r\n                    sogParser(dataSOG, rootUrl, scene)\r\n                        // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n                        .then((parsedSOG) => {\r\n                            makeGSFromParsedSOG(parsedSOG);\r\n                            resolve(babylonMeshesArray);\r\n                        })\r\n                        // eslint-disable-next-line github/no-then\r\n                        .catch((e) => {\r\n                            reject(new Error(\"Failed to parse SOG data.\", { cause: e }));\r\n                        });\r\n                });\r\n            }\r\n        }\r\n\r\n        const u8 = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\r\n        // ZIP signature check for SOG\r\n        if (u8[0] === 0x50 && u8[1] === 0x4b) {\r\n            return new Promise((resolve, reject) => {\r\n                // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n                this._unzipWithFFlateAsync(u8).then((files) => {\r\n                    sogParser(files, rootUrl, scene)\r\n                        // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n                        .then((parsedSOG) => {\r\n                            makeGSFromParsedSOG(parsedSOG);\r\n                            resolve(babylonMeshesArray);\r\n                        }) // eslint-disable-next-line github/no-then\r\n                        .catch((e) => {\r\n                            reject(new Error(\"Failed to parse SOG zip data.\", { cause: e }));\r\n                        });\r\n                });\r\n            });\r\n        }\r\n\r\n        const handlePLY = (resolve: (value: AbstractMesh[]) => void) => {\r\n            // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n            SPLATFileLoader._ConvertPLYToSplat(data as ArrayBuffer).then(async (parsedPLY) => {\r\n                scene._blockEntityCollection = !!this._assetContainer;\r\n                switch (parsedPLY.mode) {\r\n                    case Mode.Splat:\r\n                        {\r\n                            const gaussianSplatting =\r\n                                this._loadingOptions.gaussianSplattingMesh ??\r\n                                new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam, this._loadingOptions.needsRotationScaleTextures);\r\n                            gaussianSplatting._parentContainer = this._assetContainer;\r\n                            babylonMeshesArray.push(gaussianSplatting);\r\n                            gaussianSplatting.updateData(parsedPLY.data, parsedPLY.sh, { flipY: false }, undefined, parsedPLY.shDegree);\r\n                            gaussianSplatting.scaling.y *= -1.0;\r\n\r\n                            if (parsedPLY.chirality === \"RightHanded\") {\r\n                                gaussianSplatting.scaling.y *= -1.0;\r\n                            }\r\n\r\n                            switch (parsedPLY.upAxis) {\r\n                                case \"X\":\r\n                                    gaussianSplatting.rotation = new Vector3(0, 0, Math.PI / 2);\r\n                                    break;\r\n                                case \"Y\":\r\n                                    gaussianSplatting.rotation = new Vector3(0, 0, Math.PI);\r\n                                    break;\r\n                                case \"Z\":\r\n                                    gaussianSplatting.rotation = new Vector3(-Math.PI / 2, Math.PI, 0);\r\n                                    break;\r\n                            }\r\n                            gaussianSplatting.computeWorldMatrix(true);\r\n                            gaussianSplatting.safeOrbitCameraLimits = SPLATFileLoader._ExtractSafeOrbitLimits(parsedPLY);\r\n                        }\r\n                        break;\r\n                    case Mode.PointCloud:\r\n                        {\r\n                            const pointcloud = new PointsCloudSystem(\"PointCloud\", 1, scene);\r\n                            if (SPLATFileLoader._BuildPointCloud(pointcloud, parsedPLY.data)) {\r\n                                // eslint-disable-next-line github/no-then\r\n                                await pointcloud.buildMeshAsync().then((mesh) => {\r\n                                    babylonMeshesArray.push(mesh);\r\n                                });\r\n                            } else {\r\n                                pointcloud.dispose();\r\n                            }\r\n                        }\r\n                        break;\r\n                    case Mode.Mesh:\r\n                        {\r\n                            if (parsedPLY.faces) {\r\n                                babylonMeshesArray.push(SPLATFileLoader._BuildMesh(scene, parsedPLY));\r\n                            } else {\r\n                                throw new Error(\"PLY mesh doesn't contain face informations.\");\r\n                            }\r\n                        }\r\n                        break;\r\n                    default:\r\n                        throw new Error(\"Unsupported Splat mode\");\r\n                }\r\n                scene._blockEntityCollection = false;\r\n                this.applyAutoCameraLimits(SPLATFileLoader._ExtractSafeOrbitLimits(parsedPLY), scene);\r\n                resolve(babylonMeshesArray);\r\n            });\r\n        };\r\n\r\n        // Check for gzip (before SPZ V4) and NGSP (SPZ V4+) magic bytes to detect SPZ format\r\n        const isGZipped = u8[0] === 0x1f && u8[1] === 0x8b;\r\n        const isNGSP = u8[0] === 0x4e && u8[1] === 0x47 && u8[2] === 0x53 && u8[3] === 0x50;\r\n        if (!isGZipped && !isNGSP) {\r\n            return new Promise((resolve) => {\r\n                handlePLY(resolve);\r\n            });\r\n        }\r\n\r\n        const applyParsedSPZ = (parsedSPZ: IParsedSplat, resolve: (meshes: typeof babylonMeshesArray) => void) => {\r\n            scene._blockEntityCollection = !!this._assetContainer;\r\n            const gaussianSplatting =\r\n                this._loadingOptions.gaussianSplattingMesh ??\r\n                new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam, this._loadingOptions.needsRotationScaleTextures);\r\n            if (parsedSPZ.trainedWithAntialiasing) {\r\n                const gsMaterial = gaussianSplatting.material as GaussianSplattingMaterial;\r\n                gsMaterial.kernelSize = 0.1;\r\n                gsMaterial.compensation = true;\r\n            }\r\n            gaussianSplatting._parentContainer = this._assetContainer;\r\n            babylonMeshesArray.push(gaussianSplatting);\r\n            gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh, { flipY: false }, undefined, parsedSPZ.shDegree);\r\n            if (!this._loadingOptions.flipY) {\r\n                gaussianSplatting.scaling.y *= -1.0;\r\n                gaussianSplatting.computeWorldMatrix(true);\r\n            }\r\n            scene._blockEntityCollection = false;\r\n            const safeOrbitLimits = SPLATFileLoader._ExtractSafeOrbitLimits(parsedSPZ);\r\n            gaussianSplatting.safeOrbitCameraLimits = safeOrbitLimits;\r\n            this.applyAutoCameraLimits(safeOrbitLimits, scene);\r\n            resolve(babylonMeshesArray);\r\n        };\r\n\r\n        if (this._loadingOptions.spzLibraryUrl) {\r\n            // WASM path: load spz module from URL, pass raw gzip data directly\r\n            // eslint-disable-next-line github/no-then\r\n            return GetSpzModule(this._loadingOptions.spzLibraryUrl).then((spz) => {\r\n                const cloud = spz.loadSpzFromBuffer(new Uint8Array(data), { to: spz.CoordinateSystem.RUB });\r\n                // eslint-disable-next-line github/no-then\r\n                return ConvertSpzToSplatAsync(cloud, scene).then((parsedSPZ) => {\r\n                    return new Promise<AbstractMesh[]>((resolve) => {\r\n                        applyParsedSPZ(parsedSPZ, resolve);\r\n                    });\r\n                });\r\n            });\r\n        }\r\n\r\n        // NGSP (SPZ V4+) requires WASM — the native fallback only handles legacy gzip formats\r\n        if (isNGSP) {\r\n            return Promise.reject(\r\n                new Error(\r\n                    \"SPZ V4+ files (NGSP format) are not supported by the native fallback loader. \" +\r\n                        \"Please provide a valid 'spzLibraryUrl' in the loading options to use the WASM-based SPZ library, \" +\r\n                        \"or ensure WebAssembly is available in your environment.\"\r\n                )\r\n            );\r\n        }\r\n\r\n        // Manual path: decompress gzip, then parse with the built-in SPZ parser\r\n        const readableStream = new ReadableStream({\r\n            start(controller) {\r\n                controller.enqueue(new Uint8Array(data));\r\n                controller.close();\r\n            },\r\n        });\r\n        const decompressionStream = new DecompressionStream(\"gzip\");\r\n        const decompressedStream = readableStream.pipeThrough(decompressionStream);\r\n\r\n        return new Promise((resolve) => {\r\n            new Response(decompressedStream)\r\n                .arrayBuffer()\r\n                // eslint-disable-next-line github/no-then\r\n                .then((buffer) => {\r\n                    // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n                    ParseSpz(buffer, scene, this._loadingOptions).then((parsedSPZ) => {\r\n                        applyParsedSPZ(parsedSPZ, resolve);\r\n                    });\r\n                })\r\n                // eslint-disable-next-line github/no-then\r\n                .catch(() => {\r\n                    handlePLY(resolve);\r\n                });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Extracts the safe-orbit camera limits from parsed splat metadata, or null when the file\r\n     * carries none. Exposed on the loaded mesh (GaussianSplattingMeshBase.safeOrbitCameraLimits)\r\n     * so consumers can apply/track them regardless of the active camera type.\r\n     * @param meta parsed splat meta data\r\n     * @returns the parsed safe-orbit limits, or null\r\n     */\r\n    private static _ExtractSafeOrbitLimits(meta: IParsedSplat): Nullable<ISafeOrbitCameraLimits> {\r\n        if (meta.safeOrbitCameraRadiusMin === undefined && meta.safeOrbitCameraElevationMinMax === undefined) {\r\n            return null;\r\n        }\r\n        return {\r\n            radiusMin: meta.safeOrbitCameraRadiusMin,\r\n            elevationMinMax: meta.safeOrbitCameraElevationMinMax,\r\n        };\r\n    }\r\n\r\n    /**\r\n     * Applies safe-orbit camera limits parsed from the file metadata to the scene's active\r\n     * ArcRotateCamera. No-op when no limits are present, `disableAutoCameraLimits` is set, or the\r\n     * active camera is not an ArcRotateCamera — in which case consumers can still read the limits\r\n     * from the loaded mesh's `safeOrbitCameraLimits` and apply them themselves.\r\n     * @param limits parsed safe-orbit limits (see _ExtractSafeOrbitLimits)\r\n     * @param scene\r\n     */\r\n    private applyAutoCameraLimits(limits: Nullable<ISafeOrbitCameraLimits>, scene: Scene): void {\r\n        if (this._loadingOptions.disableAutoCameraLimits || !limits) {\r\n            return;\r\n        }\r\n        if (scene.activeCamera?.getClassName() === \"ArcRotateCamera\") {\r\n            const arcCam = scene.activeCamera as ArcRotateCamera;\r\n            if (limits.elevationMinMax) {\r\n                arcCam.lowerBetaLimit = Math.PI * 0.5 - limits.elevationMinMax[1];\r\n                arcCam.upperBetaLimit = Math.PI * 0.5 - limits.elevationMinMax[0];\r\n            }\r\n\r\n            if (limits.radiusMin) {\r\n                arcCam.lowerRadiusLimit = limits.radiusMin;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Load into an asset container.\r\n     * @param scene The scene to load into\r\n     * @param data The data to import\r\n     * @param rootUrl The root url for scene and resources\r\n     * @returns The loaded asset container\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r\n    public loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string): Promise<AssetContainer> {\r\n        const container = new AssetContainer(scene);\r\n        this._assetContainer = container;\r\n\r\n        return (\r\n            this.importMeshAsync(null, scene, data, rootUrl)\r\n                // eslint-disable-next-line github/no-then\r\n                .then((result) => {\r\n                    for (const mesh of result.meshes) {\r\n                        container.meshes.push(mesh);\r\n                    }\r\n                    // mesh material will be null before 1st rendered frame.\r\n                    this._assetContainer = null;\r\n                    return container;\r\n                })\r\n                // eslint-disable-next-line github/no-then\r\n                .catch((ex) => {\r\n                    this._assetContainer = null;\r\n                    throw ex;\r\n                })\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Imports all objects from the loaded OBJ data and adds them to the scene\r\n     * @param scene the scene the objects should be added to\r\n     * @param data the OBJ data to load\r\n     * @param rootUrl root url to load from\r\n     * @returns a promise which completes when objects have been loaded to the scene\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n    public loadAsync(scene: Scene, data: string, rootUrl: string): Promise<void> {\r\n        //Get the 3D model\r\n        // eslint-disable-next-line github/no-then\r\n        return this.importMeshAsync(null, scene, data, rootUrl).then(() => {\r\n            // return void\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Code from https://github.com/dylanebert/gsplat.js/blob/main/src/loaders/PLYLoader.ts Under MIT license\r\n     * Converts a .ply data array buffer to splat\r\n     * if data array buffer is not ply, returns the original buffer\r\n     * @param data the .ply data to load\r\n     * @returns the loaded splat buffer\r\n     */\r\n    private static _ConvertPLYToSplat(data: ArrayBuffer): Promise<IParsedSplat> {\r\n        const ubuf = new Uint8Array(data);\r\n        const header = new TextDecoder().decode(ubuf.slice(0, 1024 * 10));\r\n        const headerEnd = \"end_header\\n\";\r\n        const headerEndIndex = header.indexOf(headerEnd);\r\n        if (headerEndIndex < 0 || !header) {\r\n            // standard splat\r\n            return new Promise((resolve) => {\r\n                resolve({ mode: Mode.Splat, data: data, rawSplat: true });\r\n            });\r\n        }\r\n\r\n        const vertexCount = parseInt(/element vertex (\\d+)\\n/.exec(header)![1]);\r\n        const faceElement = /element face (\\d+)\\n/.exec(header);\r\n        let faceCount = 0;\r\n        if (faceElement) {\r\n            faceCount = parseInt(faceElement[1]);\r\n        }\r\n        const chunkElement = /element chunk (\\d+)\\n/.exec(header);\r\n        let chunkCount = 0;\r\n        if (chunkElement) {\r\n            chunkCount = parseInt(chunkElement[1]);\r\n        }\r\n\r\n        let rowVertexOffset = 0;\r\n        let rowChunkOffset = 0;\r\n        const offsets: Record<string, number> = {\r\n            double: 8,\r\n            int: 4,\r\n            uint: 4,\r\n            float: 4,\r\n            short: 2,\r\n            ushort: 2,\r\n            uint16: 2,\r\n            uchar: 1,\r\n            list: 0,\r\n        };\r\n\r\n        type PlyProperty = {\r\n            name: string;\r\n            type: string;\r\n            offset: number;\r\n        };\r\n\r\n        const ElementMode: Record<string, number> = {\r\n            Vertex: 0,\r\n            Chunk: 1,\r\n            SH: 2,\r\n            Float_Tuple: 3,\r\n            Float: 4,\r\n            Uchar: 5,\r\n        };\r\n\r\n        let chunkMode = ElementMode.Chunk;\r\n        const vertexProperties: PlyProperty[] = [];\r\n        const chunkProperties: PlyProperty[] = [];\r\n        const filtered = header.slice(0, headerEndIndex).split(\"\\n\");\r\n        const metaData: Partial<IParsedSplat> = {};\r\n        for (const prop of filtered) {\r\n            if (prop.startsWith(\"property \")) {\r\n                const [, type, name] = prop.split(\" \");\r\n\r\n                if (chunkMode == ElementMode.Chunk) {\r\n                    chunkProperties.push({ name, type, offset: rowChunkOffset });\r\n                    rowChunkOffset += offsets[type];\r\n                } else if (chunkMode == ElementMode.Vertex) {\r\n                    vertexProperties.push({ name, type, offset: rowVertexOffset });\r\n                    rowVertexOffset += offsets[type];\r\n                } else if (chunkMode == ElementMode.SH) {\r\n                    vertexProperties.push({ name, type, offset: rowVertexOffset });\r\n                } else if (chunkMode == ElementMode.Float_Tuple) {\r\n                    const view = new DataView(data, rowChunkOffset, offsets.float * 2);\r\n                    metaData.safeOrbitCameraElevationMinMax = [view.getFloat32(0, true), view.getFloat32(4, true)];\r\n                } else if (chunkMode == ElementMode.Float) {\r\n                    const view = new DataView(data, rowChunkOffset, offsets.float);\r\n                    metaData.safeOrbitCameraRadiusMin = view.getFloat32(0, true);\r\n                } else if (chunkMode == ElementMode.Uchar) {\r\n                    const view = new DataView(data, rowChunkOffset, offsets.uchar);\r\n                    if (name == \"up_axis\") {\r\n                        metaData.upAxis = view.getUint8(0) == 0 ? \"X\" : view.getUint8(0) == 1 ? \"Y\" : \"Z\";\r\n                    } else if (name == \"chirality\") {\r\n                        metaData.chirality = view.getUint8(0) == 0 ? \"LeftHanded\" : \"RightHanded\";\r\n                    }\r\n                }\r\n\r\n                if (!offsets[type]) {\r\n                    Logger.Warn(`Unsupported property type: ${type}.`);\r\n                }\r\n            } else if (prop.startsWith(\"element \")) {\r\n                const [, type] = prop.split(\" \");\r\n                if (type == \"chunk\") {\r\n                    chunkMode = ElementMode.Chunk;\r\n                } else if (type == \"vertex\") {\r\n                    chunkMode = ElementMode.Vertex;\r\n                } else if (type == \"sh\") {\r\n                    chunkMode = ElementMode.SH;\r\n                } else if (type == \"safe_orbit_camera_elevation_min_max_radians\") {\r\n                    chunkMode = ElementMode.Float_Tuple;\r\n                } else if (type == \"safe_orbit_camera_radius_min\") {\r\n                    chunkMode = ElementMode.Float;\r\n                } else if (type == \"up_axis\" || type == \"chirality\") {\r\n                    chunkMode = ElementMode.Uchar;\r\n                }\r\n            }\r\n        }\r\n\r\n        const rowVertexLength = rowVertexOffset;\r\n        const rowChunkLength = rowChunkOffset;\r\n\r\n        // eslint-disable-next-line github/no-then\r\n        return (GaussianSplattingMesh.ConvertPLYWithSHToSplatAsync(data) as any).then(async (splatsData: any) => {\r\n            const dataView = new DataView(data, headerEndIndex + headerEnd.length);\r\n            let offset = rowChunkLength * chunkCount + rowVertexLength * vertexCount;\r\n            // faces\r\n            const faces: number[] = [];\r\n            if (faceCount) {\r\n                for (let i = 0; i < faceCount; i++) {\r\n                    const faceVertexCount = dataView.getUint8(offset);\r\n                    if (faceVertexCount != 3) {\r\n                        continue; // only support triangles\r\n                    }\r\n                    offset += 1;\r\n\r\n                    for (let j = 0; j < faceVertexCount; j++) {\r\n                        const vertexIndex = dataView.getUint32(offset + (2 - j) * 4, true); // change face winding\r\n                        faces.push(vertexIndex);\r\n                    }\r\n                    offset += 12;\r\n                }\r\n            }\r\n\r\n            // early exit for chunked/quantized ply\r\n            if (chunkCount) {\r\n                return await new Promise((resolve) => {\r\n                    resolve({\r\n                        mode: Mode.Splat,\r\n                        data: splatsData.buffer,\r\n                        sh: splatsData.sh,\r\n                        shDegree: splatsData.shDegree,\r\n                        faces: faces,\r\n                        hasVertexColors: false,\r\n                        compressed: true,\r\n                        rawSplat: false,\r\n                    });\r\n                });\r\n            }\r\n            // count available properties. if all necessary are present then it's a splat. Otherwise, it's a point cloud\r\n            // if faces are found, then it's a standard mesh\r\n            let propertyCount = 0;\r\n            let propertyColorCount = 0;\r\n            const splatProperties = [\"x\", \"y\", \"z\", \"scale_0\", \"scale_1\", \"scale_2\", \"opacity\", \"rot_0\", \"rot_1\", \"rot_2\", \"rot_3\"];\r\n            const splatColorProperties = [\"red\", \"green\", \"blue\", \"f_dc_0\", \"f_dc_1\", \"f_dc_2\"];\r\n            for (let propertyIndex = 0; propertyIndex < vertexProperties.length; propertyIndex++) {\r\n                const property = vertexProperties[propertyIndex];\r\n                if (splatProperties.includes(property.name)) {\r\n                    propertyCount++;\r\n                }\r\n                if (splatColorProperties.includes(property.name)) {\r\n                    propertyColorCount++;\r\n                }\r\n            }\r\n            const hasMandatoryProperties = propertyCount == splatProperties.length && propertyColorCount >= 3;\r\n            const currentMode = faceCount ? Mode.Mesh : hasMandatoryProperties ? Mode.Splat : Mode.PointCloud;\r\n            // parsed ready ready to be used as a splat\r\n            return await new Promise((resolve) => {\r\n                resolve({\r\n                    ...metaData,\r\n                    mode: currentMode,\r\n                    data: splatsData.buffer,\r\n                    sh: splatsData.sh,\r\n                    shDegree: splatsData.shDegree,\r\n                    faces: faces,\r\n                    hasVertexColors: !!propertyColorCount,\r\n                    compressed: false,\r\n                    rawSplat: false,\r\n                });\r\n            });\r\n        });\r\n    }\r\n}\r\n\r\n// Add this loader into the register plugin\r\n\r\nlet _Registered = false;\r\n/**\r\n * Registers the SPLATFileLoader scene loader plugin.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterSPLATFileLoader(): void {\r\n    if (_Registered) {\r\n        return;\r\n    }\r\n    _Registered = true;\r\n\r\n    RegisterSceneLoaderPlugin(new SPLATFileLoader());\r\n}\r\n","/**\r\n * Re-exports the pure implementation and applies the runtime registration side effect.\r\n * Import \"./splatFileLoader.pure\" for tree-shakeable, side-effect-free usage.\r\n */\r\nexport * from \"./splatFileLoader.types\";\r\nexport * from \"./splatFileLoader.pure\";\r\n\r\n// The SOG-with-textures path in the pure implementation relies on the prototype-augmented\r\n// updateDynamicTexture engine extension; import its side effect here so it is present at runtime.\r\nimport \"core/Engines/Extensions/engine.dynamicTexture\";\r\n\r\nimport { RegisterSPLATFileLoader } from \"./splatFileLoader.pure\";\r\nRegisterSPLATFileLoader();\r\n","/* eslint-disable @typescript-eslint/naming-convention */\n\nimport { type ISceneLoaderPluginExtensions, type ISceneLoaderPluginMetadata } from \"core/Loading/sceneLoader\";\n\n/**\n * Defines the USD loader plugin metadata.\n */\nexport const USDFileLoaderMetadata = {\n    name: \"usd\",\n    extensions: {\n        // eslint-disable-next-line @typescript-eslint/naming-convention\n        \".usd\": { isBinary: true },\n        // eslint-disable-next-line @typescript-eslint/naming-convention\n        \".usda\": { isBinary: true },\n        // eslint-disable-next-line @typescript-eslint/naming-convention\n        \".usdc\": { isBinary: true },\n        // eslint-disable-next-line @typescript-eslint/naming-convention\n        \".usdz\": { isBinary: true },\n    } as const satisfies ISceneLoaderPluginExtensions,\n} as const satisfies ISceneLoaderPluginMetadata;\n","/* eslint-disable @typescript-eslint/naming-convention */\n\nexport const COMMAND_MAGIC = 0x42445355;\nexport const PROTOCOL_VERSION = 5;\nexport const MISSING_OFFSET = 0xffffffff;\n\nexport const enum Command {\n    Scene = 1,\n    Texture = 2,\n    Material = 3,\n    TransformNode = 4,\n    Skeleton = 5,\n    Geometry = 6,\n    Mesh = 7,\n    Instance = 8,\n    Animation = 9,\n    AnalyticPrimitive = 10,\n    ThinInstances = 11,\n    MorphTarget = 12,\n}\n\nexport const enum AnalyticPrimitiveType {\n    Cube = 0,\n    Sphere = 1,\n    Cylinder = 2,\n    Cone = 3,\n}\n\nexport const enum PrimitiveAxis {\n    X = 0,\n    Y = 1,\n    Z = 2,\n}\n\nexport const enum AnimationTarget {\n    Node = 0,\n    Bone = 1,\n    MorphTarget = 2,\n}\n\nexport const enum AnimationProperty {\n    Position = 0,\n    RotationQuaternion = 1,\n    Scaling = 2,\n    Matrix = 3,\n    Influence = 4,\n}\n\nexport const enum MaterialFlags {\n    DoubleSided = 1 << 0,\n    Unlit = 1 << 1,\n    AlphaBlend = 1 << 2,\n}\n\nexport const enum TextureOutputChannel {\n    R = 0,\n    G = 1,\n    B = 2,\n    A = 3,\n    RGB = 4,\n}\n\nexport const enum USDTextureColorSpace {\n    Auto = 0,\n    Raw = 1,\n    SRGB = 2,\n}\n\nexport const enum MeshFlags {\n    DoubleSided = 1 << 0,\n    LeftHanded = 1 << 1,\n}\n\nexport const enum GeometryFlags {\n    Normals = 1 << 0,\n    Tangents = 1 << 1,\n    Uv0 = 1 << 2,\n    Colors = 1 << 3,\n    Skin0 = 1 << 4,\n    Skin1 = 1 << 5,\n}\n\nexport interface CommandRecord {\n    opcode: Command;\n    flags: number;\n    payloadOffset: number;\n    payloadLength: number;\n}\n\nfunction expectedPayloadLength(opcode: Command): number {\n    switch (opcode) {\n        case Command.Scene:\n            return 12;\n        case Command.Texture:\n            return 48;\n        case Command.Material:\n            return 96;\n        case Command.TransformNode:\n        case Command.Skeleton:\n            return 20;\n        case Command.Geometry:\n            return 60;\n        case Command.Mesh:\n            return 40;\n        case Command.Instance:\n            return 16;\n        case Command.Animation:\n            return 32;\n        case Command.AnalyticPrimitive:\n            return 44;\n        case Command.ThinInstances:\n            return 12;\n        case Command.MorphTarget:\n            return 32;\n        default:\n            throw new Error(`Unknown OpenUSD Babylon command opcode ${opcode}.`);\n    }\n}\n\nexport function readCommands(buffer: ArrayBuffer): CommandRecord[] {\n    const view = new DataView(buffer);\n    if (view.byteLength < 16 || view.getUint32(0, true) !== COMMAND_MAGIC) {\n        throw new Error(\"Invalid OpenUSD Babylon command buffer.\");\n    }\n    if (view.getUint16(4, true) !== PROTOCOL_VERSION) {\n        throw new Error(`Unsupported OpenUSD Babylon protocol ${view.getUint16(4, true)}.`);\n    }\n    const count = view.getUint32(8, true);\n    const commands: CommandRecord[] = [];\n    let offset = 16;\n    for (let index = 0; index < count; ++index) {\n        if (offset + 8 > view.byteLength) {\n            throw new Error(\"Truncated OpenUSD Babylon command header.\");\n        }\n        const opcode = view.getUint16(offset, true) as Command;\n        const flags = view.getUint16(offset + 2, true);\n        const payloadLength = view.getUint32(offset + 4, true);\n        const payloadOffset = offset + 8;\n        const expectedLength = expectedPayloadLength(opcode);\n        if (payloadLength !== expectedLength) {\n            throw new Error(`Invalid payload length ${payloadLength} for command ${opcode}; ` + `expected ${expectedLength}.`);\n        }\n        if (payloadOffset + payloadLength > view.byteLength) {\n            throw new Error(\"Truncated OpenUSD Babylon command payload.\");\n        }\n        commands.push({ opcode, flags, payloadOffset, payloadLength });\n        offset = payloadOffset + payloadLength;\n    }\n    if (offset !== view.byteLength) {\n        throw new Error(\"Unexpected trailing data in OpenUSD Babylon command buffer.\");\n    }\n    return commands;\n}\n\nexport class PayloadReader {\n    readonly #view: DataView;\n    readonly #end: number;\n    offset: number;\n\n    constructor(buffer: ArrayBuffer, offset: number, length: number) {\n        this.#view = new DataView(buffer);\n        this.offset = offset;\n        this.#end = offset + length;\n    }\n\n    u32(): number {\n        this.#require(4);\n        const value = this.#view.getUint32(this.offset, true);\n        this.offset += 4;\n        return value;\n    }\n\n    f32(): number {\n        this.#require(4);\n        const value = this.#view.getFloat32(this.offset, true);\n        this.offset += 4;\n        return value;\n    }\n\n    #require(byteLength: number): void {\n        if (this.offset + byteLength > this.#end) {\n            throw new Error(\"OpenUSD Babylon command payload read exceeded its bounds.\");\n        }\n    }\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\n\nimport { Animation } from \"core/Animations/animation.pure\";\nimport { AnimationGroup } from \"core/Animations/animationGroup.pure\";\nimport { AbstractAssetContainer, AssetContainer } from \"core/assetContainer\";\nimport { Bone } from \"core/Bones/bone\";\nimport { Skeleton } from \"core/Bones/skeleton\";\nimport { Color3, Color4 } from \"core/Maths/math.color.pure\";\nimport { Matrix, Quaternion, Vector3 } from \"core/Maths/math.vector.pure\";\nimport { Material } from \"core/Materials/material.pure\";\nimport { MultiMaterial } from \"core/Materials/multiMaterial.pure\";\nimport { PBRMaterial } from \"core/Materials/PBR/pbrMaterial.pure\";\nimport { Texture } from \"core/Materials/Textures/texture.pure\";\nimport {\n    CreateFactorOperand,\n    CreateTextureOperand,\n    LerpTexturesAsync,\n    TextureChannel,\n    TextureColorSpace,\n    type ITextureProcessOperand,\n} from \"core/Materials/Textures/textureProcessor\";\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\nimport { MorphTarget } from \"core/Morph/morphTarget\";\nimport { MorphTargetManager } from \"core/Morph/morphTargetManager\";\nimport { CreateBox } from \"core/Meshes/Builders/boxBuilder.pure\";\nimport { CreateCylinder } from \"core/Meshes/Builders/cylinderBuilder.pure\";\nimport { CreateSphere } from \"core/Meshes/Builders/sphereBuilder.pure\";\nimport { Mesh } from \"core/Meshes/mesh.pure\";\nimport { SubMesh } from \"core/Meshes/subMesh\";\nimport { TransformNode } from \"core/Meshes/transformNode.pure\";\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\nimport { type Scene } from \"core/scene.pure\";\nimport { type IAssetContainer } from \"core/IAssetContainer\";\nimport { Constants } from \"core/Engines/constants\";\n\nimport {\n    AnalyticPrimitiveType,\n    AnimationProperty,\n    AnimationTarget,\n    Command,\n    GeometryFlags,\n    MaterialFlags,\n    MeshFlags,\n    MISSING_OFFSET,\n    PayloadReader,\n    PrimitiveAxis,\n    TextureOutputChannel,\n    USDTextureColorSpace,\n    readCommands,\n} from \"./usdCommandProtocol\";\n\ninterface GeometryDescriptor {\n    vertexCount: number;\n    indexCount: number;\n    flags: number;\n    positions: number;\n    normals: number;\n    tangents: number;\n    uv0: number;\n    colors: number;\n    joints0: number;\n    weights0: number;\n    joints1: number;\n    weights1: number;\n    indices: number;\n    influences: number;\n}\n\ninterface TextureDescriptor {\n    id: number;\n    texture: Texture;\n    sourceColorSpace: USDTextureColorSpace;\n    scale: Float32Array;\n    bias: Float32Array;\n}\n\ninterface TextureBinding {\n    descriptor: TextureDescriptor;\n    channel: TextureOutputChannel;\n}\n\ninterface MaterialTextureBindings {\n    id: number;\n    material: PBRMaterial;\n    normalScale: number;\n    base?: TextureBinding;\n    opacity?: TextureBinding;\n    normal?: TextureBinding;\n    metallic?: TextureBinding;\n    roughness?: TextureBinding;\n    occlusion?: TextureBinding;\n    emissive?: TextureBinding;\n}\n\nclass DirectAssetContainer extends AbstractAssetContainer {\n    public dispose(): void {\n        for (const animationGroup of this.animationGroups.splice(0)) {\n            animationGroup.dispose();\n        }\n        for (const mesh of this.meshes.splice(0)) {\n            mesh.dispose();\n        }\n        for (const manager of this.morphTargetManagers.splice(0)) {\n            manager.dispose();\n        }\n        for (const skeleton of this.skeletons.splice(0)) {\n            skeleton.dispose();\n        }\n        for (const multiMaterial of this.multiMaterials.splice(0)) {\n            multiMaterial.dispose();\n        }\n        for (const material of this.materials.splice(0)) {\n            material.dispose();\n        }\n        for (const geometry of this.geometries.splice(0)) {\n            geometry.dispose();\n        }\n        for (const transformNode of this.transformNodes.splice(0)) {\n            transformNode.dispose();\n        }\n        for (const texture of this.textures.splice(0)) {\n            texture.dispose();\n        }\n        this.rootNodes.length = 0;\n    }\n}\n\nexport interface MaterializationResult {\n    container: AbstractAssetContainer & { dispose(): void };\n    materializeMs: number;\n}\n\nconst decoder = new TextDecoder();\nconst NODE_MATRIX_PROPERTY = \"__babylonUsdLocalMatrix\";\n\nfunction assertRange(data: ArrayBuffer, offset: number, count: number, bytesPerElement: number, label: string): void {\n    if (\n        !Number.isInteger(offset) ||\n        !Number.isInteger(count) ||\n        offset < 0 ||\n        count < 0 ||\n        offset % Math.min(bytesPerElement, 4) !== 0 ||\n        count > Math.floor((data.byteLength - offset) / bytesPerElement)\n    ) {\n        throw new Error(`Invalid ${label} range in OpenUSD Babylon data buffer.`);\n    }\n}\n\nfunction stringAt(data: ArrayBuffer, offset: number, length: number): string {\n    assertRange(data, offset, length, 1, \"string\");\n    return decoder.decode(new Uint8Array(data, offset, length));\n}\n\nfunction matrixAt(data: ArrayBuffer, offset: number): Matrix {\n    assertRange(data, offset, 16, 4, \"matrix\");\n    const values = new Float32Array(data, offset, 16);\n    return Matrix.FromValues(\n        values[0],\n        values[1],\n        values[2],\n        values[3],\n        values[4],\n        values[5],\n        values[6],\n        values[7],\n        values[8],\n        values[9],\n        values[10],\n        values[11],\n        values[12],\n        values[13],\n        values[14],\n        values[15]\n    );\n}\n\nfunction mimeType(value: number): string {\n    switch (value) {\n        case 2:\n            return \"image/jpeg\";\n        case 3:\n            return \"image/bmp\";\n        case 4:\n            return \"image/webp\";\n        default:\n            return \"image/png\";\n    }\n}\n\nfunction wrapMode(value: number): number {\n    switch (value) {\n        case 0:\n            return Texture.CLAMP_ADDRESSMODE;\n        case 1:\n            return Texture.WRAP_ADDRESSMODE;\n        case 2:\n            return Texture.MIRROR_ADDRESSMODE;\n        default:\n            throw new Error(`Invalid texture wrap mode ${value}.`);\n    }\n}\n\nasync function awaitAbortableAsync<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n    if (!signal) {\n        return await promise;\n    }\n    let onAbort: (() => void) | undefined;\n    const aborted = new Promise<never>((_resolve, reject) => {\n        onAbort = () => reject(signal.reason instanceof Error ? signal.reason : new Error(\"USD materialization was aborted.\"));\n        signal.addEventListener(\"abort\", onAbort, { once: true });\n        if (signal.aborted) {\n            onAbort();\n        }\n    });\n    try {\n        return await Promise.race([promise, aborted]);\n    } finally {\n        if (onAbort) {\n            signal.removeEventListener(\"abort\", onAbort);\n        }\n    }\n}\n\nexport async function materializeCommandBuffers(\n    scene: Scene,\n    commandBuffer: ArrayBuffer,\n    dataBuffer: ArrayBuffer,\n    addToScene: boolean,\n    signal?: AbortSignal\n): Promise<MaterializationResult> {\n    signal?.throwIfAborted();\n    const started = performance.now();\n    const commands = readCommands(commandBuffer);\n    const container = addToScene ? new DirectAssetContainer() : new AssetContainer(scene);\n    const nodes = new Map<number, TransformNode>();\n    const pendingParents: Array<{ node: TransformNode; parentId: number }> = [];\n    const textures = new Map<number, TextureDescriptor>();\n    const materials = new Map<number, PBRMaterial>();\n    const doubleSidedMaterials = new Map<number, PBRMaterial>();\n    const skeletons = new Map<number, Skeleton>();\n    const bones = new Map<number, Bone>();\n    const geometries = new Map<number, GeometryDescriptor>();\n    const meshes = new Map<number, Mesh>();\n    const morphTargetManagers = new Map<number, MorphTargetManager>();\n    const morphTargets = new Map<number, MorphTarget>();\n    const classicInstanceSources = new Set<number>();\n    const thinInstanceSources = new Set<number>();\n    const animationGroups = new Map<number, AnimationGroup>();\n    const textureLoads: Promise<void>[] = [];\n    const textureUrls = new Set<string>();\n    const materialTextureBindings: MaterialTextureBindings[] = [];\n    const processedTextures = new Map<string, Promise<BaseTexture>>();\n    const assetContainer = container instanceof AssetContainer ? container : undefined;\n    let root: TransformNode | undefined;\n    let timeCodesPerSecond = 24;\n    let rollingBack = false;\n    const caps = scene.getEngine().getCaps();\n    const processedTextureType =\n        caps.textureHalfFloatRender && caps.textureHalfFloatLinearFiltering\n            ? Constants.TEXTURETYPE_HALF_FLOAT\n            : caps.textureFloatRender && caps.textureFloatLinearFiltering\n              ? Constants.TEXTURETYPE_FLOAT\n              : Constants.TEXTURETYPE_UNSIGNED_BYTE;\n\n    const trackAsset = <T extends { _parentContainer: IAssetContainer | null }>(assets: T[], asset: T): void => {\n        assets.push(asset);\n        if (assetContainer) {\n            asset._parentContainer = assetContainer;\n        }\n    };\n    const applyMeshOrientation = (mesh: Mesh, flags: number): void => {\n        const sourceIsRightHanded = !(flags & MeshFlags.LeftHanded);\n        mesh.sideOrientation = scene.useRightHandedSystem === sourceIsRightHanded ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;\n    };\n    const materialForMesh = (id: number, doubleSided: boolean): PBRMaterial | null => {\n        const material = materials.get(id);\n        if (!material || !doubleSided || !material.backFaceCulling) {\n            return material ?? null;\n        }\n        let variant = doubleSidedMaterials.get(id);\n        if (!variant) {\n            variant = material.clone(`${material.name} (double-sided)`);\n            trackAsset(container.materials, variant);\n            variant.backFaceCulling = false;\n            variant.twoSidedLighting = true;\n            doubleSidedMaterials.set(id, variant);\n        }\n        return variant;\n    };\n    const binding = (textureId: number, channel: number, label: string): TextureBinding | undefined => {\n        if (textureId === MISSING_OFFSET) {\n            if (channel !== MISSING_OFFSET) {\n                throw new Error(`USD ${label} binding has a channel without a texture.`);\n            }\n            return undefined;\n        }\n        const descriptor = textures.get(textureId);\n        if (!descriptor) {\n            throw new Error(`USD ${label} binding references missing texture ${textureId}.`);\n        }\n        if (channel < TextureOutputChannel.R || channel > TextureOutputChannel.RGB) {\n            throw new Error(`USD ${label} binding has invalid output channel ${channel}.`);\n        }\n        return { descriptor, channel };\n    };\n    const channelIndex = (channel: TextureOutputChannel): number => {\n        if (channel === TextureOutputChannel.RGB) {\n            throw new Error(\"A scalar USD texture binding cannot use the RGB output.\");\n        }\n        return channel;\n    };\n    const processorChannel = (channel: TextureOutputChannel): TextureChannel => {\n        switch (channel) {\n            case TextureOutputChannel.R:\n                return TextureChannel.R;\n            case TextureOutputChannel.G:\n                return TextureChannel.G;\n            case TextureOutputChannel.B:\n                return TextureChannel.B;\n            case TextureOutputChannel.A:\n                return TextureChannel.A;\n            default:\n                return TextureChannel.RGBA;\n        }\n    };\n    const processorColorSpace = (descriptor: TextureDescriptor): TextureColorSpace =>\n        descriptor.sourceColorSpace === USDTextureColorSpace.Raw ? TextureColorSpace.Linear : TextureColorSpace.SRGB;\n    const scalarTextureIsLinear = (binding: TextureBinding): boolean => binding.descriptor.sourceColorSpace === USDTextureColorSpace.Raw;\n    const valueTransformIs = (descriptor: TextureDescriptor, scale: readonly number[] | Float32Array, bias: readonly number[] | Float32Array): boolean =>\n        scale.every((value, index) => descriptor.scale[index] === value) && bias.every((value, index) => descriptor.bias[index] === value);\n    const trackProcessedTexture = (texture: BaseTexture): BaseTexture => {\n        trackAsset(container.textures, texture);\n        return texture;\n    };\n    const processTextureAsync = async (\n        name: string,\n        binding: TextureBinding,\n        scale: readonly number[] | Float32Array,\n        bias: readonly number[] | Float32Array,\n        channel = binding.channel,\n        preserveRange = false\n    ): Promise<BaseTexture> => {\n        const source = binding.descriptor;\n        const size = source.texture.getSize();\n        const supportsMipMaps = !scene.getEngine().needPOTTextures || ((size.width & (size.width - 1)) === 0 && (size.height & (size.height - 1)) === 0);\n        const outputOptions = {\n            textureType: preserveRange ? processedTextureType : Constants.TEXTURETYPE_UNSIGNED_BYTE,\n            samplingMode: supportsMipMaps ? Constants.TEXTURE_TRILINEAR_SAMPLINGMODE : Constants.TEXTURE_BILINEAR_SAMPLINGMODE,\n            generateMipMaps: supportsMipMaps,\n        };\n        if (\n            preserveRange &&\n            processedTextureType === Constants.TEXTURETYPE_UNSIGNED_BYTE &&\n            scale.slice(0, 3).some((value, index) => Math.min(bias[index], bias[index] + value) < 0)\n        ) {\n            throw new Error(`USD texture processing for '${name}' requires a floating-point render target to preserve signed values.`);\n        }\n        const key = `${source.id}:${channel}:${scale.join(\",\")}:${bias.join(\",\")}:${preserveRange}`;\n        const cached = processedTextures.get(key);\n        if (cached) {\n            return await cached;\n        }\n        const processing = (async () => {\n            const a = new Color4(bias[0], bias[1], bias[2], bias[3]);\n            const b = new Color4(bias[0] + scale[0], bias[1] + scale[1], bias[2] + scale[2], bias[3] + scale[3]);\n            const previousBlockEntityCollection = scene._blockEntityCollection;\n            scene._blockEntityCollection = true;\n            let processingPromise: Promise<ITextureProcessOperand>;\n            try {\n                processingPromise = LerpTexturesAsync(\n                    name,\n                    CreateFactorOperand(a),\n                    CreateFactorOperand(b),\n                    CreateTextureOperand(source.texture, processorChannel(channel), processorColorSpace(source)),\n                    scene,\n                    TextureColorSpace.Linear,\n                    undefined,\n                    outputOptions\n                );\n            } finally {\n                scene._blockEntityCollection = previousBlockEntityCollection;\n            }\n            const processed = await processingPromise;\n            if (!processed.texture) {\n                throw new Error(`USD texture processing for '${name}' did not produce a texture.`);\n            }\n            if (rollingBack || signal?.aborted) {\n                processed.dispose?.();\n                if (signal?.aborted) {\n                    signal.throwIfAborted();\n                }\n                throw new Error(\"USD materialization was rolled back.\");\n            }\n            if (!assetContainer) {\n                scene.addTexture(processed.texture);\n            }\n            const texture = trackProcessedTexture(processed.texture);\n            texture.gammaSpace = false;\n            const transformedTexture = texture as Texture;\n            transformedTexture.uRotationCenter = source.texture.uRotationCenter;\n            transformedTexture.vRotationCenter = source.texture.vRotationCenter;\n            transformedTexture.wRotationCenter = source.texture.wRotationCenter;\n            transformedTexture.homogeneousRotationInUVTransform = source.texture.homogeneousRotationInUVTransform;\n            return texture;\n        })();\n        processedTextures.set(key, processing);\n        try {\n            return await processing;\n        } catch (error) {\n            processedTextures.delete(key);\n            throw error;\n        }\n    };\n    const processScalarTextureAsync = async (name: string, binding: TextureBinding): Promise<BaseTexture> => {\n        const index = channelIndex(binding.channel);\n        const scale = binding.descriptor.scale[index];\n        const bias = binding.descriptor.bias[index];\n        return await processTextureAsync(name, binding, [scale, scale, scale, 1], [bias, bias, bias, 0], binding.channel);\n    };\n    const applyMaterialTextureBindingsAsync = async (bindings: MaterialTextureBindings): Promise<void> => {\n        const { material, normalScale, base, opacity, normal, metallic, roughness, occlusion, emissive } = bindings;\n        if (base) {\n            if (base.channel !== TextureOutputChannel.RGB) {\n                throw new Error(\"A USD base-color texture must use the RGB output.\");\n            }\n            material.albedoColor = Color3.White();\n            material.albedoTexture = valueTransformIs(base.descriptor, [1, 1, 1, 1], [0, 0, 0, 0])\n                ? base.descriptor.texture\n                : await processTextureAsync(`${material.name} base color`, base, base.descriptor.scale, base.descriptor.bias);\n        }\n        if (emissive) {\n            if (emissive.channel !== TextureOutputChannel.RGB) {\n                throw new Error(\"A USD emissive texture must use the RGB output.\");\n            }\n            const descriptor = emissive.descriptor;\n            const zeroBias = descriptor.bias.slice(0, 3).every((value) => value === 0);\n            if (zeroBias) {\n                material.emissiveColor = new Color3(descriptor.scale[0], descriptor.scale[1], descriptor.scale[2]);\n                material.emissiveTexture = descriptor.texture;\n            } else {\n                const factors = Array.from({ length: 3 }, (_, index) => Math.max(1, Math.abs(descriptor.bias[index]), Math.abs(descriptor.bias[index] + descriptor.scale[index])));\n                const scale = descriptor.scale.map((value, index) => (index < 3 ? value / factors[index] : value));\n                const bias = descriptor.bias.map((value, index) => (index < 3 ? value / factors[index] : value));\n                material.emissiveColor = new Color3(factors[0], factors[1], factors[2]);\n                material.emissiveTexture = await processTextureAsync(`${material.name} emissive`, emissive, scale, bias, emissive.channel, true);\n            }\n        }\n        if (normal) {\n            if (normal.channel !== TextureOutputChannel.RGB) {\n                throw new Error(\"A USD normal texture must use the RGB output.\");\n            }\n            const canonicalNormal = normal.descriptor.sourceColorSpace === USDTextureColorSpace.Raw && valueTransformIs(normal.descriptor, [2, 2, 2, 1], [-1, -1, -1, 0]);\n            if (canonicalNormal) {\n                material.bumpTexture = normal.descriptor.texture;\n            } else {\n                const scale = Array.from(normal.descriptor.scale, (value) => value * 0.5);\n                const bias = Array.from(normal.descriptor.bias, (value, index) => (index < 3 ? (value + 1) * 0.5 : value));\n                material.bumpTexture = await processTextureAsync(`${material.name} normal`, normal, scale, bias);\n            }\n            material.bumpTexture.gammaSpace = false;\n            material.bumpTexture.level = normalScale;\n        }\n\n        const packedMetallicRoughness =\n            metallic &&\n            roughness &&\n            metallic.descriptor === roughness.descriptor &&\n            (metallic.channel === TextureOutputChannel.R || metallic.channel === TextureOutputChannel.B) &&\n            (roughness.channel === TextureOutputChannel.G || roughness.channel === TextureOutputChannel.A) &&\n            scalarTextureIsLinear(metallic) &&\n            metallic.descriptor.bias[channelIndex(metallic.channel)] === 0 &&\n            roughness.descriptor.bias[channelIndex(roughness.channel)] === 0;\n        let packedOcclusion = false;\n        if (packedMetallicRoughness) {\n            const descriptor = metallic.descriptor;\n            material.metallicTexture = descriptor.texture;\n            material.metallic = (material.metallic ?? 1) * descriptor.scale[channelIndex(metallic.channel)];\n            material.roughness = (material.roughness ?? 1) * descriptor.scale[channelIndex(roughness.channel)];\n            material.useRoughnessFromMetallicTextureAlpha = roughness.channel === TextureOutputChannel.A;\n            material.useRoughnessFromMetallicTextureGreen = roughness.channel === TextureOutputChannel.G;\n            material.useMetallnessFromMetallicTextureBlue = metallic.channel === TextureOutputChannel.B;\n            packedOcclusion =\n                occlusion?.descriptor === descriptor &&\n                occlusion.channel === TextureOutputChannel.R &&\n                descriptor.scale[TextureOutputChannel.R] === 1 &&\n                descriptor.bias[TextureOutputChannel.R] === 0;\n            material.useAmbientOcclusionFromMetallicTextureRed = packedOcclusion;\n        } else {\n            if (metallic) {\n                const index = channelIndex(metallic.channel);\n                const direct =\n                    scalarTextureIsLinear(metallic) &&\n                    (metallic.channel === TextureOutputChannel.R || metallic.channel === TextureOutputChannel.B) &&\n                    metallic.descriptor.bias[index] === 0;\n                material.metallicTexture = direct ? metallic.descriptor.texture : await processScalarTextureAsync(`${material.name} metallic`, metallic);\n                material.useRoughnessFromMetallicTextureAlpha = false;\n                material.useRoughnessFromMetallicTextureGreen = false;\n                material.useMetallnessFromMetallicTextureBlue = direct && metallic.channel === TextureOutputChannel.B;\n                material.metallic = direct ? (material.metallic ?? 1) * metallic.descriptor.scale[index] : 1;\n            }\n            if (roughness) {\n                const index = channelIndex(roughness.channel);\n                const direct = scalarTextureIsLinear(roughness) && roughness.channel === TextureOutputChannel.R && roughness.descriptor.bias[index] === 0;\n                material.microSurfaceTexture = direct ? roughness.descriptor.texture : await processScalarTextureAsync(`${material.name} roughness`, roughness);\n                material.microSurfaceTexture.gammaSpace = direct ? roughness.descriptor.texture.gammaSpace : false;\n                material.roughness = direct ? (material.roughness ?? 1) * roughness.descriptor.scale[index] : 1;\n            }\n        }\n        if (occlusion && !packedOcclusion) {\n            const index = channelIndex(occlusion.channel);\n            const direct =\n                scalarTextureIsLinear(occlusion) &&\n                occlusion.channel === TextureOutputChannel.R &&\n                occlusion.descriptor.scale[index] === 1 &&\n                occlusion.descriptor.bias[index] === 0;\n            material.ambientTexture = direct ? occlusion.descriptor.texture : await processScalarTextureAsync(`${material.name} occlusion`, occlusion);\n            material.useAmbientInGrayScale = true;\n        }\n        if (opacity) {\n            if (\n                base &&\n                material.albedoTexture &&\n                opacity.descriptor === base.descriptor &&\n                opacity.channel === TextureOutputChannel.A &&\n                opacity.descriptor.scale[TextureOutputChannel.A] === 1 &&\n                opacity.descriptor.bias[TextureOutputChannel.A] === 0\n            ) {\n                material.albedoTexture.hasAlpha = true;\n                material.useAlphaFromAlbedoTexture = true;\n            } else {\n                const direct =\n                    opacity.channel === TextureOutputChannel.A && opacity.descriptor.scale[TextureOutputChannel.A] === 1 && opacity.descriptor.bias[TextureOutputChannel.A] === 0;\n                material.opacityTexture = direct ? opacity.descriptor.texture : await processScalarTextureAsync(`${material.name} opacity`, opacity);\n                material.opacityTexture.gammaSpace = direct ? opacity.descriptor.texture.gammaSpace : false;\n                material.opacityTexture.getAlphaFromRGB = !direct;\n            }\n        }\n        const doubleSidedVariant = doubleSidedMaterials.get(bindings.id);\n        if (doubleSidedVariant) {\n            doubleSidedVariant.albedoColor.copyFrom(material.albedoColor);\n            doubleSidedVariant.albedoTexture = material.albedoTexture;\n            doubleSidedVariant.emissiveColor.copyFrom(material.emissiveColor);\n            doubleSidedVariant.emissiveTexture = material.emissiveTexture;\n            doubleSidedVariant.bumpTexture = material.bumpTexture;\n            doubleSidedVariant.metallic = material.metallic;\n            doubleSidedVariant.roughness = material.roughness;\n            doubleSidedVariant.metallicTexture = material.metallicTexture;\n            doubleSidedVariant.microSurfaceTexture = material.microSurfaceTexture;\n            doubleSidedVariant.ambientTexture = material.ambientTexture;\n            doubleSidedVariant.opacityTexture = material.opacityTexture;\n            doubleSidedVariant.alpha = material.alpha;\n            doubleSidedVariant.useAlphaFromAlbedoTexture = material.useAlphaFromAlbedoTexture;\n            doubleSidedVariant.useRoughnessFromMetallicTextureAlpha = material.useRoughnessFromMetallicTextureAlpha;\n            doubleSidedVariant.useRoughnessFromMetallicTextureGreen = material.useRoughnessFromMetallicTextureGreen;\n            doubleSidedVariant.useMetallnessFromMetallicTextureBlue = material.useMetallnessFromMetallicTextureBlue;\n            doubleSidedVariant.useAmbientOcclusionFromMetallicTextureRed = material.useAmbientOcclusionFromMetallicTextureRed;\n            doubleSidedVariant.useAmbientInGrayScale = material.useAmbientInGrayScale;\n        }\n    };\n\n    try {\n        const previousBlockEntityCollection = scene._blockEntityCollection;\n        if (!addToScene) {\n            scene._blockEntityCollection = true;\n        }\n        try {\n            for (const command of commands) {\n                const payload = new PayloadReader(commandBuffer, command.payloadOffset, command.payloadLength);\n                switch (command.opcode) {\n                    case Command.Scene: {\n                        const zUp = payload.u32() === 1;\n                        const metersPerUnit = payload.f32();\n                        timeCodesPerSecond = payload.f32() || 24;\n                        root = new TransformNode(\"USD Root\", scene);\n                        trackAsset(container.transformNodes, root);\n                        container.rootNodes.push(root);\n                        root.rotationQuaternion = zUp ? Quaternion.FromArray([-0.7071068, 0, 0, 0.7071068]) : Quaternion.Identity();\n                        root.scaling.copyFrom(\n                            scene.useRightHandedSystem\n                                ? new Vector3(metersPerUnit, metersPerUnit, metersPerUnit)\n                                : zUp\n                                  ? new Vector3(metersPerUnit, -metersPerUnit, metersPerUnit)\n                                  : new Vector3(metersPerUnit, metersPerUnit, -metersPerUnit)\n                        );\n                        break;\n                    }\n                    case Command.Texture: {\n                        const id = payload.u32();\n                        if (textures.has(id)) {\n                            throw new Error(`Duplicate USD texture ${id}.`);\n                        }\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const mime = mimeType(payload.u32());\n                        const imageOffset = payload.u32();\n                        const imageLength = payload.u32();\n                        const coordinatesIndex = payload.u32();\n                        const transformOffset = payload.u32();\n                        const wrapU = payload.u32();\n                        const wrapV = payload.u32();\n                        const sourceColorSpace = payload.u32();\n                        const valueTransformOffset = payload.u32();\n                        assertRange(dataBuffer, transformOffset, 5, 4, \"texture transform\");\n                        assertRange(dataBuffer, valueTransformOffset, 8, 4, \"texture value transform\");\n                        assertRange(dataBuffer, imageOffset, imageLength, 1, \"texture image\");\n                        if (sourceColorSpace < USDTextureColorSpace.Auto || sourceColorSpace > USDTextureColorSpace.SRGB) {\n                            throw new Error(`Invalid USD texture color space ${sourceColorSpace}.`);\n                        }\n                        const transform = new Float32Array(dataBuffer, transformOffset, 5);\n                        const valueTransform = new Float32Array(dataBuffer, valueTransformOffset, 8);\n                        if (![...transform, ...valueTransform].every(Number.isFinite)) {\n                            throw new Error(`USD texture ${id} has a non-finite transform.`);\n                        }\n                        const bytes = new Uint8Array(dataBuffer, imageOffset, imageLength);\n                        const url = URL.createObjectURL(new Blob([bytes], { type: mime }));\n                        textureUrls.add(url);\n                        let resolveLoad!: () => void;\n                        let rejectLoad!: (error: Error) => void;\n                        const loaded = new Promise<void>((resolve, reject) => {\n                            resolveLoad = resolve;\n                            rejectLoad = reject;\n                        });\n                        textureLoads.push(loaded);\n                        const texture = new Texture(url, scene, false, false, Texture.TRILINEAR_SAMPLINGMODE, resolveLoad, (message, exception) => {\n                            URL.revokeObjectURL(url);\n                            rejectLoad(exception instanceof Error ? exception : new Error(message || `Could not load texture '${url}'.`));\n                        });\n                        trackAsset(container.textures, texture);\n                        texture.onDisposeObservable.addOnce(() => URL.revokeObjectURL(url));\n                        texture.name = stringAt(dataBuffer, nameOffset, nameLength);\n                        texture.coordinatesIndex = coordinatesIndex;\n                        texture.uScale = transform[0];\n                        texture.vScale = transform[1];\n                        texture.uRotationCenter = 0;\n                        texture.vRotationCenter = 0;\n                        texture.uOffset = transform[2] - transform[1] * Math.sin(transform[4]);\n                        texture.vOffset = 1 - transform[1] * Math.cos(transform[4]) - transform[3];\n                        texture.wAng = -transform[4];\n                        texture.wrapU = wrapMode(wrapU);\n                        texture.wrapV = wrapMode(wrapV);\n                        texture.gammaSpace = sourceColorSpace !== USDTextureColorSpace.Raw;\n                        textures.set(id, {\n                            id,\n                            texture,\n                            sourceColorSpace,\n                            scale: valueTransform.subarray(0, 4),\n                            bias: valueTransform.subarray(4, 8),\n                        });\n                        break;\n                    }\n                    case Command.Material: {\n                        const id = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const baseOffset = payload.u32();\n                        const emissiveOffset = payload.u32();\n                        const metallic = payload.f32();\n                        const roughness = payload.f32();\n                        const normalScale = payload.f32();\n                        const alphaCutoff = payload.f32();\n                        const flags = payload.u32();\n                        const textureIds = Array.from({ length: 7 }, () => payload.u32());\n                        const textureChannels = Array.from({ length: 7 }, () => payload.u32());\n                        assertRange(dataBuffer, baseOffset, 4, 4, \"material base color\");\n                        assertRange(dataBuffer, emissiveOffset, 3, 4, \"material emissive color\");\n                        const base = new Float32Array(dataBuffer, baseOffset, 4);\n                        const emissive = new Float32Array(dataBuffer, emissiveOffset, 3);\n                        const material = new PBRMaterial(stringAt(dataBuffer, nameOffset, nameLength), scene);\n                        trackAsset(container.materials, material);\n                        material.id = `usd-material-${id}`;\n                        material.albedoColor = new Color3(base[0], base[1], base[2]);\n                        material.alpha = base[3];\n                        material.metallic = metallic;\n                        material.roughness = roughness;\n                        material.emissiveColor = new Color3(emissive[0], emissive[1], emissive[2]);\n                        const doubleSided = Boolean(flags & MaterialFlags.DoubleSided);\n                        material.backFaceCulling = !doubleSided;\n                        material.twoSidedLighting = doubleSided;\n                        material.unlit = Boolean(flags & MaterialFlags.Unlit);\n                        if (flags & MaterialFlags.AlphaBlend) {\n                            material.transparencyMode = 2;\n                        }\n                        if (alphaCutoff > 0) {\n                            material.transparencyMode = 1;\n                            material.alphaCutOff = alphaCutoff;\n                        }\n                        materialTextureBindings.push({\n                            id,\n                            material,\n                            normalScale,\n                            base: binding(textureIds[0], textureChannels[0], \"base-color texture\"),\n                            opacity: binding(textureIds[1], textureChannels[1], \"opacity texture\"),\n                            normal: binding(textureIds[2], textureChannels[2], \"normal texture\"),\n                            metallic: binding(textureIds[3], textureChannels[3], \"metallic texture\"),\n                            roughness: binding(textureIds[4], textureChannels[4], \"roughness texture\"),\n                            occlusion: binding(textureIds[5], textureChannels[5], \"occlusion texture\"),\n                            emissive: binding(textureIds[6], textureChannels[6], \"emissive texture\"),\n                        });\n                        materials.set(id, material);\n                        break;\n                    }\n                    case Command.TransformNode: {\n                        const id = payload.u32();\n                        const parentId = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const matrixOffset = payload.u32();\n                        const node = new TransformNode(stringAt(dataBuffer, nameOffset, nameLength), scene);\n                        trackAsset(container.transformNodes, node);\n                        node.setPreTransformMatrix(matrixAt(dataBuffer, matrixOffset));\n                        Object.defineProperty(node, NODE_MATRIX_PROPERTY, {\n                            configurable: true,\n                            get: () => node.getPivotMatrix(),\n                            set: (matrix: Matrix) => node.setPreTransformMatrix(matrix),\n                        });\n                        nodes.set(id, node);\n                        if (parentId === MISSING_OFFSET) {\n                            node.parent = root ?? null;\n                        } else {\n                            pendingParents.push({ node, parentId });\n                        }\n                        break;\n                    }\n                    case Command.Skeleton: {\n                        const id = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const jointCount = payload.u32();\n                        const jointsOffset = payload.u32();\n                        const skeleton = new Skeleton(stringAt(dataBuffer, nameOffset, nameLength), `usd-skeleton-${id}`, scene);\n                        trackAsset(container.skeletons, skeleton);\n                        const jointView = new DataView(dataBuffer);\n                        assertRange(dataBuffer, jointsOffset, jointCount * 6, 4, \"skeleton joints\");\n                        const created: Bone[] = [];\n                        for (let index = 0; index < jointCount; ++index) {\n                            const offset = jointsOffset + index * 24;\n                            const parentIndex = jointView.getUint32(offset, true);\n                            const boneId = jointView.getUint32(offset + 4, true);\n                            const jointNameOffset = jointView.getUint32(offset + 8, true);\n                            const jointNameLength = jointView.getUint32(offset + 12, true);\n                            const restMatrixOffset = jointView.getUint32(offset + 16, true);\n                            const bindMatrixOffset = jointView.getUint32(offset + 20, true);\n                            if (parentIndex !== MISSING_OFFSET && parentIndex >= index) {\n                                throw new Error(`Skeleton ${id} has an invalid parent joint index.`);\n                            }\n                            const bone = new Bone(\n                                stringAt(dataBuffer, jointNameOffset, jointNameLength),\n                                skeleton,\n                                parentIndex === MISSING_OFFSET ? null : created[parentIndex],\n                                matrixAt(dataBuffer, restMatrixOffset),\n                                matrixAt(dataBuffer, restMatrixOffset),\n                                matrixAt(dataBuffer, bindMatrixOffset),\n                                index\n                            );\n                            created.push(bone);\n                            bones.set(boneId, bone);\n                        }\n                        skeletons.set(id, skeleton);\n                        break;\n                    }\n                    case Command.Geometry: {\n                        const id = payload.u32();\n                        geometries.set(id, {\n                            vertexCount: payload.u32(),\n                            indexCount: payload.u32(),\n                            flags: payload.u32(),\n                            positions: payload.u32(),\n                            normals: payload.u32(),\n                            tangents: payload.u32(),\n                            uv0: payload.u32(),\n                            colors: payload.u32(),\n                            joints0: payload.u32(),\n                            weights0: payload.u32(),\n                            joints1: payload.u32(),\n                            weights1: payload.u32(),\n                            indices: payload.u32(),\n                            influences: payload.u32(),\n                        });\n                        break;\n                    }\n                    case Command.Mesh: {\n                        const id = payload.u32();\n                        const nodeId = payload.u32();\n                        const geometryId = payload.u32();\n                        const materialId = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const flags = payload.u32();\n                        const skeletonId = payload.u32();\n                        const submeshesOffset = payload.u32();\n                        const submeshCount = payload.u32();\n                        const descriptor = geometries.get(geometryId);\n                        if (!descriptor) {\n                            throw new Error(`Mesh ${id} references missing geometry ${geometryId}.`);\n                        }\n                        const mesh = new Mesh(stringAt(dataBuffer, nameOffset, nameLength), scene);\n                        trackAsset(container.meshes, mesh);\n                        applyMeshOrientation(mesh, flags);\n                        mesh.parent = nodes.get(nodeId) ?? root ?? null;\n                        const vertexData = new VertexData();\n                        assertRange(dataBuffer, descriptor.positions, descriptor.vertexCount * 3, 4, \"positions\");\n                        vertexData.positions = new Float32Array(dataBuffer, descriptor.positions, descriptor.vertexCount * 3);\n                        if (descriptor.flags & GeometryFlags.Normals) {\n                            assertRange(dataBuffer, descriptor.normals, descriptor.vertexCount * 3, 4, \"normals\");\n                            vertexData.normals = new Float32Array(dataBuffer, descriptor.normals, descriptor.vertexCount * 3);\n                        }\n                        if (descriptor.flags & GeometryFlags.Tangents) {\n                            assertRange(dataBuffer, descriptor.tangents, descriptor.vertexCount * 4, 4, \"tangents\");\n                            vertexData.tangents = new Float32Array(dataBuffer, descriptor.tangents, descriptor.vertexCount * 4);\n                        }\n                        if (descriptor.flags & GeometryFlags.Uv0) {\n                            assertRange(dataBuffer, descriptor.uv0, descriptor.vertexCount * 2, 4, \"texture coordinates\");\n                            vertexData.uvs = new Float32Array(dataBuffer, descriptor.uv0, descriptor.vertexCount * 2);\n                        }\n                        if (descriptor.flags & GeometryFlags.Colors) {\n                            assertRange(dataBuffer, descriptor.colors, descriptor.vertexCount * 4, 4, \"vertex colors\");\n                            vertexData.colors = new Float32Array(dataBuffer, descriptor.colors, descriptor.vertexCount * 4);\n                        }\n                        if (descriptor.flags & GeometryFlags.Skin0) {\n                            assertRange(dataBuffer, descriptor.joints0, descriptor.vertexCount * 4, 2, \"joint indices\");\n                            assertRange(dataBuffer, descriptor.weights0, descriptor.vertexCount * 4, 4, \"joint weights\");\n                            vertexData.matricesIndices = Float32Array.from(new Uint16Array(dataBuffer, descriptor.joints0, descriptor.vertexCount * 4));\n                            vertexData.matricesWeights = new Float32Array(dataBuffer, descriptor.weights0, descriptor.vertexCount * 4);\n                        }\n                        if (descriptor.flags & GeometryFlags.Skin1) {\n                            assertRange(dataBuffer, descriptor.joints1, descriptor.vertexCount * 4, 2, \"extra joint indices\");\n                            assertRange(dataBuffer, descriptor.weights1, descriptor.vertexCount * 4, 4, \"extra joint weights\");\n                            vertexData.matricesIndicesExtra = Float32Array.from(new Uint16Array(dataBuffer, descriptor.joints1, descriptor.vertexCount * 4));\n                            vertexData.matricesWeightsExtra = new Float32Array(dataBuffer, descriptor.weights1, descriptor.vertexCount * 4);\n                        }\n                        assertRange(dataBuffer, descriptor.indices, descriptor.indexCount, 4, \"indices\");\n                        vertexData.indices = new Uint32Array(dataBuffer, descriptor.indices, descriptor.indexCount);\n                        vertexData.applyToMesh(mesh, true);\n                        if (mesh.geometry) {\n                            trackAsset(container.geometries, mesh.geometry);\n                        }\n                        mesh.numBoneInfluencers = Math.min(descriptor.influences, 8);\n                        if (skeletonId !== MISSING_OFFSET) {\n                            mesh.skeleton = skeletons.get(skeletonId) ?? null;\n                        }\n\n                        const submeshView = new DataView(dataBuffer);\n                        assertRange(dataBuffer, submeshesOffset, submeshCount * 5, 4, \"submeshes\");\n                        const doubleSided = Boolean(flags & MeshFlags.DoubleSided);\n                        if (submeshCount === 1 && materialId !== MISSING_OFFSET) {\n                            mesh.material = materialForMesh(materialId, doubleSided);\n                        } else {\n                            const multi = new MultiMaterial(`${mesh.name} materials`, scene);\n                            trackAsset(container.multiMaterials, multi);\n                            for (let index = 0; index < submeshCount; ++index) {\n                                const offset = submeshesOffset + index * 20;\n                                multi.subMaterials.push(materialForMesh(submeshView.getUint32(offset, true), doubleSided));\n                            }\n                            mesh.material = multi;\n                        }\n                        mesh.releaseSubMeshes();\n                        for (let index = 0; index < submeshCount; ++index) {\n                            const offset = submeshesOffset + index * 20;\n                            new SubMesh(\n                                index,\n                                submeshView.getUint32(offset + 12, true),\n                                submeshView.getUint32(offset + 16, true),\n                                submeshView.getUint32(offset + 4, true),\n                                submeshView.getUint32(offset + 8, true),\n                                mesh\n                            );\n                        }\n                        meshes.set(id, mesh);\n                        break;\n                    }\n                    case Command.MorphTarget: {\n                        const id = payload.u32();\n                        const meshId = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const vertexCount = payload.u32();\n                        const positionsOffset = payload.u32();\n                        const normalsOffset = payload.u32();\n                        const influence = payload.f32();\n                        const mesh = meshes.get(meshId);\n                        if (!mesh) {\n                            throw new Error(`Morph target references missing mesh ${meshId}.`);\n                        }\n                        if (morphTargets.has(id) || vertexCount !== mesh.getTotalVertices() || !Number.isFinite(influence)) {\n                            throw new Error(`Morph target ${id} has invalid metadata.`);\n                        }\n                        assertRange(dataBuffer, positionsOffset, vertexCount * 3, 4, \"morph target positions\");\n                        let manager = morphTargetManagers.get(meshId);\n                        if (!manager) {\n                            manager = new MorphTargetManager(scene, mesh.name);\n                            manager.areUpdatesFrozen = true;\n                            trackAsset(container.morphTargetManagers, manager);\n                            morphTargetManagers.set(meshId, manager);\n                        }\n                        const target = new MorphTarget(stringAt(dataBuffer, nameOffset, nameLength), influence, scene, manager);\n                        target.id = `usd-morph-target-${id}`;\n                        target.setPositions(new Float32Array(dataBuffer, positionsOffset, vertexCount * 3));\n                        if (normalsOffset !== MISSING_OFFSET) {\n                            assertRange(dataBuffer, normalsOffset, vertexCount * 3, 4, \"morph target normals\");\n                            target.setNormals(new Float32Array(dataBuffer, normalsOffset, vertexCount * 3));\n                        }\n                        manager.addTarget(target);\n                        morphTargets.set(id, target);\n                        break;\n                    }\n                    case Command.AnalyticPrimitive: {\n                        const id = payload.u32();\n                        const nodeId = payload.u32();\n                        const type = payload.u32();\n                        const materialId = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const flags = payload.u32();\n                        const axis = payload.u32();\n                        const sizeOrRadius = payload.f32();\n                        const height = payload.f32();\n                        const tessellation = payload.u32();\n                        const name = stringAt(dataBuffer, nameOffset, nameLength);\n                        if (!Number.isFinite(sizeOrRadius) || sizeOrRadius <= 0) {\n                            throw new Error(`Analytic primitive ${id} has an invalid size or radius.`);\n                        }\n                        if ((type === AnalyticPrimitiveType.Cylinder || type === AnalyticPrimitiveType.Cone) && (!Number.isFinite(height) || height <= 0)) {\n                            throw new Error(`Analytic primitive ${id} has an invalid height.`);\n                        }\n                        if (type !== AnalyticPrimitiveType.Cube && (!Number.isInteger(tessellation) || tessellation < 3 || tessellation > 512)) {\n                            throw new Error(`Analytic primitive ${id} has invalid tessellation.`);\n                        }\n                        let mesh: Mesh;\n                        switch (type) {\n                            case AnalyticPrimitiveType.Cube:\n                                mesh = CreateBox(name, { size: sizeOrRadius }, scene);\n                                break;\n                            case AnalyticPrimitiveType.Sphere:\n                                mesh = CreateSphere(\n                                    name,\n                                    {\n                                        diameter: sizeOrRadius * 2,\n                                        segments: tessellation,\n                                    },\n                                    scene\n                                );\n                                break;\n                            case AnalyticPrimitiveType.Cylinder:\n                            case AnalyticPrimitiveType.Cone:\n                                mesh = CreateCylinder(\n                                    name,\n                                    {\n                                        height,\n                                        diameterTop: type === AnalyticPrimitiveType.Cone ? 0 : sizeOrRadius * 2,\n                                        diameterBottom: sizeOrRadius * 2,\n                                        tessellation,\n                                    },\n                                    scene\n                                );\n                                break;\n                            default:\n                                throw new Error(`Unsupported analytic primitive type ${type}.`);\n                        }\n                        trackAsset(container.meshes, mesh);\n                        if (mesh.geometry) {\n                            trackAsset(container.geometries, mesh.geometry);\n                        }\n\n                        // Babylon builders emit left-handed local winding. Reverse only for USD's\n                        // default right-handed convention; normals already point outward.\n                        if (!(flags & MeshFlags.LeftHanded)) {\n                            const sourceIndices = mesh.getIndices();\n                            if (!sourceIndices) {\n                                throw new Error(`Analytic primitive ${id} has no generated indices.`);\n                            }\n                            const reversed = Array.from(sourceIndices);\n                            for (let index = 0; index < reversed.length; index += 3) {\n                                [reversed[index], reversed[index + 2]] = [reversed[index + 2], reversed[index]];\n                            }\n                            mesh.setIndices(reversed);\n                        }\n                        if (axis === PrimitiveAxis.X) {\n                            mesh.rotationQuaternion = Quaternion.RotationAxis(new Vector3(0, 0, 1), -Math.PI / 2);\n                        } else if (axis === PrimitiveAxis.Z) {\n                            mesh.rotationQuaternion = Quaternion.RotationAxis(new Vector3(1, 0, 0), Math.PI / 2);\n                        } else if (axis !== PrimitiveAxis.Y) {\n                            throw new Error(`Unsupported analytic primitive axis ${axis}.`);\n                        }\n                        applyMeshOrientation(mesh, flags);\n                        mesh.parent = nodes.get(nodeId) ?? root ?? null;\n                        mesh.material = materialForMesh(materialId, Boolean(flags & MeshFlags.DoubleSided));\n                        meshes.set(id, mesh);\n                        break;\n                    }\n                    case Command.Instance: {\n                        const sourceId = payload.u32();\n                        const nodeId = payload.u32();\n                        const nameOffset = payload.u32();\n                        const nameLength = payload.u32();\n                        const source = meshes.get(sourceId);\n                        if (!source) {\n                            throw new Error(`Instance references missing mesh ${sourceId}.`);\n                        }\n                        if (thinInstanceSources.has(sourceId)) {\n                            throw new Error(`Mesh ${sourceId} cannot mix classic and thin instances.`);\n                        }\n                        classicInstanceSources.add(sourceId);\n                        const instance = source.createInstance(stringAt(dataBuffer, nameOffset, nameLength));\n                        trackAsset(container.meshes, instance);\n                        instance.parent = nodes.get(nodeId) ?? root ?? null;\n                        break;\n                    }\n                    case Command.ThinInstances: {\n                        const sourceId = payload.u32();\n                        const transformsOffset = payload.u32();\n                        const instanceCount = payload.u32();\n                        const source = meshes.get(sourceId);\n                        if (!source) {\n                            throw new Error(`Thin instances reference missing mesh ${sourceId}.`);\n                        }\n                        if (thinInstanceSources.has(sourceId) || classicInstanceSources.has(sourceId)) {\n                            throw new Error(`Mesh ${sourceId} has duplicate or mixed thin instances.`);\n                        }\n                        assertRange(dataBuffer, transformsOffset, instanceCount * 16, 4, \"thin instance transforms\");\n                        source.thinInstanceSetBuffer(\"matrix\", new Float32Array(dataBuffer, transformsOffset, instanceCount * 16), 16, true);\n                        source.thinInstanceEnablePicking = true;\n                        thinInstanceSources.add(sourceId);\n                        break;\n                    }\n                    case Command.Animation: {\n                        const targetKind = payload.u32();\n                        const targetId = payload.u32();\n                        const property = payload.u32();\n                        const trackIndex = payload.u32();\n                        const keyCount = payload.u32();\n                        const timesOffset = payload.u32();\n                        const valuesOffset = payload.u32();\n                        const stride = payload.u32();\n                        if (targetKind !== AnimationTarget.Node && targetKind !== AnimationTarget.Bone && targetKind !== AnimationTarget.MorphTarget) {\n                            throw new Error(`Invalid animation target kind ${targetKind}.`);\n                        }\n                        if ((targetKind === AnimationTarget.MorphTarget) !== (property === AnimationProperty.Influence)) {\n                            throw new Error(`Invalid animation property ${property} for target kind ${targetKind}.`);\n                        }\n                        const expectedStride =\n                            property === AnimationProperty.Influence\n                                ? 1\n                                : property === AnimationProperty.Position || property === AnimationProperty.Scaling\n                                  ? 3\n                                  : property === AnimationProperty.RotationQuaternion\n                                    ? 4\n                                    : property === AnimationProperty.Matrix\n                                      ? 16\n                                      : 0;\n                        if (stride !== expectedStride) {\n                            throw new Error(`Invalid animation value stride ${stride} for property ${property}.`);\n                        }\n                        const target =\n                            targetKind === AnimationTarget.Node ? nodes.get(targetId) : targetKind === AnimationTarget.Bone ? bones.get(targetId) : morphTargets.get(targetId);\n                        if (!target) {\n                            break;\n                        }\n                        const propertyName =\n                            property === AnimationProperty.Position\n                                ? \"position\"\n                                : property === AnimationProperty.RotationQuaternion\n                                  ? \"rotationQuaternion\"\n                                  : property === AnimationProperty.Scaling\n                                    ? \"scaling\"\n                                    : property === AnimationProperty.Influence\n                                      ? \"influence\"\n                                      : targetKind === AnimationTarget.Node\n                                        ? NODE_MATRIX_PROPERTY\n                                        : \"_matrix\";\n                        const dataType =\n                            property === AnimationProperty.Influence\n                                ? Animation.ANIMATIONTYPE_FLOAT\n                                : property === AnimationProperty.RotationQuaternion\n                                  ? Animation.ANIMATIONTYPE_QUATERNION\n                                  : property === AnimationProperty.Matrix\n                                    ? Animation.ANIMATIONTYPE_MATRIX\n                                    : Animation.ANIMATIONTYPE_VECTOR3;\n                        const animation = new Animation(`USD ${propertyName}`, propertyName, timeCodesPerSecond, dataType, Animation.ANIMATIONLOOPMODE_CYCLE);\n                        assertRange(dataBuffer, timesOffset, keyCount, 4, \"animation times\");\n                        assertRange(dataBuffer, valuesOffset, keyCount * stride, 4, \"animation values\");\n                        const times = new Float32Array(dataBuffer, timesOffset, keyCount);\n                        const values = new Float32Array(dataBuffer, valuesOffset, keyCount * stride);\n                        animation.setKeys(\n                            Array.from({ length: keyCount }, (_, index) => ({\n                                frame: times[index],\n                                value:\n                                    dataType === Animation.ANIMATIONTYPE_QUATERNION\n                                        ? Quaternion.FromArray(values, index * stride)\n                                        : dataType === Animation.ANIMATIONTYPE_MATRIX\n                                          ? Matrix.FromArray(values, index * stride)\n                                          : dataType === Animation.ANIMATIONTYPE_FLOAT\n                                            ? values[index * stride]\n                                            : Vector3.FromArray(values, index * stride),\n                            }))\n                        );\n                        let group = animationGroups.get(trackIndex);\n                        if (!group) {\n                            group = new AnimationGroup(`USD Animation ${trackIndex + 1}`, scene);\n                            animationGroups.set(trackIndex, group);\n                            trackAsset(container.animationGroups, group);\n                        }\n                        group.addTargetedAnimation(animation, target);\n                        break;\n                    }\n                }\n            }\n            for (const [meshId, manager] of morphTargetManagers) {\n                manager.areUpdatesFrozen = false;\n                if (!manager.isUsingTextureForTargets && manager.numTargets <= MorphTargetManager.MaxActiveMorphTargetsInVertexAttributeMode) {\n                    manager.optimizeInfluencers = false;\n                    manager.numMaxInfluencers = manager.numTargets;\n                }\n                meshes.get(meshId)!.morphTargetManager = manager;\n            }\n        } finally {\n            if (!addToScene) {\n                scene._blockEntityCollection = previousBlockEntityCollection;\n            }\n        }\n\n        await awaitAbortableAsync(Promise.all(textureLoads), signal);\n        await awaitAbortableAsync(\n            Promise.all(\n                materialTextureBindings.map(async (bindings) => {\n                    await applyMaterialTextureBindingsAsync(bindings);\n                })\n            ),\n            signal\n        );\n        for (const { node, parentId } of pendingParents) {\n            node.parent = nodes.get(parentId) ?? root ?? null;\n        }\n        return { container, materializeMs: performance.now() - started };\n    } catch (error) {\n        rollingBack = true;\n        // Decode callbacks can arrive after rollback; observe their rejections without\n        // delaying cancellation on an image load that may never finish.\n        void Promise.allSettled(textureLoads);\n        void Promise.allSettled(processedTextures.values());\n        container.dispose();\n        for (const url of textureUrls) {\n            URL.revokeObjectURL(url);\n        }\n        throw error;\n    }\n}\n","/** This file must only contain pure code and pure imports */\n/* eslint-disable @typescript-eslint/naming-convention */\n\nimport { RegisterInstancedMesh } from \"core/Meshes/instancedMesh.pure\";\nimport { RegisterThinInstanceMesh } from \"core/Meshes/thinInstanceMesh.pure\";\nimport { RegisterPbrMaterial } from \"core/Materials/PBR/pbrMaterial.pure\";\nimport { Tools } from \"core/Misc/tools.pure\";\nimport { type AbstractAssetContainer, AssetContainer } from \"core/assetContainer\";\nimport {\n    type ISceneLoaderAsyncResult,\n    type ISceneLoaderPluginAsync,\n    type ISceneLoaderPluginFactory,\n    type ISceneLoaderProgressEvent,\n    type SceneLoaderPluginOptions,\n    RegisterSceneLoaderPlugin,\n} from \"core/Loading/sceneLoader\";\nimport { type Scene } from \"core/scene.pure\";\n\nimport { USDFileLoaderMetadata } from \"./usdFileLoader.metadata\";\nimport {\n    type USDBinaryInput,\n    type USDFileLoaderOptions,\n    type USDImportDiagnostics,\n    type USDImportStatistics,\n    type USDImportTimings,\n    type USDLoadProgress,\n    type USDVirtualFiles,\n} from \"./usdLoadingOptions\";\nimport { materializeCommandBuffers } from \"./usdSceneMaterializer\";\nimport { PROTOCOL_VERSION } from \"./usdCommandProtocol\";\nimport { type ExtractRequest, type WorkerResponse } from \"./usdWorkerMessages\";\n\ninterface PendingRequest {\n    resolve: (response: Extract<WorkerResponse, { type: \"result\" }>) => void;\n    reject: (error: Error) => void;\n    onProgress?: (progress: USDLoadProgress) => void;\n    onLog?: USDFileLoaderOptions[\"onLog\"];\n}\n\ninterface USDLoadResult {\n    container: AbstractAssetContainer;\n    timings: USDImportTimings;\n    statistics: USDImportStatistics;\n    missingAssets: string[];\n}\n\nconst _DefaultAssetRootUrl = `${Tools._DefaultCdnUrl}/babylonUsdImporter/${PROTOCOL_VERSION}/`;\nconst _SupportedExtension = /\\.(?:usd|usda|usdc|usdz)$/i;\n\nfunction _toBytes(input: USDBinaryInput): Uint8Array {\n    if (input instanceof Uint8Array) {\n        return input.slice();\n    }\n    if (input instanceof ArrayBuffer) {\n        return new Uint8Array(input.slice(0));\n    }\n    return new Uint8Array(input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength));\n}\n\nfunction _normalizeFiles(files?: USDVirtualFiles): Record<string, Uint8Array> | undefined {\n    if (!files) {\n        return undefined;\n    }\n    const normalized: Record<string, Uint8Array> = {};\n    for (const [path, input] of Object.entries(files)) {\n        normalized[path] = _toBytes(input);\n    }\n    return normalized;\n}\n\nfunction _stagedFileName(fileName: string | undefined, bytes: Uint8Array, preserveUrlCharacters: boolean): string {\n    const normalizedFileName = fileName?.replace(/\\\\/g, \"/\").replace(/^\\.\\/+/, \"\");\n    const cleanFileName = preserveUrlCharacters ? normalizedFileName : normalizedFileName?.split(/[?#]/, 1)[0];\n    const pathParts = cleanFileName?.split(\"/\").filter(Boolean);\n    if (cleanFileName && !cleanFileName.startsWith(\"/\") && pathParts?.length && !pathParts.includes(\"..\") && _SupportedExtension.test(cleanFileName)) {\n        return pathParts.join(\"/\");\n    }\n    const isZip = bytes.length >= 4 && bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04;\n    return isZip ? \"scene.usdz\" : \"scene.usd\";\n}\n\nfunction _toAsyncResult(container: AbstractAssetContainer): ISceneLoaderAsyncResult {\n    return {\n        meshes: container.meshes,\n        particleSystems: container.particleSystems,\n        skeletons: container.skeletons,\n        animationGroups: container.animationGroups,\n        transformNodes: container.transformNodes,\n        geometries: container.geometries,\n        lights: container.lights,\n        spriteManagers: container.spriteManagers,\n    };\n}\n\n/**\n * OpenUSD scene loader backed by a WebAssembly command-buffer extractor.\n */\nexport class USDFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\n    /**\n     * Default URLs for the prebuilt OpenUSD importer assets.\n     */\n    public static DefaultConfiguration = {\n        glueUrl: `${_DefaultAssetRootUrl}babylon-usd-importer.js`,\n        wasmUrl: `${_DefaultAssetRootUrl}babylon-usd-importer.wasm`,\n        dataUrl: `${_DefaultAssetRootUrl}babylon-usd-importer.data`,\n        workerUrl: `${_DefaultAssetRootUrl}babylon-usd-importer.worker.js`,\n    };\n\n    /**\n     * Defines the name of the plugin.\n     */\n    public readonly name = USDFileLoaderMetadata.name;\n\n    /**\n     * Defines the extensions the plugin can load.\n     */\n    public readonly extensions = USDFileLoaderMetadata.extensions;\n\n    private readonly _options: USDFileLoaderOptions;\n    private _worker: Worker | undefined;\n    private _workerUrl: string | undefined;\n    private _workerBlobUrl: string | undefined;\n    private _nextRequestId = 1;\n    private readonly _pending = new Map<number, PendingRequest>();\n    private readonly _activeLoads = new Set<AbortController>();\n\n    /**\n     * Creates a USD loader.\n     * @param options Options controlling worker assets, supporting files, and diagnostics.\n     */\n    public constructor(options: Partial<USDFileLoaderOptions> = {}) {\n        this._options = {\n            ...options,\n            resolveByFileName: options.resolveByFileName ?? true,\n            glueUrl: options.glueUrl ?? USDFileLoader.DefaultConfiguration.glueUrl,\n            wasmUrl: options.wasmUrl ?? USDFileLoader.DefaultConfiguration.wasmUrl,\n            dataUrl: options.dataUrl ?? USDFileLoader.DefaultConfiguration.dataUrl,\n            workerUrl: options.workerUrl ?? USDFileLoader.DefaultConfiguration.workerUrl,\n        };\n    }\n\n    /**\n     * Creates a configured plugin instance for a SceneLoader operation.\n     * @param options SceneLoader plugin options.\n     * @returns The configured USD loader.\n     */\n    public createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\n        _RegisterUSDLoaderDependencies();\n        return new USDFileLoader(options[USDFileLoaderMetadata.name]);\n    }\n\n    /**\n     * Imports all objects from a USD stage into a scene.\n     * @param _meshesNames Mesh name filtering is not currently supported.\n     * @param scene The scene receiving the imported objects.\n     * @param data The USD, USDA, USDC, or USDZ bytes.\n     * @param rootUrl The source root URL.\n     * @param onProgress SceneLoader progress callback.\n     * @param fileName Name of the root USD layer.\n     * @returns The imported Babylon.js objects.\n     */\n    public async importMeshAsync(\n        _meshesNames: string | readonly string[] | null | undefined,\n        scene: Scene,\n        data: unknown,\n        rootUrl: string,\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\n        fileName?: string\n    ): Promise<ISceneLoaderAsyncResult> {\n        const result = await this._loadAsync(scene, data, rootUrl, onProgress, fileName, true);\n        return _toAsyncResult(result.container);\n    }\n\n    /**\n     * Loads a USD stage into a scene.\n     * @param scene The scene receiving the imported objects.\n     * @param data The USD, USDA, USDC, or USDZ bytes.\n     * @param rootUrl The source root URL.\n     * @param onProgress SceneLoader progress callback.\n     * @param fileName Name of the root USD layer.\n     */\n    public async loadAsync(scene: Scene, data: unknown, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void> {\n        await this._loadAsync(scene, data, rootUrl, onProgress, fileName, true);\n    }\n\n    /**\n     * Loads a USD stage into an asset container.\n     * @param scene The scene used to create imported objects.\n     * @param data The USD, USDA, USDC, or USDZ bytes.\n     * @param rootUrl The source root URL.\n     * @param onProgress SceneLoader progress callback.\n     * @param fileName Name of the root USD layer.\n     * @returns The populated asset container.\n     */\n    public async loadAssetContainerAsync(\n        scene: Scene,\n        data: unknown,\n        rootUrl: string,\n        onProgress?: (event: ISceneLoaderProgressEvent) => void,\n        fileName?: string\n    ): Promise<AssetContainer> {\n        const container = (await this._loadAsync(scene, data, rootUrl, onProgress, fileName, false)).container;\n        if (!(container instanceof AssetContainer)) {\n            throw new Error(\"USDFileLoader failed to create an asset container.\");\n        }\n        return container;\n    }\n\n    /**\n     * Releases the worker and rejects pending loads.\n     */\n    public dispose(): void {\n        this._terminateWorker();\n        const error = new Error(\"USDFileLoader was disposed.\");\n        for (const controller of this._activeLoads) {\n            controller.abort(error);\n        }\n        for (const request of this._pending.values()) {\n            request.reject(error);\n        }\n        this._pending.clear();\n    }\n\n    private async _loadAsync(\n        scene: Scene,\n        data: unknown,\n        _rootUrl: string,\n        onProgress: ((event: ISceneLoaderProgressEvent) => void) | undefined,\n        fileName: string | undefined,\n        addToScene: boolean\n    ): Promise<USDLoadResult> {\n        if (!(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) {\n            throw new Error(\"USDFileLoader expects binary USD data.\");\n        }\n        const bytes = _toBytes(data);\n        const files = _normalizeFiles(this._options.files);\n        const requestId = this._nextRequestId++;\n        const request: ExtractRequest = {\n            type: \"extract\",\n            requestId,\n            asset: {\n                bytes,\n                files,\n                fileName: _stagedFileName(this._options.rootFileName ?? fileName, bytes, this._options.rootFileName !== undefined),\n                resolveByFileName: this._options.resolveByFileName ?? true,\n                glueUrl: this._options.glueUrl,\n                wasmUrl: this._options.wasmUrl,\n                dataUrl: this._options.dataUrl,\n            },\n        };\n        const transfer = [...new Set([bytes.buffer, ...Object.values(files ?? {}).map((file) => file.buffer)])];\n        const controller = new AbortController();\n        const signal = controller.signal;\n        this._activeLoads.add(controller);\n        try {\n            const worker = this._getWorker(this._options.workerUrl);\n            const response = await new Promise<Extract<WorkerResponse, { type: \"result\" }>>((resolve, reject) => {\n                this._pending.set(requestId, {\n                    resolve,\n                    reject,\n                    onProgress: (progress) => {\n                        this._options.onProgress?.(progress);\n                        onProgress?.({\n                            lengthComputable: false,\n                            loaded: _ProgressPhaseIndex[progress.phase],\n                            total: 4,\n                        });\n                    },\n                    onLog: this._options.onLog,\n                });\n                try {\n                    worker.postMessage(request, transfer);\n                } catch (error) {\n                    this._pending.delete(requestId);\n                    reject(error instanceof Error ? error : new Error(String(error)));\n                }\n            });\n\n            const materializingProgress = {\n                phase: \"materializing\",\n                message: \"Creating Babylon.js objects...\",\n            } as const;\n            this._options.onProgress?.(materializingProgress);\n            onProgress?.({ lengthComputable: false, loaded: 4, total: 4 });\n            signal.throwIfAborted();\n            const materialized = await materializeCommandBuffers(scene, response.commands, response.data, addToScene, signal);\n            const result = {\n                container: materialized.container,\n                timings: {\n                    ...response.timings,\n                    materializeMs: materialized.materializeMs,\n                },\n                statistics: response.statistics,\n                missingAssets: response.missingAssets,\n            };\n            try {\n                signal.throwIfAborted();\n                this._options.onComplete?.({\n                    timings: result.timings,\n                    statistics: result.statistics,\n                    missingAssets: result.missingAssets,\n                } satisfies USDImportDiagnostics);\n                signal.throwIfAborted();\n            } catch (error) {\n                materialized.container.dispose();\n                throw error;\n            }\n            return result;\n        } finally {\n            this._activeLoads.delete(controller);\n            if (this._pending.size === 0) {\n                this._terminateWorker();\n            }\n        }\n    }\n\n    private _getWorker(workerUrl?: string | URL): Worker {\n        if (!workerUrl) {\n            throw new Error(\"The USD worker URL was not configured.\");\n        }\n        const currentLocation = globalThis.location;\n        const resolvedUrl = new URL(String(workerUrl), currentLocation?.href ?? \"http://localhost/\").href;\n        if (this._worker && this._workerUrl !== resolvedUrl) {\n            if (this._pending.size > 0) {\n                throw new Error(\"Cannot change the USD worker URL while requests are pending.\");\n            }\n            this._terminateWorker();\n        }\n        if (this._worker) {\n            return this._worker;\n        }\n        this._workerUrl = resolvedUrl;\n        if (!currentLocation || new URL(resolvedUrl).origin === currentLocation.origin) {\n            this._worker = new Worker(resolvedUrl, { type: \"module\" });\n        } else {\n            this._workerBlobUrl = URL.createObjectURL(new Blob([`import ${JSON.stringify(resolvedUrl)};`], { type: \"application/javascript\" }));\n            this._worker = new Worker(this._workerBlobUrl, { type: \"module\" });\n        }\n        this._worker.addEventListener(\"message\", (event: MessageEvent<WorkerResponse>) => {\n            const response = event.data;\n            const pending = this._pending.get(response.requestId);\n            if (!pending) {\n                return;\n            }\n            if (response.type === \"progress\") {\n                pending.onProgress?.(response.progress);\n                return;\n            }\n            if (response.type === \"log\") {\n                pending.onLog?.(response.level >= 2 ? \"error\" : response.level === 1 ? \"warning\" : \"info\", response.message);\n                return;\n            }\n            this._pending.delete(response.requestId);\n            if (response.type === \"error\") {\n                const error = new Error(response.message);\n                error.stack = response.stack;\n                pending.reject(error);\n            } else {\n                pending.resolve(response);\n            }\n        });\n        const fail = (error: Error) => {\n            this._terminateWorker();\n            for (const request of this._pending.values()) {\n                request.reject(error);\n            }\n            this._pending.clear();\n        };\n        this._worker.addEventListener(\"error\", (event) => {\n            fail(event.error ?? new Error(event.message || `Could not load the USD worker from '${resolvedUrl}'.`));\n        });\n        this._worker.addEventListener(\"messageerror\", () => {\n            fail(new Error(\"The USD worker returned a message that could not be deserialized.\"));\n        });\n        return this._worker;\n    }\n\n    private _terminateWorker(): void {\n        this._worker?.terminate();\n        this._worker = undefined;\n        this._workerUrl = undefined;\n        if (this._workerBlobUrl) {\n            URL.revokeObjectURL(this._workerBlobUrl);\n            this._workerBlobUrl = undefined;\n        }\n    }\n}\n\nconst _ProgressPhaseIndex: Record<USDLoadProgress[\"phase\"], number> = {\n    initializing: 1,\n    staging: 2,\n    extracting: 3,\n    materializing: 4,\n};\n\nlet _Registered = false;\n\n/** @internal */\nexport function _RegisterUSDLoaderDependencies(): void {\n    RegisterPbrMaterial();\n    RegisterInstancedMesh();\n    RegisterThinInstanceMesh();\n}\n\n/**\n * Registers the USD scene loader plugin and its Babylon.js runtime dependencies.\n * Safe to call multiple times; only the first call has an effect.\n */\nexport function RegisterUSDFileLoader(): void {\n    if (_Registered) {\n        return;\n    }\n    _Registered = true;\n    _RegisterUSDLoaderDependencies();\n    RegisterSceneLoaderPlugin(new USDFileLoader());\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\r\n\r\nimport { type ISceneLoaderPluginFactory, type SceneLoaderPluginOptions, RegisterSceneLoaderPlugin } from \"core/Loading/sceneLoader\";\r\n\r\nimport { BVHFileLoaderMetadata } from \"./BVH/bvhFileLoader.metadata\";\r\nimport { FBXFileLoaderMetadata } from \"./FBX/fbxFileLoader.metadata\";\r\nimport { GLTFFileLoaderMetadata } from \"./glTF/glTFFileLoader.metadata\";\r\nimport { OBJFileLoaderMetadata } from \"./OBJ/objFileLoader.metadata\";\r\nimport { SPLATFileLoaderMetadata } from \"./SPLAT/splatFileLoader.metadata\";\r\nimport { STLFileLoaderMetadata } from \"./STL/stlFileLoader.metadata\";\r\nimport { USDFileLoaderMetadata } from \"./USD/usdFileLoader.metadata\";\r\n\r\nimport { registerBuiltInGLTFExtensions } from \"./glTF/2.0/Extensions/dynamic\";\r\n\r\n/**\r\n * Registers the async plugin factories for all built-in loaders.\r\n * Loaders will be dynamically imported on demand, only when a SceneLoader load operation needs each respective loader.\r\n */\r\nexport function registerBuiltInLoaders() {\r\n    // Register the BVH loader.\r\n    RegisterSceneLoaderPlugin({\r\n        ...BVHFileLoaderMetadata,\r\n        createPlugin: async (options: SceneLoaderPluginOptions) => {\r\n            const { BVHFileLoader } = await import(\"./BVH/bvhFileLoader.pure\");\r\n            return new BVHFileLoader(options[BVHFileLoaderMetadata.name]);\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n\r\n    // Register the FBX loader.\r\n    RegisterSceneLoaderPlugin({\r\n        ...FBXFileLoaderMetadata,\r\n        createPlugin: async (options: SceneLoaderPluginOptions) => {\r\n            const { FBXFileLoader } = await import(\"./FBX/fbxFileLoader.pure\");\r\n            return new FBXFileLoader(options[FBXFileLoaderMetadata.name]);\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n\r\n    // Register the glTF loader (2.0) specifically/only.\r\n    RegisterSceneLoaderPlugin({\r\n        ...GLTFFileLoaderMetadata,\r\n        createPlugin: async (options: SceneLoaderPluginOptions) => {\r\n            const [{ GLTFFileLoader, RegisterGLTF2Loader }, { RegisterInstancedMesh }] = await Promise.all([\r\n                import(\"./glTF/2.0/glTFLoader.pure\"),\r\n                import(\"core/Meshes/instancedMesh.pure\"),\r\n            ]);\r\n            RegisterInstancedMesh();\r\n            RegisterGLTF2Loader();\r\n            return new GLTFFileLoader(options[GLTFFileLoaderMetadata.name]);\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n\r\n    // Register the built-in glTF (2.0) extensions.\r\n    registerBuiltInGLTFExtensions();\r\n\r\n    // Register the OBJ loader.\r\n    RegisterSceneLoaderPlugin({\r\n        ...OBJFileLoaderMetadata,\r\n        createPlugin: async (options: SceneLoaderPluginOptions) => {\r\n            const { OBJFileLoader } = await import(\"./OBJ/objFileLoader.pure\");\r\n            return new OBJFileLoader(options[OBJFileLoaderMetadata.name]);\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n\r\n    // Register the SPLAT loader.\r\n    RegisterSceneLoaderPlugin({\r\n        ...SPLATFileLoaderMetadata,\r\n        createPlugin: async (options: SceneLoaderPluginOptions) => {\r\n            const [{ SPLATFileLoader }, { RegisterEnginesExtensionsEngineDynamicTexture }] = await Promise.all([\r\n                import(\"./SPLAT/splatFileLoader.pure\"),\r\n                import(\"core/Engines/Extensions/engine.dynamicTexture.pure\"),\r\n            ]);\r\n            RegisterEnginesExtensionsEngineDynamicTexture();\r\n            return new SPLATFileLoader(options[SPLATFileLoaderMetadata.name]);\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n\r\n    // Register the STL loader.\r\n    RegisterSceneLoaderPlugin({\r\n        ...STLFileLoaderMetadata,\r\n        createPlugin: async () => {\r\n            const [{ STLFileLoader }, { RegisterStandardMaterial }] = await Promise.all([import(\"./STL/stlFileLoader.pure\"), import(\"core/Materials/standardMaterial.pure\")]);\r\n            RegisterStandardMaterial();\r\n            return new STLFileLoader();\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n\r\n    // Register the USD loader.\r\n    RegisterSceneLoaderPlugin({\r\n        ...USDFileLoaderMetadata,\r\n        createPlugin: async (options: SceneLoaderPluginOptions) => {\r\n            const { USDFileLoader, _RegisterUSDLoaderDependencies } = await import(\"./USD/usdFileLoader.pure\");\r\n            _RegisterUSDLoaderDependencies();\r\n            return new USDFileLoader(options[USDFileLoaderMetadata.name]);\r\n        },\r\n    } satisfies ISceneLoaderPluginFactory);\r\n}\r\n","/* eslint-disable @typescript-eslint/naming-convention */\r\n\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\n/**\r\n * Registers the built-in glTF 2.0 extension async factories, which dynamically imports and loads each glTF extension on demand (e.g. only when a glTF model uses the extension).\r\n */\r\nexport function registerBuiltInGLTFExtensions() {\r\n    unregisterGLTFExtension(\"EXT_lights_image_based\");\r\n    registerGLTFExtension(\"EXT_lights_image_based\", true, async (loader) => {\r\n        const { EXT_lights_image_based } = await import(\"./EXT_lights_image_based.pure\");\r\n        return new EXT_lights_image_based(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"EXT_mesh_gpu_instancing\");\r\n    registerGLTFExtension(\"EXT_mesh_gpu_instancing\", true, async (loader) => {\r\n        const [{ EXT_mesh_gpu_instancing }, { RegisterThinInstanceMesh }] = await Promise.all([\r\n            import(\"./EXT_mesh_gpu_instancing.pure\"),\r\n            import(\"core/Meshes/thinInstanceMesh.pure\"),\r\n        ]);\r\n        RegisterThinInstanceMesh();\r\n        return new EXT_mesh_gpu_instancing(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"EXT_meshopt_compression\");\r\n    registerGLTFExtension(\"EXT_meshopt_compression\", true, async (loader) => {\r\n        const { EXT_meshopt_compression } = await import(\"./EXT_meshopt_compression.pure\");\r\n        return new EXT_meshopt_compression(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"EXT_texture_avif\");\r\n    registerGLTFExtension(\"EXT_texture_avif\", true, async (loader) => {\r\n        const { EXT_texture_avif } = await import(\"./EXT_texture_avif.pure\");\r\n        return new EXT_texture_avif(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"EXT_texture_webp\");\r\n    registerGLTFExtension(\"EXT_texture_webp\", true, async (loader) => {\r\n        const { EXT_texture_webp } = await import(\"./EXT_texture_webp.pure\");\r\n        return new EXT_texture_webp(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"ExtrasAsMetadata\");\r\n    registerGLTFExtension(\"ExtrasAsMetadata\", false, async (loader) => {\r\n        const { ExtrasAsMetadata } = await import(\"./ExtrasAsMetadata.pure\");\r\n        return new ExtrasAsMetadata(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_animation_pointer\");\r\n    registerGLTFExtension(\"KHR_animation_pointer\", true, async (loader) => {\r\n        const [{ KHR_animation_pointer }, { _RegisterKHRAnimationPointerData }] = await Promise.all([\r\n            import(\"./KHR_animation_pointer.pure\"),\r\n            import(\"./KHR_animation_pointer.data.pure\"),\r\n        ]);\r\n        _RegisterKHRAnimationPointerData();\r\n        return new KHR_animation_pointer(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_draco_mesh_compression\");\r\n    registerGLTFExtension(\"KHR_draco_mesh_compression\", true, async (loader) => {\r\n        const { KHR_draco_mesh_compression } = await import(\"./KHR_draco_mesh_compression.pure\");\r\n        return new KHR_draco_mesh_compression(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_gaussian_splatting\");\r\n    registerGLTFExtension(\"KHR_gaussian_splatting\", true, async (loader) => {\r\n        const { KHR_gaussian_splatting } = await import(\"./KHR_gaussian_splatting.pure\");\r\n        return new KHR_gaussian_splatting(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_interactivity\");\r\n    registerGLTFExtension(\"KHR_interactivity\", true, async (loader) => {\r\n        const { KHR_interactivity, _RegisterKHRInteractivityRuntime } = await import(\"./KHR_interactivity.pure\");\r\n        _RegisterKHRInteractivityRuntime();\r\n        return new KHR_interactivity(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_lights_punctual\");\r\n    registerGLTFExtension(\"KHR_lights_punctual\", true, async (loader) => {\r\n        const { KHR_lights } = await import(\"./KHR_lights_punctual.pure\");\r\n        return new KHR_lights(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"EXT_lights_area\");\r\n    registerGLTFExtension(\"EXT_lights_area\", true, async (loader) => {\r\n        const { EXT_lights_area } = await import(\"./EXT_lights_area.pure\");\r\n        return new EXT_lights_area(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"EXT_lights_ies\");\r\n    registerGLTFExtension(\"EXT_lights_ies\", true, async (loader) => {\r\n        const { EXT_lights_ies } = await import(\"./EXT_lights_ies.pure\");\r\n        return new EXT_lights_ies(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_anisotropy\");\r\n    registerGLTFExtension(\"KHR_materials_anisotropy\", true, async (loader) => {\r\n        const { KHR_materials_anisotropy } = await import(\"./KHR_materials_anisotropy.pure\");\r\n        return new KHR_materials_anisotropy(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_clearcoat\");\r\n    registerGLTFExtension(\"KHR_materials_clearcoat\", true, async (loader) => {\r\n        const { KHR_materials_clearcoat } = await import(\"./KHR_materials_clearcoat.pure\");\r\n        return new KHR_materials_clearcoat(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_diffuse_roughness\");\r\n    registerGLTFExtension(\"KHR_materials_diffuse_roughness\", true, async (loader) => {\r\n        const { KHR_materials_diffuse_roughness } = await import(\"./KHR_materials_diffuse_roughness.pure\");\r\n        return new KHR_materials_diffuse_roughness(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_diffuse_transmission\");\r\n    registerGLTFExtension(\"KHR_materials_diffuse_transmission\", true, async (loader) => {\r\n        const { KHR_materials_diffuse_transmission } = await import(\"./KHR_materials_diffuse_transmission.pure\");\r\n        return new KHR_materials_diffuse_transmission(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_dispersion\");\r\n    registerGLTFExtension(\"KHR_materials_dispersion\", true, async (loader) => {\r\n        const { KHR_materials_dispersion } = await import(\"./KHR_materials_dispersion.pure\");\r\n        return new KHR_materials_dispersion(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_emissive_strength\");\r\n    registerGLTFExtension(\"KHR_materials_emissive_strength\", true, async (loader) => {\r\n        const { KHR_materials_emissive_strength } = await import(\"./KHR_materials_emissive_strength.pure\");\r\n        return new KHR_materials_emissive_strength(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_ior\");\r\n    registerGLTFExtension(\"KHR_materials_ior\", true, async (loader) => {\r\n        const { KHR_materials_ior } = await import(\"./KHR_materials_ior.pure\");\r\n        return new KHR_materials_ior(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_iridescence\");\r\n    registerGLTFExtension(\"KHR_materials_iridescence\", true, async (loader) => {\r\n        const { KHR_materials_iridescence } = await import(\"./KHR_materials_iridescence.pure\");\r\n        return new KHR_materials_iridescence(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_pbrSpecularGlossiness\");\r\n    registerGLTFExtension(\"KHR_materials_pbrSpecularGlossiness\", true, async (loader) => {\r\n        const { KHR_materials_pbrSpecularGlossiness } = await import(\"./KHR_materials_pbrSpecularGlossiness.pure\");\r\n        return new KHR_materials_pbrSpecularGlossiness(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_sheen\");\r\n    registerGLTFExtension(\"KHR_materials_sheen\", true, async (loader) => {\r\n        const { KHR_materials_sheen } = await import(\"./KHR_materials_sheen.pure\");\r\n        return new KHR_materials_sheen(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_specular\");\r\n    registerGLTFExtension(\"KHR_materials_specular\", true, async (loader) => {\r\n        const { KHR_materials_specular } = await import(\"./KHR_materials_specular.pure\");\r\n        return new KHR_materials_specular(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_transmission\");\r\n    registerGLTFExtension(\"KHR_materials_transmission\", true, async (loader) => {\r\n        const { KHR_materials_transmission } = await import(\"./KHR_materials_transmission.pure\");\r\n        return new KHR_materials_transmission(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_unlit\");\r\n    registerGLTFExtension(\"KHR_materials_unlit\", true, async (loader) => {\r\n        const { KHR_materials_unlit } = await import(\"./KHR_materials_unlit.pure\");\r\n        return new KHR_materials_unlit(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_variants\");\r\n    registerGLTFExtension(\"KHR_materials_variants\", true, async (loader) => {\r\n        const { KHR_materials_variants } = await import(\"./KHR_materials_variants.pure\");\r\n        return new KHR_materials_variants(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_volume\");\r\n    registerGLTFExtension(\"KHR_materials_volume\", true, async (loader) => {\r\n        const { KHR_materials_volume } = await import(\"./KHR_materials_volume.pure\");\r\n        return new KHR_materials_volume(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_mesh_quantization\");\r\n    registerGLTFExtension(\"KHR_mesh_quantization\", true, async (loader) => {\r\n        const { KHR_mesh_quantization } = await import(\"./KHR_mesh_quantization.pure\");\r\n        return new KHR_mesh_quantization(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_texture_basisu\");\r\n    registerGLTFExtension(\"KHR_texture_basisu\", true, async (loader) => {\r\n        const { KHR_texture_basisu } = await import(\"./KHR_texture_basisu.pure\");\r\n        return new KHR_texture_basisu(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_texture_transform\");\r\n    registerGLTFExtension(\"KHR_texture_transform\", true, async (loader) => {\r\n        const { KHR_texture_transform } = await import(\"./KHR_texture_transform.pure\");\r\n        return new KHR_texture_transform(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_xmp_json_ld\");\r\n    registerGLTFExtension(\"KHR_xmp_json_ld\", true, async (loader) => {\r\n        const { KHR_xmp_json_ld } = await import(\"./KHR_xmp_json_ld.pure\");\r\n        return new KHR_xmp_json_ld(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"MSFT_audio_emitter\");\r\n    registerGLTFExtension(\"MSFT_audio_emitter\", true, async (loader) => {\r\n        const [{ MSFT_audio_emitter }, { RegisterAudioSceneComponent }, { Sound }] = await Promise.all([\r\n            import(\"./MSFT_audio_emitter.pure\"),\r\n            import(\"core/Audio/audioSceneComponent.pure\"),\r\n            import(\"core/Audio/sound.pure\"),\r\n        ]);\r\n        RegisterAudioSceneComponent(Sound);\r\n        return new MSFT_audio_emitter(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"MSFT_lod\");\r\n    registerGLTFExtension(\"MSFT_lod\", true, async (loader) => {\r\n        const { MSFT_lod } = await import(\"./MSFT_lod.pure\");\r\n        return new MSFT_lod(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"MSFT_minecraftMesh\");\r\n    registerGLTFExtension(\"MSFT_minecraftMesh\", true, async (loader) => {\r\n        const { MSFT_minecraftMesh } = await import(\"./MSFT_minecraftMesh.pure\");\r\n        return new MSFT_minecraftMesh(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"MSFT_sRGBFactors\");\r\n    registerGLTFExtension(\"MSFT_sRGBFactors\", true, async (loader) => {\r\n        const { MSFT_sRGBFactors } = await import(\"./MSFT_sRGBFactors.pure\");\r\n        return new MSFT_sRGBFactors(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_node_visibility\");\r\n    registerGLTFExtension(\"KHR_node_visibility\", true, async (loader) => {\r\n        const { KHR_node_visibility, _RegisterKHRNodeVisibilityRuntime } = await import(\"./KHR_node_visibility.pure\");\r\n        _RegisterKHRNodeVisibilityRuntime();\r\n        return new KHR_node_visibility(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_node_hoverability\");\r\n    registerGLTFExtension(\"KHR_node_hoverability\", true, async (loader) => {\r\n        const { KHR_node_hoverability, _RegisterKHRNodeHoverabilityRuntime } = await import(\"./KHR_node_hoverability.pure\");\r\n        _RegisterKHRNodeHoverabilityRuntime();\r\n        return new KHR_node_hoverability(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_node_selectability\");\r\n    registerGLTFExtension(\"KHR_node_selectability\", true, async (loader) => {\r\n        const { KHR_node_selectability, _RegisterKHRNodeSelectabilityRuntime } = await import(\"./KHR_node_selectability.pure\");\r\n        _RegisterKHRNodeSelectabilityRuntime();\r\n        return new KHR_node_selectability(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_coat\");\r\n    registerGLTFExtension(\"KHR_materials_coat\", true, async (loader) => {\r\n        const { KHR_materials_coat } = await import(\"./KHR_materials_coat.pure\");\r\n        return new KHR_materials_coat(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_fuzz\");\r\n    registerGLTFExtension(\"KHR_materials_fuzz\", true, async (loader) => {\r\n        const { KHR_materials_fuzz } = await import(\"./KHR_materials_fuzz.pure\");\r\n        return new KHR_materials_fuzz(loader);\r\n    });\r\n\r\n    unregisterGLTFExtension(\"KHR_materials_volume_scatter\");\r\n    registerGLTFExtension(\"KHR_materials_volume_scatter\", true, async (loader) => {\r\n        const { KHR_materials_volume_scatter } = await import(\"./KHR_materials_volume_scatter.pure\");\r\n        return new KHR_materials_volume_scatter(loader);\r\n    });\r\n}\r\n","/**\n * Re-exports the pure implementation and applies the runtime registration side effect.\n * Import \"./usdFileLoader.pure\" for tree-shakeable, side-effect-free usage.\n */\nexport * from \"./usdFileLoader.types\";\nexport * from \"./usdFileLoader.pure\";\n\nimport { RegisterUSDFileLoader } from \"./usdFileLoader.pure\";\nRegisterUSDFileLoader();\n","/* eslint-disable @typescript-eslint/no-restricted-imports */\r\nimport * as Loaders from \"loaders/BVH/index\";\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    for (const key in Loaders) {\r\n        if (!(<any>GlobalObject).BABYLON[key]) {\r\n            (<any>GlobalObject).BABYLON[key] = (<any>Loaders)[key];\r\n        }\r\n    }\r\n}\r\n\r\nexport * from \"loaders/BVH/index\";\r\n","import * as Loaders from \"loaders/dynamic\";\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    (<any>GlobalObject).BABYLON = (<any>GlobalObject).BABYLON || {};\r\n    for (const key in Loaders) {\r\n        (<any>GlobalObject).BABYLON[key] = (<any>Loaders)[key];\r\n    }\r\n}\r\n\r\nexport * from \"loaders/dynamic\";\r\n","import * as FileLoader from \"loaders/glTF/glTFFileLoader\";\r\nimport * as Validation from \"loaders/glTF/glTFValidation\";\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    (<any>GlobalObject).BABYLON = (<any>GlobalObject).BABYLON || {};\r\n    for (const key in FileLoader) {\r\n        (<any>GlobalObject).BABYLON[key] = (<any>FileLoader)[key];\r\n    }\r\n    for (const key in Validation) {\r\n        (<any>GlobalObject).BABYLON[key] = (<any>Validation)[key];\r\n    }\r\n}\r\n\r\nexport * from \"loaders/glTF/glTFFileLoader\";\r\nexport * from \"loaders/glTF/glTFValidation\";\r\n","/* eslint-disable @typescript-eslint/no-restricted-imports */\r\nimport * as GLTF1 from \"loaders/glTF/1.0/index\";\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    (<any>GlobalObject).BABYLON = (<any>GlobalObject).BABYLON || {};\r\n    (<any>GlobalObject).BABYLON.GLTF1 = (<any>GlobalObject).BABYLON.GLTF1 || {};\r\n    for (const key in GLTF1) {\r\n        (<any>GlobalObject).BABYLON.GLTF1[key] = (<any>GLTF1)[key];\r\n    }\r\n}\r\n\r\nexport { GLTF1 };\r\n","/* eslint-disable @typescript-eslint/no-restricted-imports */\r\nimport * as Extensions from \"loaders/glTF/2.0/Extensions/index\";\r\nimport * as Interfaces from \"loaders/glTF/2.0/glTFLoaderInterfaces\";\r\nimport * as GLTF2 from \"loaders/glTF/2.0/index\";\r\n\r\nconst LoaderExtensions = { ...Extensions };\r\nconst GLTF2Loader = {\r\n    ...Interfaces,\r\n    [\"Extensions\"]: LoaderExtensions,\r\n};\r\nconst GLTF2Legacy = {\r\n    ...GLTF2,\r\n    [\"Loader\"]: GLTF2Loader,\r\n} as typeof GLTF2;\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    (<any>GlobalObject).BABYLON = (<any>GlobalObject).BABYLON || {};\r\n    // eslint-disable-next-line @typescript-eslint/naming-convention\r\n    const BABYLON = (<any>GlobalObject).BABYLON;\r\n    BABYLON.GLTF2 = BABYLON.GLTF2 || {};\r\n    BABYLON.GLTF2.Loader = BABYLON.GLTF2.Loader || {};\r\n    BABYLON.GLTF2.Loader.Extensions = BABYLON.GLTF2.Loader.Extensions || {};\r\n\r\n    const keys = [\"Loader\"];\r\n    for (const key in LoaderExtensions) {\r\n        BABYLON.GLTF2.Loader.Extensions[key] = (<any>LoaderExtensions)[key];\r\n        keys.push(key);\r\n    }\r\n    for (const key in GLTF2Loader) {\r\n        if (key === \"Extensions\") {\r\n            continue;\r\n        }\r\n\r\n        BABYLON.GLTF2.Loader[key] = (<any>GLTF2Loader)[key];\r\n        keys.push(key);\r\n    }\r\n\r\n    for (const key in GLTF2Legacy) {\r\n        // Prevent Reassignment.\r\n        if (keys.indexOf(key) > -1) {\r\n            continue;\r\n        }\r\n\r\n        BABYLON.GLTF2[key] = (<any>GLTF2Legacy)[key];\r\n    }\r\n}\r\n\r\nexport { GLTF2Legacy as GLTF2 };\r\n","/* eslint-disable @typescript-eslint/no-restricted-imports */\r\nimport * as Loaders from \"loaders/OBJ/index\";\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    for (const key in Loaders) {\r\n        if (!(<any>GlobalObject).BABYLON[key]) {\r\n            (<any>GlobalObject).BABYLON[key] = (<any>Loaders)[key];\r\n        }\r\n    }\r\n}\r\n\r\nexport * from \"loaders/OBJ/index\";\r\n","/* eslint-disable @typescript-eslint/no-restricted-imports */\r\nimport * as Loaders from \"loaders/STL/index\";\r\n\r\n/**\r\n * This is the entry point for the UMD module.\r\n * The entry point for a future ESM package should be index.ts\r\n */\r\nconst GlobalObject = typeof global !== \"undefined\" ? global : typeof window !== \"undefined\" ? window : undefined;\r\nif (typeof GlobalObject !== \"undefined\") {\r\n    for (const key in Loaders) {\r\n        if (!(<any>GlobalObject).BABYLON[key]) {\r\n            (<any>GlobalObject).BABYLON[key] = (<any>Loaders)[key];\r\n        }\r\n    }\r\n}\r\n\r\nexport * from \"loaders/STL/index\";\r\n"],"names":["_XPosition","_YPosition","_ZPosition","_XRotation","_YRotation","_ZRotation","LoaderContext","constructor","skeleton","this","loopMode","Animation","ANIMATIONLOOPMODE_CYCLE","list","root","CreateBVHNode","numFrames","frameRate","name","type","offset","Vector3","channels","children","frames","parent","ConvertNode","node","context","matrix","x","y","z","Matrix","Translation","BoneOffset","bone","Bone","animations","length","hasPosition","some","c","hasRotation","posAnim","ANIMATIONTYPE_VECTOR3","rotAnim","ANIMATIONTYPE_QUATERNION","posKeys","rotKeys","i","frame","position","push","value","clone","rotation","setKeys","CreateAnimations","animation","getKeys","child","ReadFrameData","data","frameNumber","tokenIndex","keyframe","Quaternion","combinedRotation","Identity","channel","parsedValue","parseFloat","trim","endsWith","angle","Tools","ToRadians","rotationMatrix","RotationX","RotationY","RotationZ","multiply","FromRotationMatrixToRef","ReadNode","lines","firstLine","tokens","split","toUpperCase","_a","shift","Error","tokensSplit","_b","isNaN","_c","numChannels","parseInt","splice","line","_d","ReadBvh","text","scene","assetContainer","loadingOptions","_blockEntityCollection","Skeleton","_parentContainer","nodeLine","motionLine","framesLine","framesTokens","frameTimeLine","frameTimeTokens","frameTime","frameLine","returnToRest","BVHFileLoaderMetadata","extensions","isBinary","BVHFileLoader","_loadingOptions","Object","assign","_DefaultLoadingOptions","createPlugin","options","canDirectLoad","isBvhHeader","isNotBvhHeader","importMeshAsync","_meshesNames","Promise","reject","resolve","meshes","particleSystems","skeletons","animationGroups","transformNodes","geometries","lights","spriteManagers","e","loadAsync","then","loadAssetContainerAsync","AssetContainer","_Registered","RegisterBVHFileLoader","RegisterSceneLoaderPlugin","__awaiter","thisArg","_arguments","P","generator","fulfilled","step","next","rejected","result","done","apply","__classPrivateFieldGet","receiver","state","kind","f","TypeError","has","call","get","__classPrivateFieldSet","set","create","SuppressedError","LENGTH_BASE","LENGTH_EXTRA_BITS","DISTANCE_BASE","DISTANCE_EXTRA_BITS","CODE_LENGTH_ORDER","BitReader","input","byteOffset","endOffset","bitBuffer","bitCount","readBits","count","ensureBits","readBit","bit","alignToByte","readUint16LE","ensureByteAligned","readByte","OutputWriter","expectedLength","adlerA","adlerB","bytes","Uint8Array","writeByte","byteLength","byte","copy","distance","finish","adler32","HuffmanTree","codeLengths","counts","Array","MAX_BITS","fill","nonZeroCount","maxCodeLength","Number","isInteger","Math","max","allowEmpty","symbolsByLength","remaining","bits","nextCode","code","from","_","symbols","Int16Array","symbol","decode","reader","fixedLiteralLengthTree","fixedDistanceTree","getFixedLiteralLengthTree","lengths","getFixedDistanceTree","inflateStoredBlock","output","inflateCompressedBlock","literalLengthTree","distanceTree","lengthIndex","distanceSymbol","readDynamicTrees","literalLengthCount","distanceCount","codeLengthCount","codeLengthLengths","codeLengthTree","repeatLength","repeatedValue","readCodeLengths","literalLengthLengths","slice","distanceLengths","littleEndian","parseNode","view","is64Bit","limit","numProperties","propertyListLen","headerSize","ensureRange","readUint64AsNumber","getUint32","nameLen","decodeASCII","cursor","propertiesEnd","properties","parseProperty","property","nextOffset","typeCode","String","fromCharCode","getInt16","getInt32","getFloat32","getFloat64","readInt64AsNumber","isSafeInteger","raw","low","high","negative","digits","highQuotient","floor","carried","reverse","join","int64ToDecimalString","len","TextDecoder","subarray","decodeUTF8","parseArrayProperty","elementSize","arrayLength","encoding","compressedLength","expectedByteLength","arrayData","cmf","flg","isFinalBlock","expectedAdler","inflateZlib","a","b","t","swapBytesInPlace","arrayBuffer","buffer","Float32Array","Float64Array","Int32Array","DataView","values","readInt64ArrayData","parseAsciiFBX","tokenizer","Tokenizer","version","match","ext","includes","parseVersion","nodes","isEOF","skipWhitespaceAndComments","parseNodeFromTokens","reinterpretKeyAttrDataFloat","TokenType","Tokenizer$1","pos","peek","saved","tok","ch","startPos","readString","isNumberStart","readNumber","isIdentStart","readIdentifier","expect","isNextNodeStart","isIdentChar","isNode","skipSpecialNumberSuffix","substring","isDigit","isSpecialNumberWord","isFollowedByColon","p","nameTok","identTok","countTok","aTok","parseNumericValue","parseArrayValues","numVal","isInt32","canonicalIntegerText","str","test","n","sign","startsWith","body","replace","Infinity","NaN","findChildByName","find","findDocumentNode","doc","getPropertyValue","index","getNodeArray","first","out","v","cleanFBXName","fbxName","sepIdx","indexOf","colonIdx","getPropertyTemplate","templates","objectType","templateName","templatesByName","resolvePropertyValue","template","propertyName","valueIndex","resolvePropertyValues","resolveNumberProperty","fallback","toNumber","resolveVector3Property","undefined","propertyContainers","filter","found","container","propertyNode","map","findLocalPropertyValues","extractPropertyTemplate","templateNode","Map","properties70","extractPropertyNode","getPropertyEntries","hasLabel","flags","extractUserProperties","any","entry","userPropertyValue","SCALAR_PROPERTY_TYPES","Set","typeName","numbers","propertyType","label","extractNodeTransform","modelNode","translation","scale","preRotation","postRotation","rotationPivot","scalingPivot","rotationOffset","scalingOffset","geometricTranslation","geometricRotation","geometricScaling","rotationOrder","inheritType","rotationActiveValue","rotationSpaceForLimitOnly","rotationActive","diagnostics","getChildren","parentId","nodeName","childrenOf","objects","id","createVersionNode","createLegacyObject","subType","addConnection","connections","parentOf","childId","connectionIndex","reason","message","normalizeLegacyObject","createLegacyGeometry","geometryId","extractGeometry","geometryNode","nodeId","verticesNode","rawPositions","toFloat64Array","getNodeArrayValue","pviNode","polygons","rawIndices","currentPoly","startIndex","idx","indices","parsePolygons","toInt32Array","triangles","polyIndex","poly","triangulatePolygon","triangulatePolygons","polyVertexList","pi","vi","vertexInPoly","controlPointIndex","globalIndex","buildPolygonVertexList","normalNode","normals","expandLayerElement","uvNodes","uvSets","uvNode","nameNode","setName","uvs","colorNode","colors","colorData","tangentNode","binormalNode","binormals","tangents","controlPointCount","sourceStride","layerNode","dataChildName","indexChildName","dataNode","mapping","reference","indexNode","indexData","directCount","stride","layerName","inferLayerElementStride","expanded","sourceOffset","destOffset","computeTangentHandedness","expandTangentLayer","matNode","polyMaterialIndices","polygonCount","mappingNode","referenceNode","materialsNode","materialIndex","extractMaterialIndices","expandedNormals","expandedUVs","expandedUVSets","expandedColors","expandedTangents","expandedBinormals","polyVertexCount","remap","Uint32Array","unique","keyToIndex","uvSetCount","key","u","d","vertexCount","positions","controlPointIndices","gather","src","ctor","srcIndex","k","cp","indexCount","vertices","buildTriangleMesh","materialIndices","allSame","firstMat","triCount","ti","polygonIndex","projected","normal","nx","ny","nz","current","x0","y0","z0","x1","y1","z1","computeNewellNormal","ax","abs","ay","az","dropAxis","projectPolygonTo2D","fanTriangulate","polygonArea","points","area","signedArea2D","clipped","isCCW","prev","eps","turn","cross2D","reflex","inside","visitedSinceClip","clip","j","last","earClip","pv","dataIndex","s","sourceIndex","vertexIndex","to","no","tx","ty","tz","isArray","round","readTopology","form","createNurbsBasis","order","knots","basis","topology","tMin","tMax","spans","valid","degree","maxSpans","nurbsWeight","knot","prevU","nextU","nurbsDeriv","evaluateNurbsBasis","weights","derivatives","lo","hi","mid","g","dg","weight","df","evaluateNurbsCurve","curve","derivs","base","numControlPoints","px","py","pz","pw","dx","dy","dz","dw","controlPoints","ix","w","rcp","evaluateNurbsSurface","surface","scratch","baseU","basisU","wu","du","baseV","basisV","wv","dv","numU","numV","orderU","orderV","ux","uy","uz","uw","vx","vy","vz","vw","vix","weightV","derivV","ui","uix","weightU","derivU","cw","wdu","wdv","resolveSpanSubdivision","fileStep","override","isFinite","min","readFloatArray","array","readColor","nurbsSurfaceToGeometry","subdivisionOverride","orderNode","dimensionsNode","stepNode","formNode","flipNode","stepU","_e","stepV","_f","formU","formV","flipValue","knotsU","knotsV","flipNormals","extractNurbsSurface","tess","subU","subV","openU","openV","spansU","spansV","facesU","facesV","indicesU","numAttribs","positionIx","welded","numPositions","attribUv","spanV","splitsV","splitV","ixV","originalV","spanU","splitsU","splitU","ixU","originalU","neighbors","posIx","nb","nbPos","faceCorners","faceVerts","faceV","faceU","posNormals","e1x","e1y","e1z","e2x","e2y","e2z","flip","hypot","tessellateNurbsSurface","extractNurbsCurveGeometry","subdivision","extractNurbsCurve","polyline","numSub","numSpans","numIndices","numVertices","spanIx","numSplits","subIx","tessellateNurbsCurve","polylines","color","extractLineGeometry","numPoints","flush","ends","num","int","makeNode","property60","property70","arrayNode","numberAt","toFloat64","toInt32","trunc","readTransformChannelDefaults","transformChannel","sub","axis","axisName","channelHasKeys","keys","uniqueName","ctx","usedNames","connect","normalize3","convertModel","model","rawName","hasVertices","defaults","takeDefaults","r","visibilityChannel","visibility","lightType","scalars","source","target","castShadows","lightProperties","aperture","cameraProperties","size","perIndex","uvInfo","uv","uvIndex","numUV","element","assignation","materials","of","convertMesh","modelName","scalar","shading","convertMaterials","links","skinName","link","boneName","clusterName","arrayName","convertLinks","childNames","_g","TYPE_NAMES","Aim","vec3","extractConstraint","objectMap","typeChild","props","bool3","prefix","constraint","targets","active","affectTranslation","affectRotation","affectScale","offsetTranslation","offsetRotation","offsetScale","aimVector","upVector","worldUpVector","worldUpType","ikPoleVector","weightScale","conn","role","targetName","modelId","worldUpNodeId","ikFirstJointId","ikEndJointId","ikEffectorId","Flag","Transform","FeatureFlag","BASE_FBX","PHONG_PBR","MAX_PBR_FEATURES","PBR_COMMON","SHADER_TABLES","unknown","maps","features","defaultFeatures","fbxLambert","fbxPhong","oslStandardSurface","arnoldStandardSurface","textureSuffix","textureEnabledSuffix","gltfMaterial","openPbrMaterial","shaderFxGraph","texturePrefix","textureEnabledPrefix","isPbrShaderType","applyTransform","transform","sqrt","numericValues","resolveMaterialModel","shaderType","shaderPropPrefix","shadingModelName","toLowerCase","shader","renderApi","detectShaderType","table","fbx","pbr","enabled","explicit","materialPropsFor","semantic","bound","bindings","fetch","entries","prefix2","suffix","wantValue","wantTexture","wantEnabled","mapName","prop","valueComponents","textureEnabled","nums","components","texture","texturesByProp","feature","info","_k","updateFactor","factorName","colorName","factor","nonZero","transmissionRoughness","roughness","transmissionExtraRoughness","_h","remaps","roughName","glossName","rough","_j","mapColor","mapScalar","extractMaterial","materialNode","materialId","shadingModel","shadingType","getMaterialTemplate","diffuseColor","getColorProperty","diffuseFactor","getNumberProperty","ambientColor","ambientFactor","specularColor","specularFactor","shininess","emissiveColor","emissiveFactor","opacity","transparencyFactor","extractMaterialProperties","textures","textureChildren","extractTextureRef","layeredId","layers","ref","layeredTextureId","extractTextures","tp","tex","extractShaderInfo","userProperties","implementations","impl","add","shaderProp","materialProp","srcType","dst","dstType","fileNameNode","relFileNameNode","fileName","relativeFileName","uvTranslation","uvScaling","uvRotation","uvSetName","getTextureVector2","uvSet","getNumberPairChild","wrapU","wrapV","embeddedData","videoChildren","videoNode","contentNode","content","ArrayBuffer","childName","currentModelTemplate","extractSkin","skinId","_skinNode","skinParent","modelParent","modelParentNode","meshModelId","clusterEntries","boneModelMap","clusterId","clusterNode","boneChildren","bindPoseMatrices","poseNode","matrices","poseChild","nodeChild","matrixChild","matrixValue","extractBindPoseMatrices","skinDiagnostics","bones","visited","skeletonModelIds","findModelParentId","parentNode","collectSkeletonModelIds","parentByModelId","buildSkeletonParentMap","childrenByModelId","buildSkeletonChildrenMap","queue","parentIndex","boneIndex","clusterInfo","extractBoneTransform","bindPoseMatrix","transformLinkMatrix","transformAssociateModelMatrix","clusterMode","extractClusterMatrices","createBoneDiagnostics","isCluster","modelBindPoseMatrix","buildBoneHierarchy","boneIndices","boneWeights","maxVertexIndex","indexesNode","indexes","weightsNode","vertIdx","pairs","bi","sort","cappedPairs","sum","reduce","extractVertexWeights","meshBindPoseMatrix","parentConnection","isSkeletonModel","transformNode","val","transformLinkNode","transformAssociateModelNode","modeNode","mode","boneModelId","findRigGroupingRoot","clusterModelIds","lca","modelIds","chains","getModelAncestorChain","common","chain","delete","findLowestCommonAncestor","currentId","choosePreferredBoneSource","sources","areMatricesEquivalent","epsilon","createFallbackBone","toString","compareNumber","compareSourceOrder","sourceOrderByModelId","MAX_SAFE_INTEGER","FBX_TIME_UNIT","DEFAULT_WEIGHT","KEY_CLAMP_THRESHOLD","f32","u32","floatToUint32Bits","solveTcb","tension","continuity","bias","slopeLeft","slopeRight","edge","left","right","solveAutoTangent","prevTime","time","nextTime","prevValue","nextValue","weightLeft","weightRight","autoBias","slope","delta","biasWeight","biasTarget","biasDelta","absBiasWeight","biasSign","slopeSign","absSlope","rangeLeft","rangeRight","maxLeft","maxRight","solveAutoTangentOneSided","t0","t1","v0","v1","findCubicBezierT","p1","p2","p1_3","p2_3","a_3","b_2","t2","segmentTangents","dt","rightDx","rightDy","leftDx","leftDy","rightSlope","nextLeftSlope","evaluateCurve","defaultValue","noExtrapolation","minTime","maxTime","realTime","pre","preExtrapolation","postExtrapolation","repeatCount","duration","rep","repN","repD","valueDelta","extrapolateCurve","begin","end","rcpDelta","interpolation","constantMode","t3","u2","u3","y3","DEG2RAD","PI","RAD2DEG","eulerToQuat","cx","cos","sx","sin","cy","sy","cz","sz","quatToEuler","q","qx","qy","qz","qw","halfPi","asin","atan2","quatSlerp","wa","wb","dot","bx","by","bz","bw","omega","acos","rcpSin","powAbs","pow","combineLayerValue","layer","additive","composeScale","composeRotation","blended","rw","extractAnimStack","stackId","stackNode","rebaseKeyframes","declaredTimeSpan","props70","start","stop","pName","fbxTimeToSeconds","extractAnimationStackTimeSpan","layerEntries","allCurveNodes","allUnsupportedCurveNodes","layerId","blendMode","rotationAccumulationMode","scaleAccumulationMode","layerIndex","curveNodeEntries","layerCurveNodes","layerUnsupportedCurveNodes","layerDiagnostics","layerWeightCurve","curveNodeId","curveNodeNode","curveNodeData","extractCurveNode","unsupported","extractUnsupportedCurveNode","targetId","curves","scanCurveTimes","diagnostic","curveNodeType","normalizedWeight","blend","makeLayerBlend","weightCurve","curveNodes","unsupportedCurveNodes","finalizeAnimStack","hasKeys","timeOffset","cn","declaredStart","declaredStop","hasDeclaredDuration","keyStart","keyStop","startTime","stopTime","rawDefaults","extractCurveNodeDefaultValues","defaultValues","targetModelId","findCurveNodeTarget","extractCurves","geometryChannelId","deformer","findCurveNodeGeometryShapeChannel","findCurveNodeBlendShapeTarget","curveCount","visit","curveNode","extractKeyframes","extractCurveExtrapolation","ooChildren","channelNames","propName","keyTimeNode","keyValueNode","keyTimes","keyValues","toFloat32Array","keyAttrFlags","keyAttrData","keyAttrRefCount","keyAttributeIndices","keyCount","total","attrIndex","buildKeyAttributeIndices","times","attributes","numKeys","attr","nextSlopeLeft","nextWeightLeft","packed","tcbSlopeLeft","tcbSlopeRight","tcb","deltaTime","buildKeyframes","dataOffset","getFiniteKeyAttrData","read","typeValue","repetitionValue","charCodeAt","parseExtrapolation","sampleFBXCurveAtTime","curveData","LEGACY_ATTRIBUTE_CHANNELS","findLegacyShapeChannel","channelName","geometry","readLegacyTimeSpan","readLegacyCompoundChannel","decodeLegacyKeys","keyNode","vals","chr","keyVer","interp","constNext","leftSlope","leftWeight","rightWeight","autoFlag","pendingLeft","pendingLeftWeight","nextLeft","auto","isNext","slopeMode","numWeights","weightMode","solveLegacyAutoTangent","constantNext","keyframesFromSlopes","v2","evaluateLayeredChannel","staticValue","evaluateLayeredProperty","isChannelSteppedAt","sawCurve","extractBlendShape","deformerId","_deformerNode","channelChildren","channelId","channelNode","deformPercent","rawFullWeights","extractFullWeights","shapes","shapeChildren","shapeNode","shape","extractShape","fullWeights","normalizeFullWeights","sortShapesByFullWeight","rawVertices","toUint32Array","normalsNode","rawNormals","HELPER_NODE_NAMES","HANDLED_NODE_ATTRIBUTES","isSupportedDeformer","createObjectDiagnostic","objectId","objectName","parentCount","connection","childCount","flagNurbsDeformers","kinds","interpretFBX","isLegacyDocument","headerVersion","takes","take","models","implicitModels","takesNode","implicitTake","settings","frameRateNode","frameRateValue","fps","extra","replacedGlobalSettings","existing","upgradeLegacyDocument","objectEntries","connectionEntries","legacyIds","legacyIdsByCleanName","syntheticLegacyIds","legacyGeometryByModelId","objectsNode","connectionsNode","usedIds","reserve","obj","nextSyntheticId","allocateId","remappedIds","numericIdOf","getSafeFBXObjectId","toObjectId","numericId","direct","legacyName","getLegacyId","clean","getSyntheticLegacyId","idsByName","synthesizeInlineShapes","owner","synthetic","shapeName","shapeId","shapeGeometry","idProp","normalized","legacySubType","attributeId","attribute","poPropertyName","childIdRaw","parentIdRaw","rawType","accepted","resolveConnections","propertyTemplates","definitions","objectTypeNode","extractPropertyTemplates","globalSettings","upAxis","upAxisSign","frontAxis","frontAxisSign","coordAxis","coordAxisSign","unitScaleFactor","gsNode","timeMode","customFrameRate","TIME_MODE_FPS","extractGlobalSettings","materialById","m","textureTemplate","modelMaterials","materialLayer","materialIds","slotForElement","elementName","layerElements","textureRefs","textureIndex","slot","material","fbxMap","pbrMap","textureIds","texIndex","matIndex","attachLegacyLayerTextures","nurbsSubdivision","surfaceChild","skins","skin","extractSkins","rigs","groupByRoot","rootModelId","group","groupSkins","rigModelIds","sourceBonesByModelId","ancestorId","pending","pop","warnings","collectTransformLinkWarnings","preferredBoneByModelId","buildParentMap","orderedModelIds","ordered","orderParentsBeforeChildren","modelIdToBoneIndex","sourceBone","parentModelId","skinBindings","rigId","skinBoneIndexToRigBoneIndex","rigBoneIndex","buildSkinBinding","rootModelIds","buildRig","resolveRigs","blendShapes","bs","extractBlendShapes","stacks","stack","syntheticId","timeSpan","track","rawModelName","subName","shapeChannelId","extractLegacyTakes","extractAnimations","cameras","cameraTemplate","nearPlane","farPlane","projectionType","focalLength","filmWidth","filmHeight","orthoZoom","roll","resolved","resolveCameraParameters","aspectRatio","fieldOfView","fovDegY","fieldOfViewX","fovDegX","apertureMode","apertureSizeInch","orthographicSize","unknownProperties","collectUnknownLocalProperties","CAMERA_PROPERTIES","extractCameras","lightTemplate","intensity","outerAngle","innerAngle","coneAngle","decayType","decayStart","enableNearAttenuation","toBoolean","enableFarAttenuation","nearAttenuationStart","nearAttenuationEnd","farAttenuationStart","farAttenuationEnd","areaLightShape","LIGHT_PROPERTIES","extractLights","constraintType","extractSceneDiagnostics","constraints","extractConstraints","rootModels","geometryMap","curveMap","materialMap","rootChildren","rootIds","buildStack","buildModel","hasModelParent","buildModelHierarchy","displayLayers","selectionSets","modelById","walk","colorValues","show","freeze","displayLayer","members","includeNode","inSet","edges","faces","extractCollections","MAX_MODEL_DEPTH","geomChildren","matChildren","mat","extractTransform","childModelNodes","cycleDiagnostics","cullingNode","cullingOff","customProperties","flagged","hasAny","custom","SYSTEM_PROPERTIES","extractCustomProperties","lodGroup","thresholds","displayLevels","relativeEntry","relative","APERTURE_FORMATS","aspectMode","apertureFormat","gateFit","aspectX","aspectY","fov","fovX","fovY","orthoExtent","format","filmX","filmY","resX","resY","filmRatio","effectiveFit","apertureX","apertureY","orthoX","orthoY","d2r","r2d","tanX","tanY","tan","focalInch","atan","known","containerName","eulerToMatrixXYZ","rx","ry","rz","mx","my","mz","eulerToMatrix","computeFBXGeometricDeltaMatrix","scaleM","Scaling","rotationM","Scratch","invRoot","invParent","world","local","mA","mB","mC","mD","decomposedScale","localValue","up","forward","origin","axisA","axisB","axisC","eulerA","eulerB","decomposedRotation","Solvers","WeakMap","FBXConstraintSolver","_behaviors","_ordered","_cyclic","_dirty","_beforeAnimations","_afterAnimations","_scene","Get","GetOrCreate","solver","_ensureOrder","cyclicConstraints","register","behavior","onBeforeAnimationsObservable","beginFrame","onAfterAnimationsObservable","solve","unregister","remove","invalidateOrder","restoreBase","captureBase","evaluate","behaviors","dependencies","reads","dependencyNodes","driven","attachedNode","_IsAncestorOrSelf","deps","progressed","cyclic","ancestor","FBXConstraintBehavior","_options","_base","scaling","_hasBase","_offsetTranslation","_offsetRotation","_offsetScale","localBasis","_localBasisTransposed","_OrthonormalBasisToRef","transpose","init","attach","getScene","detach","rotationQuaternion","FromEulerVector","copyFrom","upNode","computeWorldMatrix","invertToRef","_fbxWorld","IdentityToRef","_solvePosition","_solveRotation","_solveScale","_solveParent","_solveAim","multiplyToRef","_blendTargets","decompose","addInPlace","scaleInPlace","SlerpToRef","_applyWeighted","desired","mask","_applyRotation","desiredLocal","toEulerAnglesToRef","FromEulerAnglesToRef","_writePosition","_writeScaling","TransformCoordinatesToRef","FromQuaternionToRef","parentScale","ComposeToRef","nodeWorld","getTranslationToRef","subtractToRef","lengthSquared","normalize","subtractInPlace","sceneUp","rotateByQuaternionToRef","TransformNormalToRef","Dot","normalizeToRef","second","cr","scaleToRef","CrossToRef","FromValuesToRef","FBXFileLoaderMetadata","FBXFileLoader","_bindRestBones","WeakSet","_sourceBonesBySkeleton","_scaleCompensationHelpersBySkeleton","_frameRate","_activeLayers","_parentModelById","_curveNodesByModelId","_inheritScaleHelpers","_meshByGeometryKey","_instanceSource","_evaluatedCurveNodeIds","_rigBoneModelIds","full","preset","normalMapCoordinateSystem","unitScale","shareGeometry","onWarning","rebaseAnimations","attachCamerasAndLights","meshesNames","rootUrl","_onProgress","_fileName","fbxScene","_parseAndInterpret","_buildScene","mesh","ag","tn","light","camera","_addMaterialToContainer","_addTextureToContainer","LinesMesh","_setAssetContainer","removeAllFromScene","_parse","_parseFromArrayBuffer","isView","headerBytes","parseBinaryFBX","head","trimStart","nameFilter","_buildNameFilter","materialCache","matData","_createMaterial","skeletonByRigId","skeletonByGeometryId","skinByGeometryId","skinBindingByGeometryId","skinById","rig","_createSkeleton","binding","modelIdToData","collectModelData","cullingConflictMaterialIds","_collectCullingConflictMaterialIds","cullingMaterialCloneCache","rootNode","TransformNode","useRightHandedSystem","cmPerTargetUnit","metadata","fbxUnitScaleFactor","fbxFrameRate","assetRoot","axisConversion","_computeFBXAxisConversionMatrix","equals","_applyMatrixToTransform","modelIdToNode","fbxWorldIdentity","_buildModel","_linkSkeletonsToTransformNodes","boneTransformNodes","skeletonBone","getTransformNode","_applyBlendShapes","instance","morphTargetManager","cameraByAttributeId","camData","cam","_createCamera","sceneLights","lightByAttributeId","lightData","_createLight","_applyConstraints","animStack","_createAnimationGroup","_reportDiagnostics","flatMap","getActiveTextures","MultiMaterial","multiMaterials","subMaterial","subMaterials","asset","basisRows","assignAxis","sourceAxis","sourceSign","targetAxis","row","every","FromValues","parentFBXWorldMatrix","fbxWorldMatrix","_computeFBXModelLocalMatrix","parentModel","parentModelNode","_isRigBone","helper","deformable","skinBinding","needInitialSkinMatrix","geometryKey","sideOrientation","fbxInstanceOf","_createMesh","meshBindMatrix","FromArray","updatePoseMatrix","Invert","alwaysSelectAsActiveMesh","_applyRestTRS","_applyMultiMaterial","_getModelMaterial","_useUnmodulatedVertexColorMaterials","_applyMaterialUVSetCoordinates","_applyModelMetadata","_createLinesMesh","_modelSubtreeMatchesNameFilter","_applyLodGroup","boneData","_getSourceBone","boneNode","scaleCompensationHelper","_getScaleCompensationHelper","helperNode","getLocalMatrix","linkTransformNode","fbxCustomProperties","fbxUserProperties","fbxDiagnostics","fbxDisplayLayer","fbxLodGroup","setEnabled","lod","lodChildren","level","display","meshesOf","Mesh","getChildMeshes","levelMeshes","threshold","useLODScreenCoverage","addLODLevel","fbxLodLevel","geometricMatrix","_computeFBXGeometricMatrix","TransformCoordinates","vertexData","VertexData","applyToMesh","Color3","fbxCurveType","fbxCurveSegments","geomData","Material","CounterClockWiseSideOrientation","ClockWiseSideOrientation","float64To32","gt","gr","gs","geometricPositionMatrix","geometricDeltaMatrix","_computeFBXGeometricDeltaMatrix","geometricNormalMatrix","_computeFBXGeometricNormalMatrix","hasGeometricPositionTransform","hasGeometricDeltaTransform","hasGeometricNormalTransform","TransformNormal","uvs2","uvs3","uvs4","uvs5","uvs6","applyTangentHandednessScale","_getNormalMapTangentHandednessScale","normalMapTangentHandednessScale","groups","vertexGroupKeys","i1","i2","i3","p3","uv1","uv2","uv3","x2","y2","z2","s1","s2","denominator","accumulateTangentContribution","normalizeVector","normalDotTangent","ox","oy","oz","tangentLength","buildFallbackTangent","handedness","generateTangents","hasVertexAlpha","matricesIndices","matricesWeights","matricesIndicesExtra","matricesWeightsExtra","numBoneInfluencers","_buildSkinningData","fbxGeometryId","fbxControlPointIndices","fbxGeometryDeltaMatrix","fbxGeometryNormalMatrix","fbxPreRotMatrix","matIndices","recorded","fbxSubMeshMaterialIndices","multiMat","matIdx","fbxMat","getIndices","sortedMatIndices","newIndices","subMeshRanges","tris","setIndices","range","subMeshes","getTotalVertices","SubMesh","usage","collect","cullingOn","conflicts","cullingCloneCache","cloneCullingOffMaterial","backFaceCulling","cached","StandardMaterial","PBRMaterial","_applyStandardMaterialUVSetCoordinates","albedoTexture","bumpTexture","emissiveTexture","ambientTexture","metallicTexture","reflectivityTexture","microSurfaceTexture","opacityTexture","clearCoat","sheen","diffuseTexture","specularTexture","reflectionTexture","fbxUVSetName","uvSetIndex","findIndex","coordinatesIndex","assignedMat","unmodulated","albedoColor","cpIdx","boneIdx","boneWts","indicesBuffer","weightsBuffer","bufferIndex","skinBoneIndex","_createPbrMaterial","_createStandardMaterial","fbxShaderType","fbxFeatures","fromEntries","specGloss","scaleColor","baseColor","baseFactor","White","metallic","reflectivityColor","microSurface","glossiness","metalness","metallicF0Factor","metallicReflectanceColor","emission","emissionColor","_l","emissionFactor","alpha","_alphaFromClassicTransparency","transparencyMode","MATERIAL_ALPHABLEND","transmission","_m","transmissionFactor","subSurface","isRefractionEnabled","refractionIntensity","tint","transmissionColor","tintColor","ior","specularIor","indexOfRefraction","coat","_o","coatFactor","_p","isEnabled","coatRough","coatRoughness","coatIor","coatColor","isTintEnabled","_q","sheenFactor","_r","sheenColor","sheenRough","sheenRoughness","unlit","textureFor","isNormal","_createTexture","_applyTextureSettings","albedo","normalMap","_configureNormalTexture","emissiveTex","ao","ambientOcclusion","useAmbientInGrayScale","spec","gloss","_s","metalRef","_t","roughSource","_u","_v","roughRef","sameTexture","usesMetalTexture","roughTex","useMetallnessFromMetallicTextureBlue","useRoughnessFromMetallicTextureGreen","useRoughnessFromMetallicTextureAlpha","_w","fbxDroppedMetalnessTexture","metalTex","_x","_y","_z","useAlphaFromAlbedoTexture","MATERIAL_ALPHATESTANDBLEND","opacityTex","coatTex","coatNormal","sheenTex","transparencyColor","amount","uOffset","vOffset","uScale","vScale","wAng","Texture","CLAMP_ADDRESSMODE","WRAP_ADDRESSMODE","fbxLayeredTextureId","hasTexture","slots","Black","specularPower","_isSupportedMaterialTextureSlot","_isNormalMapTextureSlot","gammaSpace","invertNormalMapX","invertNormalMapY","isDataTexture","sourceName","_getTextureSourceName","creationOptions","_getTextureCreationOptions","embeddedTextureName","updateURL","encodeURIComponent","forcedExtension","textureUrls","_getExternalTextureUrls","textureUrl","_createExternalTexture","texturePath","fallbackUrls","_buildTextureFallbackUrls","fallbackIndex","onError","fallbackUrl","_getForcedExtension","slashIndex","lastIndexOf","dotIndex","basePath","currentExtension","extension","mimeType","_getMimeType","textureNames","urls","textureName","_isSafeRelativeTexturePath","basename","_getTextureSourceNameFromPath","part","GetMimeType","MorphTargetManager","optimizeInfluencers","deltaMatrix","normalMatrix","cpIndices","basePositions","getVerticesData","baseNormals","initialInfluences","calculateBlendShapeInfluences","targetIndices","shapeIndex","targetData","buildMorphTargetData","morphTarget","MorphTarget","setPositions","setNormals","numTargets","addTarget","fbxBlendShapeChannelIds","fbxBlendShapeChannelTargets","numMaxInfluencers","worldMatrix","Zero","FreeCamera","fovMode","Camera","FOVMODE_VERTICAL_FIXED","minZ","maxZ","fbxCamera","ORTHOGRAPHIC_CAMERA","orthoTop","orthoBottom","orthoRight","orthoLeft","cameraParent","determinant","pivot","FromRotationMatrix","setTarget","direction","subtract","localPosition","localDirection","DirectionalLight","diffuse","SpotLight","PointLight","computeTransformedInformation","specular","fbxLight","skeletonId","sourceBones","scaleCompensationHelpers","authoredLocalMatrices","authoredAbsoluteMatrices","authoredRuntimeLocalMatrices","authoredInheritScales","_computeBoneInheritScales","authoredLocal","_computeFBXLocalMatrix","_computeFBXRuntimeLocalMatrix","_computeFBXAbsoluteMatrices","absoluteBindMatrices","localBindMatrices","absoluteBind","parentAbsoluteBindInv","useBindAsRest","_shouldUseBindMatricesAsRest","restInheritScales","localMatrix","parentBone","_splitParentScaleCompensatedLocalMatrix","_getBoneInheritedScale","helperLocalMatrix","fbxScaleCompensationForBoneIndex","fbxScaleCompensationForBoneName","boneLocalMatrix","_getMaxScaleRatio","updateMatrix","getParent","_updateAbsoluteBindMatrices","localMatrices","absoluteMatrices","ownScales","own","inheritedFrom","_getBoneInheritScaleNode","inheritScales","scales","_applyParentScaleCompensation","inheritedScale","getTranslation","setTranslation","Compose","_getInverseScaleVector","_safeInverseScale","scaleA","rotationA","translationA","scaleB","rotationB","translationB","_getScaleRatio","absA","absB","POSITIVE_INFINITY","translationM","computeFBXGeometricMatrix","inverseScaleM","computeFBXGeometricNormalMatrix","hasPivots","hasOffsets","hasPostRot","preRotM","lclRotM","T","Roff","Rp","RpInv","Soff","Sp","SpInv","Rpre","R","S","RpostInv","Rpost","computeFBXLocalMatrix","trs","_computeLocalTRS","_adjustTRSForInheritMode","propertyTargets","animGroup","AnimationGroup","animatedBoneTargetProperties","addBoneAnimation","targetProperties","targetProperty","addTargetedAnimation","modelIdToBones","boneCurves","nonBoneCurves","blendShapeCurves","inheritedRigModelIds","inheritType2ModelIds","_buildInheritedRigBoneAnimations","modelData","_buildBoneAnimations","getBindMatrix","_buildNodeAnimations","parentCurves","_collectInheritScaleCurves","baseTimes","collectAnimationSampleTimes","sampleParent","_computeInheritAwareLocalMatrix","_sampleModelLocalMatrix","_refineSampleTimes","prevQuat","sc","rq","tr","_isVector3KeysConstant","anim","areQuaternionKeysConstant","scaleCurves","blendShapeGroups","targetChannelId","targetFound","channelTargets","targetInfo","getTarget","ANIMATIONTYPE_FLOAT","_layeredScalarKeys","channelMap","targetIndex","propertyGroups","built","_buildPropertyAnimations","targetedAnimations","dispose","compensatedModelIds","sampledModelIds","rigCurveNodes","md","keysByBone","sclKeys","keysByHelper","restLocalInverses","restLocalMatrix","restLocalInverse","sampledScales","_sampleModelScale","sampledInheritScales","_pushMatrixKeys","sclAnim","helperAnimations","helperPosKeys","helperRotKeys","helperSclKeys","keySet","extraTimeCurves","rNode","sampleTRS","sampled","_sampleModelTRS","stepT","stepR","stepS","sample","maxDepth","refine","d0","d1","depth","tm","dm","lerpT","Lerp","lerpS","slerpR","Slerp","posErr","Distance","sclErr","angErr","posTol","sclTol","mapValue","buildScalarAnimationKeys","scalarCurve","layered","sampleTimes","vectorSamples","scalarKeys","inTangent","outTangent","colorKeys","meta","aspect","ANIMATIONTYPE_COLOR3","isPbr","short","upSign","summaries","summary","firstJoint","endJoint","effector","fbxConstraints","targetNode","addBehavior","JSON","stringify","details","fbxDisplayLayers","l","fbxSelectionSets","warning","seen","_getInheritScaleNode","rotM","post","postInv","_getInheritScale","inheritNode","inherited","scaleOverride","bindLocalMatrix","correctedLocalMatrix","nameSet","arr","nextIndex","prevIndex","vo","po","aLength","bLength","computeCornerAngle","uo","quantizeTangentKey","buildTangentGroupKey","quantized","is","targetPositions","targetNormals","cpToShapeIdx","shapeIdx","rv","rn","shapeCount","clamp01","influences","previousWeight","nextWeight","MAX_DENSE_SEGMENT_SAMPLES","MAX_LINEAR_SEGMENT_SAMPLES","MAX_SAMPLES_PER_TARGET","NEGATIVE_INFINITY","anchorSet","rangeStart","rangeStop","anchors","segmentIsDense","totalFrames","ceil","firstFrame","lastFrame","interior","cap","sorted","deduped","getCurveSampleRange","unshift","animationKeys","nextAnimationKey","nextKey","linearSlope","mapSlope","RegisterFBXFileLoader","ValidateAsync","getExternalResource","externalResourceFunction","uri","GLTFValidator","validateBytes","validateString","WorkerFunc","pendingExternalResources","onmessage","importScripts","url","postMessage","GLTFValidation","Worker","workerContent","workerBlobUrl","URL","createObjectURL","Blob","worker","error","removeEventListener","onMessage","_LastResults","terminate","addEventListener","GetBabylonScriptURL","Configuration","slicedData","_LoadScriptPromise","LoadBabylonScriptAsync","_DefaultCdnUrl","GLTFMagicBase64Encoded","GLTFFileLoaderMetadata","readAsync","GLTFLoaderCoordinateSystemMode","GLTFLoaderAnimationStartMode","GLTFLoaderState","DefaultPreprocessUrlAsync","GLTFLoaderBaseOptions","alwaysComputeBoundingBox","alwaysComputeSkeletonRootNode","animationStartMode","FIRST","compileMaterials","compileShadowGenerators","coordinateSystemMode","AUTO","createInstances","loadAllMaterials","loadMorphTargets","useMaxMorphTargetInfluencers","loadNodeAnimations","loadOnlyMaterials","loadSkins","skipMaterials","targetFps","transparencyAsCoverage","useClipPlane","useGltfTextureNames","useRangeRequests","useSRGBBuffers","validate","useOpenPBR","dontUseTransmissionHelper","GLTFLoaderDefaultOptions","GLTFLoaderOptions","extensionOptions","preprocessUrlAsync","capturePerformanceCounters","customRootNode","loggingEnabled","onCameraLoaded","onMaterialLoaded","onMeshLoaded","onParsed","onSkinLoaded","onTextureLoaded","onValidated","_0","_1","_2","GLTFFileLoader","super","onParsedObservable","Observable","onMeshLoadedObservable","onSkinLoadedObservable","onTextureLoadedObservable","onMaterialLoadedObservable","onCameraLoadedObservable","onCompleteObservable","onErrorObservable","onDisposeObservable","onExtensionLoadedObservable","onValidatedObservable","_loader","_state","_requests","onLoaderStateChangedObservable","_logIndentLevel","_loggingEnabled","_log","_logDisabled","_capturePerformanceCounters","_startPerformanceCounter","_startPerformanceCounterDisabled","_endPerformanceCounter","_endPerformanceCounterDisabled","_isPreprocessUrlAsyncSet","callback","_onParsedObserver","_onMeshLoadedObserver","_onSkinLoadedObserver","skinnedNode","_onTextureLoadedObserver","_onMaterialLoadedObserver","_onCameraLoadedObserver","onComplete","_onCompleteObserver","_onErrorObserver","onDispose","_onDisposeObserver","onExtensionLoaded","_onExtensionLoadedObserver","_logEnabled","_startPerformanceCounterEnabled","_endPerformanceCounterEnabled","_onValidatedObserver","request","abort","_progressCallback","clear","notifyObservers","loadFile","fileOrUrl","onSuccess","onProgress","useArrayBuffer","_loadBinary","GetFilename","Logger","Warn","fileRequest","dataBuffer","_loadFile","webRequest","setRequestHeader","_unpackBinaryAsync","DataReader","loaderData","_validate","json","_parseJson","arrayBufferView","RangeError","readViewAsync","_getLoader","morphTargetManagers","prototype","directLoad","DecodeBase64UrlToBinary","loaderState","whenCompleteAsync","addOnce","_setState","onOpened","event","_lengthComputable","_total","_loaded","lengthComputable","loaded","_loadFileAsync","minVersion","_parseVersion","_compareVersion","major","minor","createLoader","_CreateGLTF1Loader","_CreateGLTF2Loader","parsed","parse","dataReader","magic","readUint32","RuntimeError","ErrorCodes","GLTFLoaderUnexpectedMagicError","unpacked","_unpackBinaryV1Async","_unpackBinaryV2Async","contentLength","contentFormat","bodyLength","bin","startByteOffset","ChunkFormat","chunkLength","skipBytes","_logOpen","_logClose","spaces","_logSpaces","Log","counterName","StartPerformanceCounter","EndPerformanceCounter","IncrementalLoading","HomogeneousCoordinates","RegisterGLTFFileLoader","EComponentType","EShaderType","EParameterType","ETextureWrapMode","ETextureFilterType","ETextureFormat","ECullingType","EBlendingFunction","ETokenType","GLTFUtils","SetMatrix","parameter","uniformName","shaderMaterial","getWorldMatrix","getProjectionMatrix","getViewMatrix","Transpose","invert","getTransformMatrix","FLOAT_MAT2","setMatrix2x2","GetAsMatrix2x2","FLOAT_MAT3","setMatrix3x3","GetAsMatrix3x3","FLOAT_MAT4","setMatrix","SetUniform","uniform","FLOAT","setFloat","FLOAT_VEC2","setVector2","Vector2","FLOAT_VEC3","setVector3","FLOAT_VEC4","setVector4","Vector4","GetWrapMode","CLAMP_TO_EDGE","MIRRORED_REPEAT","MIRROR_ADDRESSMODE","REPEAT","GetByteStrideFromType","accessor","GetTextureFilterMode","LINEAR","LINEAR_MIPMAP_NEAREST","LINEAR_MIPMAP_LINEAR","TRILINEAR_SAMPLINGMODE","NEAREST","NEAREST_MIPMAP_NEAREST","NEAREST_SAMPLINGMODE","BILINEAR_SAMPLINGMODE","GetBufferFromBufferView","gltfRuntime","bufferView","componentType","loadedBufferView","loadedBufferViews","BYTE","Int8Array","UNSIGNED_BYTE","SHORT","UNSIGNED_SHORT","Uint16Array","GetBufferFromAccessor","bufferViews","DecodeBufferToText","GetDefaultMaterial","_DefaultMaterial","Effect","ShadersStore","shaderPath","vertex","fragment","uniforms","samplers","needAlphaBlending","ShaderMaterial","setColor4","Color4","toParse","_pos","currentToken","UNKNOWN","currentIdentifier","currentString","isLetterOrDigitPattern","_toParse","_maxPos","getNextToken","isEnd","END_OF_INPUT","IDENTIFIER","glTFTransforms","BabylonTransforms","glTFAnimationPaths","BabylonAnimationPaths","ParseObject","parsedObjects","runtimeProperty","object","parsedObject","NormalizeUVs","GetAttribute","attributeParameter","ConfigureBoneTransformation","GetParentBone","jointName","newSkeleton","nde","GetNodeToRoot","nodesToRoot","nodeToRoot","GetJointNode","NodeIsInJoints","jointNames","ImportMesh","newMesh","babylonNode","verticesStarts","verticesCounts","indexStarts","indexCounts","meshIndex","meshId","primitives","tempVertexData","primitive","accessors","uvKind","VertexBuffer","UVKind","merge","getMaterialById","Geometry","AddToMesh","ConfigureNode","newNode","ImportNode","lastNode","importOnlyMeshes","importMeshesNames","getLastSkeletonById","babylonSkeleton","nodesToRootToAdd","_parent","GetNodesToRoot","jointNode","existingBone","getBoneById","foundBone","joint","prepare","ImportSkeleton","orthoCamera","attachControl","perspectiveCamera","persCamera","getEngine","getRenderWidth","getRenderHeight","znear","zfar","ambienLight","hemiLight","HemisphericLight","directionalLight","dirLight","pointLight","ptLight","spotLight","spLight","fallOfAngle","fallOffExponent","exponent","dummy","ConfigureNodeFromMatrix","updateCache","TraverseNodes","meshIncluded","PostLoad","currentScene","thing","scenes","lastAnimation","sampler","inputData","outputData","parameters","bufferInput","bufferOutput","getNodeById","getNodeByName","isBone","targetPath","path","targetPathIndex","animationType","ANIMATIONTYPE_MATRIX","babylonAnimation","arrayOffset","modifyKey","getBaseMatrix","stopAnimation","beginAnimation","LoadAnimations","MAX_VALUE","ParseShaderUniforms","technique","unTreatedUniforms","unif","uniformParameter","transformIndex","ImportMaterials","GLTFLoaderExtension","LoadMaterialAsync","GLTFLoaderBase","CreateRuntime","parsedData","buffers","images","shaders","programs","techniques","extensionsUsed","buffersCount","shaderscount","loadedBufferCount","loadedShaderCount","dummyNodes","parsedBuffers","buf","parsedBuffer","ParseBuffers","parsedShaders","sha","parsedShader","ParseShaders","LoadBufferAsync","IsBase64","setTimeout","DecodeBase64","LoadFile","status","statusText","LoadTextureBufferAsync","babylonTexture","CreateTextureAsync","createMipMaps","minFilter","NEAREST_MIPMAP_LINEAR","samplingMode","blob","GetBlobBufferSource","blobURL","revokeBlobURL","revokeObjectURL","newTexture","wrapS","wrapT","LoadShaderStringAsync","shaderString","atob","defaultMaterial","program","states","vertexShader","pixelShader","fragmentShader","newVertexShader","newPixelShader","vertexTokenizer","pixelTokenizer","SAMPLER_2D","foundAttribute","enable","effect","OnShaderCompileError","onCompiled","materialValues","techniqueUniforms","onLoadTexture","setTexture","LoadTextureAsync","PrepareShaderMaterialUniforms","onBind","getEffect","OnBindShaderMaterial","OnShaderCompileSuccess","functions","cullFace","BACK","blendFunc","blendFuncSeparate","SRC_ALPHA","ONE_MINUS_SRC_ALPHA","ONE","alphaMode","Constants","ALPHA_COMBINE","ZERO","ALPHA_ONEONE","ALPHA_ADD","ONE_MINUS_SRC_COLOR","ALPHA_SUBTRACT","DST_COLOR","ALPHA_MULTIPLY","ALPHA_MAXIMIZED","GLTFLoader","RegisterExtension","Extensions","_importMeshAsync","LoadRuntimeAsync","_createNodes","AbstractMesh","skl","_loadBuffersAsync","_loadShadersAsync","_loadAsync","LoadRuntimeExtensionsAsync","onload","hasShaders","processShader","VERTEX","bind","onLoad","hasBuffers","processBuffer","_name","loadRuntimeAsync","loadRuntimeExtensionsAsync","loadBufferAsync","loadTextureBufferAsync","createTextureAsync","loadShaderStringAsync","loadMaterialAsync","_ApplyExtensions","loaderExtension","_LoadTextureBufferAsync","_CreateTextureAsync","func","defaultFunc","extensionName","RegisterGLTF1Loader","GLTFBinaryExtension","_bin","sourceExt","binaryExtensionShader","shaderBytes","RegisterGLTFBinaryExtension","GLTFMaterialsCommonExtension","ambientLight","ambient","point","directional","spot","fallOffAngle","standardMaterial","disableLighting","doubleSided","transparency","_loadTexture","propertyPath","RegisterGLTFMaterialsCommonExtension","RegisteredGLTFExtensions","registeredGLTFExtensions","registerGLTFExtension","isGLTFExtension","factory","unregisterGLTFExtension","OptionalPathExceptionsList","regex","RegExp","GLTFPathToObjectConverter","_gltf","_infoTree","convert","objectTree","infoTree","parts","ignoreObjectTree","__array__","__ignoreObjectTree__","__passThroughTarget__","numericIndex","orig","_index","rest","__target__","_CreateLengthAccessor","getLength","FlowGraphInteger","FromValue","getPropertyName","nodesTree","_babylonTransformNode","_findNodeMorphTargets","mtm","_roundFloat32Artifact","influence","numValue","isReadOnly","globalMatrix","forceUpdate","_isDirty","rootMatrix","childIndex","__nodeIndex","EXT_lights_ies","multiplier","KHR_node_visibility","visible","_primitiveBabylonMeshes","isVisible","forEach","animationsTree","_babylonAnimationGroup","meshesTree","_instanceData","babylonSourceMesh","weightValue","__weightValue","GetTexture","payload","textureType","textureInObject","babylonMaterial","GetMaterial","_data","fillMode","MATERIAL_TriangleFillMode","directMtm","primMeshes","sourceMesh","_getNodeMorphTargetManager","descendants","getDescendants","desc","candidate","sib","toPrecision","_gltfTextureTransform","gltfPath","createMissing","extensionKey","xform","KHR_texture_transform","GenerateTextureMap","componentsCount","o","objectModelMapping","sceneIndex","__gltfRoot","_babylonCamera","orthographic","xmag","ymag","perspective","getAspectRatio","yfov","alphaCutoff","alphaCutOff","normalTexture","occlusionTexture","strength","ambientTextureStrength","pbrMetallicRoughness","baseColorFactor","FromColor3","baseColorTexture","metallicFactor","roughnessFactor","metallicRoughnessTexture","KHR_materials_anisotropy","anisotropyStrength","anisotropy","anisotropyRotation","anisotropyTexture","KHR_materials_clearcoat","clearcoatFactor","clearcoatRoughnessFactor","clearcoatTexture","clearcoatNormalTexture","clearcoatRoughnessTexture","KHR_materials_dispersion","dispersion","KHR_materials_emissive_strength","emissiveStrength","emissiveIntensity","KHR_materials_ior","KHR_materials_iridescence","iridescenceFactor","iridescence","iridescenceIor","iridescenceTexture","iridescenceThicknessMaximum","maximumThickness","iridescenceThicknessMinimum","minimumThickness","iridescenceThicknessTexture","KHR_materials_sheen","sheenColorFactor","sheenColorTexture","sheenRoughnessFactor","sheenRoughnessTexture","KHR_materials_specular","specularColorFactor","specularColorTexture","KHR_materials_transmission","transmissionTexture","KHR_materials_diffuse_transmission","diffuseTransmissionFactor","translucencyIntensity","diffuseTransmissionTexture","diffuseTransmissionColorFactor","translucencyColor","diffuseTransmissionColorTexture","KHR_materials_volume","attenuationColor","attenuationDistance","tintColorAtDistance","thicknessFactor","thicknessTexture","KHR_lights_punctual","_babylonLight","_light","innerConeAngle","outerConeAngle","EXT_lights_area","height","rect","width","EXT_lights_image_based","_babylonTexture","getReflectionTextureMatrix","Inverse","nodeIndex","joints","jointIndex","_cloneObjectModelMapping","getPrototypeOf","GetPathToObjectConverter","gltf","configure","assetMapping","GetMappingForKey","keyParts","SetInterpolationForKey","AddObjectAccessorToKey","LazyAnimationGroupModulePromise","Lazy","BABYLON","LazyLoaderAnimationModulePromise","ArrayItem","TryGet","Assign","LoadBoundingInfoFromPositionAccessor","minArray","maxArray","minVector","TmpVectors","copyFromFloats","maxVector","divider","oneOverDivider","BoundingInfo","isMatchingMaterialType","materialImpls","_pbrMaterialImpls","materialClass","UnregisterExtension","babylonScene","_babylonScene","rootBabylonMesh","_rootBabylonMesh","_rootUrl","_completePromises","_assetContainer","_babylonLights","_disableInstancedMesh","_allMaterialsDirtyRequired","_skipStartAnimationStep","_extensions","_disposed","_uniqueRootUrl","_defaultBabylonMaterialData","_postSceneLoadActions","_materialAdapterCache","_materialAdapters","_getOrCreateMaterialAdapter","adapter","adapterClass","createdAdapter","meshesNames_1","scene_1","container_1","data_1","rootUrl_1","onProgress_1","arguments","_loadData","nodeMap","_getMeshes","_getSkeletons","_getAnimationGroups","_getTransformNodes","_getGeometries","resultFunc","RandomGUID","_loadExtensionsAsync","needsOpenPBR","isExtensionUsed","needsPBR","implPromises","all","openpbrMaterialLoadingAdapter","OpenPBRMaterial","openPBRMaterialClass","registerOpenPBRMaterial","OpenPBRMaterialLoadingAdapter","openPBRAdapterClass","pbrMaterialLoadingAdapter","pbrMaterialClass","registerPBRMaterial","PBRMaterialLoadingAdapter","pbrAdapterClass","loadingToReadyCounterName","LOADING","READY","loadingToCompleteCounterName","COMPLETE","_extensionsOnLoading","promises","oldBlockMaterialDirtyMechanism","blockMaterialDirtyMechanism","loadSceneAsync","babylonDrawMode","TriangleFillMode","_loadMaterialAsync","_forceBlockMaterialDirtyMechanism","_compileMaterialsAsync","_compileShadowGeneratorsAsync","resultPromise","maxSimultaneousLights","finalizeAsync","_extensionsOnReadyAsync","_startAnimations","SetImmediate","catch","_setupData","binaryBuffer","nodeParents","_createRootNode","extensionPromises","registeredExtension","extensionsRequired","rootMesh","_LoadTransform","FORCE_RIGHT_HANDED","extensionPromise","_extensionsLoadSceneAsync","logOpen","loadNodeAsync","babylonMesh","action","_loadAnimationsAsync","logClose","_forEachPrimitive","getClassName","_babylonTransformNodeForSkin","NONE","babylonAnimationGroups","ALL","babylonAnimationGroup","_extensionsLoadNodeAsync","loadNode","babylonTransformNode","AddPointerMetadata","loadCameraAsync","babylonCamera","childNode","childBabylonMesh","hasMesh","hasSkin","_loadMeshAsync","babylonTransformNodeForSkin","deepMerge","_loadSkinAsync","asMesh","isAnInstance","useBoundingInfoFromGeometry","_updateBoundingInfo","refreshBoundingInfo","_loadMeshPrimitiveAsync","_extensionsLoadMeshPrimitiveAsync","shouldInstance","babylonAbstractMesh","promise","createInstance","_createMorphTargets","_loadVertexDataAsync","babylonGeometry","_loadMorphTargetsAsync","_GetDrawMode","_createDefaultMaterial","_getDefaultImpl","_extensionsLoadVertexDataAsync","isUnIndexed","_loadIndicesAccessorAsync","loadAttribute","_delayInfo","_loadVertexAccessorAsync","babylonVertexBuffer","getKind","PositionKind","babylonBoundingInfo","_boundingInfo","setVerticesBuffer","MatricesIndicesExtraKind","NormalKind","TangentKind","UV2Kind","UV3Kind","UV4Kind","UV5Kind","UV6Kind","MatricesIndicesKind","MatricesWeightsKind","MatricesWeightsExtraKind","ColorKind","_numMorphTargets","targetNames","extras","areUpdatesFrozen","babylonMorphTarget","_loadMorphTargetVertexDataAsync","isUsingTextureForTargets","MaxActiveMorphTargetsInVertexAttributeMode","setData","getVertexBuffer","_loadFloatAccessorAsync","setTangents","setUVs","setUV2s","componentSize","getSize","pixid","setColors","One","_extensionsLoadSkinAsync","_loadBones","_loadSkinInverseBindMatricesDataAsync","inverseBindMatricesData","_updateBoneMatrices","_findSkeletonRootNode","isParent","skeletonNode","babylonBones","_loadBone","paths","_isJoint","babylonBone","parentBabylonBone","_getNodeMatrix","inverseBindMatrices","baseMatrix","FromArrayToRef","babylonParentBone","getAbsoluteInverseBindMatrix","_extensionsLoadCameraAsync","loadAnimationAsync","animationGroup","_extensionsLoadAnimationAsync","_loadAnimationChannelAsync","babylonTarget","animationContext","_extensionsLoadAnimationChannelAsync","channelTargetPath","pathIsWeights","RegisterGLTFLoaderAnimation","registerGLTFLoaderAnimation","_loadAnimationChannelFromTargetInfoAsync","invfps","_loadAnimationSamplerAsync","numAnimations","propertyInfos","propertyInfo","getStride","outputOffset","getValue","babylonAnimations","buildAnimations","babylonAnimatable","inputAccessor","outputAccessor","_extensionsLoadBufferAsync","loadUriAsync","cause","loadBufferViewAsync","_extensionsLoadBufferViewAsync","_loadAccessorAsync","numComponents","_GetNumComponents","byteStride","VertexBufferGetTypeByteLength","typedArray","VertexBufferForEach","_GetTypedArray","sparse","indicesBufferView","valuesBufferView","indicesData","valuesData","sparseLength","sparseData","valuesIndex","indicesIndex","componentIndex","_GetTypedArrayConstructor","_loadVertexBufferViewAsync","_babylonBuffer","engine","Buffer","_babylonVertexBuffer","babylonBuffer","_loadMaterialMetallicRoughnessPropertiesAsync","geometryOpacity","baseMetalness","specularRoughness","loadTextureInfoAsync","nonColorData","baseMetalnessTexture","specularRoughnessTexture","useMetallicFromMetallicTextureBlue","_extensionsLoadMaterialAsync","babylonData","createMaterial","babylonMeshes","loadMaterialPropertiesAsync","_selectImplForGltfMaterial","MATERIAL_OPAQUE","transparencyAsAlphaCoverage","extensionMaterial","_extensionsCreateMaterial","_extensionsLoadMaterialPropertiesAsync","loadMaterialBasePropertiesAsync","loadMaterialAlphaProperties","aoTexture","twoSidedLighting","geometryNormalTexture","setNormalMapInversions","emissionTexture","aoStrength","ambientOcclusionTexture","ambientOcclusionTextureStrength","emissionColorTexture","MATERIAL_ALPHATEST","hasAlpha","useAlphaFromBaseColorTexture","textureInfo","_extensionsLoadTextureInfoAsync","_trackTexture","texCoord","_textureInfo","_loadTextureAsync","trackAndAssign","_extensionsLoadTextureAsync","DefaultSampler","image","_createTextureAsync","imageIndex","samplerIndex","_babylonTextures","_babylonTextureSources","resolvedImageIndex","textureLoaderOptions","useSRGBBuffer","sourceTexture","samplerData","_loadSampler","deferred","Deferred","textureCreationOptions","noMipmap","noMipMaps","invertY","exception","loaderOptions","nonBase64Uri","IsBase64DataUrl","imageId","loadImageAsync","dataUrl","internalTexture","getInternalTexture","_GetTextureSamplingMode","_GetTextureWrapMode","_extensionsLoadUriAsync","_ValidateUri","log","LoadFileError","babylonObject","pointer","_internalMetadata","pointers","magFilter","LINEAR_NEAREST","LINEAR_LINEAR","LINEAR_NEAREST_MIPNEAREST","LINEAR_LINEAR_MIPNEAREST","LINEAR_NEAREST_MIPLINEAR","LINEAR_LINEAR_MIPLINEAR","NEAREST_NEAREST","NEAREST_LINEAR","NEAREST_NEAREST_MIPNEAREST","NEAREST_LINEAR_MIPNEAREST","NEAREST_NEAREST_MIPLINEAR","NEAREST_LINEAR_MIPLINEAR","GetTypedArrayConstructor","componentTypeLength","PointListDrawMode","LineListDrawMode","LineLoopDrawMode","LineStripDrawMode","TriangleStripDrawMode","TriangleFanDrawMode","forceCompilationAsync","useInstances","clipPlane","getShadowGenerator","_forEachExtensions","_applyExtensions","functionName","actionAsync","loaderProperty","_activeLoaderExtensionFunctions","activeLoaderExtensionFunctions","onLoading","onReady","_loadUriAsync","LoadExtensionAsync","LoadExtraAsync","startPerformanceCounter","endPerformanceCounter","RegisterGLTF2Loader","getVector3","_target","getQuaternion","getWeights","AnimationPropertyInfo","_buildAnimation","TransformNodeAnimationPropertyInfo","WeightAnimationPropertyInfo","babylonAnimationClone","_specWorkflow","_diffuseTransmissionTint","_diffuseTransmissionTintTexture","_material","isUnlit","_useAlphaFromBaseColorTexture","baseDiffuseRoughness","baseDiffuseRoughnessTexture","_useRoughnessFromMetallicTextureGreen","_useMetallicFromMetallicTextureBlue","enableSpecularEdgeColor","_enableEdgeColor","configureSpecularGlossiness","specularWeight","specularWeightTexture","_useSpecularWeightFromSpecularColorTexture","_useSpecularWeightFromAlpha","emissionLuminance","configureCoat","coatWeight","coatWeightTexture","coatColorTexture","coatRoughnessTexture","_useCoatRoughnessFromGreenChannel","coatDarkening","coatDarkeningTexture","coatRoughnessAnisotropy","geometryCoatTangentAngle","geometryCoatTangentTexture","_useCoatRoughnessAnisotropyFromTangentTexture","configureTransmission","geometryThinWalled","transmissionDepth","transmissionWeight","transmissionWeightTexture","transmissionScatter","transmissionScatterTexture","transmissionScatterAnisotropy","transmissionDispersionAbbeNumber","transmissionDispersionScale","refractionBackgroundTexture","backgroundRefractionTexture","configureVolume","volumeThicknessTexture","geometryThicknessTexture","_useGeometryThicknessFromGreenChannel","volumeThickness","geometryThickness","configureSubsurface","subsurfaceScatterAnisotropy","subsurfaceWeight","subsurfaceWeightTexture","_useSubsurfaceWeightFromTextureAlpha","subsurfaceColor","subsurfaceColorTexture","diffuseTransmissionTint","diffuseTransmissionTintTexture","subsurfaceRadius","subsurfaceRadiusScale","isTranslucent","configureFuzz","fuzzWeight","fuzzWeightTexture","fuzzColor","fuzzColorTexture","fuzzRoughness","fuzzRoughnessTexture","_useFuzzRoughnessFromTextureAlpha","specularRoughnessAnisotropy","geometryTangentAngle","geometryTangentTexture","_useSpecularRoughnessAnisotropyFromTangentTexture","configureGltfStyleAnisotropy","useGltfStyle","_useGltfStyleAnisotropy","thinFilmWeight","thinFilmIor","thinFilmThicknessMinimum","thinFilmThicknessMin","thinFilmThicknessMaximum","thinFilmThickness","thinFilmWeightTexture","thinFilmThicknessTexture","_useThinFilmThicknessFromTextureGreen","invertX","geometryCoatNormalTexture","geometryCoatNormalTextureScale","loader","copySurfaceToCoatAsync","TextureChannel","A","transmissionColorTexture","newRoughnessTexture","InvertTextureAsync","ExtractChannelAsync","CreateTextureWithFactorOperand","TextureColorSpace","Linear","ChannelMask","newMetallic","ExtractMaxChannelAsync","toColor4","RGBA","SRGB","RGB","newBaseColor","LerpTexturesAsync","colorSpace","oldBaseColorTexture","oldSpecularColorTexture","loader_1","weight_1","weightTexture_1","weightTextureChannel_1","color_1","colorTexture_1","weightTexture","weightTextureChannel","colorTexture","diffuseTransmission","origCoatWeight","origCoatWeightTexture","origCoatColor","origCoatColorTexture","origCoatNormalTexture","origCoatWeightCol4","weightCol4","results","allSettled","lerpCoatColor","lerpSurfaceColor","newCoatColor","MultiplyTexturesAsync","fromArray","newCoatIor","newCoatRoughness","G","newCoatDarkening","newSpecularRoughness","newCoatNormal","enableSpecularAntiAliasing","useRadianceOverAlpha","useSpecularOverAlpha","brdf","baseDiffuseModel","MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR","enableEdgeColor","dielectricSpecularModel","MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR","conductorSpecularModel","MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR","useMicroSurfaceFromReflectivityMapAlpha","metallicReflectanceTexture","useOnlyMetallicFromMetallicReflectanceTexture","reflectanceTexture","useRoughnessFromMainTexture","remapF0OnInterfaceChange","tintTexture","textureRoughness","refractionIntensityTexture","useGltfStyleTextures","diffusionDistance","multiplyInPlace","isDispersionEnabled","refractionTexture","volumeIndexOfRefraction","useAlbedoToTintRefraction","useThicknessAsDepth","useAlbedoToTintTranslucency","isTranslucencyEnabled","translucencyIntensityTexture","extinctionCoefficient","absorptionCoeff","maxChannel","exp","translucencyColorTexture","scatteringDiffusionProfile","albedoScaling","forceIrradianceInFragment","NAME","_lights","extensionContext","_loadLightAsync","environmentTexture","imageData","specularImages","mipmap","face","specularImageContext","RawCubeTexture","specularImageSize","irradianceCoefficients","sphericalHarmonics","SphericalHarmonics","convertIrradianceToLambertianRadiance","sphericalPolynomial","SphericalPolynomial","FromHarmonics","lodGenerationScale","log2","updateRGBDAsync","RegisterEXT_lights_image_based","EXT_mesh_gpu_instancing","instanceCount","translationBuffer","rotationBuffer","scaleBuffer","colorBuffer","copyToArray","thinInstanceSetBuffer","RegisterEXT_mesh_gpu_instancing","EXT_meshopt_compression","bufferViewMeshopt","_meshOptData","MeshoptCompression","Default","decodeGltfBufferAsync","RegisterEXT_meshopt_compression","EXT_texture_webp","RegisterEXT_texture_webp","EXT_texture_avif","RegisterEXT_texture_avif","babylonSpotLight","Backward","falloffType","Light","FALLOFF_GLTF","bufferData","iesProfileTexture","RegisterEXT_lights_ies","KHR_draco_mesh_compression","useNormalizedFlagFromAccessor","DracoDecoder","DefaultAvailable","dracoDecoder","uniqueId","_dracoBabylonGeometry","positionAccessor","_decodeMeshToGeometryForGltfAsync","RegisterKHR_draco_mesh_compression","ShC0","ShCoefficientCountPerDegree","Clamp255","KHR_gaussian_splatting","attributeName","accessorIndex","positionsPromise","shDegree","shAttributeNames","coef","gaussianSplattingMesh","GaussianSplattingMesh","engineCaps","getCaps","rotations","opacities","shDegree0","shHigherDegrees","splatCount","colorStride","floatView","byteView","shBuffers","shComponentCount","textureCount","maxTextureSize","AllocateShBuffers","floatBase","byteBase","offsetPerSplat","coefData","flatIndex","byteIndexInTexture","updateDataAsync","RegisterKHR_gaussian_splatting","KHR_lights","babylonLight","babylonDirectionalLight","setAll","RegisterKHR_lights","RectAreaLight","newSize","lightParentNode","BabylonTransformNode","RotationAxis","Up","RegisterEXT_lights_area","KHR_materials_pbrSpecularGlossiness","_loadSpecularGlossinessPropertiesAsync","glossinessFactor","specularGlossinessTexture","RegisterKHR_materials_pbrSpecularGlossiness","KHR_materials_unlit","_loadUnlitPropertiesAsync","RegisterKHR_materials_unlit","_loadClearCoatPropertiesAsync","RegisterKHR_materials_clearcoat","KHR_materials_coat","_loadCoatPropertiesAsync","coatRoughnessFactor","coatTexture","coatNormalTexture","coatDarkeningFactor","colorFactor","coatColorFactor","coatAnisotropyWeight","coatAnisotropyStrength","coatAnisotropyAngle","coatAnisotropyRotation","coatAnisotropyTexture","RegisterKHR_materials_coat","_loadIridescencePropertiesAsync","iridescenceIOR","RegisterKHR_materials_iridescence","_loadAnisotropyPropertiesAsync","anisotropyWeight","anisotropyAngle","EXT_materials_anisotropy_openpbr","openPbrAnisotropyEnabled","RegisterKHR_materials_anisotropy","_loadEmissiveProperties","RegisterKHR_materials_emissive_strength","_loadSheenPropertiesAsync","RegisterKHR_materials_sheen","KHR_materials_fuzz","_loadFuzzPropertiesAsync","fuzzFactor","fuzzColorFactor","fuzzRoughnessFactor","fuzzTexture","RegisterKHR_materials_fuzz","_loadSpecularPropertiesAsync","EXT_materials_specular_edge_color","specularEdgeColorEnabled","RegisterKHR_materials_specular","_loadIorPropertiesAsync","_DEFAULT_IOR","RegisterKHR_materials_ior","KHR_materials_variants","GetAvailableVariants","extensionMetadata","_GetExtensionMetadata","variants","getAvailableVariants","SelectVariant","variantName","select","lastSelected","selectVariant","Reset","original","reset","GetLastSelectedVariant","getLastSelectedVariant","_variants","defaultVariant","onLoaded","selectedVariant","lastSelectedVariant","mappingIndex","mappings","mappingVariantIndex","variantIndex","variant","onClonedObservable","newOne","newRoot","hasOwnProperty","variantEntry","RegisterKHR_materials_variants","TransmissionHelper","_GetDefaultOptions","renderSize","samples","lodGenerationOffset","renderTargetTextureType","TEXTURETYPE_HALF_FLOAT","generateMipmaps","_opaqueRenderTarget","_opaqueMeshesCache","_transparentMeshesCache","_materialObservers","_newMeshObserver","_removedMeshObserver","_materialImpls","_adapterCache","_translucentMaterialIndices","_opaqueOnlySubMeshes","_savedSubMeshes","_transmissionHelper","_parseScene","_setupRenderTargets","addMaterialImpl","updateOptions","newOptions","oldOptions","getOpaqueTarget","_getOrCreateAdapter","_classifyMeshMaterials","hasTranslucent","hasOpaque","translucentIndices","subMat","_rebuildOpaqueOnlySubMeshes","sm","_addMesh","onMaterialChangedObservable","_onMeshMaterialChanged","_removeMesh","onNewMeshAddedObservable","onMeshRemovedObservable","transparentIdx","opaqueIdx","_isRenderTargetValid","saveSceneEnvIntensity","RenderTargetTexture","ignoreCameraViewport","renderList","forceLayerMaskCheck","clearColor","renderSprites","renderParticles","disableImageProcessing","onBeforeBindObservable","opaqueRenderTarget","environmentIntensity","toLinearSpaceToRef","useExactSrgbConversions","tlEntries","tlEntry","opaqueOnly","onAfterUnbindObservable","savedEntries","savedEntry","mixedEntries","mixedEntry","allTracked","observer","ensureTransmissionHelper","existingHelper","_loadTransparentPropertiesAsync","texturePromise","RegisterKHR_materials_transmission","_loadTranslucentPropertiesAsync","RegisterKHR_materials_diffuse_transmission","_loadVolumePropertiesAsync","RegisterKHR_materials_volume","KHR_materials_volume_scatter","scatterColor","multiscatterColorFactor","scatterAnisotropy","multiscatterColorTexture","singleScatterAlbedo","multiScatter","multiScatterAlbedo","multiScatterToSingleScatterAlbedo","scatteringCoefficient","mfp","RegisterKHR_materials_volume_scatter","_loadDispersionPropertiesAsync","RegisterKHR_materials_dispersion","KHR_materials_diffuse_roughness","_loadDiffuseRoughnessPropertiesAsync","diffuseRoughnessFactor","diffuseRoughnessTexture","RegisterKHR_materials_diffuse_roughness","KHR_mesh_quantization","RegisterKHR_mesh_quantization","KHR_texture_basisu","useRGBAIfASTCBC7NotAvailableWhenUASTC","RegisterKHR_texture_basisu","uRotationCenter","vRotationCenter","RegisterKHR_texture_transform","KHR_xmp_json_ld","xmpGltf","xmpNode","packet","packets","xmp","RegisterKHR_xmp_json_ld","KHR_animation_pointer","_pathToObjectConverter","RegisterKHR_animation_pointer","getColor3","getAlpha","getFloat","getMinusFloat","getNextFloat","getFloatBy2","getTextureTransformTree","MaterialAnimationPropertyInfo","CameraAnimationPropertyInfo","LightAnimationPropertyInfo","MeshAnimationPropertyInfo","_RegisterKHRAnimationPointerData","baseColorTextureInterpolation","metallicRoughnessTextureInterpolation","normalTextureInterpolation","occlusionTextureInterpolation","emissiveTextureInterpolation","anisotropyTextureInterpolation","clearcoatTextureInterpolation","clearcoatNormalTextureInterpolation","clearcoatRoughnessTextureInterpolation","iridescenceTextureInterpolation","iridescenceThicknessTextureInterpolation","sheenTextureInterpolation","sheenRoughnessTextureInterpolation","specularTextureInterpolation","specularColorTextureInterpolation","transmissionTextureInterpolation","thicknessTextureInterpolation","diffuseTransmissionTextureInterpolation","diffuseTransmissionColorTextureInterpolation","MSFT_audio_emitter","_clips","_emitters","clips","emitters","emitterIndex","emitter","refDistance","maxDistance","rolloffFactor","distanceModel","_loadEmitterAsync","sound","_babylonSounds","attachToMesh","setLocalDirectionToMesh","Forward","setDirectionalCone","ToDegrees","events","_loadAnimationEventAsync","_loadClipAsync","_objectURL","_babylonData","clipPromises","loop","autoplay","volume","clipContext","objectURL","Sound","weightedSound","WeightedSound","directionalConeInnerAngle","directionalConeOuterAngle","_getEventAction","startOffset","currentFrame","frameOffset","play","pause","babylonAnimationEvent","AnimationEvent","addEvent","onAnimationGroupEndObservable","onAnimationGroupPauseObservable","RegisterMSFT_audio_emitter","MSFT_lod","maxLODsToLoad","onNodeLODsLoadedObservable","onMaterialLODsLoadedObservable","_bufferLODs","_nodeIndexLOD","_nodeSignalLODs","_nodePromiseLODs","_nodeBufferLODs","_materialIndexLOD","_materialSignalLODs","_materialPromiseLODs","_materialBufferLODs","indexLOD","_loadBufferLOD","firstPromise","nodeLODs","_getLODs","ids","nodeLOD","assignWrap","previousNodeLOD","_disposeTransformNode","materialLODs","materialLOD","previousDataLOD","_disposeMaterials","previousIndexLOD","bufferLODs","bufferLOD","babylonMaterials","babylonMaterialsToDispose","babylonTextures","RegisterMSFT_lod","MSFT_minecraftMesh","extraContext","forceDepthWrite","separateCullingPass","RegisterMSFT_minecraftMesh","MSFT_sRGBFactors","RegisterMSFT_sRGBFactors","getMappingForFullOperationName","fullOperationName","op","getMappingForDeclaration","HasDefaultInteractivityFlowInput","operation","NormalizeInteractivityEventDataConfiguration","normalizeValue","asArray","nested","localeCompare","malformed","definition","declaration","returnNoOpIfNotAvailable","extensionMappings","_GetOwnRegistryValue","gltfExtensionsToFlowGraphMapping","gltfToFlowGraphMapping","getNoOpMappingForDeclaration","inputs","outputs","flows","inputValueSockets","defineProperty","configurable","enumerable","writable","outputValueSockets","blocks","addNewInteractivityFlowGraphMapping","registry","GetInteractivityOperationRegistry","compatibilityOnly","timeSinceStart","gltfType","timeSinceLastTick","configuration","configurationType","required","indexSource","validationOnly","extraProcessor","gltfBlock","_mapping","parser","serializedObjects","eventId","arrays","serializedObject","config","eventData","validation","interactivityGraph","eventConfiguration","stopImmediate","in","getSimpleInputMapping","typeSourceInput","roundHalfAwayFromZero","_gltfBlock","_declaration","_parser","useMatrixPerComponent","preventIntegerFloatArithmetic","types","flowGraphType","ValidateTypes","h","condition","isValid","dataInputs","_connectionValues","keepDegenerateComponents","invalidUsesDefault","allowedValues","socketIn","valueType","socketInA","socketInB","_arrays","outputSignalCount","signalOutputs","true","false","cases","inOptions","generatesOutputFlowSockets","uniqueValues","selection","default","caseValue","uniqueCases","loopBody","completed","initialIndex","endIndex","incrementIndexWhenLoopDone","maxLoopIterations","currentCount","isRandom","configurationGroup","isLoop","lastIndex","inputFlows","minimum","maximum","generatesInputFlowSockets","remainingInputs","inputFlowsConfiguration","err","lastRemainingTime","cancel","lastDelay","lastDelayIndex","delay","variable","isVariable","dataTransformer","getVariableName","variables","minItems","generatesInputValueSockets","useSlerp","toBlock","interBlockConnectors","inputBlockIndex","outputBlockIndex","serializedValueInterpolation","propertyIndex","staticVariables","getAnimationTypeByFlowGraphType","serializedGetVariable","ValidateJsonPointerTemplate","pointerTemplate","className","outputValue","allowedSignatures","speed","convertConnectedTimeToFrames","_animationTargetFps","endTime","_context","globalGLTF","playAnimationBlock","block","useVirtualTimeline","arrayIndexBlock","referenceCollection","glTF","stopAnimationBlock","skipOnAnimationEnd","useVirtualStopAt","generatesCaseInputValueSockets","treatCasesAsIntegers","severity","debugLogTemplate","inferType","acc","HasOddBracketRun","segment","character","runLength","ParseDebugLogTemplate","parameterStart","sockets","socket","reservedSocketIds","invalid","socketIds","isIntegerParameter","isReferenceParameter","closingBracket","socketId","getAllSupportedNativeNodeTypes","KHR_INTERACTIVITY_SPECIFICATION_COMMIT","gltfTypeToBabylonType","float","elementType","bool","float2","float3","float4","float4x4","float2x2","float3x3","_NormalizeKHRInteractivityRuntimeValue","_EncodeRuntimeValueSnapshot","ancestors","getOwnPropertySymbols","getOwnPropertyNames","getOwnPropertyDescriptor","propertyIsEnumerable","encoded","unrepresentable","_CreateKHRInteractivityRuntimeValueSnapshot","runtimeValueFingerprint","_cloneJson","CloneKHRInteractivityGraph","graph","_isValidIndex","_isRecord","_addError","_isValidJsonPointer","_matchesOutputSocket","defaultSocket","eventIndex","_validateTypeIndex","typeIndex","_validateValue","runtimeType","signature","component","_validateConfigurationValue","isInt","_getIndexedArrayLength","assetNodeCount","_isEffectiveConfigurationValue","CreateEffectiveKHRInteractivityGraph","declarations","effective","support","groupedValidity","_getPointerTemplateSockets","_resolveValueTypeIndex","_resolveOutputTypeIndex","sourceNode","declaredType","findTypeIndex","configuredType","variableIndex","defaultInput","fixedSignature","_getFixedOutputSignature","outputMapping","mappedType","typeSource","_validateNode","graphPath","declarationModel","reportConfigurationIssue","issuePath","_addWarning","isConfigurationValid","numericValue","configuredIndex","defaultType","socketDefinition","expectedType","severityProperty","messageProperty","severityValid","messageValid","eventValue","expectedSignature","_3","_5","_4","validationNode","_6","_7","_8","_9","_11","_10","sourceDeclaration","sourceMapping","sourceSocket","_12","hasMappedSocket","_13","declaredOutputType","_15","_14","effectiveOutputType","mappedOutputs","_16","mappedOutput","mappedOutputSignature","fixedOutputSignature","_17","assertedSignature","_19","_18","flow","_20","_22","_21","CreateKHRInteractivityGraphModel","supportedExtensions","invalidEntryDefaults","collection","entryIndex","declarationIndex","declarationKeys","inputSockets","declarationKey","declarationSchema","schema","matches","actual","expected","actualKeys","expectedKeys","_isCompatibleExtensionDeclaration","_getDeclarationMapping","signatures","effectiveSource","CreateKHRInteractivityDocument","graphs","requestedDefaultGraphIndex","defaultGraphIndex","specificationCommit","EventReferencePrefix","DelayReferencePrefix","_GetOwnMapping","_CloneMetadataValue","_IsSerializableConfigurationValue","_CaptureKHRInteractivityRuntimeInputDefaults","flowGraph","getAllBlocks","provenance","khrInteractivity","generatedConfiguration","generatedConfigurationRuntime","isConnected","socketProvenance","runtimeValueSnapshot","_defaultValue","generatedInputDefaults","InteractivityGraphToFlowGraphParser","_graphIndex","_supportedExtensions","_declarationModels","canonicalGraph","_types","_mappings","_staticVariables","_events","_internalEventsCounter","_nodes","_insertedBlocks","_canonicalGraph","_interactivityGraph","_parseTypes","_parseDeclarations","_parseVariables","_parseEvents","_parseNodes","_strictValidation","_getAllowedDynamicValueSockets","_getAllowedDynamicFlowSockets","configuredValues","validValues","extensionEnabled","supportedMapping","flowGraphMapping","_parseVariable","dataTransform","_normalizeStaticReference","rawSegment","eventIds","internalPrefix","generatedEventId","converted","validationResult","_createUnsupportedExtensionBlock","blockType","_getEmptyBlock","_parseNodeConfiguration","_createBlockProvenance","graphIndex","sourcePath","dataOutputs","signalInputs","_setSocketProvenance","_getBlockRole","inputFlowSockets","toSockets","outputFlowSockets","_createNewSocketConnection","nodeMapping","gltfConfiguration","gltfProperty","propertyMapping","_parseNodeConnections","gltfNode","flowGraphBlocks","outputMapper","flowsFromGLTF","flowsKeys","flowKey","flowMapping","outputArrayMapping","wildcardMapping","allowedDynamicOutputs","_isUnsupportedExtensionBlock","socketOutName","inputNodeId","nodeIn","socketOut","inputMapper","flowInMapping","arrayMapping","allowedDynamicInputs","nodeInSocketName","inputBlock","connectedPointIds","valuesFromGLTF","valuesKeys","valueKey","valueMapping","socketInName","sourceValue","convertedValue","runtimeValue","nodeOutId","nodeOutSocketName","nodeOut","outBlock","_connectWithSecondsToFramesConversion","connector","_connectFlowGraphNodes","_ensureMappedSocketProvenance","ensureConnections","socketMappings","sourceKey","serializedRuntimeValue","configurationProvenance","mappedConfigurationNames","ignoredConfigurationNames","normalizedValue","isOutput","_connectionType","upstreamOutput","downstreamInput","multiplyBlock","inputA","inputB","serializedInput","serializedOutput","inputArray","outputArray","inputConnection","outputConnection","serializeToFlowGraph","_userVariables","allBlocks","concat","rightHanded","executionContexts","CompositePathToObjectConverter","_prefixes","_fallback","addPrefix","converter","BABYLON_SCENE_OBJECT_MODEL_PREFIX","BabylonScenePathToObjectConverter","_tree","collectionName","_getCollectionArray","_lookupInstanceByUniqueId","_buildIdentityAccessor","leaf","RefValidityTarget","isKhrInteractivityRef","InteractivityRefPathToObjectConverter","isEmptyEventReference","rawIndex","IsDelayActive","InteractivityLimitsPrefix","MaxSupportedGltfVersion","UndisclosedRuntimeLimit","RuntimeLimits","maxActiveAnimations","maxActiveDelays","maxActivePropertyInterpolations","maxActiveVariableInterpolations","AssetCapabilityTarget","isKhrInteractivityAssetCapability","InteractivityAssetPathToObjectConverter","_isExtensionEnabled","_createAccessor","capability","InteractivityAssetCapabilitiesPrefix","rawMajor","rawMinor","GetEffectiveGltfVersion","segments","InteractivityHostResolver","encodeEventReference","GetEventReference","decodeEventReference","GetEventReferenceKey","decodeIndexReference","tail","getObjectReference","hint","stringPointers","KHRInteractivityExportError","_KnownIndexedRootCollections","_CompanionNodeExtensions","_GetPointerExtensionNames","_FlowGraphTypeToKHRSignature","number","boolean","string","Matrix2D","Matrix3D","_CloneJson","_GetBlockProvenance","_GetSocketProvenance","_GetOwn","dictionary","_FullOperationName","_RuntimeBlockClassName","_GetRoleBlock","_FindDataInput","_NormalizeValue","_CreateEventSchemaRuntimeSnapshot","_ValuesEqual","_JsonEquivalent","leftEntries","rightKeys","_GetOrAddVariableTypeIndex","_GetConfigurationBlock","logicalNode","targetBlock","_GetMappedConfigurationValue","sourceGraph","preserveCanonicalWhenUnchanged","_GetConfigurationProvenance","_IsValidConfigurationValue","assetNodes","_GetEffectiveConfigurationValue","getCandidate","candidateKey","candidateProperty","_PushDiagnostic","_SetOwnProperty","KHRInteractivityExportPlan","additionalExtensionsUsed","_additionalExtensionsUsed","_flowGraphs","_graphAnalyses","_rootDiagnostics","_isPreflight","additionalExtensionsRequired","_refreshAnalysis","_analyzeGraphs","_collectAdditionalExtensions","unscopedBuildDiagnostics","_mergeBuildDiagnostics","_validateBuildWithSourceIndices","blockIds","classification","_sortDiagnostics","_analysis","representable","unscoped","pathNodeIndex","exec","analyze","build","analysis","_buildGraph","_writeCompanionNodeExtensions","document","_getSourceGraph","documentGraph","sourceGLTF","indexOrUndefined","getNodeCount","getNodeIndex","getAnimationIndex","getCameraIndex","getMaterialIndex","getRootIndex","entity","_getSourceRootIndex","setNodeExtension","analyses","unsupportedNodes","_classifyStandaloneBlock","blockId","_analyzeImportedNodes","candidates","graphDiagnostics","MIN_SAFE_INTEGER","logicalNodes","_validateUnsupportedExtensionBlock","_validateMappedBlocks","normalizeValueSockets","normalizeFlowSockets","expectedValueSockets","expectedInputFlows","expectedOutputFlows","actualConnectionNames","inputValues","outputValues","FlowGraphExecutionBlock","outputFlows","expectedConnectionNames","roleBlocks","allowedInternalPeers","allowInternalConnection","leftPeers","rightPeers","outputBlock","_connectedPoint","reportedUnexpectedConnections","blockProvenance","outputSignals","executionSignals","runtimeExpected","currentRuntime","khrFacing","_inferSocketProvenance","unexpectedPeers","peer","internal","_ownerBlock","importerHelper","importedName","_updateVariables","logicalBySourceIndex","rebuiltNodes","_rebuildNode","_topologicallyOrderNodes","_remapGraphReferences","sourceIndices","finalNodeIndexText","finalNodeIndex","graphAnalysis","_rebuildConfiguration","sourceEffective","_isEffectiveValueInput","currentEffective","mappingObject","_getMappingObject","_rebuildInputValue","flowOutputs","_isEffectiveFlowOutput","rebuiltFlows","sourceFlow","sourceNoOp","_isNoOpFlowTarget","currentNoOp","targetBlockProvenance","targetLogicalNode","targetSourceNode","_isEffectiveFlowInput","rebuiltFlow","_remapPointerTemplateInputs","isDataInput","isDataOutput","isSignalInput","isSignalOutput","inferredSourceName","useCurrentConfiguration","fixed","allowedSockets","effectiveValues","configurationValue","upstream","_unwrapAnimationTimeHelper","rebuiltReference","rebuiltType","sourceProvenanceValue","currentSnapshot","legacyRuntimeSnapshot","_CreateTypedRuntimeValueSnapshot","importedRuntimeSnapshot","canonicalSource","eventProperty","pointerProperty","semanticSignature","richType","_GetOrAddInputTypeIndex","_GetTypeDefault","_GetSourceValue","rebuiltValue","helperOutput","helperBlock","helperProvenance","expectedFactor","factorValue","changedConfigurationGroups","fallbackConfigurationGroups","groupChanged","groupUsedFallback","preserveUnexposedValidMember","runtimeEventData","runtimeSchema","importTimeSchema","preservesImportedEvent","eventSchema","currentSchema","expectedSchema","remapped","rebuiltConfiguration","rootPlaceholder","rootSocket","rootReference","rootMatch","indexPlaceholder","referenceIndexPlaceholder","_validateExtensionReferencePreservation","_getRemappedRootIndex","authoredVariableStructureChanged","authoredValues","authoredVariableValues","authoredTypes","authoredVariableTypes","indexText","authoredValue","_remapValueArray","referenceHint","hintedCollection","_remapReferenceToCollection","_remapReference","outgoing","indegree","hasInvalidDependency","addEdge","ready","oldIndex","newIndex","currentValue","consumerCollection","_getVariableReferenceCollection","sourceNodeIndex","pointerCollection","_getPointerReferenceCollection","sourceReference","currentReference","getterNodes","collections","placeholderIndex","parentSegment","parentPlaceholder","parentValue","parentReference","_getSourceRootObjects","_getExportedObjectIndex","roots","targetCollection","extensionCollection","resolvedCollection","nestedExtensions","extensionIndex","_CanPreserveNestedExtensionPointer","collectReferenceExtension","collectPropertyExtensions","extensionPayload","CreateKHRInteractivityExportPlan","flowGraphs","_ImportResults","GetKHRInteractivityImportResult","GetKHRInteractivityImportResults","KHR_interactivity","_initializePathConverter","_gltfPathConverter","_AddInteractivityObjectModel","initialPrefixes","RotationYawPitchRoll","refConverter","enabledExtensions","assetConverter","pathConverter","_pathConverter","interactivityDefinition","autoStart","parseOnly","strictValidation","importResults","assetIndex","hostResolver","graphModel","graphResult","serializedFlowGraph","coordinator","FlowGraphCoordinator","dispatchEventsSynchronously","ParseFlowGraphAsync","activeCamera","quat","getActivePerspectiveValue","compute","getActiveOrthographicValue","halfWidth","halfHeight","getAnimationFps","framePerSecond","isPlaying","getRetainedCurrentFrame","getVirtualCurrentFrame","_RuntimeRegistered","_RegisterKHRInteractivityRuntime","addToBlockFactory","flowGraphGLTFDataProvider","FlowGraphGLTFDataProvider","flowGraphUnsupportedInteractivityBlock","FlowGraphUnsupportedInteractivityBlock","flowGraphObjectReferenceBlock","FlowGraphObjectReferenceBlock","flowGraphEventReferenceBlock","FlowGraphEventReferenceBlock","RegisterKHR_interactivity","inheritVisibility","_RegisterKHRNodeVisibilityRuntime","RegisterKHR_node_visibility","_NodeSets","_Hoverable","_Selectable","_GetStateMap","_GetLocalState","_ApplyMeshState","isPickable","_isPointerMovePickable","_ApplyNodeState","_GetEffectiveState","_IsDescendantNode","InitializeInteractivityNodeState","getAuthoredState","stateMap","GetInteractivityNodeState","SetInteractivityNodeState","KHR_node_selectability","selectable","_RegisterKHRNodeSelectabilityRuntime","selectedNode","selectionRayOrigin","selectionPoint","controllerIndex","selectedNodeIndex","validNodeIndex","variableName","eventKey","useNaNDefaults","pointerIdDefault","RegisterKHR_node_selectability","MeshPointerOverPrefix","MeshPointerOutPrefix","KHR_node_hoverability","hoverable","_RegisterKHRNodeHoverabilityRuntime","hoveredNode","hoverNodeIndex","RegisterKHR_node_hoverability","ExtrasAsMetadata","_assignExtras","gltfProp","RegisterExtrasAsMetadata","FlowGraphBlock","registerDataOutput","RichTypeAny","GetInteractivityObjectReference","registerDataInput","RichTypeString","_updateOutputs","setValue","_assetInverse","_selectionPointValue","_selectionRayOriginValue","nanVector","controllerIndexInput","RichTypeNumber","selectionPointInput","RichTypeVector3","selectionRayOriginInput","nodeReference","_registerSignalOutput","_execute","pointerId","controllerIndices","_getGlobalContextVariable","_setGlobalContextVariable","getEventReference","_activateSignal","_GetDefaultValue","FlowGraphMatrix2D","FlowGraphMatrix3D","_unregisterSignalInput","_unregisterSignalOutput","getRichTypeByFlowGraphType","_registerSignalInput","_callingSignal","MTLFileLoader","parseMTL","invertTextureY","INVERT_TEXTURE_Y","materialNames","trackTextureLoading","textureLoadPromises","delimiterPattern","charAt","blockEntityCollection","_GetTexture","bumpMultiplierIndex","bumpMultiplier","lastDelimiter","removeFailedTextureFromCache","texturesCache","getLoadedTexturesCache","cacheIndex","queueMicrotask","delayLoadState","DELAYLOADSTATE_NOTLOADED","delayLoad","SolidParser","materialToUse","babylonMeshesArray","_positions","_normals","_uvs","_colors","_extColors","_meshesFromObj","_indicesForBabylon","_wrappedPositionForBabylon","_wrappedUvsForBabylon","_wrappedColorsForBabylon","_wrappedNormalsForBabylon","_tuplePosNorm","_curPositionInIndices","_hasMeshes","_unwrappedPositionsForBabylon","_unwrappedColorsForBabylon","_unwrappedNormalsForBabylon","_unwrappedUVForBabylon","_triangles","_materialNameFromObj","_objMeshName","_increment","_isFirstMaterial","_grayColor","_hasLineData","_materialToUse","_babylonMeshesArray","_isInArray","_isInArrayUV","_setData","indiceUvsFromObj","indiceNormalFromObj","optimizeWithUV","indicePositionFromObj","positionVectorFromOBJ","textureVectorFromOBJ","normalsVectorFromOBJ","positionColorsFromOBJ","_unwrapData","_handednessSign","_getTriangles","faceIndex","_pushTriangle","_getColor","importVertexColors","_setDataForCurrentFaceWithPattern1","_setDataForCurrentFaceWithPattern2","_setDataForCurrentFaceWithPattern3","_setDataForCurrentFaceWithPattern4","_setDataForCurrentFaceWithPattern5","_addPreviousObjMesh","_handledMesh","useLegacyBehavior","hasLines","_optimizeNormals","mapVertices","lst","v0Idx","vIdx","setVerticesData","_IsLineElement","_IsObjectElement","_IsGroupElement","_GetZbrushMRGB","notParse","regArray","regIndex","onFileToLoadFound","linesOBJ","lineLines","currentGroup","lineValues","flat","VertexPattern","NormalPattern","UVPattern","UVScaling","FacePattern3","FacePattern4","FacePattern5","FacePattern2","FacePattern1","LinePattern1","LinePattern2","LinePattern3","GroupDescriptor","ObjectDescriptor","objMesh","materialName","isObject","UseMtlDescriptor","MtlLibGroupDescriptor","SmoothDescriptor","newMaterial","RandomId","pointsCloud","directMaterial","_babylonMesh","computeNormals","ComputeNormals","blockEntityCollectionBeforeGeometry","optimizeNormals","OBJFileLoaderMetadata","OBJFileLoader","ENCODING","COMPUTE_NORMALS","OPTIMIZE_NORMALS","IMPORT_VERTEX_COLORS","INVERT_Y","waitForTextures","WAIT_FOR_TEXTURES","UV_SCALING","materialLoadingFailsSilently","MATERIAL_LOADING_FAILS_SILENTLY","OPTIMIZE_WITH_UV","SKIP_MATERIALS","USE_LEGACY_BEHAVIOR","_loadMTL","onFailure","pathOfFile","_decode","fatal","_parseSolidAsync","ex","fileToLoad","materialsFromMTLFile","mtlPromises","dataLoaded","getTotalIndices","isLine","Boolean","getBindedMeshes","sourceMaterial","lineMaterial","wireframe","RegisterOBJFileLoader","STLFileLoaderMetadata","STLFileLoader","solidPattern","facetsPattern","normalPattern","vertexPattern","importMesh","_isBinary","_parseBinary","meshName","meshNameFromEnd","_parseASCII","load","loadAssetContainer","ascii","off","getUint8","indicesCount","normalX","normalY","normalZ","vertexstart","DO_NOT_ALTER_FILE_COORDINATES","solidData","facet","normalMatches","vertexMatch","RegisterSTLFileLoader","SPLATFileLoaderMetadata","SH_C0","LoadWebpImageData","rootUrlOrData","filename","createCanvasImage","objectUrl","canvas","createCanvas","getContext","drawImage","getImageData","onerror","crossOrigin","ParseSogMeta","dataOrFiles","files","metaFile","means","quats","sh0","shN","imageDataArrays","fileData","rgba","Uint8ClampedArray","rot","unlog","meansl","meansu","mins","maxs","meansMin","meansMax","Scalar","codebook","sce","lsc","lsce","colorsMin","colorsMax","colort","csh","toComp","SQRT2","quatArray","quatsr","quatsg","quatsb","quatsa","coeffs","bands","shCentroids","shLabelsData","shCentroidsWidth","sh","shIndexWrite","shArray","shValue","shMin","shMax","hasVertexColors","ParseSogDatas","CreateSogTextureFromImage","RawTexture","TEXTUREFORMAT_RGBA","TEXTURE_NEAREST_SAMPLINGMODE","TEXTURETYPE_UNSIGNED_BYTE","TEXTURE_CLAMP_ADDRESSMODE","CreateSogTexture","LoadSogTextureDirectAsync","createImageBitmap","LoadFileAsync","bitmap","premultiplyAlpha","colorSpaceConversion","updateDynamicTexture","close","DecodeSogPositions","ParseSogMetaAsTextures","dataOrFiles_1","computeCpuPositions","downloadManager","downloadGroupId","loadMeansImageAsync","loadFileAsync","loadGpuTextureAsync","gpuFiles","meansL","meansU","meansWidth","meansHeight","gpuTextures","meansImages","gpu","meansTex","splatTexelCount","shLabels","codebookTexture","shCoeffCount","codebookSize","TEXTUREFORMAT_R","TEXTURETYPE_FLOAT","meansMins","meansMaxs","pack","meansTextureL","meansTextureU","scalesTexture","quatsTexture","sh0Texture","shCentroidsTexture","shLabelsTexture","scalesMin","scalesMax","sh0Min","sh0Max","shnMin","shnMax","sogTextures","GaussianSplattingWorkBufferVertexShaderGLSL","GaussianSplattingWorkBufferVertexShaderWGSL","GaussianSplattingWorkBuffer","supportsAsyncCentersReadback","isWebGPU","glEngine","_gl","_readPixelsAsync","webGLVersion","textureSize","_textureSize","_mrt","shTextures","_shMrts","rotationTextures","_rotMrt","capacity","externalAtlas","rotationScale","_copyMaterial","_relayoutMapData","_relayoutMapTexture","_backupMrt","_readFbo","_ownsShMrts","_shMaterial","_shCopyMaterial","_backupShMrts","_ownsRotMrt","_rotMaterial","_rotCopyMaterial","_backupRotMrt","_shaderLanguage","_capacity","mrt","_baseOffset","baseOffset","_ownsMrt","_createMrt","externalMrts","_createShMrt","_createShMaterial","externalMrt","_createRotMrt","_createRotMaterial","_quad","_createQuad","isRelayoutReady","rebindAtlas","rebindShAtlas","shMrts","rebindRotAtlas","rotMrt","setBaseOffset","canBackup","backupRegion","regionRows","baseRow","_renderRelayoutPass","_renderShCopyPass","_renderRotCopyPass","restoreRegion","enableScissor","disableScissor","disableClear","covType","_caps","textureHalfFloatRender","MultiRenderTarget","samplingModes","formats","generateDepthBuffer","generateDepthTexture","generateMipMaps","onClearObservable","TEXTURETYPE_UNSIGNED_INTEGER","TEXTUREFORMAT_RGBA_INTEGER","rotType","decodeAsync","_applyPack","decodeSh","_applyShPack","decodeRot","_applyRotPack","attempt","isReady","onBeforeRenderObservable","globalOffset","setInt","firstRow","rowCount","render","_createCopyMaterial","_createShCopyMaterial","_createRotCopyMaterial","_bindCopyMaterialsToAtlas","shReady","rotReady","relayoutSync","srcIndexByDst","mapW","mapH","mapData","update","mapTexture","temp","shTemp","rotTemp","shTemps","useMap","dstWidth","srcWidth","srcBaseOffset","dstBaseRow","isWGSL","vertexSource","fragmentSource","shaderLanguage","disableDepthWrite","srcSh","readCentersRangeAsync","splatOffset","rowStart","startInBuffer","sliceEnd","centers","readPixels","floats","gl","hardware","_hardwareTexture","underlyingResource","createFramebuffer","previousFbo","_currentFramebuffer","bindFramebuffer","FRAMEBUFFER","framebufferTexture2D","COLOR_ATTACHMENT0","TEXTURE_2D","readBuffer","deleteFramebuffer","quad","removeMesh","sMin","sMax","c0Min","c0Max","hasSh","labels","centroids","GaussianSplattingDownloadManager","_activeCount","_queue","_pending","_groups","maxConcurrent","maxRetries","isIdle","groupId","task","settled","cancelled","started","slotReleased","_pump","_abort","cancelGroup","queueIndex","cancelAttempt","_settle","_releaseSlot","settleFn","_runTaskAsync","finally","lastError","_downloadAttemptAsync","_request","GaussianSplattingMemBlock","_offset","_size","_free","_prev","_next","_prevFree","_nextFree","_bucket","GaussianSplattingBlockAllocator","growMultiplier","_headAll","_tailAll","_freeBucketHeads","_pool","_usedSize","_freeSize","_freeRegionCount","_growMultiplier","_obtain","_addToBucket","usedSize","freeSize","fragmentation","allocate","gap","_findFreeBlock","_removeFromBucket","alloc","_rebucket","_insertAfterInMainList","free","prevFree","nextFree","_removeFromMainList","_release","grow","newCapacity","added","defrag","maxMoves","_defragFull","_defragIncremental","updateAllocation","toFree","toAllocate","totalRemaining","neededCapacity","headroomCapacity","_bucketFor","clz32","after","startBucket","best","freeBlock","phase1Moves","phase2Moves","lastAlloc","_moveBlock","allocBlock","blockSize","newOffset","freed","gapPrev","GaussianSplattingResidencyController","cooldownFrames","onEvict","_blocks","_cooldown","_pinned","_allocator","_cooldownFrames","_onEvict","residentCount","file","_evictAllCooled","pin","compact","before","moves","oldOffset","getResidentBlocks","scheduleEviction","cancelEviction","tick","evicted","_evict","RefTanHalfFov","TmpInvWorld","TmpLocalCamera","TmpLocalForward","TmpWorldForward","LocalForwardAxis","BoxEdges","VerticesPerBox","GsLodDebugColors","GaussianSplattingStream","IsLODMetadata","lodLevels","filenames","tree","maxResidentSplats","_NormalizeResidentLimit","memoryBudgetMb","_leafNodes","_lod0SplatCount","_lodBaseDistance","_lodMultiplier","_lodBehindPenalty","_lodRangeMin","_maxDecodesPerFrame","_lodCooldownFrames","_lodUpdateInterval","_lodUpdateDistance","_maxDetailLod","_lodPixelThreshold","_hostBudgetAllocation","_frustumCulling","_frustumPlanes","Plane","_cullCameraViewProj","_cullViewProj","_frustumScratch","_workBuffer","_streamShDegree","_shTextureCount","_needsRotationScale","_useGpuPositionReadback","_readbackCandidate","_readbackProbed","_residency","_fileCounts","_fileMeta","_baseFileIds","_decodedFiles","_loadingFiles","_decodeQueue","_fileRefs","_cancelledDecodes","_evictionEnabled","_residentBudget","_minimumResidentSplats","_maxResidentSplats","_memoryBudgetMb","_evictionCooldownFrames","_decodeGate","_relayoutOldOffsets","_relayoutSrcIndex","_environmentRange","_environmentFiles","_lodObserver","_baseLayerReady","_metadataReady","_framesSinceLodUpdate","_lastLodCamPositions","_lastLodSignature","_forceLodUpdate","_boundsMin","_boundsMax","_debugDisplay","_debugLodSource","_debugMesh","_debugObserver","_debugColorData","_debugSignature","_hostCompound","_host","_positionBase","_unsubBeforeRebuild","_unsubAfterRebuild","_hostUnsubRemove","_hostUnsubDispose","_partReleasedByHost","_positionSnapshot","_partReadyPromise","_partReadyResolve","_partReadyReject","_partReadySettled","_metadata","_streamOptions","hostCompound","_decodeSh","needsRotationScale","maxLod","_lodRangeMax","lodBaseDistance","lodMultiplier","lodBehindPenalty","lodRangeMin","lodRangeMax","maxDecodesPerFrame","lodCooldownFrames","lodUpdateInterval","lodUpdateDistance","maxDetailLod","_splatBudget","_resolveSplatBudget","splatBudget","frustumCulling","debugLodSource","evictionCooldownFrames","_downloadManager","maxConcurrentDownloads","maxDownloadRetries","doNotSerialize","disposeObserver","_collectLodEntries","debugDisplay","_streamAllAsync","becameReady","_rejectPartReady","_disposeAndReclaim","completeCheck","streamingPartProxy","proxy","whenPartReadyAsync","_resolvePartReady","whenSettledAsync","stableFrames","stable","isSettled","_isLoadingIdle","_sinkIsDepthSortSettled","activeRenderLoops","onAfterRenderObservable","requestFrame","globalThis","requestAnimationFrame","endFrame","budget","effectiveSplatBudget","_effectiveSplatBudget","residentSplatBudget","minimumResidentSplats","lod0SplatCount","option","_computeDefaultSplatBudget","hostInformation","isMobile","navigator","userAgent","_splatBudgetEnabled","getBudgetDemand","_environmentSplatCount","optimalLod","baseLod","_countAtLevel","_cappedLevelForNode","setBudgetAllocation","splats","maxLodLevel","_refreshDebugDisplay","_clearDebugDisplay","doNotRecurse","isDisposed","unregisterLodBudgetParticipant","removePart","partIndex","compound","hadPart","compactAtlas","_getEffectiveWorldMatrix","force","_getActiveLodCameras","activeCameras","evaluateOptimalLods","mult","behindPenalty","rangeMin","rangeMax","budgetEnabled","renderHeight","camInfos","tanHalfV","FOVMODE_HORIZONTAL_FIXED","tanHalfH","fovScale","pixelHeight","viewport","localCamera","globalPosition","fwx","fwy","fwz","getDirectionToRef","localForward","mn","hx","hy","hz","radius","pixelSize","actualDistance","penalizedDistance","dotOverDistance","fovAdjustedDistance","rdx","rdy","rdz","centerDist","pixels","inFrustum","_displayedLodLevel","activeLod","_buildDebugMesh","needsObserver","_onDebugFrame","_computeDebugSignature","_updateDebugColors","corners","CreateLineSystem","updatable","useVertexAlpha","reservedDataStore","hidden","updateVerticesData","hash","lods","bmin","bmax","spanX","spanY","spanZ","diagonal","declaredLevels","maxLevel","levels","usable","minCount","availableLevels","lodCooldown","cullBounds","fileIds","_collectAllFileIds","baseFileIds","_collectBaseFileIds","fileId","progressiveMetadata","initialFileIds","envCount","_gatherCountsAsync","_resolveMinimumResidentSplats","_resolveLod0SplatCount","fullCapacity","_SafeAddCounts","largestBaseFileCount","_resolveResidentBudget","_onFileEvicted","envOffset","sogWorld","ZeroReadOnly","host","reserveStreamingPart","registerLodBudgetParticipant","removeObserver","onPartRemovedObservable","removedIndex","shExternal","shMrtAtlas","rotExternal","rotMrtAtlas","mrtAtlas","atlasWidth","_splatPositions","splatPositions","_vertexCount","onBeforeAtlasRebuild","onAfterAtlasRebuild","setActiveRanges","rotTextures","_setExternalWorkBuffer","setSplatIndexRanges","_waitForCanBackupAsync","_decodeEnvironmentAsync","_decodeFileAsync","activeFile","fineFileIds","_onLodFrame","hasExplicitLimit","bytesPerSplat","_bytesPerResidentSplat","fromMB","automaticMb","automaticCount","refinementHeadroom","coarseWithHeadroom","maxCapacity","rotBytes","environmentCount","hasLod0Entry","fileIds_1","includeEnvironment","maxShDegree","maxCoeffs","foldSh","_GetShInfo","environment","_unzipAsync","metaBytes","_GetSplatCount","relativePath","metaUrl","subRootUrl","metaBuffer","sogData","_enqueueDecode","_pumpDecodeQueue","_applyPositions","_updateBounds","_sinkPostPositionsRange","_sinkSetActiveRanges","localRanges","postPositionsRange","_postWorkerPositionsRange","_sinkNotifyDataChanged","notifyDataChanged","_notifyWorkerNewData","isDepthSortSettled","_isDepthSortSettled","_probeReadbackAsync","cpuPositions","sampleCount","ok","_applyDecodedPositionsAsync","cpu","decoded","positionsApplied","_refreshActiveRanges","_DisposePack","allocated","release","_acquireDecodeGateAsync","residency","_relayoutAndAllocateAsync","_applyDesiredLods","previous","_performRelayout","oldOffsets","resident","copyWithin","bestDiff","diff","_computeTargetLevels","targetLevel","leafBudget","_convergePixelThreshold","_budgetedLevel","ceiling","ps","steps","_totalSplatsAtThreshold","maxPixelSize","ceilT","_residentLevelAtLeast","lvl","dirty","coarse","_switchActiveFile","newPending","pendingFile","_releaseFileRef","_acquirePendingFile","_acquireFileRef","refs","cooldownExpiredWithPendingSwitch","frustumChanged","_updateNodeFrustum","runLodEval","_computeLodSignature","DistanceSquared","sig","updateFlag","vp","changed","inAny","Frustum","GetPlanesToRef","validFrustum","plane","isInFrustum","integer","shapeCoeffs","minimizeInPlaceFromFloats","maximizeInPlaceFromFloats","expandBounds","setBoundingInfo","ranges","_CoalesceRanges","merged","lastEnd","fflateModule","fflate","window","LoadScriptAsync","deflateURL","unzipped","unzipSync","_SH_C0","_SpzModulePromise","_SpzModuleUrl","SPLATFileLoader","lodStream","_tryCreateLODStream","_parseAsync","previousBlockEntityCollection","stream","_BuildPointCloud","pointcloud","uBuffer","fBuffer","addPoints","particle","_BuildMesh","parsedPLY","_unzipWithFFlateAsync","makeGSFromParsedSOG","parsedSOG","gaussianSplatting","keepInRam","needsRotationScaleTextures","setSogTextureData","updateData","flipY","safeOrbitCameraLimits","_ExtractSafeOrbitLimits","useSogTextures","sogParser","dataSOG","u8","handlePLY","_ConvertPLYToSplat","chirality","PointsCloudSystem","buildMeshAsync","applyAutoCameraLimits","isGZipped","isNGSP","applyParsedSPZ","parsedSPZ","trainedWithAntialiasing","gsMaterial","kernelSize","compensation","safeOrbitLimits","spzLibraryUrl","spzModulePromise","_LoadScriptModuleAsync","GetSpzModule","spz","cloud","runCoroutineAsync","useCoroutine","alphas","safeOrbitCameraRadiusMin","safeOrbitCameraElevationMinMax","cloudSh","chunkStarts","chunkEnds","shArrays","fBase","uBase","c0","c1","c2","shSplatBase","shT","chunkStart","chunkEnd","safeOrbitExt","safeOrbitRadiusMin","safeOrbitElevationMin","safeOrbitElevationMax","antialiased","ConvertSpzToSplat","createYieldingScheduler","ConvertSpzToSplatAsync","loadSpzFromBuffer","CoordinateSystem","RUB","readableStream","ReadableStream","controller","enqueue","decompressionStream","DecompressionStream","decompressedStream","pipeThrough","Response","ubuf","ubufu32","fractionalBits","reserved","positionScale","int32View","uint8View","read24bComponent","Clamp","sqrt12","SQRT1_2","comp","cmask","iLargest","sumSquares","mag","negbit","square","shuffle","shIndexRead","ParseSpz","radiusMin","elevationMinMax","limits","disableAutoCameraLimits","arcCam","lowerBetaLimit","upperBetaLimit","lowerRadiusLimit","header","headerEndIndex","rawSplat","faceElement","faceCount","chunkElement","chunkCount","rowVertexOffset","rowChunkOffset","offsets","double","uint","ushort","uint16","uchar","chunkMode","vertexProperties","chunkProperties","filtered","metaData","rowVertexLength","rowChunkLength","ConvertPLYWithSHToSplatAsync","splatsData","dataView","headerEnd","faceVertexCount","compressed","propertyCount","propertyColorCount","splatProperties","splatColorProperties","hasMandatoryProperties","currentMode","WebAssembly","RegisterSPLATFileLoader","USDFileLoaderMetadata","MISSING_OFFSET","Command","AnalyticPrimitiveType","PrimitiveAxis","AnimationTarget","AnimationProperty","MaterialFlags","TextureOutputChannel","USDTextureColorSpace","MeshFlags","GeometryFlags","expectedPayloadLength","opcode","PayloadReader","_PayloadReader_view","_PayloadReader_end","_PayloadReader_instances","_PayloadReader_require","DirectAssetContainer","AbstractAssetContainer","manager","multiMaterial","rootNodes","decoder","NODE_MATRIX_PROPERTY","assertRange","bytesPerElement","stringAt","matrixAt","wrapMode","awaitAbortableAsync","signal","onAbort","aborted","_resolve","once","race","_DefaultAssetRootUrl","_SupportedExtension","_toBytes","_stagedFileName","preserveUrlCharacters","normalizedFileName","cleanFileName","pathParts","USDFileLoader","_nextRequestId","_activeLoads","resolveByFileName","glueUrl","DefaultConfiguration","wasmUrl","workerUrl","_RegisterUSDLoaderDependencies","_terminateWorker","addToScene","_normalizeFiles","requestId","rootFileName","transfer","AbortController","_getWorker","response","progress","_ProgressPhaseIndex","phase","onLog","materializingProgress","throwIfAborted","materialized","commandBuffer","performance","now","commands","getUint16","payloadLength","payloadOffset","readCommands","pendingParents","doubleSidedMaterials","morphTargets","classicInstanceSources","thinInstanceSources","textureLoads","materialTextureBindings","processedTextures","timeCodesPerSecond","rollingBack","caps","processedTextureType","textureHalfFloatLinearFiltering","textureFloatRender","textureFloatLinearFiltering","trackAsset","assets","applyMeshOrientation","sourceIsRightHanded","materialForMesh","textureId","descriptor","channelIndex","scalarTextureIsLinear","sourceColorSpace","valueTransformIs","processTextureAsync","name_1","binding_1","scale_1","bias_1","args_1","preserveRange","supportsMipMaps","needPOTTextures","outputOptions","TEXTURE_TRILINEAR_SAMPLINGMODE","TEXTURE_BILINEAR_SAMPLINGMODE","processing","processingPromise","CreateFactorOperand","CreateTextureOperand","B","processorChannel","processed","addTexture","trackProcessedTexture","transformedTexture","wRotationCenter","homogeneousRotationInUVTransform","processScalarTextureAsync","applyMaterialTextureBindingsAsync","normalScale","occlusion","emissive","factors","packedOcclusion","useAmbientOcclusionFromMetallicTextureRed","getAlphaFromRGB","doubleSidedVariant","command","zUp","metersPerUnit","nameOffset","nameLength","mime","imageOffset","imageLength","transformOffset","valueTransformOffset","valueTransform","resolveLoad","rejectLoad","emissiveOffset","textureChannels","matrixOffset","setPreTransformMatrix","getPivotMatrix","jointCount","jointsOffset","jointView","created","boneId","jointNameOffset","jointNameLength","restMatrixOffset","bindMatrixOffset","uv0","joints0","weights0","joints1","weights1","submeshesOffset","submeshCount","submeshView","multi","releaseSubMeshes","positionsOffset","normalsOffset","sizeOrRadius","tessellation","CreateBox","CreateSphere","diameter","CreateCylinder","diameterTop","diameterBottom","reversed","sourceId","transformsOffset","thinInstanceEnablePicking","targetKind","trackIndex","timesOffset","valuesOffset","dataType","materializeMs","materializeCommandBuffers","timings","statistics","missingAssets","currentLocation","location","resolvedUrl","href","_worker","_workerUrl","_workerBlobUrl","fail","initializing","staging","extracting","materializing","RegisterPbrMaterial","RegisterInstancedMesh","RegisterThinInstanceMesh","RegisterUSDFileLoader","registerBuiltInLoaders","bvhFileLoader_pure","fbxFileLoader_pure","glTFLoader_pure","EXT_lights_image_based_pure","EXT_mesh_gpu_instancing_pure","EXT_meshopt_compression_pure","EXT_texture_avif_pure","EXT_texture_webp_pure","ExtrasAsMetadata_pure","KHR_animation_pointer_pure","KHR_animation_pointer_data_pure","KHR_draco_mesh_compression_pure","KHR_gaussian_splatting_pure","KHR_interactivity_pure","KHR_lights_punctual_pure","EXT_lights_area_pure","EXT_lights_ies_pure","KHR_materials_anisotropy_pure","KHR_materials_clearcoat_pure","KHR_materials_diffuse_roughness_pure","KHR_materials_diffuse_transmission_pure","KHR_materials_dispersion_pure","KHR_materials_emissive_strength_pure","KHR_materials_ior_pure","KHR_materials_iridescence_pure","KHR_materials_pbrSpecularGlossiness_pure","KHR_materials_sheen_pure","KHR_materials_specular_pure","KHR_materials_transmission_pure","KHR_materials_unlit_pure","KHR_materials_variants_pure","KHR_materials_volume_pure","KHR_mesh_quantization_pure","KHR_texture_basisu_pure","KHR_texture_transform_pure","KHR_xmp_json_ld_pure","RegisterAudioSceneComponent","MSFT_audio_emitter_pure","MSFT_lod_pure","MSFT_minecraftMesh_pure","MSFT_sRGBFactors_pure","KHR_node_visibility_pure","KHR_node_hoverability_pure","KHR_node_selectability_pure","KHR_materials_coat_pure","KHR_materials_fuzz_pure","KHR_materials_volume_scatter_pure","registerBuiltInGLTFExtensions","objFileLoader_pure","RegisterEnginesExtensionsEngineDynamicTexture","splatFileLoader_pure","RegisterStandardMaterial","stlFileLoader_pure","usdFileLoader_pure","GlobalObject","global","Loaders","FileLoader","Validation","GLTF1","LoaderExtensions","GLTF2Loader","GLTF2Legacy","GLTF2","Loader","compound_1","metadata_1"],"mappings":"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","x_google_ignoreList":[4]}