@babylonjs/loaders 9.16.2 → 9.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,7 +45,11 @@ export declare class GaussianSplattingWorkBuffer {
45
45
  */
46
46
  constructor(scene: Scene, capacity: number);
47
47
  /**
48
- * Creates a 4-attachment MRT (centers F32 / covA F32 / covB F32 / colors U8) sized to the work buffer.
48
+ * Creates a 4-attachment MRT (centers F32 / covA / covB / colors U8) sized to the work buffer. covA/covB
49
+ * use HALF_FLOAT when the engine can render to it, matching the precision the non-streamed
50
+ * GaussianSplattingMesh path already uses for these same two textures (see
51
+ * `gaussianSplattingMeshBase.pure.ts`'s `createTextureFromDataF16` covA/covB textures); centers stays F32
52
+ * and colors stays U8 in both paths.
49
53
  * @param name MRT and attachment base name
50
54
  * @param disableClear when true, clearing is suppressed so renders accumulate (the decode buffer); when
51
55
  * false the MRT clears to zero on each render (the temporary relayout buffer, so gaps stay zeroed)
@@ -69,15 +69,20 @@ export class GaussianSplattingWorkBuffer {
69
69
  this._quad.material = this._material;
70
70
  }
71
71
  /**
72
- * Creates a 4-attachment MRT (centers F32 / covA F32 / covB F32 / colors U8) sized to the work buffer.
72
+ * Creates a 4-attachment MRT (centers F32 / covA / covB / colors U8) sized to the work buffer. covA/covB
73
+ * use HALF_FLOAT when the engine can render to it, matching the precision the non-streamed
74
+ * GaussianSplattingMesh path already uses for these same two textures (see
75
+ * `gaussianSplattingMeshBase.pure.ts`'s `createTextureFromDataF16` covA/covB textures); centers stays F32
76
+ * and colors stays U8 in both paths.
73
77
  * @param name MRT and attachment base name
74
78
  * @param disableClear when true, clearing is suppressed so renders accumulate (the decode buffer); when
75
79
  * false the MRT clears to zero on each render (the temporary relayout buffer, so gaps stay zeroed)
76
80
  * @returns the created MRT
77
81
  */
78
82
  _createMrt(name, disableClear) {
83
+ const covType = this._scene.getEngine()._caps.textureHalfFloatRender ? Constants.TEXTURETYPE_HALF_FLOAT : Constants.TEXTURETYPE_FLOAT;
79
84
  const mrt = new MultiRenderTarget(name, { width: this._textureSize, height: this._textureSize }, 4, this._scene, {
80
- types: [Constants.TEXTURETYPE_FLOAT, Constants.TEXTURETYPE_FLOAT, Constants.TEXTURETYPE_FLOAT, Constants.TEXTURETYPE_UNSIGNED_BYTE],
85
+ types: [Constants.TEXTURETYPE_FLOAT, covType, covType, Constants.TEXTURETYPE_UNSIGNED_BYTE],
81
86
  samplingModes: [
82
87
  Constants.TEXTURE_NEAREST_SAMPLINGMODE,
83
88
  Constants.TEXTURE_NEAREST_SAMPLINGMODE,
@@ -1 +1 @@
1
- {"version":3,"file":"gaussianSplattingWorkBuffer.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/gaussianSplattingWorkBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { 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 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} 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 * (PlayCanvas-style: `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 private readonly _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 // 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 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 /**\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 * Creates a work buffer sized to hold `capacity` splats.\r\n * @param scene hosting scene\r\n * @param capacity total number of splats the work buffer must address\r\n */\r\n constructor(scene: Scene, capacity: number) {\r\n this._scene = scene;\r\n this._shaderLanguage = scene.getEngine().isWebGPU ? ShaderLanguage.WGSL : ShaderLanguage.GLSL;\r\n this._textureSize = Math.max(1, Math.ceil(Math.sqrt(Math.max(1, capacity))));\r\n\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 // 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\r\n /**\r\n * Creates a 4-attachment MRT (centers F32 / covA F32 / covB F32 / colors U8) sized to the work buffer.\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 * @returns the created MRT\r\n */\r\n private _createMrt(name: string, disableClear: boolean): MultiRenderTarget {\r\n const mrt = new MultiRenderTarget(\r\n name,\r\n { width: this._textureSize, height: this._textureSize },\r\n 4,\r\n this._scene,\r\n {\r\n types: [Constants.TEXTURETYPE_FLOAT, Constants.TEXTURETYPE_FLOAT, Constants.TEXTURETYPE_FLOAT, 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 * 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, offset);\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)) {\r\n this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n return;\r\n }\r\n this._mrt.renderList = [this._quad];\r\n this._mrt.render();\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 return this._copyMaterial.isReady(this._quad);\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 const size = this._textureSize;\r\n // Reuse the map buffer and its GPU texture across relayouts (the work-buffer size is fixed).\r\n if (!this._relayoutMapData) {\r\n this._relayoutMapData = new Float32Array(size * size);\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 size,\r\n size,\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 // The temporary ping-pong MRT is (re)created per relayout rather than kept resident: it is the same size\r\n // as the work buffer, so a persistent copy would double GPU memory and defeat the streaming memory budget.\r\n const temp = this._createMrt(\"gsRelayoutTemp\", false);\r\n try {\r\n // Pass 1: old -> temp using the map (temp gets the new layout; gaps stay zeroed by the clear).\r\n this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1);\r\n // Pass 2: temp -> old, identity (old textures get the new layout, full overwrite).\r\n this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0);\r\n } finally {\r\n temp.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\r\n * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n */\r\n private _renderRelayoutPass(target: MultiRenderTarget, sources: Texture[], mapTexture: RawTexture, useMap: number): 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\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", this._textureSize);\r\n material.setInt(\"uUseMap\", useMap);\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\"],\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 * 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 // 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(splatOffset / width);\r\n const rowEnd = Math.ceil((splatOffset + splatCount) / width);\r\n const rowCount = rowEnd - rowStart;\r\n const startInBuffer = (splatOffset - 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._copyMaterial?.dispose(true, false);\r\n this._relayoutMapTexture?.dispose();\r\n this._mrt.dispose();\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, offset: number): 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 material.setInt(\"uOffset\", offset);\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"]}
1
+ {"version":3,"file":"gaussianSplattingWorkBuffer.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/gaussianSplattingWorkBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { 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 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} 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 * (PlayCanvas-style: `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 private readonly _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 // 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 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 /**\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 * Creates a work buffer sized to hold `capacity` splats.\r\n * @param scene hosting scene\r\n * @param capacity total number of splats the work buffer must address\r\n */\r\n constructor(scene: Scene, capacity: number) {\r\n this._scene = scene;\r\n this._shaderLanguage = scene.getEngine().isWebGPU ? ShaderLanguage.WGSL : ShaderLanguage.GLSL;\r\n this._textureSize = Math.max(1, Math.ceil(Math.sqrt(Math.max(1, capacity))));\r\n\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 // 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\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 * @returns the created MRT\r\n */\r\n private _createMrt(name: string, disableClear: boolean): 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: this._textureSize, height: this._textureSize },\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 * 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, offset);\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)) {\r\n this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n return;\r\n }\r\n this._mrt.renderList = [this._quad];\r\n this._mrt.render();\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 return this._copyMaterial.isReady(this._quad);\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 const size = this._textureSize;\r\n // Reuse the map buffer and its GPU texture across relayouts (the work-buffer size is fixed).\r\n if (!this._relayoutMapData) {\r\n this._relayoutMapData = new Float32Array(size * size);\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 size,\r\n size,\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 // The temporary ping-pong MRT is (re)created per relayout rather than kept resident: it is the same size\r\n // as the work buffer, so a persistent copy would double GPU memory and defeat the streaming memory budget.\r\n const temp = this._createMrt(\"gsRelayoutTemp\", false);\r\n try {\r\n // Pass 1: old -> temp using the map (temp gets the new layout; gaps stay zeroed by the clear).\r\n this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1);\r\n // Pass 2: temp -> old, identity (old textures get the new layout, full overwrite).\r\n this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0);\r\n } finally {\r\n temp.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\r\n * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n */\r\n private _renderRelayoutPass(target: MultiRenderTarget, sources: Texture[], mapTexture: RawTexture, useMap: number): 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\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", this._textureSize);\r\n material.setInt(\"uUseMap\", useMap);\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\"],\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 * 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 // 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(splatOffset / width);\r\n const rowEnd = Math.ceil((splatOffset + splatCount) / width);\r\n const rowCount = rowEnd - rowStart;\r\n const startInBuffer = (splatOffset - 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._copyMaterial?.dispose(true, false);\r\n this._relayoutMapTexture?.dispose();\r\n this._mrt.dispose();\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, offset: number): 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 material.setInt(\"uOffset\", offset);\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"]}
@@ -67,8 +67,19 @@ export declare class SPLATFileLoader implements ISceneLoaderPluginAsync, ISceneL
67
67
  private _unzipWithFFlateAsync;
68
68
  private _parseAsync;
69
69
  /**
70
- * Applies camera limits based on parsed meta data
70
+ * Extracts the safe-orbit camera limits from parsed splat metadata, or null when the file
71
+ * carries none. Exposed on the loaded mesh (GaussianSplattingMeshBase.safeOrbitCameraLimits)
72
+ * so consumers can apply/track them regardless of the active camera type.
71
73
  * @param meta parsed splat meta data
74
+ * @returns the parsed safe-orbit limits, or null
75
+ */
76
+ private static _ExtractSafeOrbitLimits;
77
+ /**
78
+ * Applies safe-orbit camera limits parsed from the file metadata to the scene's active
79
+ * ArcRotateCamera. No-op when no limits are present, `disableAutoCameraLimits` is set, or the
80
+ * active camera is not an ArcRotateCamera — in which case consumers can still read the limits
81
+ * from the loaded mesh's `safeOrbitCameraLimits` and apply them themselves.
82
+ * @param limits parsed safe-orbit limits (see _ExtractSafeOrbitLimits)
72
83
  * @param scene
73
84
  */
74
85
  private applyAutoCameraLimits;
@@ -205,6 +205,8 @@ export class SPLATFileLoader {
205
205
  }
206
206
  gaussianSplatting.scaling.y *= -1;
207
207
  gaussianSplatting.computeWorldMatrix(true);
208
+ // Expose any parsed safe-orbit limits (SOG does not auto-apply them to the camera).
209
+ gaussianSplatting.safeOrbitCameraLimits = SPLATFileLoader._ExtractSafeOrbitLimits(parsedSOG);
208
210
  scene._blockEntityCollection = false;
209
211
  };
210
212
  const engine = scene.getEngine();
@@ -278,6 +280,7 @@ export class SPLATFileLoader {
278
280
  break;
279
281
  }
280
282
  gaussianSplatting.computeWorldMatrix(true);
283
+ gaussianSplatting.safeOrbitCameraLimits = SPLATFileLoader._ExtractSafeOrbitLimits(parsedPLY);
281
284
  }
282
285
  break;
283
286
  case 1 /* Mode.PointCloud */:
@@ -308,7 +311,7 @@ export class SPLATFileLoader {
308
311
  throw new Error("Unsupported Splat mode");
309
312
  }
310
313
  scene._blockEntityCollection = false;
311
- this.applyAutoCameraLimits(parsedPLY, scene);
314
+ this.applyAutoCameraLimits(SPLATFileLoader._ExtractSafeOrbitLimits(parsedPLY), scene);
312
315
  resolve(babylonMeshesArray);
313
316
  });
