@babylonjs/core 9.2.0 → 9.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Animations/animation.d.ts +9 -0
- package/Animations/animation.js +9 -0
- package/Animations/animation.js.map +1 -1
- package/Animations/runtimeAnimation.js +28 -0
- package/Animations/runtimeAnimation.js.map +1 -1
- package/Cameras/Inputs/geospatialCameraPointersInput.js +10 -8
- package/Cameras/Inputs/geospatialCameraPointersInput.js.map +1 -1
- package/Cameras/geospatialCameraMovement.js +21 -21
- package/Cameras/geospatialCameraMovement.js.map +1 -1
- package/Debug/physicsViewer.js +2 -12
- package/Debug/physicsViewer.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/webgpuEngine.js +2 -0
- package/Engines/webgpuEngine.js.map +1 -1
- package/FlowGraph/Blocks/flowGraphBlockFactory.js +14 -1
- package/FlowGraph/Blocks/flowGraphBlockFactory.js.map +1 -1
- package/FlowGraph/flowGraph.js +6 -0
- package/FlowGraph/flowGraph.js.map +1 -1
- package/FlowGraph/flowGraphEventBlock.d.ts +10 -0
- package/FlowGraph/flowGraphEventBlock.js +24 -0
- package/FlowGraph/flowGraphEventBlock.js.map +1 -1
- package/FlowGraph/flowGraphParser.js +23 -4
- package/FlowGraph/flowGraphParser.js.map +1 -1
- package/FlowGraph/serialization.js +36 -14
- package/FlowGraph/serialization.js.map +1 -1
- package/FrameGraph/Node/Blocks/Rendering/iblShadowsRendererBlock.d.ts +105 -0
- package/FrameGraph/Node/Blocks/Rendering/iblShadowsRendererBlock.js +318 -0
- package/FrameGraph/Node/Blocks/Rendering/iblShadowsRendererBlock.js.map +1 -0
- package/FrameGraph/Node/Blocks/index.d.ts +1 -0
- package/FrameGraph/Node/Blocks/index.js +1 -0
- package/FrameGraph/Node/Blocks/index.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsAccumulationTask.d.ts +34 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsAccumulationTask.js +144 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsAccumulationTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsSpatialBlurTask.d.ts +26 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsSpatialBlurTask.js +82 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsSpatialBlurTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsTracingTask.d.ts +61 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsTracingTask.js +207 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsTracingTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsVoxelizationTask.d.ts +104 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsVoxelizationTask.js +218 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsVoxelizationTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.d.ts +217 -0
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.js +640 -0
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.js.map +1 -0
- package/FrameGraph/frameGraph.js +1 -0
- package/FrameGraph/frameGraph.js.map +1 -1
- package/FrameGraph/index.d.ts +1 -0
- package/FrameGraph/index.js +1 -0
- package/FrameGraph/index.js.map +1 -1
- package/Gizmos/boundingBoxGizmo.js +4 -0
- package/Gizmos/boundingBoxGizmo.js.map +1 -1
- package/Layers/thinEffectLayer.js +8 -1
- package/Layers/thinEffectLayer.js.map +1 -1
- package/Lights/Clustered/clusteredLightContainer.js +8 -5
- package/Lights/Clustered/clusteredLightContainer.js.map +1 -1
- package/Loading/Plugins/babylonFileLoader.js +26 -0
- package/Loading/Plugins/babylonFileLoader.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +15 -2
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js +3 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.d.ts +13 -2
- package/Materials/PBR/openpbrMaterial.js +47 -16
- package/Materials/PBR/openpbrMaterial.js.map +1 -1
- package/Materials/PBR/pbrBRDFConfiguration.js +1 -1
- package/Materials/PBR/pbrBRDFConfiguration.js.map +1 -1
- package/Materials/Textures/Filtering/hdrFiltering.js +6 -0
- package/Materials/Textures/Filtering/hdrFiltering.js.map +1 -1
- package/Materials/Textures/envCubeTexture.js +13 -13
- package/Materials/Textures/envCubeTexture.js.map +1 -1
- package/Materials/materialHelper.functions.js +1 -1
- package/Materials/materialHelper.functions.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingCompoundMesh.d.ts +18 -4
- package/Meshes/GaussianSplatting/gaussianSplattingCompoundMesh.js +29 -4
- package/Meshes/GaussianSplatting/gaussianSplattingCompoundMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +48 -8
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +373 -84
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.d.ts +39 -4
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js +152 -47
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.d.ts +61 -7
- package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.js +94 -11
- package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.js.map +1 -1
- package/Meshes/mesh.d.ts +15 -0
- package/Meshes/mesh.js +40 -1
- package/Meshes/mesh.js.map +1 -1
- package/Meshes/transformNode.js +2 -2
- package/Meshes/transformNode.js.map +1 -1
- package/Misc/sceneSerializer.js +2 -1
- package/Misc/sceneSerializer.js.map +1 -1
- package/Misc/textureTools.d.ts +3 -1
- package/Misc/textureTools.js +74 -13
- package/Misc/textureTools.js.map +1 -1
- package/Misc/tools.js +1 -1
- package/Misc/tools.js.map +1 -1
- package/Particles/baseParticleSystem.d.ts +47 -1
- package/Particles/baseParticleSystem.js +88 -0
- package/Particles/baseParticleSystem.js.map +1 -1
- package/Particles/computeShaderParticleSystem.js +12 -0
- package/Particles/computeShaderParticleSystem.js.map +1 -1
- package/Particles/gpuParticleSystem.d.ts +61 -25
- package/Particles/gpuParticleSystem.js +249 -75
- package/Particles/gpuParticleSystem.js.map +1 -1
- package/Particles/particleSystem.d.ts +0 -6
- package/Particles/particleSystem.js +3 -14
- package/Particles/particleSystem.js.map +1 -1
- package/Particles/thinParticleSystem.d.ts +1 -17
- package/Particles/thinParticleSystem.js +1 -50
- package/Particles/thinParticleSystem.js.map +1 -1
- package/Particles/webgl2ParticleSystem.d.ts +1 -0
- package/Particles/webgl2ParticleSystem.js +18 -2
- package/Particles/webgl2ParticleSystem.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsAccumulationPass.js +1 -1
- package/Rendering/IBLShadows/iblShadowsAccumulationPass.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.d.ts +3 -1
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.js +11 -1
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.d.ts +0 -19
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.js +21 -65
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.d.ts +15 -52
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js +129 -220
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js +3 -0
- package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js.map +1 -1
- package/Rendering/depthRenderer.js +6 -0
- package/Rendering/depthRenderer.js.map +1 -1
- package/Rendering/geometryBufferRenderer.d.ts +14 -5
- package/Rendering/geometryBufferRenderer.js +6 -2
- package/Rendering/geometryBufferRenderer.js.map +1 -1
- package/Rendering/geometryBufferRendererSceneComponent.d.ts +4 -6
- package/Rendering/geometryBufferRendererSceneComponent.js.map +1 -1
- package/Rendering/iblCdfGenerator.d.ts +10 -0
- package/Rendering/iblCdfGenerator.js +52 -17
- package/Rendering/iblCdfGenerator.js.map +1 -1
- package/Rendering/index.d.ts +0 -6
- package/Rendering/index.js +0 -6
- package/Rendering/index.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js +25 -4
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrDirectLighting.js +6 -1
- package/Shaders/ShadersInclude/openpbrDirectLighting.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrEnvironmentLighting.js +1 -1
- package/Shaders/ShadersInclude/openpbrEnvironmentLighting.js.map +1 -1
- package/Shaders/gaussianSplatting.vertex.js +3 -0
- package/Shaders/gaussianSplatting.vertex.js.map +1 -1
- package/Shaders/gpuRenderParticles.vertex.js +14 -2
- package/Shaders/gpuRenderParticles.vertex.js.map +1 -1
- package/Shaders/gpuUpdateParticles.vertex.js +24 -6
- package/Shaders/gpuUpdateParticles.vertex.js.map +1 -1
- package/Shaders/iblShadowVoxelTracing.fragment.js +5 -1
- package/Shaders/iblShadowVoxelTracing.fragment.js.map +1 -1
- package/Shaders/iblVoxelGrid.fragment.d.ts +1 -0
- package/Shaders/iblVoxelGrid.fragment.js +33 -5
- package/Shaders/iblVoxelGrid.fragment.js.map +1 -1
- package/Shaders/{iblVoxelSlabDebug.fragment.d.ts → lod3D.fragment.d.ts} +1 -1
- package/Shaders/lod3D.fragment.js +13 -0
- package/Shaders/lod3D.fragment.js.map +1 -0
- package/Shaders/openpbr.fragment.js +5 -0
- package/Shaders/openpbr.fragment.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +37 -5
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js +6 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrEnvironmentLighting.js +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrEnvironmentLighting.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +3 -0
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/ShadersWGSL/gpuUpdateParticles.compute.js +29 -8
- package/ShadersWGSL/gpuUpdateParticles.compute.js.map +1 -1
- package/ShadersWGSL/iblShadowVoxelTracing.fragment.js +5 -1
- package/ShadersWGSL/iblShadowVoxelTracing.fragment.js.map +1 -1
- package/ShadersWGSL/iblVoxelGrid.fragment.js +1 -1
- package/ShadersWGSL/iblVoxelGrid.fragment.js.map +1 -1
- package/{Shaders/iblVoxelSlabDebug.vertex.d.ts → ShadersWGSL/lod3D.fragment.d.ts} +1 -1
- package/ShadersWGSL/lod3D.fragment.js +13 -0
- package/ShadersWGSL/lod3D.fragment.js.map +1 -0
- package/ShadersWGSL/openpbr.fragment.js +5 -0
- package/ShadersWGSL/openpbr.fragment.js.map +1 -1
- package/package.json +1 -1
- package/Shaders/iblVoxelGrid3dDebug.fragment.d.ts +0 -5
- package/Shaders/iblVoxelGrid3dDebug.fragment.js +0 -24
- package/Shaders/iblVoxelGrid3dDebug.fragment.js.map +0 -1
- package/Shaders/iblVoxelSlabDebug.fragment.js +0 -13
- package/Shaders/iblVoxelSlabDebug.fragment.js.map +0 -1
- package/Shaders/iblVoxelSlabDebug.vertex.js +0 -11
- package/Shaders/iblVoxelSlabDebug.vertex.js.map +0 -1
- package/ShadersWGSL/iblVoxelGrid3dDebug.fragment.d.ts +0 -5
- package/ShadersWGSL/iblVoxelGrid3dDebug.fragment.js +0 -23
- package/ShadersWGSL/iblVoxelGrid3dDebug.fragment.js.map +0 -1
- package/ShadersWGSL/iblVoxelSlabDebug.fragment.d.ts +0 -5
- package/ShadersWGSL/iblVoxelSlabDebug.fragment.js +0 -14
- package/ShadersWGSL/iblVoxelSlabDebug.fragment.js.map +0 -1
- package/ShadersWGSL/iblVoxelSlabDebug.vertex.d.ts +0 -5
- package/ShadersWGSL/iblVoxelSlabDebug.vertex.js +0 -12
- package/ShadersWGSL/iblVoxelSlabDebug.vertex.js.map +0 -1
|
@@ -3,8 +3,56 @@ import { GetGaussianSplattingMaxPartCount } from "../../Materials/GaussianSplatt
|
|
|
3
3
|
import { GaussianSplattingMeshBase } from "./gaussianSplattingMeshBase.js";
|
|
4
4
|
import { RawTexture } from "../../Materials/Textures/rawTexture.js";
|
|
5
5
|
|
|
6
|
+
import { DecodeBase64ToBinary, EncodeArrayBufferToBase64 } from "../../Misc/stringTools.js";
|
|
7
|
+
import { Mesh } from "../mesh.js";
|
|
6
8
|
import "../thinInstanceMesh.js";
|
|
7
9
|
import { GaussianSplattingPartProxyMesh } from "./gaussianSplattingPartProxyMesh.js";
|
|
10
|
+
const _GaussianSplattingBytesPerSplat = 32;
|
|
11
|
+
const _GaussianSplattingBytesPerShTexel = 16;
|
|
12
|
+
/**
|
|
13
|
+
* Run-Length Encoding (RLE) compression for serialization
|
|
14
|
+
* Compressed Uint32Array can be parsed using {@link ParsePartIndices}
|
|
15
|
+
* Some notes for devs: We do not expect Uint8Array larger than 4GB,
|
|
16
|
+
* so it should be safe to use Uint32Array.
|
|
17
|
+
* @param partIndices A view of partIndices from GaussianSplattingMesh
|
|
18
|
+
* @returns A compressed Uint32Array of [count, value, ...]
|
|
19
|
+
*/
|
|
20
|
+
function CompressPartIndices(partIndices) {
|
|
21
|
+
const runs = [];
|
|
22
|
+
const length = partIndices.length;
|
|
23
|
+
let i = 0;
|
|
24
|
+
while (i < length) {
|
|
25
|
+
const value = partIndices[i];
|
|
26
|
+
let count = 1;
|
|
27
|
+
while (i + count < length && partIndices[i + count] === value) {
|
|
28
|
+
count++;
|
|
29
|
+
}
|
|
30
|
+
runs.push(count, value);
|
|
31
|
+
i += count;
|
|
32
|
+
}
|
|
33
|
+
return new Uint32Array(runs);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parse partIndices compressed by {@link CompressPartIndices} to runtime array
|
|
37
|
+
* @param compressed The compressed partIndices of [count, value, ...]
|
|
38
|
+
* @returns runtime Uint8Array for GaussianSplattingMesh
|
|
39
|
+
*/
|
|
40
|
+
function ParsePartIndices(compressed) {
|
|
41
|
+
let totalCount = 0;
|
|
42
|
+
const length = compressed.length;
|
|
43
|
+
for (let i = 0; i < length; i += 2) {
|
|
44
|
+
totalCount += compressed[i];
|
|
45
|
+
}
|
|
46
|
+
const partIndices = new Uint8Array(totalCount);
|
|
47
|
+
let offset = 0;
|
|
48
|
+
for (let i = 0; i < length; i += 2) {
|
|
49
|
+
const count = compressed[i];
|
|
50
|
+
const value = compressed[i + 1];
|
|
51
|
+
partIndices.fill(value, offset, offset + count);
|
|
52
|
+
offset += count;
|
|
53
|
+
}
|
|
54
|
+
return partIndices;
|
|
55
|
+
}
|
|
8
56
|
/**
|
|
9
57
|
* Class used to render a Gaussian Splatting mesh. Supports both single-cloud and compound
|
|
10
58
|
* (multi-part) rendering. In compound mode, multiple Gaussian Splatting source meshes are
|
|
@@ -290,10 +338,88 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
290
338
|
this._worker.postMessage({ partIndices: partIndices ?? null });
|
|
291
339
|
}
|
|
292
340
|
}
|
|
341
|
+
_appendPartSourceToArrays(source, dstOffset, covA, covB, colorArray, sh, minimum, maximum) {
|
|
342
|
+
this._appendSourceToArrays(source, dstOffset, covA, covB, colorArray, sh, minimum, maximum);
|
|
343
|
+
}
|
|
344
|
+
_createRetainedPartSource(proxy) {
|
|
345
|
+
if (!this._splatsData || (this._shDegree > 0 && !this._shData)) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
const splatByteOffset = proxy._splatsDataOffset * _GaussianSplattingBytesPerSplat;
|
|
349
|
+
const splatByteLength = proxy._vertexCount * _GaussianSplattingBytesPerSplat;
|
|
350
|
+
const shByteOffset = proxy._shDataOffset * _GaussianSplattingBytesPerShTexel;
|
|
351
|
+
const shByteLength = proxy._vertexCount * _GaussianSplattingBytesPerShTexel;
|
|
352
|
+
return {
|
|
353
|
+
name: proxy.name,
|
|
354
|
+
_vertexCount: proxy._vertexCount,
|
|
355
|
+
_splatsData: this._splatsData.slice(splatByteOffset, splatByteOffset + splatByteLength),
|
|
356
|
+
_shData: this._shData?.map((texture) => texture.slice(shByteOffset, shByteOffset + shByteLength)) ?? null,
|
|
357
|
+
_shDegree: this._shData?.length ?? 0,
|
|
358
|
+
isCompound: false,
|
|
359
|
+
getWorldMatrix: () => proxy.getWorldMatrix(),
|
|
360
|
+
getBoundingInfo: () => proxy.getBoundingInfo(),
|
|
361
|
+
dispose: () => { },
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
_retainMergedPartData(existingVertexCount, totalCount, others, shDegree) {
|
|
365
|
+
if (!this._keepInRam && !this._alwaysRetainSplatsData) {
|
|
366
|
+
this._splatsData = null;
|
|
367
|
+
this._shData = null;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const getSourceBuffer = (data) => {
|
|
371
|
+
return data instanceof ArrayBuffer ? data : data.buffer;
|
|
372
|
+
};
|
|
373
|
+
const mergedSplatsData = new Uint8Array(totalCount * _GaussianSplattingBytesPerSplat);
|
|
374
|
+
let splatByteOffset = 0;
|
|
375
|
+
if (this._splatsData && existingVertexCount > 0) {
|
|
376
|
+
mergedSplatsData.set(new Uint8Array(getSourceBuffer(this._splatsData), 0, existingVertexCount * _GaussianSplattingBytesPerSplat), splatByteOffset);
|
|
377
|
+
splatByteOffset += existingVertexCount * _GaussianSplattingBytesPerSplat;
|
|
378
|
+
}
|
|
379
|
+
for (const other of others) {
|
|
380
|
+
if (!other._splatsData) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const splatByteLength = other._vertexCount * _GaussianSplattingBytesPerSplat;
|
|
384
|
+
mergedSplatsData.set(new Uint8Array(getSourceBuffer(other._splatsData), 0, splatByteLength), splatByteOffset);
|
|
385
|
+
splatByteOffset += splatByteLength;
|
|
386
|
+
}
|
|
387
|
+
this._splatsData = mergedSplatsData.buffer;
|
|
388
|
+
if (shDegree <= 0) {
|
|
389
|
+
this._shData = null;
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
const mergedShData = [];
|
|
393
|
+
for (let textureIndex = 0; textureIndex < shDegree; textureIndex++) {
|
|
394
|
+
mergedShData.push(new Uint8Array(totalCount * _GaussianSplattingBytesPerShTexel));
|
|
395
|
+
}
|
|
396
|
+
let shByteOffset = 0;
|
|
397
|
+
if (this._shData && existingVertexCount > 0) {
|
|
398
|
+
const existingShByteLength = existingVertexCount * _GaussianSplattingBytesPerShTexel;
|
|
399
|
+
for (let textureIndex = 0; textureIndex < mergedShData.length; textureIndex++) {
|
|
400
|
+
if (textureIndex < this._shData.length) {
|
|
401
|
+
mergedShData[textureIndex].set(this._shData[textureIndex].subarray(0, existingShByteLength), shByteOffset);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
shByteOffset += existingShByteLength;
|
|
405
|
+
}
|
|
406
|
+
for (const other of others) {
|
|
407
|
+
const otherShByteLength = other._vertexCount * _GaussianSplattingBytesPerShTexel;
|
|
408
|
+
if (other._shData) {
|
|
409
|
+
for (let textureIndex = 0; textureIndex < mergedShData.length; textureIndex++) {
|
|
410
|
+
if (textureIndex < other._shData.length) {
|
|
411
|
+
mergedShData[textureIndex].set(other._shData[textureIndex].subarray(0, otherShByteLength), shByteOffset);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
shByteOffset += otherShByteLength;
|
|
416
|
+
}
|
|
417
|
+
this._shData = mergedShData;
|
|
418
|
+
}
|
|
293
419
|
/**
|
|
294
|
-
* Core implementation for adding one or more
|
|
295
|
-
* parts. Writes directly into texture-sized CPU arrays
|
|
296
|
-
*
|
|
420
|
+
* Core implementation for adding one or more source parts as new
|
|
421
|
+
* parts. Writes directly into texture-sized CPU arrays, updates the retained merged source
|
|
422
|
+
* buffers, and uploads in one pass.
|
|
297
423
|
*
|
|
298
424
|
* @param others - Source meshes to append (must each be non-compound and fully loaded)
|
|
299
425
|
* @param disposeOthers - Dispose source meshes after appending
|
|
@@ -355,6 +481,7 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
355
481
|
this._partIndices = new Uint8Array(textureLength);
|
|
356
482
|
this._partIndices.set(partIndicesA.subarray(0, splatCountA));
|
|
357
483
|
const assignedPartIndices = [];
|
|
484
|
+
const assignedSplatsDataOffsets = [];
|
|
358
485
|
let dstOffset = splatCountA;
|
|
359
486
|
const maxPartCount = GetGaussianSplattingMaxPartCount(this._scene.getEngine());
|
|
360
487
|
for (const other of others) {
|
|
@@ -363,6 +490,7 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
363
490
|
}
|
|
364
491
|
const newPartIndex = nextPartIndex++;
|
|
365
492
|
assignedPartIndices.push(newPartIndex);
|
|
493
|
+
assignedSplatsDataOffsets.push(dstOffset);
|
|
366
494
|
this._partIndices.fill(newPartIndex, dstOffset, dstOffset + other._vertexCount);
|
|
367
495
|
dstOffset += other._vertexCount;
|
|
368
496
|
}
|
|
@@ -394,7 +522,7 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
394
522
|
// Rebuild the compound's legacy "own" data at part 0 (scenario A only).
|
|
395
523
|
// Skipped in the preferred empty-composer path (scenario B).
|
|
396
524
|
if (!this._partProxies[0] && this._splatsData) {
|
|
397
|
-
const proxyVertexCount = this._partProxies.reduce((sum, proxy) => sum + (proxy ? proxy.
|
|
525
|
+
const proxyVertexCount = this._partProxies.reduce((sum, proxy) => sum + (proxy ? proxy._vertexCount : 0), 0);
|
|
398
526
|
const part0Count = splatCountA - proxyVertexCount;
|
|
399
527
|
if (part0Count > 0) {
|
|
400
528
|
const uBufA = new Uint8Array(this._splatsData);
|
|
@@ -417,11 +545,15 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
417
545
|
// scenario B, part 0 is itself a proxied part with no implicit "own" data.
|
|
418
546
|
for (let partIndex = 0; partIndex < this._partProxies.length; partIndex++) {
|
|
419
547
|
const proxy = this._partProxies[partIndex];
|
|
420
|
-
if (!proxy
|
|
548
|
+
if (!proxy) {
|
|
421
549
|
continue;
|
|
422
550
|
}
|
|
423
|
-
this.
|
|
424
|
-
|
|
551
|
+
const source = this._createRetainedPartSource(proxy);
|
|
552
|
+
if (!source) {
|
|
553
|
+
throw new Error(`Cannot rebuild compound part "${proxy.name}": the retained compound source data is not available.`);
|
|
554
|
+
}
|
|
555
|
+
this._appendPartSourceToArrays(source, rebuildOffset, covA, covB, colorArray, sh, minimum, maximum);
|
|
556
|
+
rebuildOffset += source._vertexCount;
|
|
425
557
|
}
|
|
426
558
|
}
|
|
427
559
|
else {
|
|
@@ -474,7 +606,7 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
474
606
|
// Handles both layouts (see full-rebuild comment above):
|
|
475
607
|
// A) LEGACY: _partProxies[0] absent → seed lookup[0] with this._splatsData
|
|
476
608
|
// B) PREFERRED: _partProxies[0] present → all entries filled from proxies
|
|
477
|
-
const proxyTotal = this._partProxies.reduce((s, p) => s + (p ? p.
|
|
609
|
+
const proxyTotal = this._partProxies.reduce((s, p) => s + (p ? p._vertexCount : 0), 0);
|
|
478
610
|
const part0Count = splatCountA - proxyTotal; // > 0 only in legacy scenario A
|
|
479
611
|
const srcUBufs = new Array(this._partProxies.length).fill(null);
|
|
480
612
|
const srcFBufs = new Array(this._partProxies.length).fill(null);
|
|
@@ -489,14 +621,17 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
489
621
|
let cumOffset = part0Count;
|
|
490
622
|
for (let pi = 0; pi < this._partProxies.length; pi++) {
|
|
491
623
|
const proxy = this._partProxies[pi];
|
|
492
|
-
if (!proxy
|
|
624
|
+
if (!proxy) {
|
|
493
625
|
continue;
|
|
494
626
|
}
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
627
|
+
const source = this._createRetainedPartSource(proxy);
|
|
628
|
+
if (!source || !source._splatsData) {
|
|
629
|
+
throw new Error(`Cannot rebuild compound part "${proxy.name}": the retained compound source data is not available.`);
|
|
630
|
+
}
|
|
631
|
+
srcUBufs[pi] = new Uint8Array(source._splatsData);
|
|
632
|
+
srcFBufs[pi] = new Float32Array(source._splatsData);
|
|
498
633
|
partStarts[pi] = cumOffset;
|
|
499
|
-
cumOffset +=
|
|
634
|
+
cumOffset += source._vertexCount;
|
|
500
635
|
}
|
|
501
636
|
for (let splatIdx = firstNewTexel; splatIdx < splatCountA; splatIdx++) {
|
|
502
637
|
const partIdx = this._partIndices ? this._partIndices[splatIdx] : 0;
|
|
@@ -512,7 +647,7 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
512
647
|
// Append each new source
|
|
513
648
|
dstOffset = splatCountA;
|
|
514
649
|
for (const other of others) {
|
|
515
|
-
this.
|
|
650
|
+
this._appendPartSourceToArrays(other, dstOffset, covA, covB, colorArray, sh, minimum, maximum);
|
|
516
651
|
dstOffset += other._vertexCount;
|
|
517
652
|
}
|
|
518
653
|
// Pad empty splats to texture boundary
|
|
@@ -524,50 +659,82 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
524
659
|
if (totalCount !== this._vertexCount) {
|
|
525
660
|
this._updateSplatIndexBuffer(totalCount);
|
|
526
661
|
}
|
|
662
|
+
this._retainMergedPartData(splatCountA, totalCount, others, shDegreeNew);
|
|
527
663
|
this._vertexCount = totalCount;
|
|
528
664
|
this._shDegree = shDegreeNew;
|
|
529
|
-
//
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
this.
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
const other = others[i];
|
|
549
|
-
const newPartIndex = assignedPartIndices[i];
|
|
550
|
-
const partWorldMatrix = other.getWorldMatrix();
|
|
551
|
-
this.setWorldMatrixForPart(newPartIndex, partWorldMatrix);
|
|
552
|
-
const proxyMesh = new GaussianSplattingPartProxyMesh(other.name, this.getScene(), this, other, newPartIndex);
|
|
553
|
-
if (disposeOthers) {
|
|
554
|
-
other.dispose();
|
|
665
|
+
// Gate the sort worker for the duration of this operation. _updateTextures (below) may create the worker and fire an
|
|
666
|
+
// immediate sort via _postToWorker. At that point partMatrices has not yet been updated for the incoming parts, so the
|
|
667
|
+
// worker would compute depthCoeffs for fewer parts than partIndices references — crashing with
|
|
668
|
+
// "Cannot read properties of undefined (reading '0')".
|
|
669
|
+
// When called from removePart, _rebuilding is already true and _canPostToWorker is already false, so the gate is a
|
|
670
|
+
// no-op — removePart handles the final post+sort.
|
|
671
|
+
const needsWorkerGate = !this._rebuilding;
|
|
672
|
+
if (needsWorkerGate) {
|
|
673
|
+
this._canPostToWorker = false;
|
|
674
|
+
this._rebuilding = true;
|
|
675
|
+
}
|
|
676
|
+
try {
|
|
677
|
+
// --- Upload to GPU ---
|
|
678
|
+
if (incremental) {
|
|
679
|
+
// Update the part-indices texture (handles both create and update-in-place).
|
|
680
|
+
// _ensurePartIndicesTexture is a no-op when the texture already exists, so on the
|
|
681
|
+
// second+ addPart the partIndices would be stale without this call.
|
|
682
|
+
this._onUpdateTextures(textureSize);
|
|
683
|
+
this._updateSubTextures(this._splatPositions, covA, covB, colorArray, firstNewLine, textureSize.y - firstNewLine, sh);
|
|
555
684
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
this.
|
|
561
|
-
|
|
685
|
+
else {
|
|
686
|
+
this._updateTextures(covA, covB, colorArray, sh);
|
|
687
|
+
}
|
|
688
|
+
this.getBoundingInfo().reConstruct(minimum, maximum, this.getWorldMatrix());
|
|
689
|
+
this.setEnabled(true);
|
|
690
|
+
this._cachedBoundingMin = minimum.clone();
|
|
691
|
+
this._cachedBoundingMax = maximum.clone();
|
|
692
|
+
this._notifyWorkerNewData();
|
|
693
|
+
// --- Create proxy meshes ---
|
|
694
|
+
const proxyMeshes = [];
|
|
695
|
+
for (let i = 0; i < others.length; i++) {
|
|
696
|
+
const other = others[i];
|
|
697
|
+
const newPartIndex = assignedPartIndices[i];
|
|
698
|
+
const partWorldMatrix = other.getWorldMatrix();
|
|
699
|
+
this.setWorldMatrixForPart(newPartIndex, partWorldMatrix);
|
|
700
|
+
const proxyMesh = new GaussianSplattingPartProxyMesh(other.name, this.getScene(), this, newPartIndex, other.getBoundingInfo(), other._vertexCount, assignedSplatsDataOffsets[i], assignedSplatsDataOffsets[i]);
|
|
701
|
+
if (disposeOthers) {
|
|
702
|
+
other.dispose();
|
|
703
|
+
}
|
|
704
|
+
const quaternion = new Quaternion();
|
|
705
|
+
partWorldMatrix.decompose(proxyMesh.scaling, quaternion, proxyMesh.position);
|
|
706
|
+
proxyMesh.rotationQuaternion = quaternion;
|
|
707
|
+
proxyMesh.computeWorldMatrix(true);
|
|
708
|
+
this._partProxies[newPartIndex] = proxyMesh;
|
|
709
|
+
proxyMeshes.push(proxyMesh);
|
|
710
|
+
}
|
|
711
|
+
// Restore the rebuild gate and post the now-complete partMatrices in one message, then trigger a single sort pass.
|
|
712
|
+
// This ensures the worker sees a consistent partMatrices array that matches the partIndices for every splat.
|
|
713
|
+
if (needsWorkerGate) {
|
|
714
|
+
this._rebuilding = false;
|
|
715
|
+
if (this._worker) {
|
|
716
|
+
this._worker.postMessage({ partMatrices: this._partMatrices.map((matrix) => new Float32Array(matrix.m)) });
|
|
717
|
+
}
|
|
718
|
+
this._canPostToWorker = true;
|
|
719
|
+
this._postToWorker(true);
|
|
720
|
+
}
|
|
721
|
+
return { proxyMeshes, assignedPartIndices };
|
|
722
|
+
}
|
|
723
|
+
catch (e) {
|
|
724
|
+
// Ensure the gates are always restored so sorting is not permanently frozen.
|
|
725
|
+
if (needsWorkerGate) {
|
|
726
|
+
this._rebuilding = false;
|
|
727
|
+
this._canPostToWorker = true;
|
|
728
|
+
}
|
|
729
|
+
throw e;
|
|
562
730
|
}
|
|
563
|
-
return { proxyMeshes, assignedPartIndices };
|
|
564
731
|
}
|
|
565
732
|
// ---------------------------------------------------------------------------
|
|
566
733
|
// Public compound API
|
|
567
734
|
// ---------------------------------------------------------------------------
|
|
568
735
|
/**
|
|
569
736
|
* Add another mesh to this mesh, as a new part. This makes the current mesh a compound, if not already.
|
|
570
|
-
* The source mesh's splat data is read directly
|
|
737
|
+
* The source mesh's splat data is read directly and copied into the compound's retained source buffers.
|
|
571
738
|
* @param other - The other mesh to add. Must be fully loaded before calling this method.
|
|
572
739
|
* @param disposeOther - Whether to dispose the other mesh after adding it to the current mesh.
|
|
573
740
|
* @returns a placeholder mesh that can be used to manipulate the part transform
|
|
@@ -579,9 +746,9 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
579
746
|
}
|
|
580
747
|
/**
|
|
581
748
|
* Remove a part from this compound mesh.
|
|
582
|
-
* The remaining parts are rebuilt directly from
|
|
583
|
-
*
|
|
584
|
-
*
|
|
749
|
+
* The remaining parts are rebuilt directly from the compound mesh's retained source buffers.
|
|
750
|
+
* The current mesh is reset to a plain (single-part) state and then each remaining source is
|
|
751
|
+
* re-added via addParts.
|
|
585
752
|
* @param index - The index of the part to remove
|
|
586
753
|
* @deprecated Use {@link GaussianSplattingCompoundMesh.removePart} instead.
|
|
587
754
|
*/
|
|
@@ -593,15 +760,23 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
593
760
|
const survivors = [];
|
|
594
761
|
for (let proxyIndex = 0; proxyIndex < this._partProxies.length; proxyIndex++) {
|
|
595
762
|
const proxy = this._partProxies[proxyIndex];
|
|
596
|
-
if (proxy
|
|
597
|
-
|
|
763
|
+
if (!proxy || proxyIndex === index) {
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
const source = this._createRetainedPartSource(proxy);
|
|
767
|
+
if (!source) {
|
|
768
|
+
throw new Error(`Cannot remove part: the retained compound source data is not available for part "${proxy.name}".`);
|
|
598
769
|
}
|
|
770
|
+
survivors.push({ proxyMesh: proxy, source, oldIndex: proxyIndex, worldMatrix: proxy.getWorldMatrix().clone(), visibility: this._partVisibility[proxyIndex] ?? 1.0 });
|
|
599
771
|
}
|
|
600
772
|
survivors.sort((a, b) => a.oldIndex - b.oldIndex);
|
|
601
773
|
// Validate every survivor still has its source data. If even one is missing we cannot rebuild.
|
|
602
|
-
for (const { proxyMesh } of survivors) {
|
|
603
|
-
if (!
|
|
604
|
-
throw new Error(`Cannot remove part: the source
|
|
774
|
+
for (const { proxyMesh, source } of survivors) {
|
|
775
|
+
if (!source._splatsData) {
|
|
776
|
+
throw new Error(`Cannot remove part: the source data for part "${proxyMesh.name}" is not available.`);
|
|
777
|
+
}
|
|
778
|
+
if (source._shDegree > 0 && !source._shData) {
|
|
779
|
+
throw new Error(`Cannot remove part: the SH data for part "${proxyMesh.name}" is not available.`);
|
|
605
780
|
}
|
|
606
781
|
}
|
|
607
782
|
// --- Reset this mesh to an empty state ---
|
|
@@ -641,6 +816,9 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
641
816
|
this._partVisibility = [];
|
|
642
817
|
this._cachedBoundingMin = null;
|
|
643
818
|
this._cachedBoundingMax = null;
|
|
819
|
+
this._splatsData = null;
|
|
820
|
+
this._shData = null;
|
|
821
|
+
this._shDegree = 0;
|
|
644
822
|
// Remove the proxy for the removed part and dispose it
|
|
645
823
|
const proxyToRemove = this._partProxies[index];
|
|
646
824
|
if (proxyToRemove) {
|
|
@@ -657,34 +835,145 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
|
|
|
657
835
|
// Gate the sort worker: suppress any sort request until the full rebuild is committed.
|
|
658
836
|
this._rebuilding = true;
|
|
659
837
|
this._canPostToWorker = false;
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
838
|
+
try {
|
|
839
|
+
const sources = survivors.map((s) => s.source);
|
|
840
|
+
const { proxyMeshes: newProxies } = this._addPartsInternal(sources, false);
|
|
841
|
+
// Restore world matrices and re-map proxies
|
|
842
|
+
for (let i = 0; i < survivors.length; i++) {
|
|
843
|
+
const oldProxy = survivors[i].proxyMesh;
|
|
844
|
+
const newProxy = newProxies[i];
|
|
845
|
+
const newPartIndex = newProxy.partIndex;
|
|
846
|
+
// Restore the world matrix and visibility the user had set on the old proxy
|
|
847
|
+
this.setWorldMatrixForPart(newPartIndex, survivors[i].worldMatrix);
|
|
848
|
+
this.setPartVisibility(newPartIndex, survivors[i].visibility);
|
|
849
|
+
const quaternion = new Quaternion();
|
|
850
|
+
survivors[i].worldMatrix.decompose(newProxy.scaling, quaternion, newProxy.position);
|
|
851
|
+
newProxy.rotationQuaternion = quaternion;
|
|
852
|
+
newProxy.computeWorldMatrix(true);
|
|
853
|
+
// Update the old proxy's index and metadata so existing user references still work.
|
|
854
|
+
oldProxy.updatePartIndex(newPartIndex);
|
|
855
|
+
oldProxy.updatePartMetadata(newProxy._vertexCount, newProxy._splatsDataOffset, newProxy._shDataOffset);
|
|
856
|
+
this._partProxies[newPartIndex] = oldProxy;
|
|
857
|
+
// newProxy is redundant — it was created inside _addPartsInternal; dispose it
|
|
858
|
+
newProxy.dispose();
|
|
859
|
+
}
|
|
860
|
+
// Rebuild is complete: all partMatrices are now set correctly.
|
|
861
|
+
// Post the final complete set and fire one sort.
|
|
862
|
+
this._rebuilding = false;
|
|
863
|
+
// Break TypeScript's flow narrowing — _addPartsInternal may have reinstantiated _worker.
|
|
864
|
+
const workerAfterRebuild = this._worker;
|
|
865
|
+
workerAfterRebuild?.postMessage({ partMatrices: this._partMatrices.map((matrix) => new Float32Array(matrix.m)) });
|
|
866
|
+
this._canPostToWorker = true;
|
|
867
|
+
this._postToWorker(true);
|
|
868
|
+
}
|
|
869
|
+
catch (e) {
|
|
870
|
+
// Ensure the gates are always restored so sorting is not permanently frozen.
|
|
871
|
+
this._rebuilding = false;
|
|
872
|
+
this._canPostToWorker = true;
|
|
873
|
+
throw e;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Serialize current GaussianSplattingMesh
|
|
878
|
+
* @param serializationObject defines the object which will receive the serialization data
|
|
879
|
+
* @param encoding the encoding of binary data, defaults to base64 for json serialize,
|
|
880
|
+
* kept for future internal use like cloning where base64 encoding wastes cycles and memory
|
|
881
|
+
* @returns the serialized object
|
|
882
|
+
*/
|
|
883
|
+
serialize(serializationObject = {}, encoding = "base64") {
|
|
884
|
+
serializationObject = super.serialize(serializationObject);
|
|
885
|
+
serializationObject.subMeshes = [];
|
|
886
|
+
serializationObject.geometryUniqueId = undefined;
|
|
887
|
+
serializationObject.geometryId = undefined;
|
|
888
|
+
serializationObject.materialUniqueId = undefined;
|
|
889
|
+
serializationObject.materialId = undefined;
|
|
890
|
+
serializationObject.instances = [];
|
|
891
|
+
serializationObject.actions = undefined;
|
|
892
|
+
serializationObject.type = this.getClassName();
|
|
893
|
+
serializationObject.keepInRam = this._keepInRam;
|
|
894
|
+
serializationObject.disableDepthSort = this._disableDepthSort;
|
|
895
|
+
serializationObject.viewUpdateThreshold = this.viewUpdateThreshold;
|
|
896
|
+
serializationObject._flipY = this._flipY;
|
|
897
|
+
if (this._splatsData) {
|
|
898
|
+
serializationObject.splatsData = encoding === "base64" ? EncodeArrayBufferToBase64(this._splatsData) : this._splatsData;
|
|
899
|
+
}
|
|
900
|
+
if (this._shData) {
|
|
901
|
+
serializationObject.shData = encoding === "base64" ? this._shData.map(EncodeArrayBufferToBase64) : this._shData;
|
|
902
|
+
}
|
|
903
|
+
if (this._partIndices) {
|
|
904
|
+
const compressedIndices = CompressPartIndices(this._partIndices.subarray(0, this._vertexCount));
|
|
905
|
+
serializationObject.partIndices = encoding === "base64" ? EncodeArrayBufferToBase64(compressedIndices) : compressedIndices;
|
|
906
|
+
}
|
|
907
|
+
if (this._partProxies.length) {
|
|
908
|
+
serializationObject.partProxies = this._partProxies.filter((proxy) => !!proxy).map((proxy) => proxy.serialize());
|
|
909
|
+
}
|
|
910
|
+
return serializationObject;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Internal helper to parses a serialized GaussianSplattingMesh or GaussianSplattingCompoundMesh
|
|
914
|
+
* @param parsedMesh the serialized mesh
|
|
915
|
+
* @param scene the scene to create the GaussianSplattingMesh or GaussianSplattingCompoundMesh in
|
|
916
|
+
* @param ctor the constructor of the mesh to create
|
|
917
|
+
* @returns the created GaussianSplattingMesh
|
|
918
|
+
* @internal
|
|
919
|
+
*/
|
|
920
|
+
static _ParseInternal(parsedMesh, scene, ctor) {
|
|
921
|
+
const mesh = new ctor(parsedMesh.name, null, scene, parsedMesh.keepInRam);
|
|
922
|
+
mesh.disableDepthSort = parsedMesh.disableDepthSort ?? false;
|
|
923
|
+
mesh.viewUpdateThreshold = parsedMesh.viewUpdateThreshold ?? GaussianSplattingMeshBase._DefaultViewUpdateThreshold;
|
|
924
|
+
let splatsData = parsedMesh.splatsData;
|
|
925
|
+
if (typeof splatsData === "string") {
|
|
926
|
+
splatsData = DecodeBase64ToBinary(splatsData);
|
|
927
|
+
}
|
|
928
|
+
const shData = parsedMesh.shData;
|
|
929
|
+
let parsedShData;
|
|
930
|
+
if (Array.isArray(shData) && shData.length) {
|
|
931
|
+
const newData = [];
|
|
932
|
+
for (let i = 0, length = shData.length; i < length; i++) {
|
|
933
|
+
const data = shData[i];
|
|
934
|
+
if (typeof data === "string") {
|
|
935
|
+
newData[i] = new Uint8Array(DecodeBase64ToBinary(data));
|
|
936
|
+
}
|
|
937
|
+
else {
|
|
938
|
+
newData[i] = data;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
parsedShData = newData;
|
|
942
|
+
}
|
|
943
|
+
let partIndices = parsedMesh.partIndices;
|
|
944
|
+
let parsedPartIndices;
|
|
945
|
+
if (typeof partIndices === "string") {
|
|
946
|
+
partIndices = new Uint32Array(DecodeBase64ToBinary(partIndices));
|
|
947
|
+
}
|
|
948
|
+
if (partIndices) {
|
|
949
|
+
parsedPartIndices = ParsePartIndices(partIndices);
|
|
950
|
+
}
|
|
951
|
+
if (splatsData) {
|
|
952
|
+
const flipY = parsedMesh._flipY ?? false;
|
|
953
|
+
mesh.updateData(splatsData, parsedShData, { flipY }, parsedPartIndices);
|
|
954
|
+
}
|
|
955
|
+
if (parsedMesh.partProxies) {
|
|
956
|
+
for (const serializedPart of parsedMesh.partProxies) {
|
|
957
|
+
const part = Object.assign({}, serializedPart);
|
|
958
|
+
part.compoundSplatMesh = mesh;
|
|
959
|
+
const proxyMesh = Mesh.Parse(part, scene, "");
|
|
960
|
+
const newPartIndex = proxyMesh.partIndex;
|
|
961
|
+
mesh._partProxies[newPartIndex] = proxyMesh;
|
|
962
|
+
mesh.setWorldMatrixForPart(newPartIndex, proxyMesh.getWorldMatrix());
|
|
963
|
+
mesh.setPartVisibility(newPartIndex, proxyMesh.visibility);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
return mesh;
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Parses a serialized GaussianSplattingMesh
|
|
970
|
+
* @param parsedMesh the serialized mesh
|
|
971
|
+
* @param scene the scene to create the GaussianSplattingMesh in
|
|
972
|
+
* @returns the created GaussianSplattingMesh
|
|
973
|
+
*/
|
|
974
|
+
static Parse(parsedMesh, scene) {
|
|
975
|
+
return GaussianSplattingMesh._ParseInternal(parsedMesh, scene, GaussianSplattingMesh);
|
|
688
976
|
}
|
|
689
977
|
}
|
|
978
|
+
Mesh._GaussianSplattingMeshParser = GaussianSplattingMesh.Parse;
|
|
690
979
|
//# sourceMappingURL=gaussianSplattingMesh.js.map
|