{"version":3,"file":"gaussian-splats-3d.umd.min.cjs","sources":["../src/SplatBuffer.js","../src/Util.js","../src/PlyParser.js","../src/PlyLoader.js","../src/SplatLoader.js","../src/OrbitControls.js","../src/LoadingSpinner.js","../src/ArrowHelper.js","../src/SceneHelper.js","../src/raycaster/Ray.js","../src/raycaster/Hit.js","../src/raycaster/Raycaster.js","../src/splattree/SplatTreeNode.js","../src/splattree/SplatTree.js","../src/SplatMesh.js","../src/Constants.js","../src/worker/SortWorker.js","../src/Viewer.js","../src/worker/sorter.wasm"],"sourcesContent":["import * as THREE from 'three';\r\n\r\nconst tempVector3A = new THREE.Vector3();\r\nconst tempVector3B = new THREE.Vector3();\r\nconst tempVector4A = new THREE.Vector4();\r\nconst tempVector4B = new THREE.Vector4();\r\nconst tempQuaternion4A = new THREE.Quaternion();\r\nconst tempQuaternion4B = new THREE.Quaternion();\r\n\r\nlet fbf;\r\nlet tbf;\r\n\r\nexport class SplatBuffer {\r\n\r\n    static PositionComponentCount = 3;\r\n    static ScaleComponentCount = 3;\r\n    static RotationComponentCount = 4;\r\n    static ColorComponentCount = 4;\r\n\r\n    static CompressionLevels = {\r\n        0: {\r\n            BytesPerPosition: 12,\r\n            BytesPerScale: 12,\r\n            BytesPerColor: 4,\r\n            BytesPerRotation: 16,\r\n            ScaleRange: 1\r\n        },\r\n        1: {\r\n            BytesPerPosition: 6,\r\n            BytesPerScale: 6,\r\n            BytesPerColor: 4,\r\n            BytesPerRotation: 8,\r\n            ScaleRange: 32767\r\n        }\r\n    };\r\n\r\n    static CovarianceSizeFloats = 6;\r\n    static CovarianceSizeBytes = 24;\r\n\r\n    static HeaderSizeBytes = 1024;\r\n\r\n    constructor(bufferData) {\r\n        this.headerBufferData = new ArrayBuffer(SplatBuffer.HeaderSizeBytes);\r\n        this.headerArrayUint8 = new Uint8Array(this.headerBufferData);\r\n        this.headerArrayUint32 = new Uint32Array(this.headerBufferData);\r\n        this.headerArrayFloat32 = new Float32Array(this.headerBufferData);\r\n        this.headerArrayUint8.set(new Uint8Array(bufferData, 0, SplatBuffer.HeaderSizeBytes));\r\n        this.versionMajor = this.headerArrayUint8[0];\r\n        this.versionMinor = this.headerArrayUint8[1];\r\n        this.headerExtraK = this.headerArrayUint8[2];\r\n        this.compressionLevel = this.headerArrayUint8[3];\r\n        this.splatCount = this.headerArrayUint32[1];\r\n        this.bucketSize = this.headerArrayUint32[2];\r\n        this.bucketCount = this.headerArrayUint32[3];\r\n        this.bucketBlockSize = this.headerArrayFloat32[4];\r\n        this.halfBucketBlockSize = this.bucketBlockSize / 2.0;\r\n        this.bytesPerBucket = this.headerArrayUint32[5];\r\n        this.compressionScaleRange = this.headerArrayUint32[6] || SplatBuffer.CompressionLevels[this.compressionLevel].ScaleRange;\r\n        this.compressionScaleFactor = this.halfBucketBlockSize / this.compressionScaleRange;\r\n\r\n        const dataBufferSizeBytes = bufferData.byteLength - SplatBuffer.HeaderSizeBytes;\r\n        this.splatBufferData = new ArrayBuffer(dataBufferSizeBytes);\r\n        new Uint8Array(this.splatBufferData).set(new Uint8Array(bufferData, SplatBuffer.HeaderSizeBytes, dataBufferSizeBytes));\r\n\r\n        this.bytesPerPosition = SplatBuffer.CompressionLevels[this.compressionLevel].BytesPerPosition;\r\n        this.bytesPerScale = SplatBuffer.CompressionLevels[this.compressionLevel].BytesPerScale;\r\n        this.bytesPerColor = SplatBuffer.CompressionLevels[this.compressionLevel].BytesPerColor;\r\n        this.bytesPerRotation = SplatBuffer.CompressionLevels[this.compressionLevel].BytesPerRotation;\r\n\r\n        this.bytesPerSplat = this.bytesPerPosition + this.bytesPerScale + this.bytesPerColor + this.bytesPerRotation;\r\n\r\n        fbf = this.fbf.bind(this);\r\n        tbf = this.tbf.bind(this);\r\n\r\n        this.linkBufferArrays();\r\n    }\r\n\r\n    linkBufferArrays() {\r\n        let FloatArray = (this.compressionLevel === 0) ? Float32Array : Uint16Array;\r\n        this.positionArray = new FloatArray(this.splatBufferData, 0, this.splatCount * SplatBuffer.PositionComponentCount);\r\n        this.scaleArray = new FloatArray(this.splatBufferData, this.bytesPerPosition * this.splatCount,\r\n                                         this.splatCount * SplatBuffer.ScaleComponentCount);\r\n        this.colorArray = new Uint8Array(this.splatBufferData, (this.bytesPerPosition + this.bytesPerScale) * this.splatCount,\r\n                                         this.splatCount * SplatBuffer.ColorComponentCount);\r\n        this.rotationArray = new FloatArray(this.splatBufferData,\r\n                                             (this.bytesPerPosition + this.bytesPerScale + this.bytesPerColor) * this.splatCount,\r\n                                              this.splatCount * SplatBuffer.RotationComponentCount);\r\n        this.bucketsBase = this.splatCount * this.bytesPerSplat;\r\n    }\r\n\r\n    fbf(f) {\r\n        if (this.compressionLevel === 0) {\r\n            return f;\r\n        } else {\r\n            return THREE.DataUtils.fromHalfFloat(f);\r\n        }\r\n    };\r\n\r\n    tbf(f) {\r\n        if (this.compressionLevel === 0) {\r\n            return f;\r\n        } else {\r\n            return THREE.DataUtils.toHalfFloat(f);\r\n        }\r\n    };\r\n\r\n    getHeaderBufferData() {\r\n        return this.headerBufferData;\r\n    }\r\n\r\n    getSplatBufferData() {\r\n        return this.splatBufferData;\r\n    }\r\n\r\n    getPosition(index, outPosition = new THREE.Vector3()) {\r\n        let bucket = [0, 0, 0];\r\n        const positionBase = index * SplatBuffer.PositionComponentCount;\r\n        if (this.compressionLevel > 0) {\r\n            const sf = this.compressionScaleFactor;\r\n            const sr = this.compressionScaleRange;\r\n            const bucketIndex = Math.floor(index / this.bucketSize);\r\n            bucket = new Float32Array(this.splatBufferData, this.bucketsBase + bucketIndex * this.bytesPerBucket, 3);\r\n            outPosition.x = (this.positionArray[positionBase] - sr) * sf + bucket[0];\r\n            outPosition.y = (this.positionArray[positionBase + 1] - sr) * sf + bucket[1];\r\n            outPosition.z = (this.positionArray[positionBase + 2] - sr) * sf + bucket[2];\r\n        } else {\r\n            outPosition.x = this.positionArray[positionBase];\r\n            outPosition.y = this.positionArray[positionBase + 1];\r\n            outPosition.z = this.positionArray[positionBase + 2];\r\n        }\r\n        return outPosition;\r\n    }\r\n\r\n    setPosition(index, position) {\r\n        let bucket = [0, 0, 0];\r\n        const positionBase = index * SplatBuffer.PositionComponentCount;\r\n        if (this.compressionLevel > 0) {\r\n            const sf = 1.0 / this.compressionScaleFactor;\r\n            const sr = this.compressionScaleRange;\r\n            const maxR = sr * 2 + 1;\r\n            const bucketIndex = Math.floor(index / this.bucketSize);\r\n            bucket = new Float32Array(this.splatBufferData, this.bucketsBase + bucketIndex * this.bytesPerBucket, 3);\r\n            this.positionArray[positionBase] = clamp(Math.round((position.x - bucket[0]) * sf) + sr, 0, maxR);\r\n            this.positionArray[positionBase + 1] = clamp(Math.round((position.y - bucket[1]) * sf) + sr, 0, maxR);\r\n            this.positionArray[positionBase + 2] = clamp(Math.round((position.z - bucket[2]) * sf) + sr, 0, maxR);\r\n        } else {\r\n            this.positionArray[positionBase] = position.x;\r\n            this.positionArray[positionBase + 1] = position.y;\r\n            this.positionArray[positionBase + 2] = position.z;\r\n        }\r\n    }\r\n\r\n    getScale(index, outScale = new THREE.Vector3()) {\r\n        const scaleBase = index * SplatBuffer.ScaleComponentCount;\r\n        outScale.set(fbf(this.scaleArray[scaleBase]), fbf(this.scaleArray[scaleBase + 1]), fbf(this.scaleArray[scaleBase + 2]));\r\n        return outScale;\r\n    }\r\n\r\n    setScale(index, scale) {\r\n        const scaleBase = index * SplatBuffer.ScaleComponentCount;\r\n        this.scaleArray[scaleBase] = tbf(scale.x);\r\n        this.scaleArray[scaleBase + 1] = tbf(scale.y);\r\n        this.scaleArray[scaleBase + 2] = tbf(scale.z);\r\n    }\r\n\r\n    getRotation(index, outRotation = new THREE.Quaternion()) {\r\n        const rotationBase = index * SplatBuffer.RotationComponentCount;\r\n        outRotation.set(fbf(this.rotationArray[rotationBase + 1]), fbf(this.rotationArray[rotationBase + 2]),\r\n                        fbf(this.rotationArray[rotationBase + 3]), fbf(this.rotationArray[rotationBase]));\r\n        return outRotation;\r\n    }\r\n\r\n    setRotation(index, rotation) {\r\n        const rotationBase = index * SplatBuffer.RotationComponentCount;\r\n        this.rotationArray[rotationBase] = tbf(rotation.w);\r\n        this.rotationArray[rotationBase + 1] = tbf(rotation.x);\r\n        this.rotationArray[rotationBase + 2] = tbf(rotation.y);\r\n        this.rotationArray[rotationBase + 3] = tbf(rotation.z);\r\n    }\r\n\r\n    getColor(index, outColor = new THREE.Vector4()) {\r\n        const colorBase = index * SplatBuffer.ColorComponentCount;\r\n        outColor.set(this.colorArray[colorBase], this.colorArray[colorBase + 1],\r\n                     this.colorArray[colorBase + 2], this.colorArray[colorBase + 3]);\r\n        return outColor;\r\n    }\r\n\r\n    setColor(index, color) {\r\n        const colorBase = index * SplatBuffer.ColorComponentCount;\r\n        this.colorArray[colorBase] = color.x;\r\n        this.colorArray[colorBase + 1] = color.y;\r\n        this.colorArray[colorBase + 2] = color.z;\r\n        this.colorArray[colorBase + 3] = color.w;\r\n    }\r\n\r\n    getSplatCount() {\r\n        return this.splatCount;\r\n    }\r\n\r\n    fillCovarianceArray(covarianceArray) {\r\n        const splatCount = this.splatCount;\r\n\r\n        const scale = new THREE.Vector3();\r\n        const rotation = new THREE.Quaternion();\r\n        const rotationMatrix = new THREE.Matrix3();\r\n        const scaleMatrix = new THREE.Matrix3();\r\n        const covarianceMatrix = new THREE.Matrix3();\r\n        const tempMatrix4 = new THREE.Matrix4();\r\n\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const scaleBase = i * SplatBuffer.ScaleComponentCount;\r\n            scale.set(fbf(this.scaleArray[scaleBase]), fbf(this.scaleArray[scaleBase + 1]), fbf(this.scaleArray[scaleBase + 2]));\r\n            tempMatrix4.makeScale(scale.x, scale.y, scale.z);\r\n            scaleMatrix.setFromMatrix4(tempMatrix4);\r\n\r\n            const rotationBase = i * SplatBuffer.RotationComponentCount;\r\n            rotation.set(fbf(this.rotationArray[rotationBase + 1]),\r\n                         fbf(this.rotationArray[rotationBase + 2]),\r\n                         fbf(this.rotationArray[rotationBase + 3]),\r\n                         fbf(this.rotationArray[rotationBase]));\r\n            tempMatrix4.makeRotationFromQuaternion(rotation);\r\n            rotationMatrix.setFromMatrix4(tempMatrix4);\r\n\r\n            covarianceMatrix.copy(rotationMatrix).multiply(scaleMatrix);\r\n            const M = covarianceMatrix.elements;\r\n            covarianceArray[SplatBuffer.CovarianceSizeFloats * i] = M[0] * M[0] + M[3] * M[3] + M[6] * M[6];\r\n            covarianceArray[SplatBuffer.CovarianceSizeFloats * i + 1] = M[0] * M[1] + M[3] * M[4] + M[6] * M[7];\r\n            covarianceArray[SplatBuffer.CovarianceSizeFloats * i + 2] = M[0] * M[2] + M[3] * M[5] + M[6] * M[8];\r\n            covarianceArray[SplatBuffer.CovarianceSizeFloats * i + 3] = M[1] * M[1] + M[4] * M[4] + M[7] * M[7];\r\n            covarianceArray[SplatBuffer.CovarianceSizeFloats * i + 4] = M[1] * M[2] + M[4] * M[5] + M[7] * M[8];\r\n            covarianceArray[SplatBuffer.CovarianceSizeFloats * i + 5] = M[2] * M[2] + M[5] * M[5] + M[8] * M[8];\r\n        }\r\n    }\r\n\r\n    fillPositionArray(outPositionArray) {\r\n        const splatCount = this.splatCount;\r\n        let bucket = [0, 0, 0];\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const positionBase = i * SplatBuffer.PositionComponentCount;\r\n            if (this.compressionLevel > 0) {\r\n                const bucketIndex = Math.floor(i / this.bucketSize);\r\n                bucket = new Float32Array(this.splatBufferData, this.bucketsBase + bucketIndex * this.bytesPerBucket, 3);\r\n                const sf = this.compressionScaleFactor;\r\n                const sr = this.compressionScaleRange;\r\n                outPositionArray[positionBase] = (this.positionArray[positionBase] - sr) * sf + bucket[0];\r\n                outPositionArray[positionBase + 1] = (this.positionArray[positionBase + 1] - sr) * sf + bucket[1];\r\n                outPositionArray[positionBase + 2] = (this.positionArray[positionBase + 2] - sr) * sf + bucket[2];\r\n            } else {\r\n                outPositionArray[positionBase] = this.positionArray[positionBase];\r\n                outPositionArray[positionBase + 1] = this.positionArray[positionBase + 1];\r\n                outPositionArray[positionBase + 2] = this.positionArray[positionBase + 2];\r\n            }\r\n        }\r\n    }\r\n\r\n    fillScaleArray(outScaleArray) {\r\n        const fbf = this.fbf.bind(this);\r\n        const splatCount = this.splatCount;\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const scaleBase = i * SplatBuffer.ScaleComponentCount;\r\n            outScaleArray[scaleBase] = fbf(this.scaleArray[scaleBase]);\r\n            outScaleArray[scaleBase + 1] = fbf(this.scaleArray[scaleBase + 1]);\r\n            outScaleArray[scaleBase + 2] = fbf(this.scaleArray[scaleBase + 2]);\r\n        }\r\n    }\r\n\r\n    fillRotationArray(outRotationArray) {\r\n        const fbf = this.fbf.bind(this);\r\n        const splatCount = this.splatCount;\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const rotationBase = i * SplatBuffer.RotationComponentCount;\r\n            outRotationArray[rotationBase] = fbf(this.rotationArray[rotationBase]);\r\n            outRotationArray[rotationBase + 1] = fbf(this.rotationArray[rotationBase + 1]);\r\n            outRotationArray[rotationBase + 2] = fbf(this.rotationArray[rotationBase + 2]);\r\n            outRotationArray[rotationBase + 3] = fbf(this.rotationArray[rotationBase + 3]);\r\n        }\r\n    }\r\n\r\n    fillColorArray(outColorArray) {\r\n        const splatCount = this.splatCount;\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const colorBase = i * SplatBuffer.ColorComponentCount;\r\n            outColorArray[colorBase] = this.colorArray[colorBase];\r\n            outColorArray[colorBase + 1] = this.colorArray[colorBase + 1];\r\n            outColorArray[colorBase + 2] = this.colorArray[colorBase + 2];\r\n            outColorArray[colorBase + 3] = this.colorArray[colorBase + 3];\r\n        }\r\n    }\r\n\r\n    swapVertices(indexA, indexB) {\r\n\r\n        this.getPosition(indexA, tempVector3A);\r\n        this.getPosition(indexB, tempVector3B);\r\n        this.setPosition(indexB, tempVector3A);\r\n        this.setPosition(indexA, tempVector3B);\r\n\r\n        this.getScale(indexA, tempVector3A);\r\n        this.getScale(indexB, tempVector3B);\r\n        this.setScale(indexB, tempVector3A);\r\n        this.setScale(indexA, tempVector3B);\r\n\r\n        this.getRotation(indexA, tempQuaternion4A);\r\n        this.getRotation(indexB, tempQuaternion4B);\r\n        this.setRotation(indexB, tempQuaternion4A);\r\n        this.setRotation(indexA, tempQuaternion4B);\r\n\r\n        this.getColor(indexA, tempVector4A);\r\n        this.getColor(indexB, tempVector4B);\r\n        this.setColor(indexB, tempVector4A);\r\n        this.setColor(indexA, tempVector4B);\r\n\r\n    }\r\n\r\n}\r\n","export const floatToHalf = function() {\r\n\r\n    const floatView = new Float32Array(1);\r\n    const int32View = new Int32Array(floatView.buffer);\r\n\r\n    return function(val) {\r\n        floatView[0] = val;\r\n        const x = int32View[0];\r\n\r\n        let bits = (x >> 16) & 0x8000;\r\n        let m = (x >> 12) & 0x07ff;\r\n        const e = (x >> 23) & 0xff;\r\n\r\n        if (e < 103) return bits;\r\n\r\n        if (e > 142) {\r\n            bits |= 0x7c00;\r\n            bits |= ((e == 255) ? 0 : 1) && (x & 0x007fffff);\r\n            return bits;\r\n        }\r\n\r\n        if (e < 113) {\r\n            m |= 0x0800;\r\n            bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);\r\n            return bits;\r\n        }\r\n\r\n        bits |= (( e - 112) << 10) | (m >> 1);\r\n        bits += m & 1;\r\n        return bits;\r\n    };\r\n\r\n}();\r\n\r\nexport const uintEncodedFloat = function() {\r\n\r\n    const floatView = new Float32Array(1);\r\n    const int32View = new Int32Array(floatView.buffer);\r\n\r\n    return function(f) {\r\n        floatView[0] = f;\r\n        return int32View[0];\r\n    };\r\n\r\n}();\r\n\r\nexport const rgbaToInteger = function(r, g, b, a) {\r\n    return r + (g << 8) + (b << 16) + (a << 24);\r\n};\r\n\r\nexport const fetchWithProgress = function(path, onProgress) {\r\n\r\n    return new Promise((resolve, reject) => {\r\n        fetch(path)\r\n        .then(async (data) => {\r\n            const reader = data.body.getReader();\r\n            let bytesDownloaded = 0;\r\n            let _fileSize = data.headers.get('Content-Length');\r\n            let fileSize = _fileSize ? parseInt(_fileSize) : undefined;\r\n\r\n            const chunks = [];\r\n\r\n            while (true) {\r\n                try {\r\n                    const { value: chunk, done } = await reader.read();\r\n                    if (done) {\r\n                        if (onProgress) {\r\n                            onProgress(100, '100%', chunk);\r\n                        }\r\n                        const buffer = new Blob(chunks).arrayBuffer();\r\n                        resolve(buffer);\r\n                        break;\r\n                    }\r\n                    bytesDownloaded += chunk.length;\r\n                    let percent;\r\n                    let percentLabel;\r\n                    if (fileSize !== undefined) {\r\n                        percent = bytesDownloaded / fileSize * 100;\r\n                        percentLabel = `${percent.toFixed(2)}%`;\r\n                    }\r\n                    chunks.push(chunk);\r\n                    if (onProgress) {\r\n                        onProgress(percent, percentLabel, chunk);\r\n                    }\r\n                } catch (error) {\r\n                    reject(error);\r\n                    break;\r\n                }\r\n            }\r\n        });\r\n    });\r\n\r\n};\r\n\r\nexport const clamp = function(val, min, max) {\r\n    return Math.max(Math.min(val, max), min);\r\n};\r\n\r\nexport const getCurrentTime = function() {\r\n    return performance.now() / 1000;\r\n};\r\n","import { SplatBuffer } from './SplatBuffer.js';\r\nimport { clamp } from './Util.js';\r\nimport * as THREE from 'three';\r\n\r\nconst SplatBufferBucketSize = 256;\r\nconst SplatBufferBucketBlockSize = 5.0;\r\n\r\nexport class PlyParser {\r\n\r\n    constructor(plyBuffer) {\r\n        this.plyBuffer = plyBuffer;\r\n    }\r\n\r\n    decodeHeader(plyBuffer) {\r\n        const decoder = new TextDecoder();\r\n        let headerOffset = 0;\r\n        let headerText = '';\r\n\r\n        console.log('.PLY size: ' + plyBuffer.byteLength + ' bytes');\r\n\r\n        const readChunkSize = 100;\r\n\r\n        while (true) {\r\n            if (headerOffset + readChunkSize >= plyBuffer.byteLength) {\r\n                throw new Error('End of file reached while searching for end of header');\r\n            }\r\n            const headerChunk = new Uint8Array(plyBuffer, headerOffset, readChunkSize);\r\n            headerText += decoder.decode(headerChunk);\r\n            headerOffset += readChunkSize;\r\n\r\n            const endHeaderTestChunk = new Uint8Array(plyBuffer, Math.max(0, headerOffset - readChunkSize * 2), readChunkSize * 2);\r\n            const endHeaderTestText = decoder.decode(endHeaderTestChunk);\r\n            if (endHeaderTestText.includes('end_header')) {\r\n                break;\r\n            }\r\n        }\r\n\r\n        const headerLines = headerText.split('\\n');\r\n\r\n        let splatCount = 0;\r\n        let propertyTypes = {};\r\n\r\n        for (let i = 0; i < headerLines.length; i++) {\r\n            const line = headerLines[i].trim();\r\n            if (line.startsWith('element vertex')) {\r\n                const splatCountMatch = line.match(/\\d+/);\r\n                if (splatCountMatch) {\r\n                    splatCount = parseInt(splatCountMatch[0]);\r\n                }\r\n            } else if (line.startsWith('property')) {\r\n                const propertyMatch = line.match(/(\\w+)\\s+(\\w+)\\s+(\\w+)/);\r\n                if (propertyMatch) {\r\n                    const propertyType = propertyMatch[2];\r\n                    const propertyName = propertyMatch[3];\r\n                    propertyTypes[propertyName] = propertyType;\r\n                }\r\n            } else if (line === 'end_header') {\r\n                break;\r\n            }\r\n        }\r\n\r\n        const vertexByteOffset = headerText.indexOf('end_header') + 'end_header'.length + 1;\r\n        const vertexData = new DataView(plyBuffer, vertexByteOffset);\r\n\r\n        return {\r\n            'splatCount': splatCount,\r\n            'propertyTypes': propertyTypes,\r\n            'vertexData': vertexData,\r\n            'headerOffset': headerOffset\r\n        };\r\n    }\r\n\r\n    readRawVertexFast(vertexData, offset, fieldOffsets, propertiesToRead, propertyTypes, outVertex) {\r\n        let rawVertex = outVertex || {};\r\n        for (let property of propertiesToRead) {\r\n            const propertyType = propertyTypes[property];\r\n            if (propertyType === 'float') {\r\n                rawVertex[property] = vertexData.getFloat32(offset + fieldOffsets[property], true);\r\n            } else if (propertyType === 'uchar') {\r\n                rawVertex[property] = vertexData.getUint8(offset + fieldOffsets[property]) / 255.0;\r\n            }\r\n        }\r\n    }\r\n\r\n    parseToSplatBuffer(compressionLevel = 0, minimumAlpha = 1) {\r\n\r\n        const startTime = performance.now();\r\n\r\n        console.log('Parsing PLY to SPLAT...');\r\n\r\n        const {splatCount, propertyTypes, vertexData} = this.decodeHeader(this.plyBuffer);\r\n\r\n        // figure out the SH degree from the number of coefficients\r\n        let nRestCoeffs = 0;\r\n        for (const propertyName in propertyTypes) {\r\n            if (propertyName.startsWith('f_rest_')) {\r\n                nRestCoeffs += 1;\r\n            }\r\n        }\r\n        const nCoeffsPerColor = nRestCoeffs / 3;\r\n\r\n        // TODO: Eventually properly support multiple degree spherical harmonics\r\n        // const sphericalHarmonicsDegree = Math.sqrt(nCoeffsPerColor + 1) - 1;\r\n        const sphericalHarmonicsDegree = 0;\r\n\r\n        console.log('Detected degree', sphericalHarmonicsDegree, 'with ', nCoeffsPerColor, 'coefficients per color');\r\n\r\n        // figure out the order in which spherical harmonics should be read\r\n        const shFeatureOrder = [];\r\n        for (let rgb = 0; rgb < 3; ++rgb) {\r\n            shFeatureOrder.push(`f_dc_${rgb}`);\r\n        }\r\n        for (let i = 0; i < nCoeffsPerColor; ++i) {\r\n            for (let rgb = 0; rgb < 3; ++rgb) {\r\n                shFeatureOrder.push(`f_rest_${rgb * nCoeffsPerColor + i}`);\r\n            }\r\n        }\r\n\r\n        let plyRowSize = 0;\r\n        let fieldOffsets = {};\r\n        const fieldSize = {\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        };\r\n        for (let fieldName in propertyTypes) {\r\n            if (propertyTypes.hasOwnProperty(fieldName)) {\r\n                const type = propertyTypes[fieldName];\r\n                fieldOffsets[fieldName] = plyRowSize;\r\n                plyRowSize += fieldSize[type];\r\n            }\r\n        }\r\n\r\n        let rawVertex = {};\r\n\r\n        const propertiesToRead = ['scale_0', 'scale_1', 'scale_2', 'rot_0', 'rot_1', 'rot_2', 'rot_3',\r\n                                  'x', 'y', 'z', 'f_dc_0', 'f_dc_1', 'f_dc_2', 'opacity'];\r\n\r\n        const validVertexes = [];\r\n        // dummy vertex used for invalid vertexes\r\n        const vertexZero = {};\r\n        for (let propertyToRead of propertiesToRead) vertexZero[propertyToRead] = 0;\r\n        validVertexes.push(vertexZero);\r\n        for (let row = 0; row < splatCount; row++) {\r\n            this.readRawVertexFast(vertexData, row * plyRowSize, fieldOffsets, propertiesToRead, propertyTypes, rawVertex);\r\n            let alpha;\r\n            if (propertyTypes['opacity']) {\r\n                alpha = (1 / (1 + Math.exp(-rawVertex.opacity))) * 255;\r\n            } else {\r\n                alpha = 255;\r\n            }\r\n            if (alpha > minimumAlpha) {\r\n                const newVertex = {};\r\n                for (let propertyToRead of propertiesToRead) newVertex[propertyToRead] = rawVertex[propertyToRead];\r\n                validVertexes.push(newVertex);\r\n            }\r\n        }\r\n\r\n        console.log('Total valid splats: ', validVertexes.length, 'out of', splatCount);\r\n\r\n        const positionsForBucketCalcs = [];\r\n        for (let row = 0; row < validVertexes.length; row++) {\r\n            rawVertex = validVertexes[row];\r\n            positionsForBucketCalcs.push([rawVertex.x, rawVertex.y, rawVertex.z]);\r\n        }\r\n        const buckets = this.computeBuckets(positionsForBucketCalcs);\r\n\r\n        const paddedSplatCount = buckets.length * SplatBufferBucketSize;\r\n        const headerSize = SplatBuffer.HeaderSizeBytes;\r\n        const header = new Uint8Array(new ArrayBuffer(headerSize));\r\n        header[3] = compressionLevel;\r\n        (new Uint32Array(header.buffer, 4, 1))[0] = paddedSplatCount;\r\n\r\n        let bytesPerPosition = SplatBuffer.CompressionLevels[compressionLevel].BytesPerPosition;\r\n        let bytesPerScale = SplatBuffer.CompressionLevels[compressionLevel].BytesPerScale;\r\n        let bytesPerColor = SplatBuffer.CompressionLevels[compressionLevel].BytesPerColor;\r\n        let bytesPerRotation = SplatBuffer.CompressionLevels[compressionLevel].BytesPerRotation;\r\n        const positionBuffer = new ArrayBuffer(bytesPerPosition * paddedSplatCount);\r\n        const scaleBuffer = new ArrayBuffer(bytesPerScale * paddedSplatCount);\r\n        const colorBuffer = new ArrayBuffer(bytesPerColor * paddedSplatCount);\r\n        const rotationBuffer = new ArrayBuffer(bytesPerRotation * paddedSplatCount);\r\n\r\n        const blockHalfSize = SplatBufferBucketBlockSize / 2.0;\r\n        const compressionScaleRange = SplatBuffer.CompressionLevels[compressionLevel].ScaleRange;\r\n        const compressionScaleFactor = compressionScaleRange / blockHalfSize;\r\n        const doubleCompressionScaleRange = compressionScaleRange * 2 + 1;\r\n\r\n        const bucketCenter = new THREE.Vector3();\r\n        const bucketCenterDelta = new THREE.Vector3();\r\n        let outSplatIndex = 0;\r\n        for (let b = 0; b < buckets.length; b++) {\r\n            const bucket = buckets[b];\r\n            bucketCenter.fromArray(bucket.center);\r\n            for (let i = 0; i < bucket.splats.length; i++) {\r\n                let row = bucket.splats[i];\r\n                let invalidSplat = false;\r\n                if (row === 0) {\r\n                    invalidSplat = true;\r\n                }\r\n                rawVertex = validVertexes[row];\r\n\r\n                if (compressionLevel === 0) {\r\n                    const position = new Float32Array(positionBuffer, outSplatIndex * bytesPerPosition, 3);\r\n                    const scales = new Float32Array(scaleBuffer, outSplatIndex * bytesPerScale, 3);\r\n                    const rot = new Float32Array(rotationBuffer, outSplatIndex * bytesPerRotation, 4);\r\n                    if (propertyTypes['scale_0']) {\r\n                        const quat = new THREE.Quaternion(rawVertex.rot_1, rawVertex.rot_2, rawVertex.rot_3, rawVertex.rot_0);\r\n                        quat.normalize();\r\n                        rot.set([quat.w, quat.x, quat.y, quat.z]);\r\n                        scales.set([Math.exp(rawVertex.scale_0), Math.exp(rawVertex.scale_1), Math.exp(rawVertex.scale_2)]);\r\n                    } else {\r\n                        scales.set([0.01, 0.01, 0.01]);\r\n                        rot.set([1.0, 0.0, 0.0, 0.0]);\r\n                    }\r\n                    position.set([rawVertex.x, rawVertex.y, rawVertex.z]);\r\n                } else {\r\n                    const position = new Uint16Array(positionBuffer, outSplatIndex * bytesPerPosition, 3);\r\n                    const scales = new Uint16Array(scaleBuffer, outSplatIndex * bytesPerScale, 3);\r\n                    const rot = new Uint16Array(rotationBuffer, outSplatIndex * bytesPerRotation, 4);\r\n                    const thf = THREE.DataUtils.toHalfFloat.bind(THREE.DataUtils);\r\n                    if (propertyTypes['scale_0']) {\r\n                        const quat = new THREE.Quaternion(rawVertex.rot_1, rawVertex.rot_2, rawVertex.rot_3, rawVertex.rot_0);\r\n                        quat.normalize();\r\n                        rot.set([thf(quat.w), thf(quat.x), thf(quat.y), thf(quat.z)]);\r\n                        scales.set([thf(Math.exp(rawVertex.scale_0)), thf(Math.exp(rawVertex.scale_1)), thf(Math.exp(rawVertex.scale_2))]);\r\n                    } else {\r\n                        scales.set([thf(0.01), thf(0.01), thf(0.01)]);\r\n                        rot.set([thf(1.), 0, 0, 0]);\r\n                    }\r\n                    bucketCenterDelta.set(rawVertex.x, rawVertex.y, rawVertex.z).sub(bucketCenter);\r\n                    bucketCenterDelta.x = Math.round(bucketCenterDelta.x * compressionScaleFactor) + compressionScaleRange;\r\n                    bucketCenterDelta.x = clamp(bucketCenterDelta.x, 0, doubleCompressionScaleRange);\r\n                    bucketCenterDelta.y = Math.round(bucketCenterDelta.y * compressionScaleFactor) + compressionScaleRange;\r\n                    bucketCenterDelta.y = clamp(bucketCenterDelta.y, 0, doubleCompressionScaleRange);\r\n                    bucketCenterDelta.z = Math.round(bucketCenterDelta.z * compressionScaleFactor) + compressionScaleRange;\r\n                    bucketCenterDelta.z = clamp(bucketCenterDelta.z, 0, doubleCompressionScaleRange);\r\n                    position.set([bucketCenterDelta.x, bucketCenterDelta.y, bucketCenterDelta.z]);\r\n                }\r\n\r\n                const rgba = new Uint8ClampedArray(colorBuffer, outSplatIndex * bytesPerColor, 4);\r\n                if (invalidSplat) {\r\n                    rgba[0] = 255;\r\n                    rgba[1] = 0;\r\n                    rgba[2] = 0;\r\n                    rgba[3] = 0;\r\n                } else {\r\n                    if (propertyTypes['f_dc_0']) {\r\n                        const SH_C0 = 0.28209479177387814;\r\n                        rgba.set([(0.5 + SH_C0 * rawVertex.f_dc_0) * 255,\r\n                                  (0.5 + SH_C0 * rawVertex.f_dc_1) * 255,\r\n                                  (0.5 + SH_C0 * rawVertex.f_dc_2) * 255]);\r\n                    } else {\r\n                        rgba.set([255, 0, 0]);\r\n                    }\r\n                    if (propertyTypes['opacity']) {\r\n                        rgba[3] = (1 / (1 + Math.exp(-rawVertex.opacity))) * 255;\r\n                    } else {\r\n                        rgba[3] = 255;\r\n                    }\r\n                }\r\n\r\n                outSplatIndex++;\r\n            }\r\n        }\r\n\r\n        const bytesPerBucket = 12;\r\n        const bucketsSize = bytesPerBucket * buckets.length;\r\n        const splatDataBufferSize = positionBuffer.byteLength + scaleBuffer.byteLength +\r\n                                    colorBuffer.byteLength + rotationBuffer.byteLength;\r\n\r\n        const headerArrayUint32 = new Uint32Array(header.buffer);\r\n        const headerArrayFloat32 = new Float32Array(header.buffer);\r\n        let unifiedBufferSize = headerSize + splatDataBufferSize;\r\n        if (compressionLevel > 0) {\r\n            unifiedBufferSize += bucketsSize;\r\n            headerArrayUint32[2] = SplatBufferBucketSize;\r\n            headerArrayUint32[3] = buckets.length;\r\n            headerArrayFloat32[4] = SplatBufferBucketBlockSize;\r\n            headerArrayUint32[5] = bytesPerBucket;\r\n            headerArrayUint32[6] = SplatBuffer.CompressionLevels[compressionLevel].ScaleRange;\r\n        }\r\n\r\n        const unifiedBuffer = new ArrayBuffer(unifiedBufferSize);\r\n        new Uint8Array(unifiedBuffer, 0, headerSize).set(header);\r\n        new Uint8Array(unifiedBuffer, headerSize, positionBuffer.byteLength).set(new Uint8Array(positionBuffer));\r\n        new Uint8Array(unifiedBuffer, headerSize + positionBuffer.byteLength, scaleBuffer.byteLength).set(new Uint8Array(scaleBuffer));\r\n        new Uint8Array(unifiedBuffer, headerSize + positionBuffer.byteLength + scaleBuffer.byteLength,\r\n                       colorBuffer.byteLength).set(new Uint8Array(colorBuffer));\r\n        new Uint8Array(unifiedBuffer, headerSize + positionBuffer.byteLength + scaleBuffer.byteLength + colorBuffer.byteLength,\r\n                       rotationBuffer.byteLength).set(new Uint8Array(rotationBuffer));\r\n\r\n        if (compressionLevel > 0) {\r\n            const bucketArray = new Float32Array(unifiedBuffer, headerSize + splatDataBufferSize, buckets.length * 3);\r\n            for (let i = 0; i < buckets.length; i++) {\r\n                const bucket = buckets[i];\r\n                const base = i * 3;\r\n                bucketArray[base] = bucket.center[0];\r\n                bucketArray[base + 1] = bucket.center[1];\r\n                bucketArray[base + 2] = bucket.center[2];\r\n            }\r\n        }\r\n\r\n        const splatBuffer = new SplatBuffer(unifiedBuffer);\r\n\r\n        const endTime = performance.now();\r\n\r\n        console.log('Parsing PLY to SPLAT complete!');\r\n        console.log('Total time: ', (endTime - startTime).toFixed(2) + ' ms');\r\n\r\n        return splatBuffer;\r\n    }\r\n\r\n    computeBuckets(positions) {\r\n        const blockSize = SplatBufferBucketBlockSize;\r\n        const halfBlockSize = blockSize / 2.0;\r\n        const splatCount = positions.length;\r\n\r\n        const min = new THREE.Vector3();\r\n        const max = new THREE.Vector3();\r\n\r\n        // ignore the first splat since it's the invalid designator\r\n        for (let i = 1; i < splatCount; i++) {\r\n            const position = positions[i];\r\n            if (i === 0 || position[0] < min.x) min.x = position[0];\r\n            if (i === 0 || position[0] > max.x) max.x = position[0];\r\n            if (i === 0 || position[1] < min.y) min.y = position[1];\r\n            if (i === 0 || position[1] > max.y) max.y = position[1];\r\n            if (i === 0 || position[2] < min.z) min.z = position[2];\r\n            if (i === 0 || position[2] > max.z) max.z = position[2];\r\n        }\r\n\r\n        const dimensions = new THREE.Vector3().copy(max).sub(min);\r\n        const yBlocks = Math.ceil(dimensions.y / blockSize);\r\n        const zBlocks = Math.ceil(dimensions.z / blockSize);\r\n\r\n        const blockCenter = new THREE.Vector3();\r\n        const fullBuckets = [];\r\n        const partiallyFullBuckets = {};\r\n\r\n        // ignore the first splat since it's the invalid designator\r\n        for (let i = 1; i < splatCount; i++) {\r\n            const position = positions[i];\r\n            const xBlock = Math.ceil((position[0] - min.x) / blockSize);\r\n            const yBlock = Math.ceil((position[1] - min.y) / blockSize);\r\n            const zBlock = Math.ceil((position[2] - min.z) / blockSize);\r\n\r\n            blockCenter.x = (xBlock - 1) * blockSize + min.x + halfBlockSize;\r\n            blockCenter.y = (yBlock - 1) * blockSize + min.y + halfBlockSize;\r\n            blockCenter.z = (zBlock - 1) * blockSize + min.z + halfBlockSize;\r\n\r\n            const bucketId = xBlock * (yBlocks * zBlocks) + yBlock * zBlocks + zBlock;\r\n            let bucket = partiallyFullBuckets[bucketId];\r\n            if (!bucket) {\r\n                partiallyFullBuckets[bucketId] = bucket = {\r\n                    'splats': [],\r\n                    'center': blockCenter.toArray()\r\n                };\r\n            }\r\n\r\n            bucket.splats.push(i);\r\n            if (bucket.splats.length >= SplatBufferBucketSize) {\r\n                fullBuckets.push(bucket);\r\n                partiallyFullBuckets[bucketId] = null;\r\n            }\r\n        }\r\n\r\n        // fill partially full buckets with invalid splats (splat 0)\r\n        // to get them up to SplatBufferBucketSize\r\n        for (let bucketId in partiallyFullBuckets) {\r\n            if (partiallyFullBuckets.hasOwnProperty(bucketId)) {\r\n                const bucket = partiallyFullBuckets[bucketId];\r\n                if (bucket) {\r\n                    while (bucket.splats.length < SplatBufferBucketSize) {\r\n                        bucket.splats.push(0);\r\n                    }\r\n                    fullBuckets.push(bucket);\r\n                }\r\n            }\r\n        }\r\n\r\n        return fullBuckets;\r\n    }\r\n}\r\n","import { PlyParser } from './PlyParser.js';\r\nimport { fetchWithProgress } from './Util.js';\r\n\r\nexport class PlyLoader {\r\n\r\n    constructor() {\r\n        this.splatBuffer = null;\r\n    }\r\n\r\n    fetchFile(fileName, onProgress) {\r\n        return new Promise((resolve, reject) => {\r\n            fetchWithProgress(fileName, onProgress)\r\n            .then((data) => {\r\n                resolve(data);\r\n            })\r\n            .catch((err) => {\r\n                reject(err);\r\n            });\r\n        });\r\n    }\r\n\r\n    loadFromURL(fileName, compressionLevel = 0, minimumAlpha = 1) {\r\n        return new Promise((resolve, reject) => {\r\n            const loadPromise = this.fetchFile(fileName);\r\n            loadPromise\r\n            .then((plyFileData) => {\r\n                const plyParser = new PlyParser(plyFileData);\r\n                const splatBuffer = plyParser.parseToSplatBuffer(compressionLevel, minimumAlpha);\r\n                this.splatBuffer = splatBuffer;\r\n                resolve(splatBuffer);\r\n            })\r\n            .catch((err) => {\r\n                reject(err);\r\n            });\r\n        });\r\n    }\r\n\r\n}\r\n","import { SplatBuffer } from './SplatBuffer.js';\r\nimport { fetchWithProgress } from './Util.js';\r\n\r\nexport class SplatLoader {\r\n\r\n    constructor(splatBuffer = null) {\r\n        this.splatBuffer = splatBuffer;\r\n        this.downLoadLink = null;\r\n    }\r\n\r\n    loadFromURL(fileName, onProgress) {\r\n        return new Promise((resolve, reject) => {\r\n            fetchWithProgress(fileName, onProgress)\r\n            .then((bufferData) => {\r\n                const splatBuffer = new SplatBuffer(bufferData);\r\n                resolve(splatBuffer);\r\n            })\r\n            .catch((err) => {\r\n                reject(err);\r\n            });\r\n        });\r\n    }\r\n\r\n    setFromBuffer(splatBuffer) {\r\n        this.splatBuffer = splatBuffer;\r\n    }\r\n\r\n    downloadFile(fileName) {\r\n        const headerData = new Uint8Array(this.splatBuffer.getHeaderBufferData());\r\n        const splatData = new Uint8Array(this.splatBuffer.getSplatBufferData());\r\n        const blob = new Blob([headerData.buffer, splatData.buffer], {\r\n            type: 'application/octet-stream',\r\n        });\r\n\r\n        if (!this.downLoadLink) {\r\n            this.downLoadLink = document.createElement('a');\r\n            document.body.appendChild(this.downLoadLink);\r\n        }\r\n        this.downLoadLink.download = fileName;\r\n        this.downLoadLink.href = URL.createObjectURL(blob);\r\n        this.downLoadLink.click();\r\n    }\r\n\r\n}\r\n","import {\n    EventDispatcher,\n    MOUSE,\n    Quaternion,\n    Spherical,\n    TOUCH,\n    Vector2,\n    Vector3,\n    Plane,\n    Ray,\n    MathUtils\n} from 'three';\n\n// OrbitControls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n//\n//    Orbit - left mouse / touch: one-finger move\n//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n//    Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move\n\nconst _changeEvent = { type: 'change' };\nconst _startEvent = { type: 'start' };\nconst _endEvent = { type: 'end' };\nconst _ray = new Ray();\nconst _plane = new Plane();\nconst TILT_LIMIT = Math.cos( 70 * MathUtils.DEG2RAD );\n\nclass OrbitControls extends EventDispatcher {\n\n    constructor( object, domElement ) {\n\n        super();\n\n        this.object = object;\n        this.domElement = domElement;\n        this.domElement.style.touchAction = 'none'; // disable touch scroll\n\n        // Set to false to disable this control\n        this.enabled = true;\n\n        // \"target\" sets the location of focus, where the object orbits around\n        this.target = new Vector3();\n\n        // How far you can dolly in and out ( PerspectiveCamera only )\n        this.minDistance = 0;\n        this.maxDistance = Infinity;\n\n        // How far you can zoom in and out ( OrthographicCamera only )\n        this.minZoom = 0;\n        this.maxZoom = Infinity;\n\n        // How far you can orbit vertically, upper and lower limits.\n        // Range is 0 to Math.PI radians.\n        this.minPolarAngle = 0; // radians\n        this.maxPolarAngle = Math.PI; // radians\n\n        // How far you can orbit horizontally, upper and lower limits.\n        // If set, the interval [min, max] must be a sub-interval of [- 2 PI, 2 PI], with ( max - min < 2 PI )\n        this.minAzimuthAngle = - Infinity; // radians\n        this.maxAzimuthAngle = Infinity; // radians\n\n        // Set to true to enable damping (inertia)\n        // If damping is enabled, you must call controls.update() in your animation loop\n        this.enableDamping = false;\n        this.dampingFactor = 0.05;\n\n        // This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n        // Set to false to disable zooming\n        this.enableZoom = true;\n        this.zoomSpeed = 1.0;\n\n        // Set to false to disable rotating\n        this.enableRotate = true;\n        this.rotateSpeed = 1.0;\n\n        // Set to false to disable panning\n        this.enablePan = true;\n        this.panSpeed = 1.0;\n        this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up\n        this.keyPanSpeed = 7.0; // pixels moved per arrow key push\n        this.zoomToCursor = false;\n\n        // Set to true to automatically rotate around the target\n        // If auto-rotate is enabled, you must call controls.update() in your animation loop\n        this.autoRotate = false;\n        this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60\n\n        // The four arrow keys\n        this.keys = { LEFT: 'KeyA', UP: 'KeyW', RIGHT: 'KeyD', BOTTOM: 'KeyS' };\n\n        // Mouse buttons\n        this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\n\n        // Touch fingers\n        this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\n\n        // for reset\n        this.target0 = this.target.clone();\n        this.position0 = this.object.position.clone();\n        this.zoom0 = this.object.zoom;\n\n        // the target DOM element for key events\n        this._domElementKeyEvents = null;\n\n        //\n        // public methods\n        //\n\n        this.getPolarAngle = function() {\n\n            return spherical.phi;\n\n        };\n\n        this.getAzimuthalAngle = function() {\n\n            return spherical.theta;\n\n        };\n\n        this.getDistance = function() {\n\n            return this.object.position.distanceTo( this.target );\n\n        };\n\n        this.listenToKeyEvents = function( domElement ) {\n\n            domElement.addEventListener( 'keydown', onKeyDown );\n            this._domElementKeyEvents = domElement;\n\n        };\n\n        this.stopListenToKeyEvents = function() {\n\n            this._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );\n            this._domElementKeyEvents = null;\n\n        };\n\n        this.saveState = function() {\n\n            scope.target0.copy( scope.target );\n            scope.position0.copy( scope.object.position );\n            scope.zoom0 = scope.object.zoom;\n\n        };\n\n        this.reset = function() {\n\n            scope.target.copy( scope.target0 );\n            scope.object.position.copy( scope.position0 );\n            scope.object.zoom = scope.zoom0;\n\n            scope.object.updateProjectionMatrix();\n            scope.dispatchEvent( _changeEvent );\n\n            scope.update();\n\n            state = STATE.NONE;\n\n        };\n\n        // this method is exposed, but perhaps it would be better if we can make it private...\n        this.update = function() {\n\n            const offset = new Vector3();\n\n            // so camera.up is the orbit axis\n            const quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n            const quatInverse = quat.clone().invert();\n\n            const lastPosition = new Vector3();\n            const lastQuaternion = new Quaternion();\n            const lastTargetPosition = new Vector3();\n\n            const twoPI = 2 * Math.PI;\n\n            return function update() {\n\n                quat.setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n                quatInverse.copy(quat).invert();\n\n                const position = scope.object.position;\n\n                offset.copy( position ).sub( scope.target );\n\n                // rotate offset to \"y-axis-is-up\" space\n                offset.applyQuaternion( quat );\n\n                // angle from z-axis around y-axis\n                spherical.setFromVector3( offset );\n\n                if ( scope.autoRotate && state === STATE.NONE ) {\n\n                    rotateLeft( getAutoRotationAngle() );\n\n                }\n\n                if ( scope.enableDamping ) {\n\n                    spherical.theta += sphericalDelta.theta * scope.dampingFactor;\n                    spherical.phi += sphericalDelta.phi * scope.dampingFactor;\n\n                } else {\n\n                    spherical.theta += sphericalDelta.theta;\n                    spherical.phi += sphericalDelta.phi;\n\n                }\n\n                // restrict theta to be between desired limits\n\n                let min = scope.minAzimuthAngle;\n                let max = scope.maxAzimuthAngle;\n\n                if ( isFinite( min ) && isFinite( max ) ) {\n\n                    if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;\n\n                    if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;\n\n                    if ( min <= max ) {\n\n                        spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );\n\n                    } else {\n\n                        spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?\n                            Math.max( min, spherical.theta ) :\n                            Math.min( max, spherical.theta );\n\n                    }\n\n                }\n\n                // restrict phi to be between desired limits\n                spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\n\n                spherical.makeSafe();\n\n\n                // move target to panned location\n\n                if ( scope.enableDamping === true ) {\n\n                    scope.target.addScaledVector( panOffset, scope.dampingFactor );\n\n                } else {\n\n                    scope.target.add( panOffset );\n\n                }\n\n                // adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera\n                // we adjust zoom later in these cases\n                if ( scope.zoomToCursor && performCursorZoom || scope.object.isOrthographicCamera ) {\n\n                    spherical.radius = clampDistance( spherical.radius );\n\n                } else {\n\n                    spherical.radius = clampDistance( spherical.radius * scale );\n\n                }\n\n\n                offset.setFromSpherical( spherical );\n\n                // rotate offset back to \"camera-up-vector-is-up\" space\n                offset.applyQuaternion( quatInverse );\n\n                position.copy( scope.target ).add( offset );\n\n                scope.object.lookAt( scope.target );\n\n                if ( scope.enableDamping === true ) {\n\n                    sphericalDelta.theta *= ( 1 - scope.dampingFactor );\n                    sphericalDelta.phi *= ( 1 - scope.dampingFactor );\n\n                    panOffset.multiplyScalar( 1 - scope.dampingFactor );\n\n                } else {\n\n                    sphericalDelta.set( 0, 0, 0 );\n\n                    panOffset.set( 0, 0, 0 );\n\n                }\n\n                // adjust camera position\n                let zoomChanged = false;\n                if ( scope.zoomToCursor && performCursorZoom ) {\n\n                    let newRadius = null;\n                    if ( scope.object.isPerspectiveCamera ) {\n\n                        // move the camera down the pointer ray\n                        // this method avoids floating point error\n                        const prevRadius = offset.length();\n                        newRadius = clampDistance( prevRadius * scale );\n\n                        const radiusDelta = prevRadius - newRadius;\n                        scope.object.position.addScaledVector( dollyDirection, radiusDelta );\n                        scope.object.updateMatrixWorld();\n\n                    } else if ( scope.object.isOrthographicCamera ) {\n\n                        // adjust the ortho camera position based on zoom changes\n                        const mouseBefore = new Vector3( mouse.x, mouse.y, 0 );\n                        mouseBefore.unproject( scope.object );\n\n                        scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );\n                        scope.object.updateProjectionMatrix();\n                        zoomChanged = true;\n\n                        const mouseAfter = new Vector3( mouse.x, mouse.y, 0 );\n                        mouseAfter.unproject( scope.object );\n\n                        scope.object.position.sub( mouseAfter ).add( mouseBefore );\n                        scope.object.updateMatrixWorld();\n\n                        newRadius = offset.length();\n\n                    } else {\n\n                        console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );\n                        scope.zoomToCursor = false;\n\n                    }\n\n                    // handle the placement of the target\n                    if ( newRadius !== null ) {\n\n                        if ( this.screenSpacePanning ) {\n\n                            // position the orbit target in front of the new camera position\n                            scope.target.set( 0, 0, - 1 )\n                                .transformDirection( scope.object.matrix )\n                                .multiplyScalar( newRadius )\n                                .add( scope.object.position );\n\n                        } else {\n\n                            // get the ray and translation plane to compute target\n                            _ray.origin.copy( scope.object.position );\n                            _ray.direction.set( 0, 0, - 1 ).transformDirection( scope.object.matrix );\n\n                            // if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid\n                            // extremely large values\n                            if ( Math.abs( scope.object.up.dot( _ray.direction ) ) < TILT_LIMIT ) {\n\n                                object.lookAt( scope.target );\n\n                            } else {\n\n                                _plane.setFromNormalAndCoplanarPoint( scope.object.up, scope.target );\n                                _ray.intersectPlane( _plane, scope.target );\n\n                            }\n\n                        }\n\n                    }\n\n                } else if ( scope.object.isOrthographicCamera ) {\n\n                    scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );\n                    scope.object.updateProjectionMatrix();\n                    zoomChanged = true;\n\n                }\n\n                scale = 1;\n                performCursorZoom = false;\n\n                // update condition is:\n                // min(camera displacement, camera rotation in radians)^2 > EPS\n                // using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n                if ( zoomChanged ||\n                    lastPosition.distanceToSquared( scope.object.position ) > EPS ||\n                    8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ||\n                    lastTargetPosition.distanceToSquared( scope.target ) > 0 ) {\n\n                    scope.dispatchEvent( _changeEvent );\n\n                    lastPosition.copy( scope.object.position );\n                    lastQuaternion.copy( scope.object.quaternion );\n                    lastTargetPosition.copy( scope.target );\n\n                    zoomChanged = false;\n\n                    return true;\n\n                }\n\n                return false;\n\n            };\n\n        }();\n\n        this.dispose = function() {\n\n            scope.domElement.removeEventListener( 'contextmenu', onContextMenu );\n\n            scope.domElement.removeEventListener( 'pointerdown', onPointerDown );\n            scope.domElement.removeEventListener( 'pointercancel', onPointerUp );\n            scope.domElement.removeEventListener( 'wheel', onMouseWheel );\n\n            scope.domElement.removeEventListener( 'pointermove', onPointerMove );\n            scope.domElement.removeEventListener( 'pointerup', onPointerUp );\n\n\n            if ( scope._domElementKeyEvents !== null ) {\n\n                scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );\n                scope._domElementKeyEvents = null;\n\n            }\n\n        };\n\n        //\n        // internals\n        //\n\n        const scope = this;\n\n        const STATE = {\n            NONE: - 1,\n            ROTATE: 0,\n            DOLLY: 1,\n            PAN: 2,\n            TOUCH_ROTATE: 3,\n            TOUCH_PAN: 4,\n            TOUCH_DOLLY_PAN: 5,\n            TOUCH_DOLLY_ROTATE: 6\n        };\n\n        let state = STATE.NONE;\n\n        const EPS = 0.000001;\n\n        // current position in spherical coordinates\n        const spherical = new Spherical();\n        const sphericalDelta = new Spherical();\n\n        let scale = 1;\n        const panOffset = new Vector3();\n\n        const rotateStart = new Vector2();\n        const rotateEnd = new Vector2();\n        const rotateDelta = new Vector2();\n\n        const panStart = new Vector2();\n        const panEnd = new Vector2();\n        const panDelta = new Vector2();\n\n        const dollyStart = new Vector2();\n        const dollyEnd = new Vector2();\n        const dollyDelta = new Vector2();\n\n        const dollyDirection = new Vector3();\n        const mouse = new Vector2();\n        let performCursorZoom = false;\n\n        const pointers = [];\n        const pointerPositions = {};\n\n        function getAutoRotationAngle() {\n\n            return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\n        }\n\n        function getZoomScale() {\n\n            return Math.pow( 0.95, scope.zoomSpeed );\n\n        }\n\n        function rotateLeft( angle ) {\n\n            sphericalDelta.theta -= angle;\n\n        }\n\n        function rotateUp( angle ) {\n\n            sphericalDelta.phi -= angle;\n\n        }\n\n        const panLeft = function() {\n\n            const v = new Vector3();\n\n            return function panLeft( distance, objectMatrix ) {\n\n                v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n                v.multiplyScalar( - distance );\n\n                panOffset.add( v );\n\n            };\n\n        }();\n\n        const panUp = function() {\n\n            const v = new Vector3();\n\n            return function panUp( distance, objectMatrix ) {\n\n                if ( scope.screenSpacePanning === true ) {\n\n                    v.setFromMatrixColumn( objectMatrix, 1 );\n\n                } else {\n\n                    v.setFromMatrixColumn( objectMatrix, 0 );\n                    v.crossVectors( scope.object.up, v );\n\n                }\n\n                v.multiplyScalar( distance );\n\n                panOffset.add( v );\n\n            };\n\n        }();\n\n        // deltaX and deltaY are in pixels; right and down are positive\n        const pan = function() {\n\n            const offset = new Vector3();\n\n            return function pan( deltaX, deltaY ) {\n\n                const element = scope.domElement;\n\n                if ( scope.object.isPerspectiveCamera ) {\n\n                    // perspective\n                    const position = scope.object.position;\n                    offset.copy( position ).sub( scope.target );\n                    let targetDistance = offset.length();\n\n                    // half of the fov is center to top of screen\n                    targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\n\n                    // we use only clientHeight here so aspect ratio does not distort speed\n                    panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\n                    panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\n\n                } else if ( scope.object.isOrthographicCamera ) {\n\n                    // orthographic\n                    panLeft( deltaX * ( scope.object.right - scope.object.left ) /\n                                        scope.object.zoom / element.clientWidth, scope.object.matrix );\n                    panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom /\n                                      element.clientHeight, scope.object.matrix );\n\n                } else {\n\n                    // camera neither orthographic nor perspective\n                    console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n                    scope.enablePan = false;\n\n                }\n\n            };\n\n        }();\n\n        function dollyOut( dollyScale ) {\n\n            if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {\n\n                scale /= dollyScale;\n\n            } else {\n\n                console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n                scope.enableZoom = false;\n\n            }\n\n        }\n\n        function dollyIn( dollyScale ) {\n\n            if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {\n\n                scale *= dollyScale;\n\n            } else {\n\n                console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n                scope.enableZoom = false;\n\n            }\n\n        }\n\n        function updateMouseParameters( event ) {\n\n            if ( ! scope.zoomToCursor ) {\n\n                return;\n\n            }\n\n            performCursorZoom = true;\n\n            const rect = scope.domElement.getBoundingClientRect();\n            const x = event.clientX - rect.left;\n            const y = event.clientY - rect.top;\n            const w = rect.width;\n            const h = rect.height;\n\n            mouse.x = ( x / w ) * 2 - 1;\n            mouse.y = - ( y / h ) * 2 + 1;\n\n            dollyDirection.set( mouse.x, mouse.y, 1 ).unproject( object ).sub( object.position ).normalize();\n\n        }\n\n        function clampDistance( dist ) {\n\n            return Math.max( scope.minDistance, Math.min( scope.maxDistance, dist ) );\n\n        }\n\n        //\n        // event callbacks - update the object state\n        //\n\n        function handleMouseDownRotate( event ) {\n\n            rotateStart.set( event.clientX, event.clientY );\n\n        }\n\n        function handleMouseDownDolly( event ) {\n\n            updateMouseParameters( event );\n            dollyStart.set( event.clientX, event.clientY );\n\n        }\n\n        function handleMouseDownPan( event ) {\n\n            panStart.set( event.clientX, event.clientY );\n\n        }\n\n        function handleMouseMoveRotate( event ) {\n\n            rotateEnd.set( event.clientX, event.clientY );\n\n            rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n            const element = scope.domElement;\n\n            rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n            rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n            rotateStart.copy( rotateEnd );\n\n            scope.update();\n\n        }\n\n        function handleMouseMoveDolly( event ) {\n\n            dollyEnd.set( event.clientX, event.clientY );\n\n            dollyDelta.subVectors( dollyEnd, dollyStart );\n\n            if ( dollyDelta.y > 0 ) {\n\n                dollyOut( getZoomScale() );\n\n            } else if ( dollyDelta.y < 0 ) {\n\n                dollyIn( getZoomScale() );\n\n            }\n\n            dollyStart.copy( dollyEnd );\n\n            scope.update();\n\n        }\n\n        function handleMouseMovePan( event ) {\n\n            panEnd.set( event.clientX, event.clientY );\n\n            panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n            pan( panDelta.x, panDelta.y );\n\n            panStart.copy( panEnd );\n\n            scope.update();\n\n        }\n\n        function handleMouseWheel( event ) {\n\n            updateMouseParameters( event );\n\n            if ( event.deltaY < 0 ) {\n\n                dollyIn( getZoomScale() );\n\n            } else if ( event.deltaY > 0 ) {\n\n                dollyOut( getZoomScale() );\n\n            }\n\n            scope.update();\n\n        }\n\n        function handleKeyDown( event ) {\n\n            let needsUpdate = false;\n\n            switch ( event.code ) {\n\n                case scope.keys.UP:\n\n                    if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n                        rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );\n\n                    } else {\n\n                        pan( 0, scope.keyPanSpeed );\n\n                    }\n\n                    needsUpdate = true;\n                    break;\n\n                case scope.keys.BOTTOM:\n\n                    if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n                        rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );\n\n                    } else {\n\n                        pan( 0, - scope.keyPanSpeed );\n\n                    }\n\n                    needsUpdate = true;\n                    break;\n\n                case scope.keys.LEFT:\n\n                    if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n                        rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );\n\n                    } else {\n\n                        pan( scope.keyPanSpeed, 0 );\n\n                    }\n\n                    needsUpdate = true;\n                    break;\n\n                case scope.keys.RIGHT:\n\n                    if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n                        rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );\n\n                    } else {\n\n                        pan( - scope.keyPanSpeed, 0 );\n\n                    }\n\n                    needsUpdate = true;\n                    break;\n\n            }\n\n            if ( needsUpdate ) {\n\n                // prevent the browser from scrolling on cursor keys\n                event.preventDefault();\n\n                scope.update();\n\n            }\n\n\n        }\n\n        function handleTouchStartRotate() {\n\n            if ( pointers.length === 1 ) {\n\n                rotateStart.set( pointers[0].pageX, pointers[0].pageY );\n\n            } else {\n\n                const x = 0.5 * ( pointers[0].pageX + pointers[1].pageX );\n                const y = 0.5 * ( pointers[0].pageY + pointers[1].pageY );\n\n                rotateStart.set( x, y );\n\n            }\n\n        }\n\n        function handleTouchStartPan() {\n\n            if ( pointers.length === 1 ) {\n\n                panStart.set( pointers[0].pageX, pointers[0].pageY );\n\n            } else {\n\n                const x = 0.5 * ( pointers[0].pageX + pointers[1].pageX );\n                const y = 0.5 * ( pointers[0].pageY + pointers[1].pageY );\n\n                panStart.set( x, y );\n\n            }\n\n        }\n\n        function handleTouchStartDolly() {\n\n            const dx = pointers[0].pageX - pointers[1].pageX;\n            const dy = pointers[0].pageY - pointers[1].pageY;\n\n            const distance = Math.sqrt( dx * dx + dy * dy );\n\n            dollyStart.set( 0, distance );\n\n        }\n\n        function handleTouchStartDollyPan() {\n\n            if ( scope.enableZoom ) handleTouchStartDolly();\n\n            if ( scope.enablePan ) handleTouchStartPan();\n\n        }\n\n        function handleTouchStartDollyRotate() {\n\n            if ( scope.enableZoom ) handleTouchStartDolly();\n\n            if ( scope.enableRotate ) handleTouchStartRotate();\n\n        }\n\n        function handleTouchMoveRotate( event ) {\n\n            if ( pointers.length == 1 ) {\n\n                rotateEnd.set( event.pageX, event.pageY );\n\n            } else {\n\n                const position = getSecondPointerPosition( event );\n\n                const x = 0.5 * ( event.pageX + position.x );\n                const y = 0.5 * ( event.pageY + position.y );\n\n                rotateEnd.set( x, y );\n\n            }\n\n            rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n            const element = scope.domElement;\n\n            rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n            rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n            rotateStart.copy( rotateEnd );\n\n        }\n\n        function handleTouchMovePan( event ) {\n\n            if ( pointers.length === 1 ) {\n\n                panEnd.set( event.pageX, event.pageY );\n\n            } else {\n\n                const position = getSecondPointerPosition( event );\n\n                const x = 0.5 * ( event.pageX + position.x );\n                const y = 0.5 * ( event.pageY + position.y );\n\n                panEnd.set( x, y );\n\n            }\n\n            panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n            pan( panDelta.x, panDelta.y );\n\n            panStart.copy( panEnd );\n\n        }\n\n        function handleTouchMoveDolly( event ) {\n\n            const position = getSecondPointerPosition( event );\n\n            const dx = event.pageX - position.x;\n            const dy = event.pageY - position.y;\n\n            const distance = Math.sqrt( dx * dx + dy * dy );\n\n            dollyEnd.set( 0, distance );\n\n            dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );\n\n            dollyOut( dollyDelta.y );\n\n            dollyStart.copy( dollyEnd );\n\n        }\n\n        function handleTouchMoveDollyPan( event ) {\n\n            if ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n            if ( scope.enablePan ) handleTouchMovePan( event );\n\n        }\n\n        function handleTouchMoveDollyRotate( event ) {\n\n            if ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n            if ( scope.enableRotate ) handleTouchMoveRotate( event );\n\n        }\n\n        //\n        // event handlers - FSM: listen for events and reset state\n        //\n\n        function onPointerDown( event ) {\n\n            if ( scope.enabled === false ) return;\n\n            if ( pointers.length === 0 ) {\n\n                scope.domElement.setPointerCapture( event.pointerId );\n\n                scope.domElement.addEventListener( 'pointermove', onPointerMove );\n                scope.domElement.addEventListener( 'pointerup', onPointerUp );\n\n            }\n\n            //\n\n            addPointer( event );\n\n            if ( event.pointerType === 'touch' ) {\n\n                onTouchStart( event );\n\n            } else {\n\n                onMouseDown( event );\n\n            }\n\n        }\n\n        function onPointerMove( event ) {\n\n            if ( scope.enabled === false ) return;\n\n            if ( event.pointerType === 'touch' ) {\n\n                onTouchMove( event );\n\n            } else {\n\n                onMouseMove( event );\n\n            }\n\n        }\n\n        function onPointerUp( event ) {\n\n            removePointer( event );\n\n            if ( pointers.length === 0 ) {\n\n                scope.domElement.releasePointerCapture( event.pointerId );\n\n                scope.domElement.removeEventListener( 'pointermove', onPointerMove );\n                scope.domElement.removeEventListener( 'pointerup', onPointerUp );\n\n            }\n\n            scope.dispatchEvent( _endEvent );\n\n            state = STATE.NONE;\n\n        }\n\n        function onMouseDown( event ) {\n\n            let mouseAction;\n\n            switch ( event.button ) {\n\n                case 0:\n\n                    mouseAction = scope.mouseButtons.LEFT;\n                    break;\n\n                case 1:\n\n                    mouseAction = scope.mouseButtons.MIDDLE;\n                    break;\n\n                case 2:\n\n                    mouseAction = scope.mouseButtons.RIGHT;\n                    break;\n\n                default:\n\n                    mouseAction = - 1;\n\n            }\n\n            switch ( mouseAction ) {\n\n                case MOUSE.DOLLY:\n\n                    if ( scope.enableZoom === false ) return;\n\n                    handleMouseDownDolly( event );\n\n                    state = STATE.DOLLY;\n\n                    break;\n\n                case MOUSE.ROTATE:\n\n                    if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n                        if ( scope.enablePan === false ) return;\n\n                        handleMouseDownPan( event );\n\n                        state = STATE.PAN;\n\n                    } else {\n\n                        if ( scope.enableRotate === false ) return;\n\n                        handleMouseDownRotate( event );\n\n                        state = STATE.ROTATE;\n\n                    }\n\n                    break;\n\n                case MOUSE.PAN:\n\n                    if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n                        if ( scope.enableRotate === false ) return;\n\n                        handleMouseDownRotate( event );\n\n                        state = STATE.ROTATE;\n\n                    } else {\n\n                        if ( scope.enablePan === false ) return;\n\n                        handleMouseDownPan( event );\n\n                        state = STATE.PAN;\n\n                    }\n\n                    break;\n\n                default:\n\n                    state = STATE.NONE;\n\n            }\n\n            if ( state !== STATE.NONE ) {\n\n                scope.dispatchEvent( _startEvent );\n\n            }\n\n        }\n\n        function onMouseMove( event ) {\n\n            switch ( state ) {\n\n                case STATE.ROTATE:\n\n                    if ( scope.enableRotate === false ) return;\n\n                    handleMouseMoveRotate( event );\n\n                    break;\n\n                case STATE.DOLLY:\n\n                    if ( scope.enableZoom === false ) return;\n\n                    handleMouseMoveDolly( event );\n\n                    break;\n\n                case STATE.PAN:\n\n                    if ( scope.enablePan === false ) return;\n\n                    handleMouseMovePan( event );\n\n                    break;\n\n            }\n\n        }\n\n        function onMouseWheel( event ) {\n\n            if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;\n\n            event.preventDefault();\n\n            scope.dispatchEvent( _startEvent );\n\n            handleMouseWheel( event );\n\n            scope.dispatchEvent( _endEvent );\n\n        }\n\n        function onKeyDown( event ) {\n\n            if ( scope.enabled === false || scope.enablePan === false ) return;\n\n            handleKeyDown( event );\n\n        }\n\n        function onTouchStart( event ) {\n\n            trackPointer( event );\n\n            switch ( pointers.length ) {\n\n                case 1:\n\n                    switch ( scope.touches.ONE ) {\n\n                        case TOUCH.ROTATE:\n\n                            if ( scope.enableRotate === false ) return;\n\n                            handleTouchStartRotate();\n\n                            state = STATE.TOUCH_ROTATE;\n\n                            break;\n\n                        case TOUCH.PAN:\n\n                            if ( scope.enablePan === false ) return;\n\n                            handleTouchStartPan();\n\n                            state = STATE.TOUCH_PAN;\n\n                            break;\n\n                        default:\n\n                            state = STATE.NONE;\n\n                    }\n\n                    break;\n\n                case 2:\n\n                    switch ( scope.touches.TWO ) {\n\n                        case TOUCH.DOLLY_PAN:\n\n                            if ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n                            handleTouchStartDollyPan();\n\n                            state = STATE.TOUCH_DOLLY_PAN;\n\n                            break;\n\n                        case TOUCH.DOLLY_ROTATE:\n\n                            if ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n                            handleTouchStartDollyRotate();\n\n                            state = STATE.TOUCH_DOLLY_ROTATE;\n\n                            break;\n\n                        default:\n\n                            state = STATE.NONE;\n\n                    }\n\n                    break;\n\n                default:\n\n                    state = STATE.NONE;\n\n            }\n\n            if ( state !== STATE.NONE ) {\n\n                scope.dispatchEvent( _startEvent );\n\n            }\n\n        }\n\n        function onTouchMove( event ) {\n\n            trackPointer( event );\n\n            switch ( state ) {\n\n                case STATE.TOUCH_ROTATE:\n\n                    if ( scope.enableRotate === false ) return;\n\n                    handleTouchMoveRotate( event );\n\n                    scope.update();\n\n                    break;\n\n                case STATE.TOUCH_PAN:\n\n                    if ( scope.enablePan === false ) return;\n\n                    handleTouchMovePan( event );\n\n                    scope.update();\n\n                    break;\n\n                case STATE.TOUCH_DOLLY_PAN:\n\n                    if ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n                    handleTouchMoveDollyPan( event );\n\n                    scope.update();\n\n                    break;\n\n                case STATE.TOUCH_DOLLY_ROTATE:\n\n                    if ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n                    handleTouchMoveDollyRotate( event );\n\n                    scope.update();\n\n                    break;\n\n                default:\n\n                    state = STATE.NONE;\n\n            }\n\n        }\n\n        function onContextMenu( event ) {\n\n            if ( scope.enabled === false ) return;\n\n            event.preventDefault();\n\n        }\n\n        function addPointer( event ) {\n\n            pointers.push( event );\n\n        }\n\n        function removePointer( event ) {\n\n            delete pointerPositions[event.pointerId];\n\n            for ( let i = 0; i < pointers.length; i ++ ) {\n\n                if ( pointers[i].pointerId == event.pointerId ) {\n\n                    pointers.splice( i, 1 );\n                    return;\n\n                }\n\n            }\n\n        }\n\n        function trackPointer( event ) {\n\n            let position = pointerPositions[event.pointerId];\n\n            if ( position === undefined ) {\n\n                position = new Vector2();\n                pointerPositions[event.pointerId] = position;\n\n            }\n\n            position.set( event.pageX, event.pageY );\n\n        }\n\n        function getSecondPointerPosition( event ) {\n\n            const pointer = ( event.pointerId === pointers[0].pointerId ) ? pointers[1] : pointers[0];\n\n            return pointerPositions[pointer.pointerId];\n\n        }\n\n        //\n\n        scope.domElement.addEventListener( 'contextmenu', onContextMenu );\n\n        scope.domElement.addEventListener( 'pointerdown', onPointerDown );\n        scope.domElement.addEventListener( 'pointercancel', onPointerUp );\n        scope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );\n\n        // force an update at start\n\n        this.update();\n\n    }\n    listenToKeyEvents( domElement ) {\n\n        domElement.addEventListener( 'keydown', onKeyDown );\n        this._domElementKeyEvents = domElement;\n\n    };\n    stopListenToKeyEvents() {\n\n        this._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );\n        this._domElementKeyEvents = null;\n\n    };\n}\n\nexport { OrbitControls };\n","export class LoadingSpinner {\r\n\r\n    constructor(message, container) {\r\n        this.message = message || 'Loading...';\r\n        this.container = container || document.body;\r\n\r\n        this.spinnerDivContainer = document.createElement('div');\r\n        this.spinnerDiv = document.createElement('div');\r\n        this.messageDiv = document.createElement('div');\r\n        this.spinnerDivContainer.className = 'loaderContainer';\r\n        this.spinnerDiv.className = 'loader';\r\n        this.spinnerDivContainer.style.display = 'none';\r\n        this.messageDiv.className = 'message';\r\n        this.messageDiv.innerHTML = this.message;\r\n        this.spinnerDivContainer.appendChild(this.spinnerDiv);\r\n        this.spinnerDivContainer.appendChild(this.messageDiv);\r\n        this.container.appendChild(this.spinnerDivContainer);\r\n\r\n        const style = document.createElement('style');\r\n        style.innerHTML = `\r\n\r\n            .message {\r\n                font-family: arial;\r\n                font-size: 12pt;\r\n                color: #ffffff;\r\n                text-align: center;\r\n                padding-top:15px;\r\n                width: 180px;\r\n            }\r\n\r\n            .loaderContainer {\r\n                position: absolute;\r\n                top: 50%;\r\n                left: 50%;\r\n                transform: translate(-80px, -80px);\r\n                width: 180px;\r\n            }\r\n\r\n            .loader {\r\n                width: 120px;        /* the size */\r\n                padding: 15px;       /* the border thickness */\r\n                background: #07e8d6; /* the color */\r\n                z-index:99999;\r\n            \r\n                aspect-ratio: 1;\r\n                border-radius: 50%;\r\n                --_m: \r\n                    conic-gradient(#0000,#000),\r\n                    linear-gradient(#000 0 0) content-box;\r\n                -webkit-mask: var(--_m);\r\n                    mask: var(--_m);\r\n                -webkit-mask-composite: source-out;\r\n                    mask-composite: subtract;\r\n                box-sizing: border-box;\r\n                animation: load 1s linear infinite;\r\n                margin-left: 30px;\r\n            }\r\n            \r\n            @keyframes load {\r\n                to{transform: rotate(1turn)}\r\n            }\r\n\r\n        `;\r\n        this.spinnerDivContainer.appendChild(style);\r\n    }\r\n\r\n    show() {\r\n        this.spinnerDivContainer.style.display = 'block';\r\n    }\r\n\r\n    hide() {\r\n        this.spinnerDivContainer.style.display = 'none';\r\n    }\r\n\r\n    setMessage(msg) {\r\n        this.messageDiv.innerHTML = msg;\r\n    }\r\n}\r\n","import * as THREE from 'three';\n\nexport class ArrowHelper extends THREE.Object3D {\n\n    constructor(dir = new THREE.Vector3(0, 0, 1), origin = new THREE.Vector3(0, 0, 0), length = 1,\n                radius = 0.1, color = 0xffff00, headLength = length * 0.2, headRadius = headLength * 0.2) {\n        super();\n\n        this.type = 'ArrowHelper';\n\n        const lineGeometry = new THREE.CylinderGeometry(radius, radius, length, 32);\n        lineGeometry.translate(0, length / 2.0, 0);\n        const coneGeometry = new THREE.CylinderGeometry( 0, headRadius, headLength, 32);\n        coneGeometry.translate(0, length, 0);\n\n        this.position.copy( origin );\n\n        this.line = new THREE.Mesh(lineGeometry, new THREE.MeshBasicMaterial({color: color, toneMapped: false}));\n        this.line.matrixAutoUpdate = false;\n        this.add(this.line);\n\n        this.cone = new THREE.Mesh(coneGeometry, new THREE.MeshBasicMaterial({color: color, toneMapped: false}));\n        this.cone.matrixAutoUpdate = false;\n        this.add(this.cone);\n\n        this.setDirection(dir);\n    }\n\n    setDirection( dir ) {\n        if (dir.y > 0.99999) {\n            this.quaternion.set(0, 0, 0, 1);\n        } else if (dir.y < - 0.99999) {\n            this.quaternion.set(1, 0, 0, 0);\n        } else {\n            _axis.set(dir.z, 0, -dir.x).normalize();\n            const radians = Math.acos(dir.y);\n            this.quaternion.setFromAxisAngle(_axis, radians);\n        }\n    }\n\n    setColor( color ) {\n        this.line.material.color.set(color);\n        this.cone.material.color.set(color);\n    }\n\n    copy(source) {\n        super.copy(source, false);\n        this.line.copy(source.line);\n        this.cone.copy(source.cone);\n        return this;\n    }\n\n    dispose() {\n        this.line.geometry.dispose();\n        this.line.material.dispose();\n        this.cone.geometry.dispose();\n        this.cone.material.dispose();\n    }\n\n}\n","import * as THREE from 'three';\r\nimport { ArrowHelper } from './ArrowHelper.js';\r\n\r\nexport class SceneHelper {\r\n\r\n    constructor(scene) {\r\n        this.scene = scene;\r\n        this.splatRenderTarget = null;\r\n        this.renderTargetCopyMaterial = null;\r\n        this.renderTargetCopyQuad = null;\r\n        this.renderTargetCopyCamera = null;\r\n        this.meshCursor = null;\r\n        this.focusMarker = null;\r\n        this.controlPlane = null;\r\n    }\r\n\r\n    updateSplatRenderTargetForRenderDimensions(width, height) {\r\n        this.splatRenderTarget = new THREE.WebGLRenderTarget(width, height, {\r\n            format: THREE.RGBAFormat,\r\n            stencilBuffer: false,\r\n            depthBuffer: true,\r\n\r\n        });\r\n        this.splatRenderTarget.depthTexture = new THREE.DepthTexture(width, height);\r\n        this.splatRenderTarget.depthTexture.format = THREE.DepthFormat;\r\n        this.splatRenderTarget.depthTexture.type = THREE.UnsignedIntType;\r\n    }\r\n\r\n    setupRenderTargetCopyObjects() {\r\n        const uniforms = {\r\n            'sourceColorTexture': {\r\n                'type': 't',\r\n                'value': null\r\n            },\r\n            'sourceDepthTexture': {\r\n                'type': 't',\r\n                'value': null\r\n            },\r\n        };\r\n        this.renderTargetCopyMaterial = new THREE.ShaderMaterial({\r\n            vertexShader: `\r\n                varying vec2 vUv;\r\n                void main() {\r\n                    vUv = uv;\r\n                    gl_Position = vec4( position.xy, 0.0, 1.0 );    \r\n                }\r\n            `,\r\n            fragmentShader: `\r\n                #include <common>\r\n                #include <packing>\r\n                varying vec2 vUv;\r\n                uniform sampler2D sourceColorTexture;\r\n                uniform sampler2D sourceDepthTexture;\r\n                void main() {\r\n                    vec4 color = texture2D(sourceColorTexture, vUv);\r\n                    float fragDepth = texture2D(sourceDepthTexture, vUv).x;\r\n                    gl_FragDepth = fragDepth;\r\n                    gl_FragColor = vec4(color.rgb, color.a * 2.0);\r\n              }\r\n            `,\r\n            uniforms: uniforms,\r\n            depthWrite: false,\r\n            depthTest: false,\r\n            transparent: true,\r\n            blending: THREE.CustomBlending,\r\n            blendSrc: THREE.SrcAlphaFactor,\r\n            blendSrcAlpha: THREE.SrcAlphaFactor,\r\n            blendDst: THREE.OneMinusSrcAlphaFactor,\r\n            blendDstAlpha: THREE.OneMinusSrcAlphaFactor\r\n        });\r\n        this.renderTargetCopyMaterial.extensions.fragDepth = true;\r\n        this.renderTargetCopyQuad = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), this.renderTargetCopyMaterial);\r\n        this.renderTargetCopyCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);\r\n    }\r\n\r\n    setupMeshCursor() {\r\n        if (!this.meshCursor) {\r\n            const coneGeometry = new THREE.ConeGeometry(0.5, 1.5, 32);\r\n            const coneMaterial = new THREE.MeshBasicMaterial({color: 0xFFFFFF});\r\n\r\n            const downArrow = new THREE.Mesh(coneGeometry, coneMaterial);\r\n            downArrow.rotation.set(0, 0, Math.PI);\r\n            downArrow.position.set(0, 1, 0);\r\n            const upArrow = new THREE.Mesh(coneGeometry, coneMaterial);\r\n            upArrow.position.set(0, -1, 0);\r\n            const leftArrow = new THREE.Mesh(coneGeometry, coneMaterial);\r\n            leftArrow.rotation.set(0, 0, Math.PI / 2.0);\r\n            leftArrow.position.set(1, 0, 0);\r\n            const rightArrow = new THREE.Mesh(coneGeometry, coneMaterial);\r\n            rightArrow.rotation.set(0, 0, -Math.PI / 2.0);\r\n            rightArrow.position.set(-1, 0, 0);\r\n\r\n            this.meshCursor = new THREE.Object3D();\r\n            this.meshCursor.add(downArrow);\r\n            this.meshCursor.add(upArrow);\r\n            this.meshCursor.add(leftArrow);\r\n            this.meshCursor.add(rightArrow);\r\n            this.meshCursor.scale.set(0.1, 0.1, 0.1);\r\n            this.scene.add(this.meshCursor);\r\n            this.meshCursor.visible = false;\r\n        }\r\n    }\r\n\r\n    destroyMeshCursor() {\r\n        if (this.meshCursor) {\r\n            this.meshCursor.children.forEach((child) => {\r\n                child.geometry.dispose();\r\n                child.material.dispose();\r\n            });\r\n            this.scene.remove(this.meshCursor);\r\n            this.meshCursor = null;\r\n        }\r\n    }\r\n\r\n    setMeshCursorVisibility(visible) {\r\n        this.meshCursor.visible = visible;\r\n    }\r\n\r\n    setMeshCursorPosition(position) {\r\n        this.meshCursor.position.copy(position);\r\n    }\r\n\r\n    positionAndOrientMeshCursor(position, camera) {\r\n        this.meshCursor.position.copy(position);\r\n        this.meshCursor.up.copy(camera.up);\r\n        this.meshCursor.lookAt(camera.position);\r\n    }\r\n\r\n    setupFocusMarker() {\r\n        if (!this.focusMarker) {\r\n            const sphereGeometry = new THREE.SphereGeometry(.5, 32, 32);\r\n            const focusMarkerMaterial = SceneHelper.buildFocusMarkerMaterial();\r\n            focusMarkerMaterial.depthTest = false;\r\n            focusMarkerMaterial.depthWrite = false;\r\n            focusMarkerMaterial.transparent = true;\r\n            const sphereMesh = new THREE.Mesh(sphereGeometry, focusMarkerMaterial);\r\n            this.focusMarker = sphereMesh;\r\n        }\r\n    }\r\n\r\n    updateFocusMarker = function() {\r\n\r\n        const tempPosition = new THREE.Vector3();\r\n        const tempMatrix = new THREE.Matrix4();\r\n\r\n        return function(position, camera, viewport) {\r\n            tempMatrix.copy(camera.matrixWorld).invert();\r\n            tempPosition.copy(position).applyMatrix4(tempMatrix);\r\n            tempPosition.normalize().multiplyScalar(10);\r\n            tempPosition.applyMatrix4(camera.matrixWorld);\r\n            this.focusMarker.position.copy(tempPosition);\r\n            this.focusMarker.material.uniforms.realFocusPosition.value.copy(position);\r\n            this.focusMarker.material.uniforms.viewport.value.copy(viewport);\r\n            this.focusMarker.material.uniformsNeedUpdate = true;\r\n        };\r\n\r\n    }();\r\n\r\n    setFocusMarkerVisibility(visible) {\r\n        this.focusMarker.visible = visible;\r\n    }\r\n\r\n    setFocusMarkerOpacity(opacity) {\r\n        this.focusMarker.material.uniforms.opacity.value = opacity;\r\n        this.focusMarker.material.uniformsNeedUpdate = true;\r\n    }\r\n\r\n    getFocusMarkerOpacity() {\r\n        return this.focusMarker.material.uniforms.opacity.value;\r\n    }\r\n\r\n    setupControlPlane() {\r\n        const planeGeometry = new THREE.PlaneGeometry(1, 1);\r\n        planeGeometry.rotateX(-Math.PI / 2);\r\n        const planeMaterial = new THREE.MeshBasicMaterial({color: 0xffffff});\r\n        planeMaterial.transparent = true;\r\n        planeMaterial.opacity = 0.6;\r\n        planeMaterial.depthTest = false;\r\n        planeMaterial.depthWrite = false;\r\n        planeMaterial.side = THREE.DoubleSide;\r\n        const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);\r\n\r\n        const arrowDir = new THREE.Vector3(0, 1, 0);\r\n        arrowDir.normalize();\r\n        const arrowOrigin = new THREE.Vector3(0, 0, 0);\r\n        const arrowLength = 0.5;\r\n        const arrowRadius = 0.01;\r\n        const arrowColor = 0x00dd00;\r\n        const arrowHelper = new ArrowHelper(arrowDir, arrowOrigin, arrowLength, arrowRadius, arrowColor, 0.1, 0.03);\r\n\r\n        this.controlPlane = new THREE.Object3D();\r\n        this.controlPlane.add(planeMesh);\r\n        this.controlPlane.add(arrowHelper);\r\n    }\r\n\r\n    setControlPlaneVisibility(visible) {\r\n        this.controlPlane.visible = visible;\r\n    }\r\n\r\n    positionAndOrientControlPlane = function() {\r\n\r\n        const tempQuaternion = new THREE.Quaternion();\r\n        const defaultUp = new THREE.Vector3(0, 1, 0);\r\n\r\n        return function(position, up) {\r\n            tempQuaternion.setFromUnitVectors(defaultUp, up);\r\n            this.controlPlane.position.copy(position);\r\n            this.controlPlane.quaternion.copy(tempQuaternion);\r\n        };\r\n\r\n    }();\r\n\r\n    addDebugMeshes() {\r\n        this.debugRoot = this.createDebugMeshes();\r\n        this.secondaryDebugRoot = this.createSecondaryDebugMeshes();\r\n        this.scene.add(this.debugRoot);\r\n        this.scene.add(this.secondaryDebugRoot);\r\n    }\r\n\r\n    createDebugMeshes(renderOrder) {\r\n        const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);\r\n        const debugMeshRoot = new THREE.Object3D();\r\n\r\n        const createMesh = (color, position) => {\r\n            let sphereMesh = new THREE.Mesh(sphereGeometry, SceneHelper.buildDebugMaterial(color));\r\n            sphereMesh.renderOrder = renderOrder;\r\n            debugMeshRoot.add(sphereMesh);\r\n            sphereMesh.position.fromArray(position);\r\n        };\r\n\r\n        createMesh(0xff0000, [-50, 0, 0]);\r\n        createMesh(0xff0000, [50, 0, 0]);\r\n        createMesh(0x00ff00, [0, 0, -50]);\r\n        createMesh(0x00ff00, [0, 0, 50]);\r\n        createMesh(0xffaa00, [5, 0, 5]);\r\n\r\n        return debugMeshRoot;\r\n    }\r\n\r\n    createSecondaryDebugMeshes(renderOrder) {\r\n        const boxGeometry = new THREE.BoxGeometry(3, 3, 3);\r\n        const debugMeshRoot = new THREE.Object3D();\r\n\r\n        let boxColor = 0xBBBBBB;\r\n        const createMesh = (position) => {\r\n            let boxMesh = new THREE.Mesh(boxGeometry, SceneHelper.buildDebugMaterial(boxColor));\r\n            boxMesh.renderOrder = renderOrder;\r\n            debugMeshRoot.add(boxMesh);\r\n            boxMesh.position.fromArray(position);\r\n        };\r\n\r\n        let separation = 10;\r\n        createMesh([-separation, 0, -separation]);\r\n        createMesh([-separation, 0, separation]);\r\n        createMesh([separation, 0, -separation]);\r\n        createMesh([separation, 0, separation]);\r\n\r\n        return debugMeshRoot;\r\n    }\r\n\r\n    static buildDebugMaterial(color) {\r\n        const vertexShaderSource = `\r\n            #include <common>\r\n            varying float ndcDepth;\r\n\r\n            void main() {\r\n                gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position.xyz, 1.0);\r\n                ndcDepth = gl_Position.z / gl_Position.w;\r\n                gl_Position.x = gl_Position.x / gl_Position.w;\r\n                gl_Position.y = gl_Position.y / gl_Position.w;\r\n                gl_Position.z = 0.0;\r\n                gl_Position.w = 1.0;\r\n    \r\n            }\r\n        `;\r\n\r\n        const fragmentShaderSource = `\r\n            #include <common>\r\n            uniform vec3 color;\r\n            varying float ndcDepth;\r\n            void main() {\r\n                gl_FragDepth = (ndcDepth + 1.0) / 2.0;\r\n                gl_FragColor = vec4(color.rgb, 0.0);\r\n            }\r\n        `;\r\n\r\n        const uniforms = {\r\n            'color': {\r\n                'type': 'v3',\r\n                'value': new THREE.Color(color)\r\n            },\r\n        };\r\n\r\n        const material = new THREE.ShaderMaterial({\r\n            uniforms: uniforms,\r\n            vertexShader: vertexShaderSource,\r\n            fragmentShader: fragmentShaderSource,\r\n            transparent: false,\r\n            depthTest: true,\r\n            depthWrite: true,\r\n            side: THREE.FrontSide\r\n        });\r\n        material.extensions.fragDepth = true;\r\n\r\n        return material;\r\n    }\r\n\r\n    static buildFocusMarkerMaterial(color) {\r\n        const vertexShaderSource = `\r\n            #include <common>\r\n\r\n            uniform vec2 viewport;\r\n            uniform vec3 realFocusPosition;\r\n\r\n            varying vec4 ndcPosition;\r\n            varying vec4 ndcCenter;\r\n            varying vec4 ndcFocusPosition;\r\n\r\n            void main() {\r\n                float radius = 0.01;\r\n\r\n                vec4 viewPosition = modelViewMatrix * vec4(position.xyz, 1.0);\r\n                vec4 viewCenter = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);\r\n\r\n                vec4 viewFocusPosition = modelViewMatrix * vec4(realFocusPosition, 1.0);\r\n\r\n                ndcPosition = projectionMatrix * viewPosition;\r\n                ndcPosition = ndcPosition * vec4(1.0 / ndcPosition.w);\r\n                ndcCenter = projectionMatrix * viewCenter;\r\n                ndcCenter = ndcCenter * vec4(1.0 / ndcCenter.w);\r\n\r\n                ndcFocusPosition = projectionMatrix * viewFocusPosition;\r\n                ndcFocusPosition = ndcFocusPosition * vec4(1.0 / ndcFocusPosition.w);\r\n\r\n                gl_Position = projectionMatrix * viewPosition;\r\n\r\n            }\r\n        `;\r\n\r\n        const fragmentShaderSource = `\r\n            #include <common>\r\n            uniform vec3 color;\r\n            uniform vec2 viewport;\r\n            uniform float opacity;\r\n\r\n            varying vec4 ndcPosition;\r\n            varying vec4 ndcCenter;\r\n            varying vec4 ndcFocusPosition;\r\n\r\n            void main() {\r\n                vec2 screenPosition = vec2(ndcPosition) * viewport;\r\n                vec2 screenCenter = vec2(ndcCenter) * viewport;\r\n\r\n                vec2 screenVec = screenPosition - screenCenter;\r\n\r\n                float projectedRadius = length(screenVec);\r\n\r\n                float lineWidth = 0.0005 * viewport.y;\r\n                float aaRange = 0.0025 * viewport.y;\r\n                float radius = 0.06 * viewport.y;\r\n                float radDiff = abs(projectedRadius - radius) - lineWidth;\r\n                float alpha = 1.0 - clamp(radDiff / 5.0, 0.0, 1.0); \r\n\r\n                gl_FragColor = vec4(color.rgb, alpha * opacity);\r\n            }\r\n        `;\r\n\r\n        const uniforms = {\r\n            'color': {\r\n                'type': 'v3',\r\n                'value': new THREE.Color(color)\r\n            },\r\n            'realFocusPosition': {\r\n                'type': 'v3',\r\n                'value': new THREE.Vector3()\r\n            },\r\n            'viewport': {\r\n                'type': 'v2',\r\n                'value': new THREE.Vector2()\r\n            },\r\n            'opacity': {\r\n                'value': 0.0\r\n            }\r\n        };\r\n\r\n        const material = new THREE.ShaderMaterial({\r\n            uniforms: uniforms,\r\n            vertexShader: vertexShaderSource,\r\n            fragmentShader: fragmentShaderSource,\r\n            transparent: true,\r\n            depthTest: false,\r\n            depthWrite: false,\r\n            side: THREE.FrontSide\r\n        });\r\n\r\n        return material;\r\n    }\r\n}\r\n","import * as THREE from 'three';\r\n\r\nconst VectorRight = new THREE.Vector3(1, 0, 0);\r\nconst VectorUp = new THREE.Vector3(0, 1, 0);\r\nconst VectorBackward = new THREE.Vector3(0, 0, 1);\r\n\r\nexport class Ray {\r\n\r\n    constructor(origin = new THREE.Vector3(), direction = new THREE.Vector3()) {\r\n        this.origin = new THREE.Vector3();\r\n        this.direction = new THREE.Vector3();\r\n        this.setParameters(origin, direction);\r\n    }\r\n\r\n    setParameters(origin, direction) {\r\n        this.origin.copy(origin);\r\n        this.direction.copy(direction).normalize();\r\n    }\r\n\r\n    boxContainsPoint(box, point, epsilon) {\r\n        return point.x < box.min.x - epsilon || point.x > box.max.x + epsilon ||\r\n               point.y < box.min.y - epsilon || point.y > box.max.y + epsilon ||\r\n               point.z < box.min.z - epsilon || point.z > box.max.z + epsilon ? false : true;\r\n    }\r\n\r\n    intersectBox = function() {\r\n\r\n        const planeIntersectionPoint = new THREE.Vector3();\r\n        const planeIntersectionPointArray = [];\r\n        const originArray = [];\r\n        const directionArray = [];\r\n\r\n        return function(box, outHit) {\r\n\r\n            originArray[0] = this.origin.x;\r\n            originArray[1] = this.origin.y;\r\n            originArray[2] = this.origin.z;\r\n            directionArray[0] = this.direction.x;\r\n            directionArray[1] = this.direction.y;\r\n            directionArray[2] = this.direction.z;\r\n\r\n            if (this.boxContainsPoint(box, this.origin, 0.0001)) {\r\n                if (outHit) {\r\n                    outHit.origin.copy(this.origin);\r\n                    outHit.normal.set(0, 0, 0);\r\n                    outHit.distance = -1;\r\n                }\r\n                return true;\r\n            }\r\n\r\n            for (let i = 0; i < 3; i++) {\r\n                if (directionArray[i] == 0.0) continue;\r\n\r\n                const hitNormal = i == 0 ? VectorRight : i == 1 ? VectorUp : VectorBackward;\r\n                const extremeVec = directionArray[i] < 0 ? box.max : box.min;\r\n                let multiplier = -Math.sign(directionArray[i]);\r\n                planeIntersectionPointArray[0] = i == 0 ? extremeVec.x : i == 1 ? extremeVec.y : extremeVec.z;\r\n                let toSide = planeIntersectionPointArray[0] - originArray[i];\r\n\r\n                if (toSide * multiplier < 0) {\r\n                    const idx1 = (i + 1) % 3;\r\n                    const idx2 = (i + 2) % 3;\r\n                    planeIntersectionPointArray[2] = directionArray[idx1] / directionArray[i] * toSide + originArray[idx1];\r\n                    planeIntersectionPointArray[1] = directionArray[idx2] / directionArray[i] * toSide + originArray[idx2];\r\n                    planeIntersectionPoint.set(planeIntersectionPointArray[i],\r\n                                               planeIntersectionPointArray[idx2],\r\n                                               planeIntersectionPointArray[idx1]);\r\n                    if (this.boxContainsPoint(box, planeIntersectionPoint, 0.0001)) {\r\n                        if (outHit) {\r\n                            outHit.origin.copy(planeIntersectionPoint);\r\n                            outHit.normal.copy(hitNormal).multiplyScalar(multiplier);\r\n                            outHit.distance = planeIntersectionPoint.sub(this.origin).length();\r\n                        }\r\n                        return true;\r\n                    }\r\n                }\r\n            }\r\n\r\n            return false;\r\n        };\r\n\r\n    }();\r\n\r\n    intersectSphere = function() {\r\n\r\n        const toSphereCenterVec = new THREE.Vector3();\r\n\r\n        return function(center, radius, outHit) {\r\n            toSphereCenterVec.copy(center).sub(this.origin);\r\n            const toClosestApproach = toSphereCenterVec.dot(this.direction);\r\n            const toClosestApproachSq = toClosestApproach * toClosestApproach;\r\n            const toSphereCenterSq = toSphereCenterVec.dot(toSphereCenterVec);\r\n            const diffSq = toSphereCenterSq - toClosestApproachSq;\r\n            const radiusSq = radius * radius;\r\n\r\n            if (diffSq > radiusSq) return false;\r\n\r\n            const thc = Math.sqrt(radiusSq - diffSq);\r\n            const t0 = toClosestApproach - thc;\r\n            const t1 = toClosestApproach + thc;\r\n\r\n            if (t1 < 0) return false;\r\n            let t = t0 < 0 ? t1 : t0;\r\n\r\n            if (outHit) {\r\n                outHit.origin.copy(this.origin).addScaledVector(this.direction, t);\r\n                outHit.normal.copy(outHit.origin).sub(center).normalize();\r\n                outHit.distance = t;\r\n            }\r\n            return true;\r\n        };\r\n\r\n    }();\r\n}\r\n","import * as THREE from 'three';\r\n\r\nexport class Hit {\r\n\r\n    constructor() {\r\n        this.origin = new THREE.Vector3();\r\n        this.normal = new THREE.Vector3();\r\n        this.distance = 0;\r\n    }\r\n\r\n    set(origin, normal, distance) {\r\n        this.origin.copy(origin);\r\n        this.normal.copy(normal);\r\n        this.distance = distance;\r\n    }\r\n\r\n    clone() {\r\n        const hitClone = new Hit();\r\n        hitClone.origin.copy(this.origin);\r\n        hitClone.normal.copy(this.normal);\r\n        hitClone.distance = this.distance;\r\n        return hitClone;\r\n    }\r\n\r\n}\r\n","import * as THREE from 'three';\nimport { Ray } from './Ray.js';\nimport { Hit } from './Hit.js';\n\nexport class Raycaster {\n\n    constructor(origin, direction) {\n        this.ray = new Ray(origin, direction);\n        this.setFromCameraAndScreenPosition = function() {\n\n            const ndcCoords = new THREE.Vector2();\n\n            return function(camera, screenPosition, screenDimensions) {\n                ndcCoords.x = screenPosition.x / screenDimensions.x * 2.0 - 1.0;\n                ndcCoords.y = (screenDimensions.y - screenPosition.y) / screenDimensions.y * 2.0 - 1.0;\n                if (camera.isPerspectiveCamera) {\n                    this.ray.origin.setFromMatrixPosition(camera.matrixWorld);\n                    this.ray.direction.set(ndcCoords.x, ndcCoords.y, 0.5 ).unproject(camera).sub(this.ray.origin).normalize();\n                    this.camera = camera;\n                } else if (camera.isOrthographicCamera) {\n                    this.ray.origin.set(screenPosition.x, screenPosition.y,\n                                       (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera);\n                    this.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld);\n                    this.camera = camera;\n                } else {\n                    throw new Error('Raycaster::setFromCameraAndScreenPosition() -> Unsupported camera type');\n                }\n            };\n\n        }();\n        this.intersectSplatMesh = function intersectSplatMesh() {\n\n            const toLocal = new THREE.Matrix4();\n            const fromLocal = new THREE.Matrix4();\n            const localRay = new Ray();\n\n            return function(splatMesh, outHits = []) {\n                fromLocal.copy(splatMesh.matrixWorld);\n                toLocal.copy(fromLocal).invert();\n                localRay.origin.copy(this.ray.origin).applyMatrix4(toLocal);\n                localRay.direction.copy(this.ray.direction).transformDirection(toLocal);\n\n                const splatTree = splatMesh.getSplatTree();\n                if (splatTree.rootNode) {\n                    this.castRayAtSplatTreeNode(localRay, splatTree, splatTree.rootNode, outHits);\n                }\n                outHits.sort((a, b) => {\n                    if (a.distance > b.distance) return 1;\n                    else return -1;\n                });\n                outHits.forEach((hit) => {\n                    hit.origin.applyMatrix4(fromLocal);\n                    hit.normal.transformDirection(fromLocal);\n                });\n                return outHits;\n            };\n\n        }();\n        this.castRayAtSplatTreeNode = function castRayAtSplatTreeNode() {\n\n            const tempPosition = new THREE.Vector3();\n            const tempScale = new THREE.Vector3();\n            const tempRotation = new THREE.Quaternion();\n            const tempHit = new Hit();\n            const scaleEpsilon = 0.0000001;\n\n            // Used for raycasting against splat ellipsoid\n            /*\n            const origin = new THREE.Vector3(0, 0, 0);\n            const tempRotationMatrix = new THREE.Matrix4();\n            const tempScaleMatrix = new THREE.Matrix4();\n            const toSphereSpace = new THREE.Matrix4();\n            const fromSphereSpace = new THREE.Matrix4();\n            const tempRay = new Ray();\n            */\n\n            return function(ray, splatTree, node, outHits = []) {\n                if (!ray.intersectBox(node.boundingBox)) {\n                    return;\n                }\n                if (node.data.indexes && node.data.indexes.length > 0) {\n                    for (let i = 0; i < node.data.indexes.length; i++) {\n                        const splatIndex = node.data.indexes[i];\n                        splatTree.splatBuffer.getPosition(splatIndex, tempPosition);\n                        splatTree.splatBuffer.getRotation(splatIndex, tempRotation);\n                        splatTree.splatBuffer.getScale(splatIndex, tempScale);\n\n                        if (tempScale.x <= scaleEpsilon || tempScale.y <= scaleEpsilon || tempScale.z <= scaleEpsilon) {\n                            continue;\n                        }\n\n                        // Simple approximated sphere intersection\n                        const radius = (tempScale.x + tempScale.y + tempScale.z) / 3;\n                        if (ray.intersectSphere(tempPosition, radius, tempHit)) {\n                            outHits.push(tempHit.clone());\n                        }\n\n                        // Raycast against actual splat ellipsoid ... doesn't actually work as well\n                        // as the approximated sphere approach\n                        /*\n                        tempScaleMatrix.makeScale(tempScale.x, tempScale.y, tempScale.z);\n                        tempRotationMatrix.makeRotationFromQuaternion(tempRotation);\n                        fromSphereSpace.copy(tempScaleMatrix).premultiply(tempRotationMatrix);\n                        toSphereSpace.copy(fromSphereSpace).invert();\n                        tempRay.origin.copy(this.ray.origin).sub(tempPosition).applyMatrix4(toSphereSpace);\n                        tempRay.direction.copy(this.ray.direction).transformDirection(toSphereSpace).normalize();\n                        if (tempRay.intersectSphere(origin, 1.0, tempHit)) {\n                            const hitClone = tempHit.clone();\n                            hitClone.origin.applyMatrix4(fromSphereSpace).add(tempPosition);\n                            outHits.push(hitClone);\n                        }\n                        */\n\n                    }\n                 }\n                if (node.children && node.children.length > 0) {\n                    for (let child of node.children) {\n                        this.castRayAtSplatTreeNode(ray, splatTree, child, outHits);\n                    }\n                }\n                return outHits;\n            };\n\n        }();\n    }\n\n    setFromCameraAndScreenPosition(camera, screenPosition, screenDimensions) {\n\n    }\n\n    intersectSplatMesh(splatMesh, outHits = []) {\n\n    }\n\n    castRayAtSplatTreeNode(ray, splatTree, node, outHits = []) {\n\n    }\n}\n","import * as THREE from 'three';\r\n\r\nlet idGen = 0;\r\n\r\nexport class SplatTreeNode {\r\n\r\n    constructor(min, max, depth, id) {\r\n        this.min = new THREE.Vector3().copy(min);\r\n        this.max = new THREE.Vector3().copy(max);\r\n        this.boundingBox = new THREE.Box3(this.min, this.max);\r\n        this.center = new THREE.Vector3().copy(this.max).sub(this.min).multiplyScalar(0.5).add(this.min);\r\n        this.depth = depth;\r\n        this.children = [];\r\n        this.data = null;\r\n        this.id = id || idGen++;\r\n    }\r\n\r\n}\r\n","import * as THREE from 'three';\r\nimport { SplatTreeNode } from './SplatTreeNode.js';\r\n\r\nexport class SplatTree {\r\n\r\n    constructor(maxDepth, maxPositionsPerNode) {\r\n        this.maxDepth = maxDepth;\r\n        this.maxPositionsPerNode = maxPositionsPerNode;\r\n        this.splatBuffer = null;\r\n        this.sceneDimensions = new THREE.Vector3();\r\n        this.sceneMin = new THREE.Vector3();\r\n        this.sceneMax = new THREE.Vector3();\r\n        this.rootNode = null;\r\n        this.addedIndexes = {};\r\n        this.nodesWithIndexes = [];\r\n    }\r\n\r\n    processSplatBuffer(splatBuffer, filterFunc = () => true) {\r\n        this.splatBuffer = splatBuffer;\r\n        this.addedIndexes = {};\r\n        this.nodesWithIndexes = [];\r\n        const splatCount = splatBuffer.getSplatCount();\r\n\r\n        const position = new THREE.Vector3();\r\n        for (let i = 0; i < splatCount; i++) {\r\n            if (filterFunc(i)) {\r\n                splatBuffer.getPosition(i, position);\r\n                if (i === 0 || position.x < this.sceneMin.x) this.sceneMin.x = position.x;\r\n                if (i === 0 || position.x > this.sceneMax.x) this.sceneMax.x = position.x;\r\n                if (i === 0 || position.y < this.sceneMin.y) this.sceneMin.y = position.y;\r\n                if (i === 0 || position.y > this.sceneMax.y) this.sceneMax.y = position.y;\r\n                if (i === 0 || position.z < this.sceneMin.z) this.sceneMin.z = position.z;\r\n                if (i === 0 || position.z > this.sceneMax.z) this.sceneMax.z = position.z;\r\n            }\r\n        }\r\n\r\n        this.sceneDimensions.copy(this.sceneMin).sub(this.sceneMin);\r\n\r\n        const indexes = [];\r\n        for (let i = 0; i < splatCount; i ++) {\r\n            if (filterFunc(i)) {\r\n                indexes.push(i);\r\n            }\r\n        }\r\n        this.rootNode = new SplatTreeNode(this.sceneMin, this.sceneMax, 0);\r\n        this.rootNode.data = {\r\n            'indexes': indexes\r\n        };\r\n        this.processNode(this.rootNode, splatBuffer);\r\n    }\r\n\r\n    processNode(node, splatBuffer) {\r\n        const splatCount = node.data.indexes.length;\r\n\r\n        if (splatCount < this.maxPositionsPerNode || node.depth > this.maxDepth) {\r\n            const newIndexes = [];\r\n            for (let i = 0; i < node.data.indexes.length; i++) {\r\n                if (!this.addedIndexes[node.data.indexes[i]]) {\r\n                    newIndexes.push(node.data.indexes[i]);\r\n                    this.addedIndexes[node.data.indexes[i]] = true;\r\n                }\r\n            }\r\n            node.data.indexes = newIndexes;\r\n            this.nodesWithIndexes.push(node);\r\n            return;\r\n        }\r\n\r\n        const nodeDimensions = new THREE.Vector3().copy(node.max).sub(node.min);\r\n        const halfDimensions = new THREE.Vector3().copy(nodeDimensions).multiplyScalar(0.5);\r\n\r\n        const nodeCenter = new THREE.Vector3().copy(node.min).add(halfDimensions);\r\n\r\n        const childrenBounds = [\r\n            // top section, clockwise from upper-left (looking from above, +Y)\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x - halfDimensions.x, nodeCenter.y, nodeCenter.z - halfDimensions.z),\r\n                           new THREE.Vector3(nodeCenter.x, nodeCenter.y + halfDimensions.y, nodeCenter.z)),\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x, nodeCenter.y, nodeCenter.z - halfDimensions.z),\r\n                           new THREE.Vector3(nodeCenter.x + halfDimensions.x, nodeCenter.y + halfDimensions.y, nodeCenter.z)),\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x, nodeCenter.y, nodeCenter.z),\r\n                           new THREE.Vector3(nodeCenter.x + halfDimensions.x,\r\n                                             nodeCenter.y + halfDimensions.y, nodeCenter.z + halfDimensions.z)),\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x - halfDimensions.x, nodeCenter.y, nodeCenter.z ),\r\n                           new THREE.Vector3(nodeCenter.x, nodeCenter.y + halfDimensions.y, nodeCenter.z + halfDimensions.z)),\r\n\r\n            // bottom section, clockwise from lower-left (looking from above, +Y)\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x - halfDimensions.x,\r\n                                             nodeCenter.y - halfDimensions.y, nodeCenter.z - halfDimensions.z),\r\n                           new THREE.Vector3(nodeCenter.x, nodeCenter.y, nodeCenter.z)),\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x, nodeCenter.y - halfDimensions.y, nodeCenter.z - halfDimensions.z),\r\n                           new THREE.Vector3(nodeCenter.x + halfDimensions.x, nodeCenter.y, nodeCenter.z)),\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x, nodeCenter.y - halfDimensions.y, nodeCenter.z),\r\n                           new THREE.Vector3(nodeCenter.x + halfDimensions.x, nodeCenter.y, nodeCenter.z + halfDimensions.z)),\r\n            new THREE.Box3(new THREE.Vector3(nodeCenter.x - halfDimensions.x, nodeCenter.y - halfDimensions.y, nodeCenter.z),\r\n                           new THREE.Vector3(nodeCenter.x, nodeCenter.y, nodeCenter.z + halfDimensions.z)),\r\n        ];\r\n\r\n        const splatCounts = [];\r\n        const baseIndexes = [];\r\n        for (let i = 0; i < childrenBounds.length; i++) {\r\n            splatCounts[i] = 0;\r\n            baseIndexes[i] = [];\r\n        }\r\n\r\n        const position = new THREE.Vector3();\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const splatIndex = node.data.indexes[i];\r\n            splatBuffer.getPosition(splatIndex, position);\r\n            for (let j = 0; j < childrenBounds.length; j++) {\r\n                if (childrenBounds[j].containsPoint(position)) {\r\n                    splatCounts[j]++;\r\n                    baseIndexes[j].push(splatIndex);\r\n                }\r\n            }\r\n        }\r\n\r\n        for (let i = 0; i < childrenBounds.length; i++) {\r\n            const childNode = new SplatTreeNode(childrenBounds[i].min, childrenBounds[i].max, node.depth + 1);\r\n            childNode.data = {\r\n                'indexes': baseIndexes[i]\r\n            };\r\n            node.children.push(childNode);\r\n        }\r\n\r\n        node.data = {};\r\n        for (let child of node.children) {\r\n            this.processNode(child, splatBuffer);\r\n        }\r\n    }\r\n\r\n\r\n    countLeaves() {\r\n\r\n        let leafCount = 0;\r\n        this.visitLeaves(() => {\r\n            leafCount++;\r\n        });\r\n\r\n        return leafCount;\r\n    }\r\n\r\n    visitLeaves(visitFunc) {\r\n\r\n        const visitLeavesFromNode = (node, visitFunc) => {\r\n            if (node.children.length === 0) visitFunc(node);\r\n            for (let child of node.children) {\r\n                visitLeavesFromNode(child, visitFunc);\r\n            }\r\n        };\r\n\r\n        return visitLeavesFromNode(this.rootNode, visitFunc);\r\n    }\r\n\r\n}\r\n","import * as THREE from 'three';\r\nimport { SplatTree } from './splattree/SplatTree.js';\r\nimport { uintEncodedFloat, rgbaToInteger } from './Util.js';\r\n\r\nexport class SplatMesh extends THREE.Mesh {\r\n\r\n    static buildMesh(splatBuffer, splatAlphaRemovalThreshold = 1, halfPrecisionCovariancesOnGPU = false, devicePixelRatio = 1) {\r\n        const geometry = SplatMesh.buildGeomtery(splatBuffer);\r\n        const material = SplatMesh.buildMaterial();\r\n        return new SplatMesh(splatBuffer, geometry, material, splatAlphaRemovalThreshold, halfPrecisionCovariancesOnGPU, devicePixelRatio);\r\n    }\r\n\r\n    constructor(splatBuffer, geometry, material, splatAlphaRemovalThreshold = 1,\r\n                halfPrecisionCovariancesOnGPU = false, devicePixelRatio = 1) {\r\n        super(geometry, material);\r\n        this.splatBuffer = splatBuffer;\r\n        this.geometry = geometry;\r\n        this.material = material;\r\n        this.splatTree = null;\r\n        this.splatDataTextures = null;\r\n        this.splatAlphaRemovalThreshold = splatAlphaRemovalThreshold;\r\n        this.halfPrecisionCovariancesOnGPU = halfPrecisionCovariancesOnGPU;\r\n        this.devicePixelRatio = devicePixelRatio;\r\n        this.buildSplatTree();\r\n        this.resetLocalSplatDataAndTexturesFromSplatBuffer();\r\n    }\r\n\r\n    static buildMaterial() {\r\n\r\n        const vertexShaderSource = `\r\n            precision highp float;\r\n            #include <common>\r\n\r\n            attribute uint splatIndex;\r\n\r\n            uniform highp sampler2D covariancesTexture;\r\n            uniform highp usampler2D centersColorsTexture;\r\n            uniform vec2 focal;\r\n            uniform vec2 viewport;\r\n            uniform vec2 basisViewport;\r\n            uniform vec2 covariancesTextureSize;\r\n            uniform vec2 centersColorsTextureSize;\r\n\r\n            varying vec4 vColor;\r\n            varying vec2 vUv;\r\n\r\n            varying vec2 vPosition;\r\n\r\n            const vec4 encodeNorm4 = vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);\r\n            const uvec4 mask4 = uvec4(uint(0x000000FF), uint(0x0000FF00), uint(0x00FF0000), uint(0xFF000000));\r\n            const uvec4 shift4 = uvec4(0, 8, 16, 24);\r\n            vec4 uintToRGBAVec (uint u) {\r\n               uvec4 urgba = mask4 & u;\r\n               urgba = urgba >> shift4;\r\n               vec4 rgba = vec4(urgba) * encodeNorm4;\r\n               return rgba;\r\n            }\r\n\r\n            vec2 getDataUV(in int stride, in int offset, in vec2 dimensions) {\r\n                vec2 samplerUV = vec2(0.0, 0.0);\r\n                float d = float(splatIndex * uint(stride) + uint(offset)) / dimensions.x;\r\n                samplerUV.y = float(floor(d)) / dimensions.y;\r\n                samplerUV.x = fract(d);\r\n                return samplerUV;\r\n            }\r\n\r\n            void main () {\r\n                uvec4 sampledCenterColor = texture(centersColorsTexture, getDataUV(1, 0, centersColorsTextureSize));\r\n                vec3 splatCenter = uintBitsToFloat(uvec3(sampledCenterColor.gba));\r\n                vColor = uintToRGBAVec(sampledCenterColor.r);\r\n\r\n                vPosition = position.xy * 2.0;\r\n\r\n                vec4 viewCenter = modelViewMatrix * vec4(splatCenter, 1.0);\r\n                vec4 clipCenter = projectionMatrix * viewCenter;\r\n\r\n                vec2 sampledCovarianceA = texture(covariancesTexture, getDataUV(3, 0, covariancesTextureSize)).rg;\r\n                vec2 sampledCovarianceB = texture(covariancesTexture, getDataUV(3, 1, covariancesTextureSize)).rg;\r\n                vec2 sampledCovarianceC = texture(covariancesTexture, getDataUV(3, 2, covariancesTextureSize)).rg;\r\n\r\n                vec3 cov3D_M11_M12_M13 = vec3(sampledCovarianceA.rg, sampledCovarianceB.r);\r\n                vec3 cov3D_M22_M23_M33 = vec3(sampledCovarianceB.g, sampledCovarianceC.rg);\r\n\r\n                // Compute the 2D covariance matrix from the upper-right portion of the 3D covariance matrix\r\n                mat3 Vrk = mat3(\r\n                    cov3D_M11_M12_M13.x, cov3D_M11_M12_M13.y, cov3D_M11_M12_M13.z,\r\n                    cov3D_M11_M12_M13.y, cov3D_M22_M23_M33.x, cov3D_M22_M23_M33.y,\r\n                    cov3D_M11_M12_M13.z, cov3D_M22_M23_M33.y, cov3D_M22_M23_M33.z\r\n                );\r\n                float s = 1.0 / (viewCenter.z * viewCenter.z);\r\n                mat3 J = mat3(\r\n                    focal.x / viewCenter.z, 0., -(focal.x * viewCenter.x) * s,\r\n                    0., focal.y / viewCenter.z, -(focal.y * viewCenter.y) * s,\r\n                    0., 0., 0.\r\n                );\r\n                mat3 W = transpose(mat3(modelViewMatrix));\r\n                mat3 T = W * J;\r\n                mat3 cov2Dm = transpose(T) * Vrk * T;\r\n                cov2Dm[0][0] += 0.3;\r\n                cov2Dm[1][1] += 0.3;\r\n\r\n                // We are interested in the upper-left 2x2 portion of the projected 3D covariance matrix because\r\n                // we only care about the X and Y values. We want the X-diagonal, cov2Dm[0][0],\r\n                // the Y-diagonal, cov2Dm[1][1], and the correlation between the two cov2Dm[0][1]. We don't\r\n                // need cov2Dm[1][0] because it is a symetric matrix.\r\n                vec3 cov2Dv = vec3(cov2Dm[0][0], cov2Dm[0][1], cov2Dm[1][1]);\r\n\r\n                vec3 ndcCenter = clipCenter.xyz / clipCenter.w;\r\n\r\n                // We now need to solve for the eigen-values and eigen vectors of the 2D covariance matrix\r\n                // so that we can determine the 2D basis for the splat. This is done using the method described\r\n                // here: https://people.math.harvard.edu/~knill/teaching/math21b2004/exhibits/2dmatrices/index.html\r\n                //\r\n                // This is a different approach than in the original work at INRIA. In that work they compute the\r\n                // max extents of the 2D covariance matrix in screen space to form an axis aligned bounding rectangle\r\n                // which forms the geometry that is actually rasterized. They then use the inverse 2D covariance\r\n                // matrix (called 'conic') to determine fragment opacity.\r\n                float a = cov2Dv.x;\r\n                float d = cov2Dv.z;\r\n                float b = cov2Dv.y;\r\n                float D = a * d - b * b;\r\n                float trace = a + d;\r\n                float traceOver2 = 0.5 * trace;\r\n                float term2 = sqrt(trace * trace / 4.0 - D);\r\n                float eigenValue1 = traceOver2 + term2;\r\n                float eigenValue2 = max(traceOver2 - term2, 0.00); // prevent negative eigen value\r\n\r\n                const float maxSplatSize = 1024.0;\r\n                vec2 eigenVector1 = normalize(vec2(b, eigenValue1 - a));\r\n                // since the eigen vectors are orthogonal, we derive the second one from the first\r\n                vec2 eigenVector2 = vec2(eigenVector1.y, -eigenVector1.x);\r\n                vec2 basisVector1 = eigenVector1 * min(sqrt(2.0 * eigenValue1), maxSplatSize);\r\n                vec2 basisVector2 = eigenVector2 * min(sqrt(2.0 * eigenValue2), maxSplatSize);\r\n\r\n                vec2 ndcOffset = vec2(vPosition.x * basisVector1 + vPosition.y * basisVector2) * basisViewport;\r\n\r\n                gl_Position = vec4(ndcCenter.xy + ndcOffset, ndcCenter.z, 1.0);\r\n            }`;\r\n\r\n        const fragmentShaderSource = `\r\n            precision highp float;\r\n            #include <common>\r\n\r\n            uniform vec3 debugColor;\r\n\r\n            varying vec4 vColor;\r\n            varying vec2 vUv;\r\n\r\n            varying vec2 vPosition;\r\n\r\n            void main () {\r\n                // compute the negative squared distance from the center of the splat to the\r\n                // current fragment in the splat's local space.\r\n                float A = -dot(vPosition, vPosition);\r\n                if (A < -4.0) discard;\r\n                vec3 color = vColor.rgb;\r\n                A = exp(A) * vColor.a;\r\n                gl_FragColor = vec4(color.rgb, A);\r\n            }`;\r\n\r\n        const uniforms = {\r\n            'covariancesTexture': {\r\n                'type': 't',\r\n                'value': null\r\n            },\r\n            'centersColorsTexture': {\r\n                'type': 't',\r\n                'value': null\r\n            },\r\n            'focal': {\r\n                'type': 'v2',\r\n                'value': new THREE.Vector2()\r\n            },\r\n            'viewport': {\r\n                'type': 'v2',\r\n                'value': new THREE.Vector2()\r\n            },\r\n            'basisViewport': {\r\n                'type': 'v2',\r\n                'value': new THREE.Vector2()\r\n            },\r\n            'debugColor': {\r\n                'type': 'v3',\r\n                'value': new THREE.Color()\r\n            },\r\n            'covariancesTextureSize': {\r\n                'type': 'v2',\r\n                'value': new THREE.Vector2(1024, 1024)\r\n            },\r\n            'centersColorsTextureSize': {\r\n                'type': 'v2',\r\n                'value': new THREE.Vector2(1024, 1024)\r\n            }\r\n        };\r\n\r\n        const material = new THREE.ShaderMaterial({\r\n            uniforms: uniforms,\r\n            vertexShader: vertexShaderSource,\r\n            fragmentShader: fragmentShaderSource,\r\n            transparent: true,\r\n            alphaTest: 1.0,\r\n            blending: THREE.NormalBlending,\r\n            depthTest: true,\r\n            depthWrite: false,\r\n            side: THREE.DoubleSide\r\n        });\r\n\r\n        return material;\r\n    }\r\n\r\n    static buildGeomtery(splatBuffer) {\r\n\r\n        const splatCount = splatBuffer.getSplatCount();\r\n\r\n        const baseGeometry = new THREE.BufferGeometry();\r\n        baseGeometry.setIndex([0, 1, 2, 0, 2, 3]);\r\n\r\n        const positionsArray = new Float32Array(4 * 3);\r\n        const positions = new THREE.BufferAttribute(positionsArray, 3);\r\n        baseGeometry.setAttribute('position', positions);\r\n        positions.setXYZ(0, -1.0, -1.0, 0.0);\r\n        positions.setXYZ(1, -1.0, 1.0, 0.0);\r\n        positions.setXYZ(2, 1.0, 1.0, 0.0);\r\n        positions.setXYZ(3, 1.0, -1.0, 0.0);\r\n        positions.needsUpdate = true;\r\n\r\n        const geometry = new THREE.InstancedBufferGeometry().copy(baseGeometry);\r\n\r\n        const splatIndexArray = new Uint32Array(splatCount);\r\n        const splatIndexes = new THREE.InstancedBufferAttribute(splatIndexArray, 1, false);\r\n        splatIndexes.setUsage(THREE.DynamicDrawUsage);\r\n        geometry.setAttribute('splatIndex', splatIndexes);\r\n\r\n        geometry.instanceCount = splatCount;\r\n\r\n        return geometry;\r\n    }\r\n\r\n    buildSplatTree() {\r\n\r\n        this.splatTree = new SplatTree(10, 500);\r\n        console.time('SplatTree build');\r\n        const splatColor = new THREE.Vector4();\r\n        this.splatTree.processSplatBuffer(this.splatBuffer, (splatIndex) => {\r\n            this.splatBuffer.getColor(splatIndex, splatColor);\r\n            return splatColor.w > this.splatAlphaRemovalThreshold;\r\n        });\r\n        console.timeEnd('SplatTree build');\r\n\r\n        let leavesWithVertices = 0;\r\n        let avgSplatCount = 0;\r\n        let maxSplatCount = 0;\r\n        let nodeCount = 0;\r\n\r\n        this.splatTree.visitLeaves((node) => {\r\n            const nodeSplatCount = node.data.indexes.length;\r\n            if (nodeSplatCount > 0) {\r\n                avgSplatCount += nodeSplatCount;\r\n                maxSplatCount = Math.max(maxSplatCount, nodeSplatCount);\r\n                nodeCount++;\r\n                leavesWithVertices++;\r\n            }\r\n        });\r\n        console.log(`SplatTree leaves: ${this.splatTree.countLeaves()}`);\r\n        console.log(`SplatTree leaves with splats:${leavesWithVertices}`);\r\n        avgSplatCount = avgSplatCount / nodeCount;\r\n        console.log(`Avg splat count per node: ${avgSplatCount}`);\r\n    }\r\n\r\n    getSplatTree() {\r\n        return this.splatTree;\r\n    }\r\n\r\n    resetLocalSplatDataAndTexturesFromSplatBuffer() {\r\n        this.updateLocalSplatDataFromSplatBuffer();\r\n        this.allocateAndStoreLocalSplatDataInTextures();\r\n    }\r\n\r\n    updateLocalSplatDataFromSplatBuffer() {\r\n        const splatCount = this.splatBuffer.getSplatCount();\r\n        this.covariances = new Float32Array(splatCount * 6);\r\n        this.colors = new Uint8Array(splatCount * 4);\r\n        this.centers = new Float32Array(splatCount * 3);\r\n        this.splatBuffer.fillCovarianceArray(this.covariances);\r\n        this.splatBuffer.fillPositionArray(this.centers);\r\n        this.splatBuffer.fillColorArray(this.colors);\r\n    }\r\n\r\n    allocateAndStoreLocalSplatDataInTextures() {\r\n        const COVARIANCES_ELEMENTS_PER_TEXEL = 2;\r\n        const CENTER_COLORS_ELEMENTS_PER_TEXEL = 4;\r\n        const splatCount = this.splatBuffer.getSplatCount();\r\n\r\n        const covariancesTextureSize = new THREE.Vector2(4096, 1024);\r\n        while (covariancesTextureSize.x * covariancesTextureSize.y * COVARIANCES_ELEMENTS_PER_TEXEL < splatCount * 6) {\r\n            covariancesTextureSize.y *= 2;\r\n        }\r\n\r\n        const centersColorsTextureSize = new THREE.Vector2(4096, 1024);\r\n        while (centersColorsTextureSize.x * centersColorsTextureSize.y * CENTER_COLORS_ELEMENTS_PER_TEXEL < splatCount * 4) {\r\n            centersColorsTextureSize.y *= 2;\r\n        }\r\n\r\n        let covariancesTexture;\r\n        let paddedCovariances;\r\n        if (this.halfPrecisionCovariancesOnGPU) {\r\n            paddedCovariances = new Uint16Array(covariancesTextureSize.x * covariancesTextureSize.y * COVARIANCES_ELEMENTS_PER_TEXEL);\r\n            for (let i = 0; i < this.covariances.length; i++) {\r\n                paddedCovariances[i] = THREE.DataUtils.toHalfFloat(this.covariances[i]);\r\n            }\r\n            covariancesTexture = new THREE.DataTexture(paddedCovariances, covariancesTextureSize.x,\r\n                                                       covariancesTextureSize.y, THREE.RGFormat, THREE.HalfFloatType);\r\n        } else {\r\n            paddedCovariances = new Float32Array(covariancesTextureSize.x * covariancesTextureSize.y * COVARIANCES_ELEMENTS_PER_TEXEL);\r\n            paddedCovariances.set(this.covariances);\r\n            covariancesTexture = new THREE.DataTexture(paddedCovariances, covariancesTextureSize.x,\r\n                                                       covariancesTextureSize.y, THREE.RGFormat, THREE.FloatType);\r\n        }\r\n        covariancesTexture.needsUpdate = true;\r\n        this.material.uniforms.covariancesTexture.value = covariancesTexture;\r\n        this.material.uniforms.covariancesTextureSize.value.copy(covariancesTextureSize);\r\n\r\n        const paddedCenterColors = new Uint32Array(centersColorsTextureSize.x *\r\n                                                   centersColorsTextureSize.y * CENTER_COLORS_ELEMENTS_PER_TEXEL);\r\n        for (let c = 0; c < splatCount; c++) {\r\n            const colorsBase = c * 4;\r\n            const centersBase = c * 3;\r\n            const centerColorsBase = c * 4;\r\n            paddedCenterColors[centerColorsBase] = rgbaToInteger(this.colors[colorsBase], this.colors[colorsBase + 1],\r\n                                                                 this.colors[colorsBase + 2], this.colors[colorsBase + 3]);\r\n            paddedCenterColors[centerColorsBase + 1] = uintEncodedFloat(this.centers[centersBase]);\r\n            paddedCenterColors[centerColorsBase + 2] = uintEncodedFloat(this.centers[centersBase + 1]);\r\n            paddedCenterColors[centerColorsBase + 3] = uintEncodedFloat(this.centers[centersBase + 2]);\r\n        }\r\n        const centersColorsTexture = new THREE.DataTexture(paddedCenterColors, centersColorsTextureSize.x,\r\n                                                           centersColorsTextureSize.y, THREE.RGBAIntegerFormat, THREE.UnsignedIntType);\r\n        centersColorsTexture.internalFormat = 'RGBA32UI';\r\n        centersColorsTexture.needsUpdate = true;\r\n        this.material.uniforms.centersColorsTexture.value = centersColorsTexture;\r\n        this.material.uniforms.centersColorsTextureSize.value.copy(centersColorsTextureSize);\r\n        this.material.uniformsNeedUpdate = true;\r\n\r\n        this.splatDataTextures = {\r\n            'covariances': {\r\n                'data': paddedCovariances,\r\n                'texture': covariancesTexture,\r\n                'size': covariancesTextureSize\r\n            },\r\n            'centerColors': {\r\n                'data': paddedCenterColors,\r\n                'texture': centersColorsTexture,\r\n                'size': centersColorsTextureSize\r\n            }\r\n        };\r\n    }\r\n\r\n    updateSplatDataToDataTextures() {\r\n        this.updateLocalCovarianceDataToDataTexture();\r\n        this.updateLocalCenterColorDataToDataTexture();\r\n    }\r\n\r\n    updateLocalCovarianceDataToDataTexture() {\r\n        this.splatDataTextures.covariances.data.set(this.covariances);\r\n        this.splatDataTextures.covariances.texture.needsUpdate = true;\r\n    }\r\n\r\n    updateLocalCenterColorDataToDataTexture() {\r\n        this.splatDataTextures.centerColors.data.set(this.centerColors);\r\n        this.splatDataTextures.centerColors.texture.needsUpdate = true;\r\n    }\r\n\r\n    updateIndexes(indexes, renderSplatCount) {\r\n        const geometry = this.geometry;\r\n\r\n        geometry.attributes.splatIndex.set(indexes);\r\n        geometry.attributes.splatIndex.needsUpdate = true;\r\n\r\n        geometry.instanceCount = renderSplatCount;\r\n    }\r\n\r\n    updateUniforms = function() {\r\n\r\n        const viewport = new THREE.Vector2();\r\n\r\n        return function(renderDimensions, cameraFocalLengthX, cameraFocalLengthY) {\r\n            const splatCount = this.splatBuffer.getSplatCount();\r\n            if (splatCount > 0) {\r\n                viewport.set(renderDimensions.x * this.devicePixelRatio,\r\n                             renderDimensions.y * this.devicePixelRatio);\r\n                this.material.uniforms.viewport.value.copy(viewport);\r\n                this.material.uniforms.basisViewport.value.set(2.0 / viewport.x, 2.0 / viewport.y);\r\n                this.material.uniforms.focal.value.set(cameraFocalLengthX, cameraFocalLengthY);\r\n                this.material.uniformsNeedUpdate = true;\r\n            }\r\n        };\r\n\r\n    }();\r\n\r\n    getSplatDataTextures() {\r\n        return this.splatDataTextures;\r\n    }\r\n\r\n    getSplatCount() {\r\n        return this.splatBuffer.getSplatCount();\r\n    }\r\n\r\n    getCenters() {\r\n        return this.centers;\r\n    }\r\n\r\n    getColors() {\r\n        return this.colors;\r\n    }\r\n\r\n    getCovariances() {\r\n        return this.covariances;\r\n    }\r\n}\r\n","export class Constants {\r\n\r\n    static DepthMapRange = 1 << 16;\r\n    static MemoryPageSize = 65536;\r\n    static BytesPerFloat = 4;\r\n    static BytesPerInt = 4;\r\n\r\n}\r\n","import SorterWasm from './sorter.wasm';\r\nimport { Constants } from '../Constants.js';\r\n\r\nfunction sortWorker(self) {\r\n\r\n    let wasmInstance;\r\n    let splatCount;\r\n    let indexesOffset;\r\n    let positionsOffset;\r\n    let viewProjOffset;\r\n    let indexesOutOffset;\r\n    let sortBuffersOffset;\r\n    let wasmMemory;\r\n    let positions;\r\n    let countsZero;\r\n\r\n    let Constants;\r\n\r\n    function sort(splatSortCount, splatRenderCount, viewProj, cameraPosition) {\r\n\r\n        // console.time('WASM SORT');\r\n        const sortStartTime = performance.now();\r\n        if (!countsZero) countsZero = new Uint32Array(Constants.DepthMapRange);\r\n        const viewProjArray = new Int32Array(wasmMemory, viewProjOffset, 16);\r\n        for (let i = 0; i < 16; i++) {\r\n            viewProjArray[i] = Math.round(viewProj[i] * 1000.0);\r\n        }\r\n        const frequencies = new Uint32Array(wasmMemory, sortBuffersOffset + splatCount * 4, Constants.DepthMapRange);\r\n        frequencies.set(countsZero);\r\n        wasmInstance.exports.sortIndexes(indexesOffset, positionsOffset, sortBuffersOffset, viewProjOffset,\r\n                                         indexesOutOffset, cameraPosition[0], cameraPosition[1],\r\n                                         cameraPosition[2], Constants.DepthMapRange, splatSortCount, splatRenderCount, splatCount);\r\n        const sortEndTime = performance.now();\r\n        // console.timeEnd('WASM SORT');\r\n\r\n        self.postMessage({\r\n            'sortDone': true,\r\n            'splatSortCount': splatSortCount,\r\n            'splatRenderCount': splatRenderCount,\r\n            'sortTime': sortEndTime - sortStartTime\r\n        });\r\n    }\r\n\r\n    self.onmessage = (e) => {\r\n        if (e.data.positions) {\r\n            positions = e.data.positions;\r\n            const floatPositions = new Float32Array(positions);\r\n            const intPositions = new Int32Array(splatCount * 3);\r\n            for (let i = 0; i < splatCount * 3; i++) {\r\n                intPositions[i] = Math.round(floatPositions[i] * 1000.0);\r\n            }\r\n            new Int32Array(wasmMemory, positionsOffset, splatCount * 3).set(intPositions);\r\n            self.postMessage({\r\n                'sortSetupComplete': true,\r\n            });\r\n        } else if (e.data.sort) {\r\n            const renderCount = e.data.sort.splatRenderCount || 0;\r\n            const sortCount = e.data.sort.splatSortCount || 0;\r\n            sort(sortCount, renderCount, e.data.sort.view, e.data.sort.cameraPosition, e.data.sort.inIndexBuffer);\r\n        } else if (e.data.init) {\r\n            // Yep, this is super hacky and gross :(\r\n            Constants = e.data.init.Constants;\r\n\r\n            splatCount = e.data.init.splatCount;\r\n\r\n            const INDEXES_BYTES_PER_ENTRY = Constants.BytesPerInt;\r\n            const POSITIONS_BYTES_PER_ENTRY = Constants.BytesPerFloat * 3;\r\n\r\n            const sorterWasmBytes = new Uint8Array(e.data.init.sorterWasmBytes);\r\n            const memoryBytesPerVertex = INDEXES_BYTES_PER_ENTRY + POSITIONS_BYTES_PER_ENTRY;\r\n            const memoryRequiredForVertices = splatCount * memoryBytesPerVertex;\r\n            const memoryRequiredForSortBuffers = splatCount * Constants.BytesPerInt * 2 +\r\n                                                 Constants.DepthMapRange * Constants.BytesPerInt * 2;\r\n            const extraMemory = Constants.MemoryPageSize * 32;\r\n            const totalRequiredMemory = memoryRequiredForVertices + memoryRequiredForSortBuffers + extraMemory;\r\n            const totalPagesRequired = Math.floor(totalRequiredMemory / Constants.MemoryPageSize ) + 1;\r\n            const sorterWasmImport = {\r\n                module: {},\r\n                env: {\r\n                    memory: new WebAssembly.Memory({\r\n                        initial: totalPagesRequired * 2,\r\n                        maximum: totalPagesRequired * 3,\r\n                        shared: true,\r\n                    }),\r\n                }\r\n            };\r\n            WebAssembly.compile(sorterWasmBytes)\r\n            .then((wasmModule) => {\r\n                return WebAssembly.instantiate(wasmModule, sorterWasmImport);\r\n            })\r\n            .then((instance) => {\r\n                wasmInstance = instance;\r\n                indexesOffset = 0;\r\n                positionsOffset = splatCount * INDEXES_BYTES_PER_ENTRY;\r\n                viewProjOffset = positionsOffset + splatCount * POSITIONS_BYTES_PER_ENTRY;\r\n                sortBuffersOffset = viewProjOffset + 16 * Constants.BytesPerFloat;\r\n                indexesOutOffset = sortBuffersOffset + splatCount * Constants.BytesPerInt +\r\n                                   Constants.DepthMapRange * Constants.BytesPerInt * 2;\r\n                wasmMemory = sorterWasmImport.env.memory.buffer;\r\n                self.postMessage({\r\n                    'sortSetupPhase1Complete': true,\r\n                    'inIndexBuffer': wasmMemory,\r\n                    'inIndexOffset': 0,\r\n                    'outIndexBuffer': wasmMemory,\r\n                    'outIndexOffset': indexesOutOffset\r\n                });\r\n            });\r\n        }\r\n    };\r\n}\r\n\r\nexport function createSortWorker(splatCount) {\r\n    const worker = new Worker(\r\n        URL.createObjectURL(\r\n            new Blob(['(', sortWorker.toString(), ')(self)'], {\r\n                type: 'application/javascript',\r\n            }),\r\n        ),\r\n    );\r\n\r\n    const sorterWasmBinaryString = atob(SorterWasm);\r\n    const sorterWasmBytes = new Uint8Array(sorterWasmBinaryString.length);\r\n    for (let i = 0; i < sorterWasmBinaryString.length; i++) {\r\n        sorterWasmBytes[i] = sorterWasmBinaryString.charCodeAt(i);\r\n    }\r\n\r\n    worker.postMessage({\r\n        'init': {\r\n            'sorterWasmBytes': sorterWasmBytes.buffer,\r\n            'splatCount': splatCount,\r\n            // Super hacky\r\n            'Constants': {\r\n                'BytesPerFloat': Constants.BytesPerFloat,\r\n                'BytesPerInt': Constants.BytesPerInt,\r\n                'DepthMapRange': Constants.DepthMapRange,\r\n                'MemoryPageSize': Constants.MemoryPageSize\r\n            }\r\n        }\r\n    });\r\n    return worker;\r\n}\r\n","import * as THREE from 'three';\nimport { OrbitControls } from './OrbitControls.js';\nimport { PlyLoader } from './PlyLoader.js';\nimport { SplatLoader } from './SplatLoader.js';\nimport { LoadingSpinner } from './LoadingSpinner.js';\nimport { SceneHelper } from './SceneHelper.js';\nimport { Raycaster } from './raycaster/Raycaster.js';\nimport { SplatMesh } from './SplatMesh.js';\nimport { createSortWorker } from './worker/SortWorker.js';\nimport { Constants } from './Constants.js';\nimport { getCurrentTime } from './Util.js';\n\nconst THREE_CAMERA_FOV = 50;\nconst MINIMUM_DISTANCE_TO_NEW_FOCAL_POINT = .75;\n\nexport class Viewer {\n\n    // 用于stop取消中使用\n    requestAnimationFrameID = undefined;\n    constructor(params = {}) {\n\n        if (!params.cameraUp) params.cameraUp = [0, 1, 0];\n        if (!params.initialCameraPosition) params.initialCameraPosition = [0, 10, 15];\n        if (!params.initialCameraLookAt) params.initialCameraLookAt = [0, 0, 0];\n        if (params.selfDrivenMode === undefined) params.selfDrivenMode = true;\n        if (params.useBuiltInControls === undefined) params.useBuiltInControls = true;\n\n        this.rootElement = params.rootElement;\n        this.usingExternalCamera = params.camera ? true : false;\n        this.usingExternalRenderer = params.renderer ? true : false;\n\n        this.cameraUp = new THREE.Vector3().fromArray(params.cameraUp);\n        this.initialCameraPosition = new THREE.Vector3().fromArray(params.initialCameraPosition);\n        this.initialCameraLookAt = new THREE.Vector3().fromArray(params.initialCameraLookAt);\n\n        this.scene = params.scene;\n        this.renderer = params.renderer;\n        this.camera = params.camera;\n        this.useBuiltInControls = params.useBuiltInControls;\n        this.controls = null;\n\n        this.ignoreDevicePixelRatio = params.ignoreDevicePixelRatio || false;\n        this.devicePixelRatio = this.ignoreDevicePixelRatio ? 1 : window.devicePixelRatio;\n\n        this.selfDrivenMode = params.selfDrivenMode;\n        this.selfDrivenUpdateFunc = this.selfDrivenUpdate.bind(this);\n\n        this.showMeshCursor = false;\n        this.showControlPlane = false;\n        this.showInfo = false;\n\n        this.sceneHelper = null;\n\n        this.sortWorker = null;\n        this.splatRenderCount = 0;\n        this.splatSortCount = 0;\n\n        this.inIndexArray = null;\n\n        this.splatMesh = null;\n\n        this.sortRunning = false;\n        this.selfDrivenModeRunning = false;\n        this.splatRenderingInitialized = false;\n\n        this.raycaster = new Raycaster();\n\n        this.infoPanel = null;\n        this.infoPanelCells = {};\n\n        this.currentFPS = 0;\n        this.lastSortTime = 0;\n\n        this.previousCameraTarget = new THREE.Vector3();\n        this.nextCameraTarget = new THREE.Vector3();\n\n        this.mousePosition = new THREE.Vector2();\n        this.mouseDownPosition = new THREE.Vector2();\n        this.mouseDownTime = null;\n\n        this.initialized = false;\n        this.init();\n\n        this.onKeyDown = (() => {\n\n            const forward = new THREE.Vector3();\n            const tempMatrixLeft = new THREE.Matrix4();\n            const tempMatrixRight = new THREE.Matrix4();\n\n            return function onKeyDown(e) {\n                forward.set(0, 0, -1);\n                forward.transformDirection(this.camera.matrixWorld);\n                tempMatrixLeft.makeRotationAxis(forward, Math.PI / 128);\n                tempMatrixRight.makeRotationAxis(forward, -Math.PI / 128);\n                switch (e.code) {\n                    case 'ArrowLeft':\n                        this.camera.up.transformDirection(tempMatrixLeft);\n                    break;\n                    case 'ArrowRight':\n                        this.camera.up.transformDirection(tempMatrixRight);\n                    break;\n                    case 'KeyC':\n                        this.showMeshCursor = !this.showMeshCursor;\n                    break;\n                    case 'KeyP':\n                        this.showControlPlane = !this.showControlPlane;\n                    break;\n                    case 'KeyI':\n                        this.showInfo = !this.showInfo;\n                        if (this.showInfo) {\n                            this.infoPanel.style.display = 'block';\n                        } else {\n                            this.infoPanel.style.display = 'none';\n                        }\n                    break;\n                }\n            };\n\n        })();\n        this.onMouseUp = (() => {\n\n            const renderDimensions = new THREE.Vector2();\n            const clickOffset = new THREE.Vector2();\n            const toNewFocalPoint = new THREE.Vector3();\n            const outHits = [];\n\n            return function onMouseUp(mouse) {\n                clickOffset.copy(this.mousePosition).sub(this.mouseDownPosition);\n                const mouseUpTime = getCurrentTime();\n                const wasClick = mouseUpTime - this.mouseDownTime < 0.5 && clickOffset.length() < 2;\n                if (!this.transitioningCameraTarget && wasClick) {\n                    this.getRenderDimensions(renderDimensions);\n                    outHits.length = 0;\n                    this.raycaster.setFromCameraAndScreenPosition(this.camera, this.mousePosition, renderDimensions);\n                    this.mousePosition.set(mouse.offsetX, mouse.offsetY);\n                    this.raycaster.intersectSplatMesh(this.splatMesh, outHits);\n                    if (outHits.length > 0) {\n                        const intersectionPoint = outHits[0].origin;\n                        toNewFocalPoint.copy(intersectionPoint).sub(this.camera.position);\n                        if (toNewFocalPoint.length() > MINIMUM_DISTANCE_TO_NEW_FOCAL_POINT) {\n                            this.previousCameraTarget.copy(this.controls.target);\n                            this.nextCameraTarget.copy(intersectionPoint);\n                            this.transitioningCameraTarget = true;\n                            this.transitioningCameraTargetStartTime = getCurrentTime();\n                        }\n                    }\n                }\n            };\n\n        })();\n        this.updateSplatMeshUniforms = (() => {\n\n            const renderDimensions = new THREE.Vector2();\n\n            return function updateSplatMeshUniforms() {\n                const splatCount = this.splatMesh.getSplatCount();\n                if (splatCount > 0) {\n                    this.getRenderDimensions(renderDimensions);\n                    this.cameraFocalLengthX = this.camera.projectionMatrix.elements[0] *\n                                              this.devicePixelRatio * renderDimensions.x * 0.45;\n                                              this.cameraFocalLengthY = this.camera.projectionMatrix.elements[5] *\n                                              this.devicePixelRatio * renderDimensions.y * 0.45;\n                    this.splatMesh.updateUniforms(renderDimensions, this.cameraFocalLengthX, this.cameraFocalLengthY);\n                }\n            };\n\n        })();\n        this.gatherSceneNodes = (() => {\n\n            const nodeRenderList = [];\n            const tempVectorYZ = new THREE.Vector3();\n            const tempVectorXZ = new THREE.Vector3();\n            const tempVector = new THREE.Vector3();\n            const tempMatrix4 = new THREE.Matrix4();\n            const renderDimensions = new THREE.Vector3();\n            const forward = new THREE.Vector3(0, 0, -1);\n\n            const tempMax = new THREE.Vector3();\n            const nodeSize = (node) => {\n                return tempMax.copy(node.max).sub(node.min).length();\n            };\n\n            const MaximumDistanceToSort = 125;\n            const MaximumDistanceToRender = 125;\n\n            return function gatherSceneNodes(gatherAllNodes) {\n\n                this.getRenderDimensions(renderDimensions);\n                const cameraFocalLength = (renderDimensions.y / 2.0) / Math.tan(this.camera.fov / 2.0 * THREE.MathUtils.DEG2RAD);\n                const fovXOver2 = Math.atan(renderDimensions.x / 2.0 / cameraFocalLength);\n                const fovYOver2 = Math.atan(renderDimensions.y / 2.0 / cameraFocalLength);\n                const cosFovXOver2 = Math.cos(fovXOver2);\n                const cosFovYOver2 = Math.cos(fovYOver2);\n                tempMatrix4.copy(this.camera.matrixWorld).invert();\n                tempMatrix4.multiply(this.splatMesh.matrixWorld);\n\n                const splatTree = this.splatMesh.getSplatTree();\n                let nodeRenderCount = 0;\n                let splatRenderCount = 0;\n                const nodeCount = splatTree.nodesWithIndexes.length;\n                for (let i = 0; i < nodeCount; i++) {\n                    const node = splatTree.nodesWithIndexes[i];\n                    tempVector.copy(node.center).applyMatrix4(tempMatrix4);\n                    const distanceToNode = tempVector.length();\n                    tempVector.normalize();\n\n                    tempVectorYZ.copy(tempVector).setX(0).normalize();\n                    tempVectorXZ.copy(tempVector).setY(0).normalize();\n\n                    const cameraAngleXZDot = forward.dot(tempVectorXZ);\n                    const cameraAngleYZDot = forward.dot(tempVectorYZ);\n\n                    const ns = nodeSize(node);\n                    const outOfFovY = cameraAngleYZDot < (cosFovYOver2 - .5);\n                    const outOfFovX = cameraAngleXZDot < (cosFovXOver2 - .5);\n                    if (!gatherAllNodes && ((outOfFovX || outOfFovY || distanceToNode > MaximumDistanceToRender) && distanceToNode > ns)) {\n                        continue;\n                    }\n                    splatRenderCount += node.data.indexes.length;\n                    nodeRenderList[nodeRenderCount] = node;\n                    node.data.distanceToNode = distanceToNode;\n                    nodeRenderCount++;\n                }\n\n                nodeRenderList.length = nodeRenderCount;\n                nodeRenderList.sort((a, b) => {\n                    if (a.data.distanceToNode < b.data.distanceToNode) return 1;\n                    else return -1;\n                });\n\n                this.splatRenderCount = splatRenderCount;\n                this.splatSortCount = 0;\n                let currentByteOffset = splatRenderCount * Constants.BytesPerInt;\n                for (let i = 0; i < nodeRenderCount; i++) {\n                    const node = nodeRenderList[i];\n                    const shouldSort = node.data.distanceToNode <= MaximumDistanceToSort;\n                    if (shouldSort) {\n                        this.splatSortCount += node.data.indexes.length;\n                    }\n                    const windowSizeInts = node.data.indexes.length;\n                    const windowSizeBytes = windowSizeInts * Constants.BytesPerInt;\n                    let destView = new Uint32Array(this.inIndexArray.buffer, currentByteOffset - windowSizeBytes, windowSizeInts);\n                    destView.set(node.data.indexes);\n                    currentByteOffset -= windowSizeBytes;\n                }\n\n            };\n\n        })();\n        this.updateFPS = (() => {\n\n            let lastCalcTime = getCurrentTime();\n            let frameCount = 0;\n\n            return function updateFPS() {\n                const currentTime = getCurrentTime();\n                const calcDelta = currentTime - lastCalcTime;\n                if (calcDelta >= 1.0) {\n                    this.currentFPS = frameCount;\n                    frameCount = 0;\n                    lastCalcTime = currentTime;\n                } else {\n                    frameCount++;\n                }\n            };\n\n        })();\n        this.timingSensitiveUpdates = (() => {\n\n            let lastUpdateTime;\n\n            return function timingSensitiveUpdates() {\n                const currentTime = getCurrentTime();\n                if (!lastUpdateTime) lastUpdateTime = currentTime;\n                const timeDelta = currentTime - lastUpdateTime;\n\n                this.updateCameraTransition(currentTime);\n                this.updateFocusMarker(timeDelta);\n\n                lastUpdateTime = currentTime;\n            };\n\n        })();\n        this.updateCameraTransition = (() => {\n\n            let tempCameraTarget = new THREE.Vector3();\n            let toPreviousTarget = new THREE.Vector3();\n            let toNextTarget = new THREE.Vector3();\n\n            return function updateCameraTransition(currentTime) {\n                if (this.transitioningCameraTarget) {\n                    toPreviousTarget.copy(this.previousCameraTarget).sub(this.camera.position).normalize();\n                    toNextTarget.copy(this.nextCameraTarget).sub(this.camera.position).normalize();\n                    const rotationAngle = Math.acos(toPreviousTarget.dot(toNextTarget));\n                    const rotationSpeed = rotationAngle / (Math.PI / 3) * .65 + .3;\n                    const t = (rotationSpeed / rotationAngle * (currentTime - this.transitioningCameraTargetStartTime));\n                    tempCameraTarget.copy(this.previousCameraTarget).lerp(this.nextCameraTarget, t);\n                    this.camera.lookAt(tempCameraTarget);\n                    this.controls.target.copy(tempCameraTarget);\n                    if (t >= 1.0) {\n                        this.transitioningCameraTarget = false;\n                    }\n                }\n            };\n\n        })();\n        this.updateMeshCursor = (() => {\n\n            const outHits = [];\n            const renderDimensions = new THREE.Vector2();\n\n            return function updateMeshCursor() {\n                if (this.showMeshCursor) {\n                    this.getRenderDimensions(renderDimensions);\n                    outHits.length = 0;\n                    this.raycaster.setFromCameraAndScreenPosition(this.camera, this.mousePosition, renderDimensions);\n                    this.raycaster.intersectSplatMesh(this.splatMesh, outHits);\n                    if (outHits.length > 0) {\n                        this.sceneHelper.setMeshCursorVisibility(true);\n                        this.sceneHelper.positionAndOrientMeshCursor(outHits[0].origin, this.camera);\n                    } else {\n                        this.sceneHelper.setMeshCursorVisibility(false);\n                    }\n                } else {\n                    this.sceneHelper.setMeshCursorVisibility(false);\n                }\n            };\n\n        })();\n        this.updateForRendererSizeChanges = (() => {\n\n            const lastRendererSize = new THREE.Vector2();\n            const currentRendererSize = new THREE.Vector2();\n\n            return function updateForRendererSizeChanges() {\n                this.renderer.getSize(currentRendererSize);\n                if (currentRendererSize.x !== lastRendererSize.x || currentRendererSize.y !== lastRendererSize.y) {\n                    if (!this.usingExternalCamera) {\n                        this.camera.aspect = currentRendererSize.x / currentRendererSize.y;\n                        this.camera.updateProjectionMatrix();\n                    }\n                    if (this.splatRenderingInitialized) {\n                        this.updateSplatMeshUniforms();\n                    }\n                    lastRendererSize.copy(currentRendererSize);\n                }\n            };\n\n        })();\n        this.updateInfo = (() => {\n\n            const renderDimensions = new THREE.Vector2();\n\n            return function updateInfo() {\n                if (this.showInfo) {\n                    const splatCount = this.splatMesh.getSplatCount();\n                    this.getRenderDimensions(renderDimensions);\n\n                    const cameraPos = this.camera.position;\n                    const cameraPosString = `[${cameraPos.x.toFixed(5)}, ${cameraPos.y.toFixed(5)}, ${cameraPos.z.toFixed(5)}]`;\n                    this.infoPanelCells.cameraPosition.innerHTML = cameraPosString;\n\n                    const cameraLookAt = this.controls.target;\n                    const cameraLookAtString = `[${cameraLookAt.x.toFixed(5)}, ${cameraLookAt.y.toFixed(5)}, ${cameraLookAt.z.toFixed(5)}]`;\n                    this.infoPanelCells.cameraLookAt.innerHTML = cameraLookAtString;\n\n                    const cameraUp = this.camera.up;\n                    const cameraUpString = `[${cameraUp.x.toFixed(5)}, ${cameraUp.y.toFixed(5)}, ${cameraUp.z.toFixed(5)}]`;\n                    this.infoPanelCells.cameraUp.innerHTML = cameraUpString;\n\n                    if (this.showMeshCursor) {\n                        const cursorPos = this.sceneHelper.meshCursor.position;\n                        const cursorPosString = `[${cursorPos.x.toFixed(5)}, ${cursorPos.y.toFixed(5)}, ${cursorPos.z.toFixed(5)}]`;\n                        this.infoPanelCells.cursorPosition.innerHTML = cursorPosString;\n                    } else {\n                        this.infoPanelCells.cursorPosition.innerHTML = 'N/A';\n                    }\n\n                    this.infoPanelCells.fps.innerHTML = this.currentFPS;\n                    this.infoPanelCells.renderWindow.innerHTML = `${renderDimensions.x} x ${renderDimensions.y}`;\n\n                    const renderPct = this.splatRenderCount / splatCount * 100;\n                    this.infoPanelCells.renderSplatCount.innerHTML =\n                        `${this.splatRenderCount} splats out of ${splatCount} (${renderPct.toFixed(2)}%)`;\n\n                    this.infoPanelCells.sortTime.innerHTML = `${this.lastSortTime.toFixed(3)} ms`;\n                }\n            };\n\n        })();\n        this.updateFocusMarker = (() => {\n\n            const renderDimensions = new THREE.Vector2();\n            let wasTransitioning = false;\n\n            return function updateFocusMarker(timeDelta) {\n                this.getRenderDimensions(renderDimensions);\n                const fadeInSpeed = 10.0;\n                const fadeOutSpeed = 2.5;\n                if (this.transitioningCameraTarget) {\n                    this.sceneHelper.setFocusMarkerVisibility(true);\n                    const currentFocusMarkerOpacity = Math.max(this.sceneHelper.getFocusMarkerOpacity(), 0.0);\n                    let newFocusMarkerOpacity = Math.min(currentFocusMarkerOpacity + fadeInSpeed * timeDelta, 1.0);\n                    this.sceneHelper.setFocusMarkerOpacity(newFocusMarkerOpacity);\n                    this.sceneHelper.updateFocusMarker(this.nextCameraTarget, this.camera, renderDimensions);\n                    wasTransitioning = true;\n                } else {\n                    let currentFocusMarkerOpacity;\n                    if (wasTransitioning) currentFocusMarkerOpacity = 1.0;\n                    else currentFocusMarkerOpacity = Math.min(this.sceneHelper.getFocusMarkerOpacity(), 1.0);\n                    if (currentFocusMarkerOpacity > 0) {\n                        this.sceneHelper.updateFocusMarker(this.nextCameraTarget, this.camera, renderDimensions);\n                        let newFocusMarkerOpacity = Math.max(currentFocusMarkerOpacity - fadeOutSpeed * timeDelta, 0.0);\n                        this.sceneHelper.setFocusMarkerOpacity(newFocusMarkerOpacity);\n                        if (newFocusMarkerOpacity === 0.0) this.sceneHelper.setFocusMarkerVisibility(false);\n                    }\n                    wasTransitioning = false;\n                }\n            };\n\n        })();\n        this.render = function render() {\n\n            return function() {\n                const hasRenderables = (scene) => {\n                    for (let child of scene.children) {\n                        if (child.visible) {\n                        return true;\n                        }\n                    }\n                    return false;\n                };\n\n                const savedAuoClear = this.renderer.autoClear;\n                this.renderer.autoClear = false;\n                if (hasRenderables(this.scene)) this.renderer.render(this.scene, this.camera);\n                this.renderer.render(this.splatMesh, this.camera);\n                if (this.sceneHelper.getFocusMarkerOpacity() > 0.0) this.renderer.render(this.sceneHelper.focusMarker, this.camera);\n                if (this.showControlPlane) this.renderer.render(this.sceneHelper.controlPlane, this.camera);\n                this.renderer.autoClear = savedAuoClear;\n            };\n\n        }();\n        this.updateView = function updateView() {\n\n            const tempMatrix = new THREE.Matrix4();\n            const cameraPositionArray = [];\n            const lastSortViewDir = new THREE.Vector3(0, 0, -1);\n            const sortViewDir = new THREE.Vector3(0, 0, -1);\n            const lastSortViewPos = new THREE.Vector3();\n            const sortViewOffset = new THREE.Vector3();\n\n            return function updateView(force = false, gatherAllNodes = false) {\n                if (!force) {\n                    sortViewDir.set(0, 0, -1).applyQuaternion(this.camera.quaternion);\n                    let needsRefreshForRotation = false;\n                    let needsRefreshForPosition = false;\n                    if (sortViewDir.dot(lastSortViewDir) <= 0.95) needsRefreshForRotation = true;\n                    if (sortViewOffset.copy(this.camera.position).sub(lastSortViewPos).length() >= 1.0) needsRefreshForPosition = true;\n                    if (!needsRefreshForRotation && !needsRefreshForPosition) return;\n                }\n\n                tempMatrix.copy(this.camera.matrixWorld).invert();\n                tempMatrix.premultiply(this.camera.projectionMatrix);\n                tempMatrix.multiply(this.splatMesh.matrixWorld);\n                cameraPositionArray[0] = this.camera.position.x;\n                cameraPositionArray[1] = this.camera.position.y;\n                cameraPositionArray[2] = this.camera.position.z;\n\n                if (!this.sortRunning) {\n                    this.gatherSceneNodes(gatherAllNodes);\n                    this.sortRunning = true;\n                    this.sortWorker.postMessage({\n                        sort: {\n                            'view': tempMatrix.elements,\n                            'cameraPosition': cameraPositionArray,\n                            'splatRenderCount': this.splatRenderCount,\n                            'splatSortCount': this.splatSortCount,\n                            'inIndexBuffer': this.inIndexArray.buffer\n                        }\n                    });\n                    lastSortViewPos.copy(this.camera.position);\n                    lastSortViewDir.copy(sortViewDir);\n                }\n            };\n\n        }();\n    }\n\n    init() {\n\n        if (this.initialized) return;\n\n        if (!this.rootElement && !this.usingExternalRenderer) {\n            this.rootElement = document.createElement('div');\n            this.rootElement.style.width = '100%';\n            this.rootElement.style.height = '100%';\n            document.body.appendChild(this.rootElement);\n        }\n\n        const renderDimensions = new THREE.Vector2();\n        this.getRenderDimensions(renderDimensions);\n\n        if (!this.usingExternalCamera) {\n            this.camera = new THREE.PerspectiveCamera(THREE_CAMERA_FOV, renderDimensions.x / renderDimensions.y, 0.1, 500);\n            this.camera.position.copy(this.initialCameraPosition);\n            this.camera.lookAt(this.initialCameraLookAt);\n            this.camera.up.copy(this.cameraUp).normalize();\n        }\n\n        if (!this.usingExternalRenderer) {\n            this.renderer = new THREE.WebGLRenderer({\n                antialias: false,\n                precision: 'highp'\n            });\n            this.renderer.setPixelRatio(this.devicePixelRatio);\n            this.renderer.autoClear = true;\n            this.renderer.setClearColor(0.0, 0.0, 0.0, 0.0);\n            this.renderer.setSize(renderDimensions.x, renderDimensions.y);\n        }\n\n        this.scene = this.scene || new THREE.Scene();\n        this.sceneHelper = new SceneHelper(this.scene);\n        this.sceneHelper.setupMeshCursor();\n        this.sceneHelper.setupFocusMarker();\n        this.sceneHelper.setupControlPlane();\n\n        if (this.useBuiltInControls) {\n            this.controls = new OrbitControls(this.camera, this.renderer.domElement);\n            this.controls.listenToKeyEvents(window);\n            this.controls.rotateSpeed = 0.5;\n            this.controls.maxPolarAngle = Math.PI * .75;\n            this.controls.minPolarAngle = 0.1;\n            this.controls.enableDamping = true;\n            this.controls.dampingFactor = 0.05;\n            this.controls.target.copy(this.initialCameraLookAt);\n            this.rootElement.addEventListener('pointermove', this.onMouseMove.bind(this), false);\n            this.rootElement.addEventListener('pointerdown', this.onMouseDown.bind(this), false);\n            this.rootElement.addEventListener('pointerup', this.onMouseUp.bind(this), false);\n            window.addEventListener('keydown', this.onKeyDown.bind(this), false);\n        }\n\n        if (!this.usingExternalRenderer) {\n            const resizeObserver = new ResizeObserver(() => {\n                this.getRenderDimensions(renderDimensions);\n                this.renderer.setSize(renderDimensions.x, renderDimensions.y);\n            });\n            resizeObserver.observe(this.rootElement);\n            this.rootElement.appendChild(this.renderer.domElement);\n        }\n\n        this.setupInfoPanel();\n\n        this.loadingSpinner = new LoadingSpinner(null, this.rootElement);\n        this.loadingSpinner.hide();\n\n        this.initialized = true;\n    }\n\n    onKeyDown(e) {\n\n    }\n\n    onMouseMove(mouse) {\n        this.mousePosition.set(mouse.offsetX, mouse.offsetY);\n    }\n\n    onMouseDown() {\n        this.mouseDownPosition.copy(this.mousePosition);\n        this.mouseDownTime = getCurrentTime();\n    }\n\n    onMouseUp(mouse) {\n\n    }\n\n    getRenderDimensions(outDimensions) {\n        if (this.rootElement) {\n            outDimensions.x = this.rootElement.offsetWidth;\n            outDimensions.y = this.rootElement.offsetHeight;\n        } else {\n            this.renderer.getSize(outDimensions);\n        }\n    };\n\n    setupInfoPanel() {\n        this.infoPanel = document.createElement('div');\n        this.infoPanel.style.position = 'absolute';\n        this.infoPanel.style.padding = '10px';\n        this.infoPanel.style.backgroundColor = '#cccccc';\n        this.infoPanel.style.border = '#aaaaaa 1px solid';\n        this.infoPanel.style.zIndex = 100;\n        this.infoPanel.style.width = '375px';\n        this.infoPanel.style.fontFamily = 'arial';\n        this.infoPanel.style.fontSize = '10pt';\n        this.infoPanel.style.textAlign = 'left';\n\n        const layout = [\n            ['Camera position', 'cameraPosition'],\n            ['Camera look-at', 'cameraLookAt'],\n            ['Camera up', 'cameraUp'],\n            ['Cursor position', 'cursorPosition'],\n            ['FPS', 'fps'],\n            ['Render window', 'renderWindow'],\n            ['Rendering:', 'renderSplatCount'],\n            ['Sort time', 'sortTime']\n        ];\n\n        const infoTable = document.createElement('div');\n        infoTable.style.display = 'table';\n\n        for (let layoutEntry of layout) {\n            const row = document.createElement('div');\n            row.style.display = 'table-row';\n\n            const labelCell = document.createElement('div');\n            labelCell.style.display = 'table-cell';\n            labelCell.style.width = '110px';\n            labelCell.innerHTML = `${layoutEntry[0]}: `;\n\n            const spacerCell = document.createElement('div');\n            spacerCell.style.display = 'table-cell';\n            spacerCell.style.width = '10px';\n            spacerCell.innerHTML = ' ';\n\n            const infoCell = document.createElement('div');\n            infoCell.style.display = 'table-cell';\n            infoCell.innerHTML = '';\n\n            this.infoPanelCells[layoutEntry[1]] = infoCell;\n\n            row.appendChild(labelCell);\n            row.appendChild(spacerCell);\n            row.appendChild(infoCell);\n\n            infoTable.appendChild(row);\n        }\n\n        this.infoPanel.appendChild(infoTable);\n        this.infoPanel.style.display = 'none';\n        this.renderer.domElement.parentElement.prepend(this.infoPanel);\n    }\n\n    updateSplatMeshUniforms() {\n\n    }\n\n    loadFile(fileURL, options = {}) {\n        if (options.position) options.position = new THREE.Vector3().fromArray(options.position);\n        if (options.orientation) options.orientation = new THREE.Quaternion().fromArray(options.orientation);\n        options.splatAlphaRemovalThreshold = options.splatAlphaRemovalThreshold || 1;\n        options.halfPrecisionCovariancesOnGPU = !!options.halfPrecisionCovariancesOnGPU;\n        if (options.showLoadingSpinner !== false) options.showLoadingSpinner = true;\n\n        if (options.showLoadingSpinner) this.loadingSpinner.show();\n        const downloadProgress = (percent, percentLabel) => {\n            if (options.showLoadingSpinner) {\n                if (percent == 100) {\n                    this.loadingSpinner.setMessage(`Download complete!`);\n                } else {\n                    const suffix = percentLabel ? `: ${percentLabel}` : `...`;\n                    this.loadingSpinner.setMessage(`Downloading${suffix}`);\n                }\n            }\n            if (options.onProgress) options.onProgress(percent, percentLabel, 'downloading');\n        };\n\n        return new Promise((resolve, reject) => {\n            let fileLoadPromise;\n            if (fileURL.endsWith('.splat')) {\n                fileLoadPromise = new SplatLoader().loadFromURL(fileURL, downloadProgress);\n            } else if (fileURL.endsWith('.ply')) {\n                fileLoadPromise = new PlyLoader().loadFromURL(fileURL, downloadProgress);\n            } else {\n                reject(new Error(`Viewer::loadFile -> File format not supported: ${fileURL}`));\n            }\n            fileLoadPromise\n            .then((splatBuffer) => {\n                if (options.showLoadingSpinner) this.loadingSpinner.hide();\n                if (options.onProgress) options.onProgress(0, '0%', 'processing');\n                this.loadSplatBuffer(splatBuffer, options).then(() => {\n                    if (options.onProgress) options.onProgress(100, '100%', 'processing');\n                    resolve();\n                });\n            })\n            .catch((e) => {\n                reject(new Error(`Viewer::loadFile -> Could not load file ${fileURL}`));\n            });\n        });\n    }\n\n    loadSplatBuffer(splatBuffer, options) {\n        if (options.showLoadingSpinner !== false) options.showLoadingSpinner = true;\n        return new Promise((resolve) => {\n            if (options.showLoadingSpinner) {\n                this.loadingSpinner.show();\n                this.loadingSpinner.setMessage(`Processing splats...`);\n            }\n            window.setTimeout(() => {\n                this.setupSplatMesh(splatBuffer, options.splatAlphaRemovalThreshold, options.position,\n                                    options.orientation, options.halfPrecisionCovariancesOnGPU, this.devicePixelRatio);\n                this.setupSortWorker(splatBuffer).then(() => {\n                    if (options.showLoadingSpinner) this.loadingSpinner.hide();\n                    resolve();\n                });\n            }, 1);\n        });\n    }\n\n    setupSplatMesh(splatBuffer, splatAlphaRemovalThreshold = 1, position = new THREE.Vector3(), quaternion = new THREE.Quaternion(),\n                   halfPrecisionCovariancesOnGPU = false, devicePixelRatio = 1) {\n        const splatCount = splatBuffer.getSplatCount();\n        console.log(`Splat count: ${splatCount}`);\n\n        this.splatMesh = SplatMesh.buildMesh(splatBuffer, splatAlphaRemovalThreshold, halfPrecisionCovariancesOnGPU, devicePixelRatio);\n        this.splatMesh.position.copy(position);\n        this.splatMesh.quaternion.copy(quaternion);\n        this.splatMesh.frustumCulled = false;\n        this.updateSplatMeshUniforms();\n\n        this.splatRenderCount = splatCount;\n    }\n\n    setupSortWorker(splatBuffer) {\n        return new Promise((resolve) => {\n            const splatCount = splatBuffer.getSplatCount();\n            this.sortWorker = createSortWorker(splatCount);\n            this.sortWorker.onmessage = (e) => {\n                if (e.data.sortDone) {\n                    this.sortRunning = false;\n                    this.splatMesh.updateIndexes(this.outIndexArray, e.data.splatRenderCount);\n                    this.lastSortTime = e.data.sortTime;\n                } else if (e.data.sortCanceled) {\n                    this.sortRunning = false;\n                } else if (e.data.sortSetupPhase1Complete) {\n                    console.log('Sorting web worker WASM setup complete.');\n                    this.sortWorker.postMessage({\n                        'positions': this.splatMesh.getCenters().buffer\n                    });\n                    this.outIndexArray = new Uint32Array(e.data.outIndexBuffer, e.data.outIndexOffset, splatBuffer.getSplatCount());\n                    this.inIndexArray = new Uint32Array(e.data.inIndexBuffer, e.data.inIndexOffset, splatBuffer.getSplatCount());\n                    for (let i = 0; i < splatCount; i++) this.inIndexArray[i] = i;\n                } else if (e.data.sortSetupComplete) {\n                    console.log('Sorting web worker ready.');\n                    this.splatMesh.updateIndexes(this.outIndexArray, splatBuffer.getSplatCount());\n                    const splatDataTextures = this.splatMesh.getSplatDataTextures();\n                    const covariancesTextureSize = splatDataTextures.covariances.size;\n                    const centersColorsTextureSize = splatDataTextures.centerColors.size;\n                    console.log('Covariances texture size: ' + covariancesTextureSize.x + ' x ' + covariancesTextureSize.y);\n                    console.log('Centers/colors texture size: ' + centersColorsTextureSize.x + ' x ' + centersColorsTextureSize.y);\n                    this.updateView(true, true);\n                    this.splatRenderingInitialized = true;\n                    resolve();\n                }\n            };\n        });\n    }\n\n    gatherSceneNodes(gatherAllNodes) {\n\n    }\n\n    start() {\n        if (this.selfDrivenMode) {\n            this.requestAnimationFrameID = requestAnimationFrame(this.selfDrivenUpdateFunc);\n            this.selfDrivenModeRunning = true;\n        } else {\n            throw new Error('Cannot start viewer unless it is in self driven mode.');\n        }\n    }\n\n    stop() {\n        if (this.selfDrivenMode && this.selfDrivenModeRunning) {\n            cancelAnimationFrame(this.requestAnimationFrameID);\n            this.selfDrivenModeRunning = false;\n        }\n    }\n\n    updateFPS() {\n\n    }\n\n    updateForRendererSizeChanges() {\n\n    }\n\n    selfDrivenUpdate() {\n        if (this.selfDrivenMode) {\n            this.requestAnimationFrameID = requestAnimationFrame(this.selfDrivenUpdateFunc);\n        }\n        this.update();\n        this.render();\n    }\n\n    update() {\n        if (this.controls) {\n            this.controls.update();\n        }\n        this.updateView();\n        this.updateForRendererSizeChanges();\n        this.updateMeshCursor();\n        this.updateFPS();\n        this.timingSensitiveUpdates();\n        this.updateInfo();\n        this.updateControlPlane();\n    }\n\n    timingSensitiveUpdates() {\n\n    }\n\n    updateCameraTransition(currentTime) {\n\n    }\n\n    updateFocusMarker(timeDelta) {\n\n    }\n\n    updateMeshCursor() {\n\n    }\n\n    updateInfo() {\n\n    }\n\n    updateControlPlane() {\n        if (this.showControlPlane) {\n            this.sceneHelper.setControlPlaneVisibility(true);\n            this.sceneHelper.positionAndOrientControlPlane(this.controls.target, this.camera.up);\n        } else {\n            this.sceneHelper.setControlPlaneVisibility(false);\n        }\n    }\n\n    render() {\n\n    }\n\n    updateView(force = false, gatherAllNodes = false) {\n\n    }\n\n    getSplatMesh() {\n        return this.splatMesh;\n    }\n}\n","\u0000asm\u0001\u0000\u0000\u0000\u0000\f\u0006dylink\u0000\u0000\u0000\u0000\u0000\u0001\u0017\u0003`\u0000\u0000`\f}}}\u0000`\u0000\u0001\u0002\u0012\u0001\u0003env\u0006memory\u0002\u0003\u0000��\u0004\u0003\u0004\u0003\u0000\u0001\u0002\u00079\u0003\u0011__wasm_call_ctors\u0000\u0000\u000bsortIndexes\u0000\u0001\u0013emscripten_tls_init\u0000\u0002\n�\u0004\u0003\u0003\u0000\u0001\u000b�\u0004\u0001\u0005\u0002@ \n \tk\"\u000e \nI\"\u0010\u0004@A����\u0007!\fA����x!\u000f \u000e!\r\u0003@ \u0002 \rA\u0002t\"\tj \u0001 \u0000 \tj(\u0002\u0000A\flj\"\t(\u0002\u0004 \u0003(\u0002\u0018l \t(\u0002\u0000 \u0003(\u0002\blj \t(\u0002\b \u0003(\u0002(lj\"\t6\u0002\u0000 \t \f \t \fH\u001b!\f \t \u000f \t \u000fJ\u001b!\u000f \rA\u0001j\"\r \nG\r\u0000\u000b \u0002 \u000bA\u0002tj!\r \b� \u000f� \f���!\u0005 \u0010E\r\u0001 \u000e!\t\u0003@ \r\u0002 \u0005 \u0002 \tA\u0002tj(\u0002\u0000 \fk��\"\u0006�C\u0000\u0000\u0000O]\u0004@ \u0006�\f\u0001\u000bA����x\u000bA\u0002tj\"\u0001 \u0001(\u0002\u0000A\u0001j6\u0002\u0000 \tA\u0001j\"\t \nG\r\u0000\u000b\f\u0001\u000b \u0002 \u000bA\u0002tj!\r \b�C\u0000\u0000���!\u0005A����\u0007!\f\u000b \bA\u0002O\u0004@ \r(\u0002\u0000!\u0003A\u0001!\t\u0003@ \u0002 \t \u000bjA\u0002tj\"\u0001 \u0001(\u0002\u0000 \u0003j\"\u00036\u0002\u0000 \tA\u0001j\"\t \bG\r\u0000\u000b\u000b \u000eA\u0000J\u0004@ \u000e!\t\u0003@ \u0004 \tA\u0001k\"\u0001A\u0002t\"\u0003j \u0000 \u0003j(\u0002\u00006\u0002\u0000 \tA\u0001J!\u0003 \u0001!\t \u0003\r\u0000\u000b\u000b \u000e \nA\u0001k\"\u0001L\u0004@ \u0001!\t\u0003@ \u0004 \u0001 \u0002\u0002 \u0005 \u0002 \tA\u0002t\"\u0003j(\u0002\u0000 \fk��\"\u0006�C\u0000\u0000\u0000O]\u0004@ \u0006�\f\u0001\u000bA����x\u000b \u000bjA\u0002tj\"\b(\u0002\u0000A\u0001k\"\nkA\u0002tj \u0000 \u0003j(\u0002\u00006\u0002\u0000 \b \n6\u0002\u0000 \t \u000eJ!\u0003 \tA\u0001k!\t \u0003\r\u0000\u000b\u000b\u000b\u0004\u0000A\u0000\u000b"],"names":["tempVector3A","THREE","Vector3","tempVector3B","tempVector4A","Vector4","tempVector4B","tempQuaternion4A","Quaternion","tempQuaternion4B","fbf","tbf","SplatBuffer","static","BytesPerPosition","BytesPerScale","BytesPerColor","BytesPerRotation","ScaleRange","constructor","bufferData","this","headerBufferData","ArrayBuffer","HeaderSizeBytes","headerArrayUint8","Uint8Array","headerArrayUint32","Uint32Array","headerArrayFloat32","Float32Array","set","versionMajor","versionMinor","headerExtraK","compressionLevel","splatCount","bucketSize","bucketCount","bucketBlockSize","halfBucketBlockSize","bytesPerBucket","compressionScaleRange","CompressionLevels","compressionScaleFactor","dataBufferSizeBytes","byteLength","splatBufferData","bytesPerPosition","bytesPerScale","bytesPerColor","bytesPerRotation","bytesPerSplat","bind","linkBufferArrays","FloatArray","Uint16Array","positionArray","PositionComponentCount","scaleArray","ScaleComponentCount","colorArray","ColorComponentCount","rotationArray","RotationComponentCount","bucketsBase","f","DataUtils","fromHalfFloat","toHalfFloat","getHeaderBufferData","getSplatBufferData","getPosition","index","outPosition","bucket","positionBase","sf","sr","bucketIndex","Math","floor","x","y","z","setPosition","position","maxR","clamp","round","getScale","outScale","scaleBase","setScale","scale","getRotation","outRotation","rotationBase","setRotation","rotation","w","getColor","outColor","colorBase","setColor","color","getSplatCount","fillCovarianceArray","covarianceArray","rotationMatrix","Matrix3","scaleMatrix","covarianceMatrix","tempMatrix4","Matrix4","i","makeScale","setFromMatrix4","makeRotationFromQuaternion","copy","multiply","M","elements","CovarianceSizeFloats","fillPositionArray","outPositionArray","fillScaleArray","outScaleArray","fillRotationArray","outRotationArray","fillColorArray","outColorArray","swapVertices","indexA","indexB","floatView","int32View","Int32Array","buffer","uintEncodedFloat","fetchWithProgress","path","onProgress","Promise","resolve","reject","fetch","then","async","data","reader","body","getReader","bytesDownloaded","_fileSize","headers","get","fileSize","parseInt","undefined","chunks","value","chunk","done","read","Blob","arrayBuffer","percent","percentLabel","length","toFixed","push","error","val","min","max","getCurrentTime","performance","now","SplatBufferBucketSize","PlyParser","plyBuffer","decodeHeader","decoder","TextDecoder","headerOffset","headerText","console","log","readChunkSize","Error","headerChunk","decode","endHeaderTestChunk","includes","headerLines","split","propertyTypes","line","trim","startsWith","splatCountMatch","match","propertyMatch","propertyType","vertexByteOffset","indexOf","vertexData","DataView","readRawVertexFast","offset","fieldOffsets","propertiesToRead","outVertex","rawVertex","property","getFloat32","getUint8","parseToSplatBuffer","minimumAlpha","startTime","nRestCoeffs","propertyName","nCoeffsPerColor","shFeatureOrder","rgb","plyRowSize","fieldSize","double","int","uint","float","short","ushort","uchar","fieldName","hasOwnProperty","type","validVertexes","vertexZero","propertyToRead","row","alpha","exp","opacity","newVertex","positionsForBucketCalcs","buckets","computeBuckets","paddedSplatCount","headerSize","header","positionBuffer","scaleBuffer","colorBuffer","rotationBuffer","SplatBufferBucketBlockSize","doubleCompressionScaleRange","bucketCenter","bucketCenterDelta","outSplatIndex","b","fromArray","center","splats","invalidSplat","scales","rot","quat","rot_1","rot_2","rot_3","rot_0","normalize","scale_0","scale_1","scale_2","thf","sub","rgba","Uint8ClampedArray","SH_C0","f_dc_0","f_dc_1","f_dc_2","bucketsSize","splatDataBufferSize","unifiedBufferSize","unifiedBuffer","bucketArray","base","splatBuffer","endTime","positions","dimensions","yBlocks","ceil","zBlocks","blockCenter","fullBuckets","partiallyFullBuckets","xBlock","yBlock","zBlock","blockSize","bucketId","toArray","PlyLoader","fetchFile","fileName","catch","err","loadFromURL","plyFileData","SplatLoader","downLoadLink","setFromBuffer","downloadFile","headerData","splatData","blob","document","createElement","appendChild","download","href","URL","createObjectURL","click","_changeEvent","_startEvent","_endEvent","_ray","Ray","_plane","Plane","TILT_LIMIT","cos","MathUtils","DEG2RAD","OrbitControls","EventDispatcher","object","domElement","super","style","touchAction","enabled","target","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","PI","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","enablePan","panSpeed","screenSpacePanning","keyPanSpeed","zoomToCursor","autoRotate","autoRotateSpeed","keys","LEFT","UP","RIGHT","BOTTOM","mouseButtons","MOUSE","ROTATE","MIDDLE","DOLLY","PAN","touches","ONE","TOUCH","TWO","DOLLY_PAN","target0","clone","position0","zoom0","zoom","_domElementKeyEvents","getPolarAngle","spherical","phi","getAzimuthalAngle","theta","getDistance","distanceTo","listenToKeyEvents","addEventListener","onKeyDown","stopListenToKeyEvents","removeEventListener","saveState","scope","reset","updateProjectionMatrix","dispatchEvent","update","state","STATE","NONE","setFromUnitVectors","up","quatInverse","invert","lastPosition","lastQuaternion","lastTargetPosition","twoPI","applyQuaternion","setFromVector3","rotateLeft","sphericalDelta","isFinite","makeSafe","addScaledVector","panOffset","add","performCursorZoom","isOrthographicCamera","radius","clampDistance","setFromSpherical","lookAt","multiplyScalar","zoomChanged","newRadius","isPerspectiveCamera","prevRadius","radiusDelta","dollyDirection","updateMatrixWorld","mouseBefore","mouse","unproject","mouseAfter","warn","transformDirection","matrix","origin","direction","abs","dot","setFromNormalAndCoplanarPoint","intersectPlane","distanceToSquared","EPS","quaternion","dispose","onContextMenu","onPointerDown","onPointerUp","onMouseWheel","onPointerMove","TOUCH_ROTATE","TOUCH_PAN","TOUCH_DOLLY_PAN","TOUCH_DOLLY_ROTATE","Spherical","rotateStart","Vector2","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","pointers","pointerPositions","getZoomScale","pow","angle","rotateUp","panLeft","v","distance","objectMatrix","setFromMatrixColumn","panUp","crossVectors","pan","deltaX","deltaY","element","targetDistance","tan","fov","clientHeight","right","left","clientWidth","top","bottom","dollyOut","dollyScale","dollyIn","updateMouseParameters","event","rect","getBoundingClientRect","clientX","clientY","width","h","height","dist","handleMouseDownRotate","handleMouseDownPan","handleTouchStartRotate","pageX","pageY","handleTouchStartPan","handleTouchStartDolly","dx","dy","sqrt","handleTouchMoveRotate","getSecondPointerPosition","subVectors","handleTouchMovePan","handleTouchMoveDolly","setPointerCapture","pointerId","addPointer","pointerType","trackPointer","DOLLY_ROTATE","onTouchStart","mouseAction","button","handleMouseDownDolly","ctrlKey","metaKey","shiftKey","onMouseDown","handleTouchMoveDollyPan","handleTouchMoveDollyRotate","onTouchMove","handleMouseMoveRotate","handleMouseMoveDolly","handleMouseMovePan","onMouseMove","splice","removePointer","releasePointerCapture","preventDefault","handleMouseWheel","needsUpdate","code","handleKeyDown","pointer","passive","LoadingSpinner","message","container","spinnerDivContainer","spinnerDiv","messageDiv","className","display","innerHTML","show","hide","setMessage","msg","ArrowHelper","Object3D","dir","headLength","headRadius","lineGeometry","CylinderGeometry","translate","coneGeometry","Mesh","MeshBasicMaterial","toneMapped","matrixAutoUpdate","cone","setDirection","_axis","radians","acos","setFromAxisAngle","material","source","geometry","SceneHelper","scene","splatRenderTarget","renderTargetCopyMaterial","renderTargetCopyQuad","renderTargetCopyCamera","meshCursor","focusMarker","controlPlane","updateSplatRenderTargetForRenderDimensions","WebGLRenderTarget","format","RGBAFormat","stencilBuffer","depthBuffer","depthTexture","DepthTexture","DepthFormat","UnsignedIntType","setupRenderTargetCopyObjects","ShaderMaterial","vertexShader","fragmentShader","uniforms","sourceColorTexture","sourceDepthTexture","depthWrite","depthTest","transparent","blending","CustomBlending","blendSrc","SrcAlphaFactor","blendSrcAlpha","blendDst","OneMinusSrcAlphaFactor","blendDstAlpha","extensions","fragDepth","PlaneGeometry","OrthographicCamera","setupMeshCursor","ConeGeometry","coneMaterial","downArrow","upArrow","leftArrow","rightArrow","visible","destroyMeshCursor","children","forEach","child","remove","setMeshCursorVisibility","setMeshCursorPosition","positionAndOrientMeshCursor","camera","setupFocusMarker","sphereGeometry","SphereGeometry","focusMarkerMaterial","buildFocusMarkerMaterial","sphereMesh","updateFocusMarker","tempPosition","tempMatrix","viewport","matrixWorld","applyMatrix4","realFocusPosition","uniformsNeedUpdate","setFocusMarkerVisibility","setFocusMarkerOpacity","getFocusMarkerOpacity","setupControlPlane","planeGeometry","rotateX","planeMaterial","side","DoubleSide","planeMesh","arrowDir","arrowOrigin","arrowHelper","setControlPlaneVisibility","positionAndOrientControlPlane","tempQuaternion","defaultUp","addDebugMeshes","debugRoot","createDebugMeshes","secondaryDebugRoot","createSecondaryDebugMeshes","renderOrder","debugMeshRoot","createMesh","buildDebugMaterial","boxGeometry","BoxGeometry","boxMesh","separation","Color","FrontSide","VectorRight","VectorUp","VectorBackward","setParameters","boxContainsPoint","box","point","epsilon","intersectBox","planeIntersectionPoint","planeIntersectionPointArray","originArray","directionArray","outHit","normal","hitNormal","extremeVec","multiplier","sign","toSide","idx1","idx2","intersectSphere","toSphereCenterVec","toClosestApproach","toClosestApproachSq","diffSq","radiusSq","thc","t0","t1","t","Hit","hitClone","Raycaster","ray","setFromCameraAndScreenPosition","ndcCoords","screenPosition","screenDimensions","setFromMatrixPosition","near","far","intersectSplatMesh","toLocal","fromLocal","localRay","splatMesh","outHits","splatTree","getSplatTree","rootNode","castRayAtSplatTreeNode","sort","a","hit","tempScale","tempRotation","tempHit","scaleEpsilon","node","boundingBox","indexes","splatIndex","idGen","SplatTreeNode","depth","id","Box3","SplatTree","maxDepth","maxPositionsPerNode","sceneDimensions","sceneMin","sceneMax","addedIndexes","nodesWithIndexes","processSplatBuffer","filterFunc","processNode","newIndexes","nodeDimensions","halfDimensions","nodeCenter","childrenBounds","splatCounts","baseIndexes","j","containsPoint","childNode","countLeaves","leafCount","visitLeaves","visitFunc","visitLeavesFromNode","SplatMesh","buildMesh","splatAlphaRemovalThreshold","halfPrecisionCovariancesOnGPU","devicePixelRatio","buildGeomtery","buildMaterial","splatDataTextures","buildSplatTree","resetLocalSplatDataAndTexturesFromSplatBuffer","covariancesTexture","centersColorsTexture","focal","basisViewport","debugColor","covariancesTextureSize","centersColorsTextureSize","alphaTest","NormalBlending","baseGeometry","BufferGeometry","setIndex","positionsArray","BufferAttribute","setAttribute","setXYZ","InstancedBufferGeometry","splatIndexArray","splatIndexes","InstancedBufferAttribute","setUsage","DynamicDrawUsage","instanceCount","time","splatColor","timeEnd","leavesWithVertices","avgSplatCount","maxSplatCount","nodeCount","nodeSplatCount","updateLocalSplatDataFromSplatBuffer","allocateAndStoreLocalSplatDataInTextures","covariances","colors","centers","paddedCovariances","DataTexture","RGFormat","HalfFloatType","FloatType","paddedCenterColors","c","colorsBase","centersBase","centerColorsBase","r","g","RGBAIntegerFormat","internalFormat","texture","size","centerColors","updateSplatDataToDataTextures","updateLocalCovarianceDataToDataTexture","updateLocalCenterColorDataToDataTexture","updateIndexes","renderSplatCount","attributes","updateUniforms","renderDimensions","cameraFocalLengthX","cameraFocalLengthY","getSplatDataTextures","getCenters","getColors","getCovariances","Constants","sortWorker","self","wasmInstance","indexesOffset","positionsOffset","viewProjOffset","indexesOutOffset","sortBuffersOffset","wasmMemory","countsZero","onmessage","e","floatPositions","intPositions","postMessage","sortSetupComplete","renderCount","splatRenderCount","splatSortCount","viewProj","cameraPosition","sortStartTime","DepthMapRange","viewProjArray","exports","sortIndexes","sortEndTime","sortDone","sortTime","view","inIndexBuffer","init","INDEXES_BYTES_PER_ENTRY","BytesPerInt","POSITIONS_BYTES_PER_ENTRY","BytesPerFloat","sorterWasmBytes","totalRequiredMemory","MemoryPageSize","totalPagesRequired","sorterWasmImport","module","env","memory","WebAssembly","Memory","initial","maximum","shared","compile","wasmModule","instantiate","instance","sortSetupPhase1Complete","inIndexOffset","outIndexBuffer","outIndexOffset","requestAnimationFrameID","params","cameraUp","initialCameraPosition","initialCameraLookAt","selfDrivenMode","useBuiltInControls","rootElement","usingExternalCamera","usingExternalRenderer","renderer","controls","ignoreDevicePixelRatio","window","selfDrivenUpdateFunc","selfDrivenUpdate","showMeshCursor","showControlPlane","showInfo","sceneHelper","inIndexArray","sortRunning","selfDrivenModeRunning","splatRenderingInitialized","raycaster","infoPanel","infoPanelCells","currentFPS","lastSortTime","previousCameraTarget","nextCameraTarget","mousePosition","mouseDownPosition","mouseDownTime","initialized","forward","tempMatrixLeft","tempMatrixRight","makeRotationAxis","onMouseUp","clickOffset","toNewFocalPoint","wasClick","transitioningCameraTarget","getRenderDimensions","offsetX","offsetY","intersectionPoint","transitioningCameraTargetStartTime","updateSplatMeshUniforms","projectionMatrix","gatherSceneNodes","nodeRenderList","tempVectorYZ","tempVectorXZ","tempVector","tempMax","nodeSize","gatherAllNodes","cameraFocalLength","fovXOver2","atan","fovYOver2","cosFovXOver2","cosFovYOver2","nodeRenderCount","distanceToNode","setX","setY","cameraAngleXZDot","cameraAngleYZDot","ns","currentByteOffset","windowSizeInts","windowSizeBytes","updateFPS","lastCalcTime","frameCount","currentTime","timingSensitiveUpdates","lastUpdateTime","timeDelta","updateCameraTransition","tempCameraTarget","toPreviousTarget","toNextTarget","rotationAngle","lerp","updateMeshCursor","updateForRendererSizeChanges","lastRendererSize","currentRendererSize","getSize","aspect","updateInfo","cameraPos","cameraPosString","cameraLookAt","cameraLookAtString","cameraUpString","cursorPos","cursorPosString","cursorPosition","fps","renderWindow","renderPct","wasTransitioning","currentFocusMarkerOpacity","newFocusMarkerOpacity","render","savedAuoClear","autoClear","hasRenderables","updateView","cameraPositionArray","lastSortViewDir","sortViewDir","lastSortViewPos","sortViewOffset","force","needsRefreshForRotation","needsRefreshForPosition","premultiply","PerspectiveCamera","WebGLRenderer","antialias","precision","setPixelRatio","setClearColor","setSize","Scene","ResizeObserver","observe","setupInfoPanel","loadingSpinner","outDimensions","offsetWidth","offsetHeight","padding","backgroundColor","border","zIndex","fontFamily","fontSize","textAlign","layout","infoTable","layoutEntry","labelCell","spacerCell","infoCell","parentElement","prepend","loadFile","fileURL","options","orientation","showLoadingSpinner","downloadProgress","suffix","fileLoadPromise","endsWith","loadSplatBuffer","setTimeout","setupSplatMesh","setupSortWorker","frustumCulled","worker","Worker","toString","sorterWasmBinaryString","atob","charCodeAt","createSortWorker","outIndexArray","sortCanceled","start","requestAnimationFrame","stop","cancelAnimationFrame","updateControlPlane","getSplatMesh"],"mappings":"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"}