314
317
  };
@@ -337,7 +340,9 @@ export class SPLATFileLoader {
337
340
  gaussianSplatting.computeWorldMatrix(true);
338
341
  }
339
342
  scene._blockEntityCollection = false;
340
- this.applyAutoCameraLimits(parsedSPZ, scene);
343
+ const safeOrbitLimits = SPLATFileLoader._ExtractSafeOrbitLimits(parsedSPZ);
344
+ gaussianSplatting.safeOrbitCameraLimits = safeOrbitLimits;
345
+ this.applyAutoCameraLimits(safeOrbitLimits, scene);
341
346
  resolve(babylonMeshesArray);
342
347
  };
343
348
  if (this._loadingOptions.spzLibraryUrl) {
@@ -385,22 +390,41 @@ export class SPLATFileLoader {
385
390
  });
386
391
  }
387
392
  /**
388
- * Applies camera limits based on parsed meta data
393
+ * Extracts the safe-orbit camera limits from parsed splat metadata, or null when the file
394
+ * carries none. Exposed on the loaded mesh (GaussianSplattingMeshBase.safeOrbitCameraLimits)
395
+ * so consumers can apply/track them regardless of the active camera type.
389
396
  * @param meta parsed splat meta data
397
+ * @returns the parsed safe-orbit limits, or null
398
+ */
399
+ static _ExtractSafeOrbitLimits(meta) {
400
+ if (meta.safeOrbitCameraRadiusMin === undefined && meta.safeOrbitCameraElevationMinMax === undefined) {
401
+ return null;
402
+ }
403
+ return {
404
+ radiusMin: meta.safeOrbitCameraRadiusMin,
405
+ elevationMinMax: meta.safeOrbitCameraElevationMinMax,
406
+ };
407
+ }
408
+ /**
409
+ * Applies safe-orbit camera limits parsed from the file metadata to the scene's active
410
+ * ArcRotateCamera. No-op when no limits are present, `disableAutoCameraLimits` is set, or the
411
+ * active camera is not an ArcRotateCamera — in which case consumers can still read the limits
412
+ * from the loaded mesh's `safeOrbitCameraLimits` and apply them themselves.
413
+ * @param limits parsed safe-orbit limits (see _ExtractSafeOrbitLimits)
390
414
  * @param scene
391
415
  */
392
- applyAutoCameraLimits(meta, scene) {
393
- if (this._loadingOptions.disableAutoCameraLimits) {
416
+ applyAutoCameraLimits(limits, scene) {
417
+ if (this._loadingOptions.disableAutoCameraLimits || !limits) {
394
418
  return;
395
419
  }
396
- if ((meta.safeOrbitCameraRadiusMin !== undefined || meta.safeOrbitCameraElevationMinMax !== undefined) && scene.activeCamera?.getClassName() === "ArcRotateCamera") {
420
+ if (scene.activeCamera?.getClassName() === "ArcRotateCamera") {
397
421
  const arcCam = scene.activeCamera;
398
- if (meta.safeOrbitCameraElevationMinMax) {
399
- arcCam.lowerBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[1];
400
- arcCam.upperBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[0];
422
+ if (limits.elevationMinMax) {
423
+ arcCam.lowerBetaLimit = Math.PI * 0.5 - limits.elevationMinMax[1];
424
+ arcCam.upperBetaLimit = Math.PI * 0.5 - limits.elevationMinMax[0];
401
425
  }
402
- if (meta.safeOrbitCameraRadiusMin) {
403
- arcCam.lowerRadiusLimit = meta.safeOrbitCameraRadiusMin;
426
+ if (limits.radiusMin) {
427
+ arcCam.lowerRadiusLimit = limits.radiusMin;
404
428
  }
405
429
  }
406
430
  }
@@ -1 +1 @@
1
- {"version":3,"file":"splatFileLoader.pure.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.pure.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,yDAAyD;AACzD,OAAO,EAMH,yBAAyB,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0DAA0D,CAAC;AACjG,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAoB,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAM7C;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAexB;;;OAGG;IACH,YAAY,iBAAyD,EAAE;QAlBvE;;WAEG;QACa,SAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC;QAE5C,oBAAe,GAA6B,IAAI,CAAC;QAGzD;;;WAGG;QACa,eAAU,GAAG,uBAAuB,CAAC,UAAU,CAAC;QAO5D,IAAI,CAAC,eAAe,GAAG,EAAE,GAAG,eAAe,CAAC,sBAAsB,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5F,CAAC;IASD,gBAAgB;IAChB,YAAY,CAAC,OAAiC;QAC1C,OAAO,IAAI,eAAe,CAAC,OAAO,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,eAAe,CACxB,WAAgB,EAChB,KAAY,EACZ,IAAS,EACT,OAAe,EACf,WAAwD,EACxD,SAAkB;QAElB,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACjE,IAAI,SAAS,EAAE,CAAC;YACZ,OAAO;gBACH,MAAM,EAAE,CAAC,SAAS,CAAC;gBACnB,eAAe,EAAE,EAAE;gBACnB,SAAS,EAAE,EAAE;gBACb,eAAe,EAAE,EAAE;gBACnB,cAAc,EAAE,EAAE;gBAClB,UAAU,EAAE,EAAE;gBACd,MAAM,EAAE,EAAE;gBACV,cAAc,EAAE,EAAE;aACrB,CAAC;QACN,CAAC;QAED,0CAA0C;QAC1C,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YAC7E,OAAO;gBACH,MAAM,EAAE,MAAM;gBACd,eAAe,EAAE,EAAE;gBACnB,SAAS,EAAE,EAAE;gBACb,eAAe,EAAE,EAAE;gBACnB,cAAc,EAAE,EAAE;gBAClB,UAAU,EAAE,EAAE;gBACd,MAAM,EAAE,EAAE;gBACV,cAAc,EAAE,EAAE;aACrB,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;;;;;OAMG;IACK,mBAAmB,CAAC,KAAY,EAAE,IAAS,EAAE,OAAe;QAChE,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,6BAA6B,GAAG,KAAK,CAAC,sBAAsB,CAAC;QACnE,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;QACtD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,uBAAuB,CAAC,yBAAyB,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE;gBAC1F,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU;gBAC3C,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM;aACtC,CAAC,CAAC;YACH,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC;YAC/C,OAAO,MAAM,CAAC;QAClB,CAAC;gBAAS,CAAC;YACP,KAAK,CAAC,sBAAsB,GAAG,6BAA6B,CAAC;QACjE,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,gBAAgB,CAAC,UAA6B,EAAE,IAAiB;QAC5E,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QAEvC,2GAA2G;QAC3G,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;QAE/C,MAAM,cAAc,GAAG,UAAU,QAAa,EAAE,CAAS;YACrD,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,QAAQ,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAEzC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAChD,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAChD,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAChD,QAAQ,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,MAAM,CAAC,UAAU,CAAC,KAAY,EAAE,SAAuB;QAC3D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAExC,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEjD,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;QAE/C,MAAM,SAAS,GAAG,EAAE,CAAC;QAErB,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,SAAS,CAAC,eAAe,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;YACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;gBAChD,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;gBAChD,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;gBAChD,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtB,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtB,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtB,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YACD,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC;QAC/B,CAAC;QAED,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC;QACjC,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC,KAAM,CAAC;QAEtC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,iIAAiI;IACzH,KAAK,CAAC,qBAAqB,CAAC,IAAgB;QAChD,6DAA6D;QAC7D,aAAa;QACb,IAAI,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAiC,CAAC;QACpE,0BAA0B;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,IAAI,OAAQ,MAAc,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAChD,MAAM,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,IAAI,uCAAuC,CAAC,CAAC;YAC5G,CAAC;YACD,MAAM,GAAI,MAAc,CAAC,MAAuB,CAAC;QACrD,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;QAE7B,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAA+B,CAAC,CAAC,qCAAqC;QAErG,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,2FAA2F;IACnF,WAAW,CAAC,WAAgB,EAAE,KAAY,EAAE,IAAS,EAAE,OAAe;QAC1E,MAAM,kBAAkB,GAAgB,EAAE,CAAC,CAAC,sBAAsB;QAElE,MAAM,mBAAmB,GAAG,CAAC,SAAuB,EAAE,EAAE;YACpD,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;YACtD,MAAM,iBAAiB,GACnB,IAAI,CAAC,eAAe,CAAC,qBAAqB;gBAC1C,IAAI,qBAAqB,CAAC,mBAAmB,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAAC;YACjJ,iBAAiB,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC;YAC1D,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC3C,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC;gBACxB,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACJ,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;YAChH,CAAC;YACD,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAClC,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC3C,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC;QACzC,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC;QACzD,IAAI,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;YACpG,cAAc,GAAG,KAAK,CAAC;QAC3B,CAAC;QACD,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,YAAY,CAAC;QAEzE,+BAA+B;QAC/B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;YAChD,IAAI,OAAO,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAC7E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;oBACnC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC;wBAC9B,mFAAmF;yBAClF,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;wBAChB,mBAAmB,CAAC,SAAS,CAAC,CAAC;wBAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC;oBAChC,CAAC,CAAC;wBACF,0CAA0C;yBACzC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;wBACT,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBACjE,CAAC,CAAC,CAAC;gBACX,CAAC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,8BAA8B;QAC9B,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACnC,mFAAmF;gBACnF,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;oBAC1C,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC;wBAC5B,mFAAmF;yBAClF,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;wBAChB,mBAAmB,CAAC,SAAS,CAAC,CAAC;wBAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC;oBAChC,CAAC,CAAC,CAAC,0CAA0C;yBAC5C,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;wBACT,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;oBACrE,CAAC,CAAC,CAAC;gBACX,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC;QAED,MAAM,SAAS,GAAG,CAAC,OAAwC,EAAE,EAAE;YAC3D,mFAAmF;YACnF,eAAe,CAAC,kBAAkB,CAAC,IAAmB,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;gBAC7E,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;gBACtD,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;oBACrB;wBACI,CAAC;4BACG,MAAM,iBAAiB,GACnB,IAAI,CAAC,eAAe,CAAC,qBAAqB;gCAC1C,IAAI,qBAAqB,CAAC,mBAAmB,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAAC;4BACjJ,iBAAiB,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC;4BAC1D,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;4BAC3C,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;4BAC5G,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;4BAEpC,IAAI,SAAS,CAAC,SAAS,KAAK,aAAa,EAAE,CAAC;gCACxC,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;4BACxC,CAAC;4BAED,QAAQ,SAAS,CAAC,MAAM,EAAE,CAAC;gCACvB,KAAK,GAAG;oCACJ,iBAAiB,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;oCAC5D,MAAM;gCACV,KAAK,GAAG;oCACJ,iBAAiB,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;oCACxD,MAAM;gCACV,KAAK,GAAG;oCACJ,iBAAiB,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;oCACnE,MAAM;4BACd,CAAC;4BACD,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;wBAC/C,CAAC;wBACD,MAAM;oBACV;wBACI,CAAC;4BACG,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,YAAY,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;4BACjE,IAAI,eAAe,CAAC,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gCAC/D,0CAA0C;gCAC1C,MAAM,UAAU,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;oCAC5C,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gCAClC,CAAC,CAAC,CAAC;4BACP,CAAC;iCAAM,CAAC;gCACJ,UAAU,CAAC,OAAO,EAAE,CAAC;4BACzB,CAAC;wBACL,CAAC;wBACD,MAAM;oBACV;wBACI,CAAC;4BACG,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gCAClB,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;4BAC1E,CAAC;iCAAM,CAAC;gCACJ,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;4BACnE,CAAC;wBACL,CAAC;wBACD,MAAM;oBACV;wBACI,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;gBAClD,CAAC;gBACD,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC;gBACrC,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAC7C,OAAO,CAAC,kBAAkB,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;QAEF,qFAAqF;QACrF,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QACnD,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QACpF,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC3B,SAAS,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACP,CAAC;QAED,MAAM,cAAc,GAAG,CAAC,SAAuB,EAAE,OAAoD,EAAE,EAAE;YACrG,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;YACtD,MAAM,iBAAiB,GACnB,IAAI,CAAC,eAAe,CAAC,qBAAqB;gBAC1C,IAAI,qBAAqB,CAAC,mBAAmB,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAAC;YACjJ,IAAI,SAAS,CAAC,uBAAuB,EAAE,CAAC;gBACpC,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAqC,CAAC;gBAC3E,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC;gBAC5B,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC;YACnC,CAAC;YACD,iBAAiB,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC;YAC1D,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC3C,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC5G,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;gBAC9B,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACpC,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;YACD,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC;YACrC,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC7C,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAChC,CAAC,CAAC;QAEF,IAAI,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;YACrC,mEAAmE;YACnE,0CAA0C;YAC1C,OAAO,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;gBACjE,MAAM,KAAK,GAAG,GAAG,CAAC,iBAAiB,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC5F,0CAA0C;gBAC1C,OAAO,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;oBAC3D,OAAO,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE;wBAC3C,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;oBACvC,CAAC,CAAC,CAAC;gBACP,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC;QAED,sFAAsF;QACtF,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,OAAO,CAAC,MAAM,CACjB,IAAI,KAAK,CACL,+EAA+E;gBAC3E,mGAAmG;gBACnG,yDAAyD,CAChE,CACJ,CAAC;QACN,CAAC;QAED,wEAAwE;QACxE,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC;YACtC,KAAK,CAAC,UAAU;gBACZ,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;gBACzC,UAAU,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;SACJ,CAAC,CAAC;QACH,MAAM,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,kBAAkB,GAAG,cAAc,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;QAE3E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,IAAI,QAAQ,CAAC,kBAAkB,CAAC;iBAC3B,WAAW,EAAE;gBACd,0CAA0C;iBACzC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBACb,mFAAmF;gBACnF,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;oBAC7D,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACvC,CAAC,CAAC,CAAC;YACP,CAAC,CAAC;gBACF,0CAA0C;iBACzC,KAAK,CAAC,GAAG,EAAE;gBACR,SAAS,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;;;OAIG;IACK,qBAAqB,CAAC,IAAkB,EAAE,KAAY;QAC1D,IAAI,IAAI,CAAC,eAAe,CAAC,uBAAuB,EAAE,CAAC;YAC/C,OAAO;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,wBAAwB,KAAK,SAAS,IAAI,IAAI,CAAC,8BAA8B,KAAK,SAAS,CAAC,IAAI,KAAK,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,CAAC;YACjK,MAAM,MAAM,GAAG,KAAK,CAAC,YAA+B,CAAC;YACrD,IAAI,IAAI,CAAC,8BAA8B,EAAE,CAAC;gBACtC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC,CAAC;gBAC/E,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC,CAAC;YACnF,CAAC;YAED,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBAChC,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC,wBAAwB,CAAC;YAC5D,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,gDAAgD;IACzC,uBAAuB,CAAC,KAAY,EAAE,IAAY,EAAE,OAAe;QACtE,MAAM,SAAS,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QAEjC,OAAO,CACH,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC;YAC5C,0CAA0C;aACzC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACb,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC/B,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;YACD,wDAAwD;YACxD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAC5B,OAAO,SAAS,CAAC;QACrB,CAAC,CAAC;YACF,0CAA0C;aACzC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE;YACV,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAC5B,MAAM,EAAE,CAAC;QACb,CAAC,CAAC,CACT,CAAC;IACN,CAAC;IAED;;;;;;OAMG;IACH,2FAA2F;IACpF,SAAS,CAAC,KAAY,EAAE,IAAY,EAAE,OAAe;QACxD,kBAAkB;QAClB,0CAA0C;QAC1C,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC9D,cAAc;QAClB,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,kBAAkB,CAAC,IAAiB;QAC/C,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,cAAc,CAAC;QACjC,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,cAAc,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,iBAAiB;YACjB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC3B,OAAO,CAAC,EAAE,IAAI,oBAAY,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACP,CAAC;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,WAAW,EAAE,CAAC;YACd,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,YAAY,GAAG,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,YAAY,EAAE,CAAC;YACf,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,eAAe,GAAG,CAAC,CAAC;QACxB,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,MAAM,OAAO,GAA2B;YACpC,MAAM,EAAE,CAAC;YACT,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,CAAC;SACV,CAAC;QAQF,MAAM,WAAW,GAA2B;YACxC,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,CAAC;YACR,EAAE,EAAE,CAAC;YACL,WAAW,EAAE,CAAC;YACd,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;SACX,CAAC;QAEF,IAAI,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC;QAClC,MAAM,gBAAgB,GAAkB,EAAE,CAAC;QAC3C,MAAM,eAAe,GAAkB,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAA0B,EAAE,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAEvC,IAAI,SAAS,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBACjC,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;oBAC7D,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;gBACpC,CAAC;qBAAM,IAAI,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;oBACzC,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;oBAC/D,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC;qBAAM,IAAI,SAAS,IAAI,WAAW,CAAC,EAAE,EAAE,CAAC;oBACrC,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;gBACnE,CAAC;qBAAM,IAAI,SAAS,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;oBAC9C,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;oBACnE,QAAQ,CAAC,8BAA8B,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBACnG,CAAC;qBAAM,IAAI,SAAS,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBACxC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;oBAC/D,QAAQ,CAAC,wBAAwB,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBACjE,CAAC;qBAAM,IAAI,SAAS,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBACxC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;oBAC/D,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;wBACpB,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;oBACtF,CAAC;yBAAM,IAAI,IAAI,IAAI,WAAW,EAAE,CAAC;wBAC7B,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;oBAC9E,CAAC;gBACL,CAAC;gBAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjB,MAAM,CAAC,IAAI,CAAC,8BAA8B,IAAI,GAAG,CAAC,CAAC;gBACvD,CAAC;YACL,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACrC,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACjC,IAAI,IAAI,IAAI,OAAO,EAAE,CAAC;oBAClB,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC;gBAClC,CAAC;qBAAM,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;oBAC1B,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC;gBACnC,CAAC;qBAAM,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;oBACtB,SAAS,GAAG,WAAW,CAAC,EAAE,CAAC;gBAC/B,CAAC;qBAAM,IAAI,IAAI,IAAI,6CAA6C,EAAE,CAAC;oBAC/D,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC;gBACxC,CAAC;qBAAM,IAAI,IAAI,IAAI,8BAA8B,EAAE,CAAC;oBAChD,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC;gBAClC,CAAC;qBAAM,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,WAAW,EAAE,CAAC;oBAClD,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC;gBAClC,CAAC;YACL,CAAC;QACL,CAAC;QAED,MAAM,eAAe,GAAG,eAAe,CAAC;QACxC,MAAM,cAAc,GAAG,cAAc,CAAC;QAEtC,0CAA0C;QAC1C,OAAQ,qBAAqB,CAAC,4BAA4B,CAAC,IAAI,CAAS,CAAC,IAAI,CAAC,KAAK,EAAE,UAAe,EAAE,EAAE;YACpG,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YACvE,IAAI,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,eAAe,GAAG,WAAW,CAAC;YACzE,QAAQ;YACR,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,SAAS,EAAE,CAAC;gBACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;oBACjC,MAAM,eAAe,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAClD,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;wBACvB,SAAS,CAAC,yBAAyB;oBACvC,CAAC;oBACD,MAAM,IAAI,CAAC,CAAC;oBAEZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;wBACvC,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,sBAAsB;wBAC1F,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBAC5B,CAAC;oBACD,MAAM,IAAI,EAAE,CAAC;gBACjB,CAAC;YACL,CAAC;YAED,uCAAuC;YACvC,IAAI,UAAU,EAAE,CAAC;gBACb,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;oBACjC,OAAO,CAAC;wBACJ,IAAI,oBAAY;wBAChB,IAAI,EAAE,UAAU,CAAC,MAAM;wBACvB,EAAE,EAAE,UAAU,CAAC,EAAE;wBACjB,QAAQ,EAAE,UAAU,CAAC,QAAQ;wBAC7B,KAAK,EAAE,KAAK;wBACZ,eAAe,EAAE,KAAK;wBACtB,UAAU,EAAE,IAAI;wBAChB,QAAQ,EAAE,KAAK;qBAClB,CAAC,CAAC;gBACP,CAAC,CAAC,CAAC;YACP,CAAC;YACD,4GAA4G;YAC5G,gDAAgD;YAChD,IAAI,aAAa,GAAG,CAAC,CAAC;YACtB,IAAI,kBAAkB,GAAG,CAAC,CAAC;YAC3B,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACxH,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACpF,KAAK,IAAI,aAAa,GAAG,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,CAAC;gBACnF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;gBACjD,IAAI,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1C,aAAa,EAAE,CAAC;gBACpB,CAAC;gBACD,IAAI,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/C,kBAAkB,EAAE,CAAC;gBACzB,CAAC;YACL,CAAC;YACD,MAAM,sBAAsB,GAAG,aAAa,IAAI,eAAe,CAAC,MAAM,IAAI,kBAAkB,IAAI,CAAC,CAAC;YAClG,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,mBAAW,CAAC,CAAC,sBAAsB,CAAC,CAAC,oBAAY,CAAC,wBAAgB,CAAC;YAClG,2CAA2C;YAC3C,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACjC,OAAO,CAAC;oBACJ,GAAG,QAAQ;oBACX,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,UAAU,CAAC,MAAM;oBACvB,EAAE,EAAE,UAAU,CAAC,EAAE;oBACjB,QAAQ,EAAE,UAAU,CAAC,QAAQ;oBAC7B,KAAK,EAAE,KAAK;oBACZ,eAAe,EAAE,CAAC,CAAC,kBAAkB;oBACrC,UAAU,EAAE,KAAK;oBACjB,QAAQ,EAAE,KAAK;iBAClB,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;;AA3oBuB,sCAAsB,GAAG;IAC7C,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,KAAK;IACZ,0BAA0B,EAAE,KAAK;IACjC,aAAa,EAAE,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,SAAS;CACzE,AALM,CAKL;AAyoB7C,2CAA2C;AAE3C,IAAI,WAAW,GAAG,KAAK,CAAC;AACxB;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACnC,IAAI,WAAW,EAAE,CAAC;QACd,OAAO;IACX,CAAC;IACD,WAAW,GAAG,IAAI,CAAC;IAEnB,yBAAyB,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;AACrD,CAAC","sourcesContent":["/* 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 { 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 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 }\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(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 this.applyAutoCameraLimits(parsedSPZ, 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 * Applies camera limits based on parsed meta data\r\n * @param meta parsed splat meta data\r\n * @param scene\r\n */\r\n private applyAutoCameraLimits(meta: IParsedSplat, scene: Scene): void {\r\n if (this._loadingOptions.disableAutoCameraLimits) {\r\n return;\r\n }\r\n if ((meta.safeOrbitCameraRadiusMin !== undefined || meta.safeOrbitCameraElevationMinMax !== undefined) && scene.activeCamera?.getClassName() === \"ArcRotateCamera\") {\r\n const arcCam = scene.activeCamera as ArcRotateCamera;\r\n if (meta.safeOrbitCameraElevationMinMax) {\r\n arcCam.lowerBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[1];\r\n arcCam.upperBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[0];\r\n }\r\n\r\n if (meta.safeOrbitCameraRadiusMin) {\r\n arcCam.lowerRadiusLimit = meta.safeOrbitCameraRadiusMin;\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 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"]}
1
+ {"version":3,"file":"splatFileLoader.pure.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.pure.ts"],"names":[],"mappings":"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","sourcesContent":["/* 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 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"]}