@cesium/engine 23.0.0 → 24.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Build/Workers/{chunk-QTOHIXGF.js → chunk-2N4KDHS3.js} +10 -10
- package/Build/Workers/{chunk-SQTRWKO2.js → chunk-44EMEGKW.js} +5 -5
- package/Build/Workers/{chunk-OHBM4YG4.js → chunk-4TIG36AW.js} +12 -12
- package/Build/Workers/{chunk-BNBD2YZK.js → chunk-5A2SW66E.js} +16 -16
- package/Build/Workers/{chunk-52K3GJKG.js → chunk-5GXYJQ2K.js} +3 -3
- package/Build/Workers/{chunk-NQCAZU7S.js → chunk-63SIWPLS.js} +13 -13
- package/Build/Workers/{chunk-UEEGWJJP.js → chunk-6MPGQEHA.js} +2 -2
- package/Build/Workers/{chunk-PQVNT5CJ.js → chunk-6RMS4S72.js} +6 -6
- package/Build/Workers/{chunk-HYTFXWMY.js → chunk-6WLHJFD3.js} +7 -7
- package/Build/Workers/{chunk-DT5SJBKA.js → chunk-72VYSVEW.js} +9 -9
- package/Build/Workers/{chunk-JUGY5AZN.js → chunk-7MDYBRYJ.js} +4 -4
- package/Build/Workers/{chunk-6SLGTBB2.js → chunk-7O5XJTVE.js} +5 -5
- package/Build/Workers/{chunk-4UNQX2MP.js → chunk-7QRFIKWQ.js} +2 -2
- package/Build/Workers/{chunk-GN5NEUDT.js → chunk-7TYLCBGK.js} +8 -8
- package/Build/Workers/{chunk-SGKTBHFQ.js → chunk-7X322WP2.js} +13 -13
- package/Build/Workers/{chunk-T43FXHNC.js → chunk-A47HVBC5.js} +7 -7
- package/Build/Workers/{chunk-FSDVXW7M.js → chunk-AF3MU2RL.js} +5 -5
- package/Build/Workers/{chunk-3B65YFXC.js → chunk-AJLTU6PF.js} +1 -1
- package/Build/Workers/{chunk-OQ3EAJNW.js → chunk-AMIHNSST.js} +2 -2
- package/Build/Workers/{chunk-N4AWE7TZ.js → chunk-B6SCUUFP.js} +10 -10
- package/Build/Workers/{chunk-OMXN7YF4.js → chunk-BJD6QGXZ.js} +12 -12
- package/Build/Workers/{chunk-APDKMX7W.js → chunk-C6P4IG5P.js} +6 -6
- package/Build/Workers/{chunk-QA24Q62E.js → chunk-D4EJ2NXG.js} +17 -17
- package/Build/Workers/{chunk-HYLEKKO5.js → chunk-DHKPFLSJ.js} +1 -1
- package/Build/Workers/{chunk-MQJG522T.js → chunk-DVB56LG7.js} +6 -6
- package/Build/Workers/{chunk-Y5AJSEEN.js → chunk-EDXL4W76.js} +2 -2
- package/Build/Workers/{chunk-QQX7S5QT.js → chunk-EV3VGO6Y.js} +17 -17
- package/Build/Workers/{chunk-IFA7VHHP.js → chunk-GOQBUCXH.js} +10 -10
- package/Build/Workers/{chunk-5A7YSAXT.js → chunk-GQUNK2XC.js} +14 -14
- package/Build/Workers/{chunk-36LBFITA.js → chunk-HKUES6UG.js} +12 -12
- package/Build/Workers/{chunk-OC6X22PG.js → chunk-HRHRYFHS.js} +9 -9
- package/Build/Workers/{chunk-L7RDJ4V7.js → chunk-HXJMS2ZI.js} +1 -1
- package/Build/Workers/{chunk-NAYRNPEP.js → chunk-ILMFADZA.js} +4 -4
- package/Build/Workers/{chunk-AA33B6PU.js → chunk-ISY4EZCA.js} +4 -4
- package/Build/Workers/{chunk-7KRN6JPQ.js → chunk-J6AW5YHS.js} +14 -14
- package/Build/Workers/{chunk-OQBPOKPZ.js → chunk-JCI63T3K.js} +6 -6
- package/Build/Workers/{chunk-2WI4HGJU.js → chunk-KLPGTXS3.js} +6 -6
- package/Build/Workers/{chunk-5R7SBUTW.js → chunk-LIB2H534.js} +10 -10
- package/Build/Workers/{chunk-IYVDOB5V.js → chunk-LXMCPFFS.js} +4 -4
- package/Build/Workers/{chunk-NUYLNQKV.js → chunk-MKM27KGV.js} +2 -2
- package/Build/Workers/{chunk-R7M4XNPP.js → chunk-N65BAKSH.js} +8 -8
- package/Build/Workers/{chunk-4LGFX2P5.js → chunk-NKT5K3K3.js} +11 -11
- package/Build/Workers/{chunk-NNHU33JK.js → chunk-NPF7SSHZ.js} +7 -7
- package/Build/Workers/{chunk-LDQWNMEC.js → chunk-PVV64VFW.js} +1 -1
- package/Build/Workers/{chunk-WKXDCVBO.js → chunk-Q3C6VQH6.js} +4 -4
- package/Build/Workers/{chunk-ARCFIOKA.js → chunk-RQNJD3O4.js} +12 -12
- package/Build/Workers/{chunk-G3YT7M7A.js → chunk-UIGVOKKI.js} +1 -1
- package/Build/Workers/{chunk-ZIW5FCIW.js → chunk-UQU4RXLT.js} +27 -19
- package/Build/Workers/{chunk-MT5M7RLZ.js → chunk-VLDEUTOP.js} +2 -2
- package/Build/Workers/{chunk-5JP5FG7U.js → chunk-VMVOUQ5J.js} +7 -7
- package/Build/Workers/{chunk-2GL2EUEE.js → chunk-XJRBB253.js} +11 -11
- package/Build/Workers/{chunk-ESD4IEOU.js → chunk-XY6HMDGI.js} +5 -5
- package/Build/Workers/{chunk-56OHFSLH.js → chunk-Y7HNNPNK.js} +10 -10
- package/Build/Workers/{chunk-6FVFM2KB.js → chunk-YAOZMOFL.js} +5 -5
- package/Build/Workers/{chunk-AP6XWET5.js → chunk-YJZGW74L.js} +8 -8
- package/Build/Workers/{chunk-KPYU6YZG.js → chunk-YQFTYQMZ.js} +1 -1
- package/Build/Workers/{chunk-5VKZVPO5.js → chunk-ZBZRTRJB.js} +10 -10
- package/Build/Workers/combineGeometry.js +24 -24
- package/Build/Workers/createBoxGeometry.js +18 -18
- package/Build/Workers/createBoxOutlineGeometry.js +16 -16
- package/Build/Workers/createCircleGeometry.js +26 -26
- package/Build/Workers/createCircleOutlineGeometry.js +19 -19
- package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
- package/Build/Workers/createCorridorGeometry.js +29 -29
- package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
- package/Build/Workers/createCylinderGeometry.js +20 -20
- package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
- package/Build/Workers/createEllipseGeometry.js +26 -26
- package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
- package/Build/Workers/createEllipsoidGeometry.js +19 -19
- package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
- package/Build/Workers/createFrustumGeometry.js +18 -18
- package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
- package/Build/Workers/createGeometry.js +24 -24
- package/Build/Workers/createGroundPolylineGeometry.js +22 -22
- package/Build/Workers/createPlaneGeometry.js +16 -16
- package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
- package/Build/Workers/createPolygonGeometry.js +32 -32
- package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
- package/Build/Workers/createPolylineGeometry.js +25 -25
- package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
- package/Build/Workers/createRectangleGeometry.js +27 -27
- package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
- package/Build/Workers/createSimplePolylineGeometry.js +23 -23
- package/Build/Workers/createSphereGeometry.js +19 -19
- package/Build/Workers/createSphereOutlineGeometry.js +18 -18
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
- package/Build/Workers/createVectorTileGeometries.js +24 -24
- package/Build/Workers/createVectorTilePoints.js +13 -13
- package/Build/Workers/createVectorTilePolygons.js +22 -22
- package/Build/Workers/createVectorTilePolylines.js +14 -14
- package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -22
- package/Build/Workers/createVerticesFromHeightmap.js +22 -22
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
- package/Build/Workers/createWallGeometry.js +25 -25
- package/Build/Workers/createWallOutlineGeometry.js +24 -24
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
- package/Build/Workers/decodeI3S.js +12 -12
- package/Build/Workers/gaussianSplatSorter.js +4 -4
- package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
- package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
- package/Build/Workers/transcodeKTX2.js +6 -6
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -22
- package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Source/Core/BoundingSphere.js +1 -1
- package/Source/Core/Cartesian2.js +7 -5
- package/Source/Core/Cartesian3.js +8 -6
- package/Source/Core/Cartesian4.js +8 -6
- package/Source/Core/Color.js +5 -3
- package/Source/Core/DeveloperError.js +2 -1
- package/Source/Core/ITwinPlatform.js +1 -0
- package/Source/Core/Ion.js +1 -1
- package/Source/Core/S2Cell.js +2 -2
- package/Source/Core/TerrainMesh.js +10 -1
- package/Source/Core/TerrainPicker.js +1 -0
- package/Source/Core/WallGeometry.js +1 -1
- package/Source/Core/WallOutlineGeometry.js +1 -1
- package/Source/Core/assert.js +27 -0
- package/Source/Core/globalTypes.js +4 -0
- package/Source/DataSources/CzmlDataSource.js +9 -0
- package/Source/DataSources/PathGraphics.js +13 -0
- package/Source/DataSources/PathVisualizer.js +330 -18
- package/Source/DataSources/StaticGeometryColorBatch.js +7 -2
- package/Source/DataSources/StaticGeometryPerMaterialBatch.js +7 -2
- package/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js +3 -1
- package/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js +3 -1
- package/Source/Renderer/Context.js +1 -1
- package/Source/Renderer/RenderState.js +2 -2
- package/Source/Renderer/VertexArray.js +80 -0
- package/Source/Scene/ArcGisMapService.js +1 -1
- package/Source/Scene/BillboardCollection.js +65 -364
- package/Source/Scene/BufferPoint.js +148 -0
- package/Source/Scene/BufferPointCollection.js +135 -0
- package/Source/Scene/BufferPointMaterial.js +95 -0
- package/Source/Scene/BufferPolygon.js +516 -0
- package/Source/Scene/BufferPolygonCollection.js +368 -0
- package/Source/Scene/BufferPolygonMaterial.js +41 -0
- package/Source/Scene/BufferPolyline.js +185 -0
- package/Source/Scene/BufferPolylineCollection.js +136 -0
- package/Source/Scene/BufferPolylineMaterial.js +93 -0
- package/Source/Scene/BufferPrimitive.js +347 -0
- package/Source/Scene/BufferPrimitiveCollection.js +702 -0
- package/Source/Scene/BufferPrimitiveMaterial.js +140 -0
- package/Source/Scene/Cesium3DTileContent.js +5 -1
- package/Source/Scene/Cesium3DTileContentFactory.js +9 -0
- package/Source/Scene/Cesium3DTileStyle.js +22 -0
- package/Source/Scene/Cesium3DTileset.js +1 -0
- package/Source/Scene/ClippingPolygonCollection.js +270 -101
- package/Source/Scene/CubeMapPanorama.js +4 -4
- package/Source/Scene/GaussianSplat3DTileContent.js +40 -46
- package/Source/Scene/GaussianSplatPrimitive.js +413 -70
- package/Source/Scene/GetFeatureInfoFormat.js +3 -3
- package/Source/Scene/GltfLoader.js +227 -34
- package/Source/Scene/GltfSpzLoader.js +109 -0
- package/Source/Scene/ITwinData.js +1 -0
- package/Source/Scene/Label.js +32 -0
- package/Source/Scene/LabelCollection.js +14 -13
- package/Source/Scene/Material.js +2 -0
- package/Source/Scene/Megatexture.js +1 -0
- package/Source/Scene/MetadataClassProperty.js +24 -10
- package/Source/Scene/MetadataComponentType.js +115 -23
- package/Source/Scene/Model/CustomShaderPipelineStage.js +3 -1
- package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +761 -263
- package/Source/Scene/Model/MaterialPipelineStage.js +147 -0
- package/Source/Scene/Model/MetadataPipelineStage.js +3 -3
- package/Source/Scene/Model/ModelDrawCommand.js +6 -0
- package/Source/Scene/Model/ModelReader.js +1 -1
- package/Source/Scene/Model/ModelUtility.js +3 -1
- package/Source/Scene/Model/createVectorTileBuffersFromModelComponents.js +330 -0
- package/Source/Scene/ModelComponents.js +1632 -1542
- package/Source/Scene/PickedMetadataInfo.js +1 -0
- package/Source/Scene/ScreenSpaceCameraController.js +13 -0
- package/Source/Scene/SkyBox.js +17 -8
- package/Source/Scene/TileBoundingRegion.js +1 -1
- package/Source/Scene/TileBoundingS2Cell.js +1 -1
- package/Source/Scene/TileBoundingSphere.js +1 -1
- package/Source/Scene/TweenCollection.js +7 -0
- package/Source/Scene/VectorGltf3DTileContent.js +382 -0
- package/Source/Scene/VertexAttributeSemantic.js +14 -0
- package/Source/Scene/WebMapServiceImageryProvider.js +2 -2
- package/Source/Scene/WebMapTileServiceImageryProvider.js +366 -131
- package/Source/Scene/parseStructuralMetadata.js +97 -37
- package/Source/Scene/renderBufferPointCollection.js +334 -0
- package/Source/Scene/renderBufferPolygonCollection.js +386 -0
- package/Source/Scene/renderBufferPolylineCollection.js +529 -0
- package/Source/Shaders/BillboardCollectionFS.glsl +2 -77
- package/Source/Shaders/BillboardCollectionFS.js +2 -77
- package/Source/Shaders/BillboardCollectionVS.glsl +2 -60
- package/Source/Shaders/BillboardCollectionVS.js +2 -60
- package/Source/Shaders/BufferPointMaterialFS.glsl +27 -0
- package/Source/Shaders/BufferPointMaterialFS.js +29 -0
- package/Source/Shaders/BufferPointMaterialVS.glsl +48 -0
- package/Source/Shaders/BufferPointMaterialVS.js +50 -0
- package/Source/Shaders/BufferPolygonMaterialFS.glsl +13 -0
- package/Source/Shaders/BufferPolygonMaterialFS.js +15 -0
- package/Source/Shaders/BufferPolygonMaterialVS.glsl +30 -0
- package/Source/Shaders/BufferPolygonMaterialVS.js +32 -0
- package/Source/Shaders/BufferPolylineMaterialFS.glsl +13 -0
- package/Source/Shaders/BufferPolylineMaterialFS.js +15 -0
- package/Source/Shaders/BufferPolylineMaterialVS.glsl +49 -0
- package/Source/Shaders/BufferPolylineMaterialVS.js +51 -0
- package/Source/Shaders/Model/EdgeVisibilityStageFS.glsl +34 -48
- package/Source/Shaders/Model/EdgeVisibilityStageFS.js +34 -49
- package/Source/Shaders/Model/EdgeVisibilityStageVS.glsl +98 -0
- package/Source/Shaders/Model/EdgeVisibilityStageVS.js +100 -0
- package/Source/Shaders/Model/ModelFS.glsl +15 -0
- package/Source/Shaders/Model/ModelFS.js +15 -0
- package/Source/Shaders/Model/ModelVS.glsl +8 -0
- package/Source/Shaders/Model/ModelVS.js +8 -0
- package/Source/Shaders/PolygonSignedDistanceFS.glsl +64 -33
- package/Source/Shaders/PolygonSignedDistanceFS.js +64 -33
- package/Source/Shaders/PrimitiveGaussianSplatVS.glsl +9 -2
- package/Source/Shaders/PrimitiveGaussianSplatVS.js +9 -2
- package/Source/Shaders/Voxels/VoxelFS.glsl +1 -1
- package/Source/Shaders/Voxels/VoxelFS.js +1 -1
- package/Source/Workers/decodeDraco.js +3 -0
- package/Source/Workers/decodeI3S.js +5 -2
- package/index.d.ts +1007 -111
- package/index.js +368 -343
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Frozen from "../Core/Frozen.js";
|
|
2
2
|
import Matrix4 from "../Core/Matrix4.js";
|
|
3
|
+
import Matrix3 from "../Core/Matrix3.js";
|
|
3
4
|
import ModelUtility from "./Model/ModelUtility.js";
|
|
4
5
|
import GaussianSplatSorter from "./GaussianSplatSorter.js";
|
|
5
6
|
import GaussianSplatTextureGenerator from "./GaussianSplatTextureGenerator.js";
|
|
@@ -36,9 +37,16 @@ import ContextLimits from "../Renderer/ContextLimits.js";
|
|
|
36
37
|
import Transforms from "../Core/Transforms.js";
|
|
37
38
|
|
|
38
39
|
const scratchMatrix4A = new Matrix4();
|
|
39
|
-
const scratchMatrix4B = new Matrix4();
|
|
40
40
|
const scratchMatrix4C = new Matrix4();
|
|
41
41
|
const scratchMatrix4D = new Matrix4();
|
|
42
|
+
const scratchMatrix3 = new Matrix3();
|
|
43
|
+
const scratchTransformQuat = new Quaternion();
|
|
44
|
+
const scratchTransformPosition = new Cartesian3();
|
|
45
|
+
const scratchTransformRotation = new Quaternion();
|
|
46
|
+
const scratchTransformScale = new Cartesian3();
|
|
47
|
+
const TRANSFORM_CACHE_EPSILON = 1e-12;
|
|
48
|
+
const RIGID_TRANSFORM_EPSILON = 1e-5;
|
|
49
|
+
const UNIT_SCALE_FAST_PATH_EPSILON = 1e-7;
|
|
42
50
|
|
|
43
51
|
/**
|
|
44
52
|
* Runtime state machine for steady-state re-sorting of an already committed snapshot.
|
|
@@ -337,6 +345,49 @@ function releaseRetiredTextures(primitive, frameNumber) {
|
|
|
337
345
|
primitive._retiredTextures = next;
|
|
338
346
|
}
|
|
339
347
|
|
|
348
|
+
function getSnapshotArrayBuffer(snapshot, key) {
|
|
349
|
+
const value = snapshot?.[key];
|
|
350
|
+
return defined(value) ? value.buffer : undefined;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function acquireAggregateScratchBuffer(
|
|
354
|
+
primitive,
|
|
355
|
+
key,
|
|
356
|
+
componentDatatype,
|
|
357
|
+
requiredLength,
|
|
358
|
+
) {
|
|
359
|
+
let pool = primitive._aggregateScratchBuffers[key];
|
|
360
|
+
if (!defined(pool)) {
|
|
361
|
+
pool = [];
|
|
362
|
+
primitive._aggregateScratchBuffers[key] = pool;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const activeBuffer = getSnapshotArrayBuffer(primitive._snapshot, key);
|
|
366
|
+
for (let i = 0; i < pool.length; i++) {
|
|
367
|
+
const candidate = pool[i];
|
|
368
|
+
if (
|
|
369
|
+
candidate.length >= requiredLength &&
|
|
370
|
+
candidate.buffer !== activeBuffer
|
|
371
|
+
) {
|
|
372
|
+
return candidate;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const created = ComponentDatatype.createTypedArray(
|
|
377
|
+
componentDatatype,
|
|
378
|
+
requiredLength,
|
|
379
|
+
);
|
|
380
|
+
pool.push(created);
|
|
381
|
+
return created;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function trimAggregateScratchBuffer(buffer, length) {
|
|
385
|
+
if (buffer.length === length) {
|
|
386
|
+
return buffer;
|
|
387
|
+
}
|
|
388
|
+
return buffer.subarray(0, length);
|
|
389
|
+
}
|
|
390
|
+
|
|
340
391
|
/**
|
|
341
392
|
* Atomically promotes a fully-built snapshot to be the active splat data for
|
|
342
393
|
* the primitive. This includes swapping attribute arrays, GPU textures, and
|
|
@@ -389,6 +440,13 @@ function commitSnapshot(primitive, snapshot, frameState) {
|
|
|
389
440
|
primitive.sphericalHarmonicsTexture = snapshot.sphericalHarmonicsTexture;
|
|
390
441
|
primitive._lastTextureWidth = snapshot.lastTextureWidth;
|
|
391
442
|
primitive._lastTextureHeight = snapshot.lastTextureHeight;
|
|
443
|
+
// Commit row-addressing params alongside the texture; the shader must
|
|
444
|
+
// always see the mask/shift that matches the active texture layout.
|
|
445
|
+
primitive._splatRowMask = snapshot.splatRowMask;
|
|
446
|
+
primitive._splatRowShift = snapshot.splatRowShift;
|
|
447
|
+
// Above 1.0 when the previous snapshot hit the hard cap; used in
|
|
448
|
+
// _wrappedUpdate to inflate traversal SSE and reduce tile load.
|
|
449
|
+
primitive._splatBudgetSSEScale = snapshot.splatBudgetSSEScale ?? 1.0;
|
|
392
450
|
primitive._hasGaussianSplatTexture = defined(snapshot.gaussianSplatTexture);
|
|
393
451
|
primitive._needsGaussianSplatTexture = false;
|
|
394
452
|
primitive._gaussianSplatTexturePending = false;
|
|
@@ -422,6 +480,72 @@ async function processGeneratedSplatTextureData(
|
|
|
422
480
|
) {
|
|
423
481
|
try {
|
|
424
482
|
const splatTextureData = await promise;
|
|
483
|
+
const maxTex = ContextLimits.maximumTextureSize;
|
|
484
|
+
|
|
485
|
+
// Use maximumTextureSize as the texture width; splatsPerRow = maxTex / 2
|
|
486
|
+
// (each splat occupies 2 side-by-side texels). The WASM buffer layout is
|
|
487
|
+
// width-independent, so the raw data is reused as-is.
|
|
488
|
+
const optimalWidth = maxTex;
|
|
489
|
+
let optimalHeight = Math.ceil(snapshot.numSplats / (maxTex / 2));
|
|
490
|
+
const splatRowShift = Math.log2(maxTex / 2);
|
|
491
|
+
const splatRowMask = maxTex / 2 - 1;
|
|
492
|
+
|
|
493
|
+
// Hard cap: >maxTex*(maxTex/2) splats cannot fit in any valid texture.
|
|
494
|
+
if (optimalHeight > maxTex) {
|
|
495
|
+
const originalCount = snapshot.numSplats;
|
|
496
|
+
optimalHeight = maxTex;
|
|
497
|
+
const splatsPerRow = optimalWidth / 2;
|
|
498
|
+
snapshot.numSplats = maxTex * splatsPerRow;
|
|
499
|
+
// Truncate CPU attribute arrays to match numSplats.
|
|
500
|
+
snapshot.positions = snapshot.positions.subarray(
|
|
501
|
+
0,
|
|
502
|
+
snapshot.numSplats * 3,
|
|
503
|
+
);
|
|
504
|
+
snapshot.rotations = snapshot.rotations.subarray(
|
|
505
|
+
0,
|
|
506
|
+
snapshot.numSplats * 4,
|
|
507
|
+
);
|
|
508
|
+
snapshot.scales = snapshot.scales.subarray(0, snapshot.numSplats * 3);
|
|
509
|
+
snapshot.colors = snapshot.colors.subarray(0, snapshot.numSplats * 4);
|
|
510
|
+
// shData is allocated independently and must be truncated separately.
|
|
511
|
+
if (defined(snapshot.shData)) {
|
|
512
|
+
const shPerSplat = snapshot.shData.length / originalCount;
|
|
513
|
+
snapshot.shData = snapshot.shData.subarray(
|
|
514
|
+
0,
|
|
515
|
+
Math.floor(snapshot.numSplats * shPerSplat),
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
// Scale up SSE next frame so traversal selects fewer tiles.
|
|
519
|
+
snapshot.splatBudgetSSEScale = originalCount / snapshot.numSplats;
|
|
520
|
+
console.warn(
|
|
521
|
+
`[GaussianSplat][HARD CAP] ${originalCount} splats exceed the maximum texture capacity ` +
|
|
522
|
+
`(${maxTex}\u00d7${splatsPerRow} = ${snapshot.numSplats} splats at width=${optimalWidth}). ` +
|
|
523
|
+
`Rendering only the first ${snapshot.numSplats} splats to avoid a WebGL crash. ` +
|
|
524
|
+
`Increasing maximumScreenSpaceError by ${snapshot.splatBudgetSSEScale.toFixed(2)}x next frame.`,
|
|
525
|
+
);
|
|
526
|
+
} else {
|
|
527
|
+
// Within budget; clear any SSE inflation carried over from a previous cap.
|
|
528
|
+
snapshot.splatBudgetSSEScale = 1.0;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Trim or zero-pad the raw WASM buffer to match the chosen dimensions.
|
|
532
|
+
const requiredLen = optimalWidth * optimalHeight * 4;
|
|
533
|
+
let effectiveData;
|
|
534
|
+
if (requiredLen <= splatTextureData.data.length) {
|
|
535
|
+
effectiveData = splatTextureData.data.subarray(0, requiredLen);
|
|
536
|
+
} else {
|
|
537
|
+
effectiveData = new Uint32Array(requiredLen);
|
|
538
|
+
effectiveData.set(splatTextureData.data);
|
|
539
|
+
}
|
|
540
|
+
const effectiveTextureData = {
|
|
541
|
+
width: optimalWidth,
|
|
542
|
+
height: optimalHeight,
|
|
543
|
+
data: effectiveData,
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
snapshot.splatRowMask = splatRowMask;
|
|
547
|
+
snapshot.splatRowShift = splatRowShift;
|
|
548
|
+
|
|
425
549
|
if (primitive._pendingSnapshot !== snapshot) {
|
|
426
550
|
snapshot.state = SnapshotState.BUILDING;
|
|
427
551
|
return;
|
|
@@ -429,29 +553,29 @@ async function processGeneratedSplatTextureData(
|
|
|
429
553
|
if (!defined(snapshot.gaussianSplatTexture)) {
|
|
430
554
|
snapshot.gaussianSplatTexture = createGaussianSplatTexture(
|
|
431
555
|
frameState.context,
|
|
432
|
-
|
|
556
|
+
effectiveTextureData,
|
|
433
557
|
);
|
|
434
558
|
} else if (
|
|
435
|
-
snapshot.lastTextureHeight !==
|
|
436
|
-
snapshot.lastTextureWidth !==
|
|
559
|
+
snapshot.lastTextureHeight !== effectiveTextureData.height ||
|
|
560
|
+
snapshot.lastTextureWidth !== effectiveTextureData.width
|
|
437
561
|
) {
|
|
438
562
|
const oldTex = snapshot.gaussianSplatTexture;
|
|
439
563
|
snapshot.gaussianSplatTexture = createGaussianSplatTexture(
|
|
440
564
|
frameState.context,
|
|
441
|
-
|
|
565
|
+
effectiveTextureData,
|
|
442
566
|
);
|
|
443
567
|
oldTex.destroy();
|
|
444
568
|
} else {
|
|
445
569
|
snapshot.gaussianSplatTexture.copyFrom({
|
|
446
570
|
source: {
|
|
447
|
-
width:
|
|
448
|
-
height:
|
|
449
|
-
arrayBufferView:
|
|
571
|
+
width: effectiveTextureData.width,
|
|
572
|
+
height: effectiveTextureData.height,
|
|
573
|
+
arrayBufferView: effectiveTextureData.data,
|
|
450
574
|
},
|
|
451
575
|
});
|
|
452
576
|
}
|
|
453
|
-
snapshot.lastTextureHeight =
|
|
454
|
-
snapshot.lastTextureWidth =
|
|
577
|
+
snapshot.lastTextureHeight = effectiveTextureData.height;
|
|
578
|
+
snapshot.lastTextureWidth = effectiveTextureData.width;
|
|
455
579
|
|
|
456
580
|
if (defined(snapshot.shData) && snapshot.sphericalHarmonicsDegree > 0) {
|
|
457
581
|
const oldTex = snapshot.sphericalHarmonicsTexture;
|
|
@@ -459,28 +583,44 @@ async function processGeneratedSplatTextureData(
|
|
|
459
583
|
const dims = snapshot.shCoefficientCount / 3;
|
|
460
584
|
const splatsPerRow = Math.floor(width / dims);
|
|
461
585
|
const floatsPerRow = splatsPerRow * (dims * 2);
|
|
462
|
-
const texBuf = new Uint32Array(
|
|
463
|
-
width * Math.ceil(snapshot.numSplats / splatsPerRow) * 2,
|
|
464
|
-
);
|
|
465
586
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
587
|
+
const shHeight = Math.ceil(snapshot.numSplats / splatsPerRow);
|
|
588
|
+
|
|
589
|
+
// SH texture width is already maxTex and cannot be widened further.
|
|
590
|
+
// When height would exceed the GPU limit, gracefully disable SH for this
|
|
591
|
+
// snapshot and fall back to base color rendering rather than crashing.
|
|
592
|
+
if (shHeight > width) {
|
|
593
|
+
console.warn(
|
|
594
|
+
`[GaussianSplat][SHTexture] ${snapshot.numSplats} splats require SH height ${shHeight} > maxTex ${width}. ` +
|
|
595
|
+
`Disabling spherical harmonics for this snapshot (color-only fallback).`,
|
|
471
596
|
);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
597
|
+
snapshot.sphericalHarmonicsDegree = 0;
|
|
598
|
+
if (defined(oldTex)) {
|
|
599
|
+
oldTex.destroy();
|
|
600
|
+
}
|
|
601
|
+
snapshot.sphericalHarmonicsTexture = undefined;
|
|
602
|
+
} else {
|
|
603
|
+
const texBuf = new Uint32Array(width * shHeight * 2);
|
|
604
|
+
|
|
605
|
+
let dataIndex = 0;
|
|
606
|
+
for (let i = 0; dataIndex < snapshot.shData.length; i += width * 2) {
|
|
607
|
+
texBuf.set(
|
|
608
|
+
snapshot.shData.subarray(dataIndex, dataIndex + floatsPerRow),
|
|
609
|
+
i,
|
|
610
|
+
);
|
|
611
|
+
dataIndex += floatsPerRow;
|
|
612
|
+
}
|
|
613
|
+
snapshot.sphericalHarmonicsTexture = createSphericalHarmonicsTexture(
|
|
614
|
+
frameState.context,
|
|
615
|
+
{
|
|
616
|
+
data: texBuf,
|
|
617
|
+
width: width,
|
|
618
|
+
height: shHeight,
|
|
619
|
+
},
|
|
620
|
+
);
|
|
621
|
+
if (defined(oldTex)) {
|
|
622
|
+
oldTex.destroy();
|
|
623
|
+
}
|
|
484
624
|
}
|
|
485
625
|
}
|
|
486
626
|
|
|
@@ -713,6 +853,12 @@ function GaussianSplatPrimitive(options) {
|
|
|
713
853
|
this._snapshot = undefined;
|
|
714
854
|
this._pendingSnapshot = undefined;
|
|
715
855
|
this._retiredTextures = [];
|
|
856
|
+
this._aggregateScratchBuffers = {
|
|
857
|
+
positions: [],
|
|
858
|
+
scales: [],
|
|
859
|
+
rotations: [],
|
|
860
|
+
colors: [],
|
|
861
|
+
};
|
|
716
862
|
|
|
717
863
|
/**
|
|
718
864
|
* Scratch buffer re-used across frames for aggregating packed spherical
|
|
@@ -860,6 +1006,15 @@ function GaussianSplatPrimitive(options) {
|
|
|
860
1006
|
new Matrix4(),
|
|
861
1007
|
);
|
|
862
1008
|
|
|
1009
|
+
/**
|
|
1010
|
+
* Cached inverse rotation for SH evaluation, updated each snapshot rebuild.
|
|
1011
|
+
* Converts a world-space view direction to the original GLB Y-up model space
|
|
1012
|
+
* so that spherical harmonic coefficients are evaluated in the correct frame.
|
|
1013
|
+
* @type {Matrix3}
|
|
1014
|
+
* @private
|
|
1015
|
+
*/
|
|
1016
|
+
this._shInverseRotation = new Matrix3();
|
|
1017
|
+
|
|
863
1018
|
/**
|
|
864
1019
|
* Indicates whether or not the primitive has been destroyed.
|
|
865
1020
|
* @type {boolean}
|
|
@@ -899,6 +1054,22 @@ function GaussianSplatPrimitive(options) {
|
|
|
899
1054
|
* @private
|
|
900
1055
|
*/
|
|
901
1056
|
this._sorterError = undefined;
|
|
1057
|
+
|
|
1058
|
+
// Splat texture row-addressing params; forwarded to the shader as uniforms.
|
|
1059
|
+
// The texture width is always maximumTextureSize (varies by GPU), so these
|
|
1060
|
+
// are computed per-snapshot and initialized here as safe placeholders.
|
|
1061
|
+
this._splatRowMask = 0; // overwritten on first snapshot commit
|
|
1062
|
+
this._splatRowShift = 0; // overwritten on first snapshot commit
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Multiplier applied to maximumScreenSpaceError during tile traversal when
|
|
1066
|
+
* the previous snapshot exceeded the splat texture budget. A value above 1.0
|
|
1067
|
+
* biases traversal toward coarser LODs, lowering the total splat count.
|
|
1068
|
+
* Resets to 1.0 once the splat count is within budget.
|
|
1069
|
+
* @type {number}
|
|
1070
|
+
* @private
|
|
1071
|
+
*/
|
|
1072
|
+
this._splatBudgetSSEScale = 1.0;
|
|
902
1073
|
}
|
|
903
1074
|
|
|
904
1075
|
Object.defineProperties(GaussianSplatPrimitive.prototype, {
|
|
@@ -951,14 +1122,25 @@ Object.defineProperties(GaussianSplatPrimitive.prototype, {
|
|
|
951
1122
|
});
|
|
952
1123
|
|
|
953
1124
|
/**
|
|
954
|
-
*
|
|
955
|
-
*
|
|
1125
|
+
* Replaces the tileset's own update function so this primitive is updated
|
|
1126
|
+
* immediately after the tileset traversal, within the same frame. When
|
|
1127
|
+
* _splatBudgetSSEScale is above 1.0, maximumScreenSpaceError is inflated
|
|
1128
|
+
* for the duration of the traversal to reduce the number of tiles selected.
|
|
956
1129
|
* @param {FrameState} frameState
|
|
957
1130
|
* @private
|
|
958
|
-
*
|
|
959
1131
|
*/
|
|
960
1132
|
GaussianSplatPrimitive.prototype._wrappedUpdate = function (frameState) {
|
|
961
|
-
this.
|
|
1133
|
+
const tileset = this._tileset;
|
|
1134
|
+
if (this._splatBudgetSSEScale !== 1.0) {
|
|
1135
|
+
// Inflate SSE for this traversal only; the original value is restored
|
|
1136
|
+
// immediately so the user-visible tileset property is never permanently changed.
|
|
1137
|
+
const originalSSE = tileset.maximumScreenSpaceError;
|
|
1138
|
+
tileset.maximumScreenSpaceError *= this._splatBudgetSSEScale;
|
|
1139
|
+
this._baseTilesetUpdate.call(tileset, frameState);
|
|
1140
|
+
tileset.maximumScreenSpaceError = originalSSE;
|
|
1141
|
+
} else {
|
|
1142
|
+
this._baseTilesetUpdate.call(tileset, frameState);
|
|
1143
|
+
}
|
|
962
1144
|
this.update(frameState);
|
|
963
1145
|
};
|
|
964
1146
|
|
|
@@ -982,6 +1164,7 @@ GaussianSplatPrimitive.prototype.destroy = function () {
|
|
|
982
1164
|
this._retiredTextures = [];
|
|
983
1165
|
this._pendingSnapshot = undefined;
|
|
984
1166
|
this._snapshot = undefined;
|
|
1167
|
+
this._aggregateScratchBuffers = undefined;
|
|
985
1168
|
this.gaussianSplatTexture = undefined;
|
|
986
1169
|
this.sphericalHarmonicsTexture = undefined;
|
|
987
1170
|
|
|
@@ -1065,20 +1248,95 @@ GaussianSplatPrimitive.transformTile = function (tile) {
|
|
|
1065
1248
|
computedModelMatrix,
|
|
1066
1249
|
);
|
|
1067
1250
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
const toLocal = Matrix4.inverse(
|
|
1251
|
+
// toLocal is inverse(rootTransform) only. tileset.modelMatrix is already
|
|
1252
|
+
// factored into computedModelMatrix via tile.computedTransform, so its effect
|
|
1253
|
+
// is baked directly into the splat values rather than split into the draw
|
|
1254
|
+
// command's modelMatrix. This keeps czm_view * modelMatrix numerically small,
|
|
1255
|
+
// avoiding float32 precision loss at ECEF-scale translations.
|
|
1256
|
+
const toLocal = Matrix4.inverse(rootTransform, scratchMatrix4C);
|
|
1074
1257
|
const transform = Matrix4.multiplyTransformation(
|
|
1075
1258
|
toLocal,
|
|
1076
1259
|
computedModelMatrix,
|
|
1077
1260
|
scratchMatrix4A,
|
|
1078
1261
|
);
|
|
1262
|
+
const cachedTransform = tile.content._lastSplatTransform;
|
|
1263
|
+
if (
|
|
1264
|
+
tile.content._transformed &&
|
|
1265
|
+
defined(cachedTransform) &&
|
|
1266
|
+
Matrix4.equalsEpsilon(transform, cachedTransform, TRANSFORM_CACHE_EPSILON)
|
|
1267
|
+
) {
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1079
1270
|
const positions = tile.content.positions;
|
|
1080
1271
|
const rotations = tile.content.rotations;
|
|
1081
1272
|
const scales = tile.content.scales;
|
|
1273
|
+
|
|
1274
|
+
// Extract the rotation quaternion from transform once, before the per-splat
|
|
1275
|
+
// loop. The columns of transform's upper-left 3x3 have magnitude ≈ 1 (rigid
|
|
1276
|
+
// body placement), so normalizing is numerically stable. We cannot decompose
|
|
1277
|
+
// the per-splat combined matrix (transform × TRS_i) instead, because each
|
|
1278
|
+
// splat's scale can be very small, causing catastrophic cancellation when
|
|
1279
|
+
// dividing to recover a pure rotation matrix.
|
|
1280
|
+
const col0Len = Math.sqrt(
|
|
1281
|
+
transform[0] * transform[0] +
|
|
1282
|
+
transform[1] * transform[1] +
|
|
1283
|
+
transform[2] * transform[2],
|
|
1284
|
+
);
|
|
1285
|
+
const col1Len = Math.sqrt(
|
|
1286
|
+
transform[4] * transform[4] +
|
|
1287
|
+
transform[5] * transform[5] +
|
|
1288
|
+
transform[6] * transform[6],
|
|
1289
|
+
);
|
|
1290
|
+
const col2Len = Math.sqrt(
|
|
1291
|
+
transform[8] * transform[8] +
|
|
1292
|
+
transform[9] * transform[9] +
|
|
1293
|
+
transform[10] * transform[10],
|
|
1294
|
+
);
|
|
1295
|
+
scratchMatrix3[0] = transform[0] / col0Len;
|
|
1296
|
+
scratchMatrix3[1] = transform[1] / col0Len;
|
|
1297
|
+
scratchMatrix3[2] = transform[2] / col0Len;
|
|
1298
|
+
scratchMatrix3[3] = transform[4] / col1Len;
|
|
1299
|
+
scratchMatrix3[4] = transform[5] / col1Len;
|
|
1300
|
+
scratchMatrix3[5] = transform[6] / col1Len;
|
|
1301
|
+
scratchMatrix3[6] = transform[8] / col2Len;
|
|
1302
|
+
scratchMatrix3[7] = transform[9] / col2Len;
|
|
1303
|
+
scratchMatrix3[8] = transform[10] / col2Len;
|
|
1304
|
+
const dot01 =
|
|
1305
|
+
scratchMatrix3[0] * scratchMatrix3[3] +
|
|
1306
|
+
scratchMatrix3[1] * scratchMatrix3[4] +
|
|
1307
|
+
scratchMatrix3[2] * scratchMatrix3[5];
|
|
1308
|
+
const dot02 =
|
|
1309
|
+
scratchMatrix3[0] * scratchMatrix3[6] +
|
|
1310
|
+
scratchMatrix3[1] * scratchMatrix3[7] +
|
|
1311
|
+
scratchMatrix3[2] * scratchMatrix3[8];
|
|
1312
|
+
const dot12 =
|
|
1313
|
+
scratchMatrix3[3] * scratchMatrix3[6] +
|
|
1314
|
+
scratchMatrix3[4] * scratchMatrix3[7] +
|
|
1315
|
+
scratchMatrix3[5] * scratchMatrix3[8];
|
|
1316
|
+
const hasUnitScale =
|
|
1317
|
+
Math.abs(col0Len - 1.0) <= UNIT_SCALE_FAST_PATH_EPSILON &&
|
|
1318
|
+
Math.abs(col1Len - 1.0) <= UNIT_SCALE_FAST_PATH_EPSILON &&
|
|
1319
|
+
Math.abs(col2Len - 1.0) <= UNIT_SCALE_FAST_PATH_EPSILON;
|
|
1320
|
+
const isOrthogonal =
|
|
1321
|
+
Math.abs(dot01) <= RIGID_TRANSFORM_EPSILON &&
|
|
1322
|
+
Math.abs(dot02) <= RIGID_TRANSFORM_EPSILON &&
|
|
1323
|
+
Math.abs(dot12) <= RIGID_TRANSFORM_EPSILON;
|
|
1324
|
+
const determinant =
|
|
1325
|
+
scratchMatrix3[0] *
|
|
1326
|
+
(scratchMatrix3[4] * scratchMatrix3[8] -
|
|
1327
|
+
scratchMatrix3[5] * scratchMatrix3[7]) -
|
|
1328
|
+
scratchMatrix3[3] *
|
|
1329
|
+
(scratchMatrix3[1] * scratchMatrix3[8] -
|
|
1330
|
+
scratchMatrix3[2] * scratchMatrix3[7]) +
|
|
1331
|
+
scratchMatrix3[6] *
|
|
1332
|
+
(scratchMatrix3[1] * scratchMatrix3[5] -
|
|
1333
|
+
scratchMatrix3[2] * scratchMatrix3[4]);
|
|
1334
|
+
const useFastPath =
|
|
1335
|
+
hasUnitScale &&
|
|
1336
|
+
isOrthogonal &&
|
|
1337
|
+
Math.abs(determinant - 1.0) <= RIGID_TRANSFORM_EPSILON;
|
|
1338
|
+
Quaternion.fromRotationMatrix(scratchMatrix3, scratchTransformQuat);
|
|
1339
|
+
Quaternion.normalize(scratchTransformQuat, scratchTransformQuat);
|
|
1082
1340
|
const attributePositions = ModelUtility.getAttributeBySemantic(
|
|
1083
1341
|
gltfPrimitive,
|
|
1084
1342
|
VertexAttributeSemantic.POSITION,
|
|
@@ -1094,9 +1352,9 @@ GaussianSplatPrimitive.transformTile = function (tile) {
|
|
|
1094
1352
|
VertexAttributeSemantic.SCALE,
|
|
1095
1353
|
).typedArray;
|
|
1096
1354
|
|
|
1097
|
-
const position =
|
|
1098
|
-
const rotation =
|
|
1099
|
-
const scale =
|
|
1355
|
+
const position = scratchTransformPosition;
|
|
1356
|
+
const rotation = scratchTransformRotation;
|
|
1357
|
+
const scale = scratchTransformScale;
|
|
1100
1358
|
for (let i = 0; i < attributePositions.length / 3; ++i) {
|
|
1101
1359
|
position.x = attributePositions[i * 3];
|
|
1102
1360
|
position.y = attributePositions[i * 3 + 1];
|
|
@@ -1111,18 +1369,31 @@ GaussianSplatPrimitive.transformTile = function (tile) {
|
|
|
1111
1369
|
scale.y = attributeScales[i * 3 + 1];
|
|
1112
1370
|
scale.z = attributeScales[i * 3 + 2];
|
|
1113
1371
|
|
|
1114
|
-
|
|
1115
|
-
position,
|
|
1116
|
-
rotation,
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1372
|
+
if (useFastPath) {
|
|
1373
|
+
Matrix4.multiplyByPoint(transform, position, position);
|
|
1374
|
+
Quaternion.multiply(scratchTransformQuat, rotation, rotation);
|
|
1375
|
+
Quaternion.normalize(rotation, rotation);
|
|
1376
|
+
} else {
|
|
1377
|
+
Matrix4.fromTranslationQuaternionRotationScale(
|
|
1378
|
+
position,
|
|
1379
|
+
rotation,
|
|
1380
|
+
scale,
|
|
1381
|
+
scratchMatrix4D,
|
|
1382
|
+
);
|
|
1120
1383
|
|
|
1121
|
-
|
|
1384
|
+
Matrix4.multiplyTransformation(
|
|
1385
|
+
transform,
|
|
1386
|
+
scratchMatrix4D,
|
|
1387
|
+
scratchMatrix4D,
|
|
1388
|
+
);
|
|
1122
1389
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1390
|
+
Matrix4.getTranslation(scratchMatrix4D, position);
|
|
1391
|
+
Matrix4.getScale(scratchMatrix4D, scale);
|
|
1392
|
+
// rotation still holds the original splat quaternion from attributeRotations.
|
|
1393
|
+
// Apply the transform's rotation by left-multiplying the transform quaternion.
|
|
1394
|
+
Quaternion.multiply(scratchTransformQuat, rotation, rotation);
|
|
1395
|
+
Quaternion.normalize(rotation, rotation);
|
|
1396
|
+
}
|
|
1126
1397
|
|
|
1127
1398
|
positions[i * 3] = position.x;
|
|
1128
1399
|
positions[i * 3 + 1] = position.y;
|
|
@@ -1137,6 +1408,11 @@ GaussianSplatPrimitive.transformTile = function (tile) {
|
|
|
1137
1408
|
scales[i * 3 + 1] = scale.y;
|
|
1138
1409
|
scales[i * 3 + 2] = scale.z;
|
|
1139
1410
|
}
|
|
1411
|
+
tile.content._lastSplatTransform = Matrix4.clone(
|
|
1412
|
+
transform,
|
|
1413
|
+
tile.content._lastSplatTransform,
|
|
1414
|
+
);
|
|
1415
|
+
tile.content._transformed = true;
|
|
1140
1416
|
};
|
|
1141
1417
|
|
|
1142
1418
|
/**
|
|
@@ -1243,10 +1519,21 @@ GaussianSplatPrimitive.buildGSplatDrawCommand = function (
|
|
|
1243
1519
|
|
|
1244
1520
|
const uniformMap = renderResources.uniformMap;
|
|
1245
1521
|
|
|
1522
|
+
// Row-addressing uniforms: read from primitive each draw so they stay in sync
|
|
1523
|
+
// with the texture width chosen for the current snapshot.
|
|
1524
|
+
shaderBuilder.addUniform("int", "u_splatRowMask", ShaderDestination.VERTEX);
|
|
1525
|
+
shaderBuilder.addUniform("int", "u_splatRowShift", ShaderDestination.VERTEX);
|
|
1526
|
+
|
|
1246
1527
|
const textureCache = primitive.gaussianSplatTexture;
|
|
1247
1528
|
uniformMap.u_splatAttributeTexture = function () {
|
|
1248
1529
|
return textureCache;
|
|
1249
1530
|
};
|
|
1531
|
+
uniformMap.u_splatRowMask = function () {
|
|
1532
|
+
return primitive._splatRowMask;
|
|
1533
|
+
};
|
|
1534
|
+
uniformMap.u_splatRowShift = function () {
|
|
1535
|
+
return primitive._splatRowShift;
|
|
1536
|
+
};
|
|
1250
1537
|
|
|
1251
1538
|
if (primitive._sphericalHarmonicsDegree > 0) {
|
|
1252
1539
|
shaderBuilder.addDefine(
|
|
@@ -1272,17 +1559,12 @@ GaussianSplatPrimitive.buildGSplatDrawCommand = function (
|
|
|
1272
1559
|
};
|
|
1273
1560
|
|
|
1274
1561
|
uniformMap.u_inverseModelRotation = function () {
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
const inverseModelRotation = Matrix4.getRotation(
|
|
1282
|
-
Matrix4.inverse(modelMatrix, scratchMatrix4C),
|
|
1283
|
-
scratchMatrix4D,
|
|
1284
|
-
);
|
|
1285
|
-
return inverseModelRotation;
|
|
1562
|
+
// SH coefficients are encoded in the GLB Y-up training space. To evaluate
|
|
1563
|
+
// them the world-space view direction must be rotated by
|
|
1564
|
+
// inverse(computedTransform × axisCorrectionMatrix × worldTransform).
|
|
1565
|
+
// This matrix is pre-computed each snapshot rebuild and stored on the
|
|
1566
|
+
// primitive so the uniform closure just returns the cached value.
|
|
1567
|
+
return primitive._shInverseRotation;
|
|
1286
1568
|
};
|
|
1287
1569
|
|
|
1288
1570
|
uniformMap.u_splitDirection = function () {
|
|
@@ -1357,8 +1639,11 @@ GaussianSplatPrimitive.buildGSplatDrawCommand = function (
|
|
|
1357
1639
|
|
|
1358
1640
|
primitive._vertexArrayLen = primitive._indexes.length;
|
|
1359
1641
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1642
|
+
// The draw command uses rootTransform as its modelMatrix. tileset.modelMatrix
|
|
1643
|
+
// is baked into the splat positions by transformTile and must not appear here
|
|
1644
|
+
// as well. This keeps czm_view * modelMatrix numerically small (ENU frame),
|
|
1645
|
+
// avoiding float32 precision loss from ECEF-scale translations.
|
|
1646
|
+
const modelMatrix = Matrix4.clone(
|
|
1362
1647
|
primitive._rootTransform,
|
|
1363
1648
|
primitive._drawCommandModelMatrix,
|
|
1364
1649
|
);
|
|
@@ -1489,36 +1774,88 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
1489
1774
|
}
|
|
1490
1775
|
|
|
1491
1776
|
const tiles = tileset._selectedTiles;
|
|
1777
|
+
|
|
1778
|
+
// Rebuild the ENU origin from the current tileset world center so that
|
|
1779
|
+
// baked splat positions remain in a numerically small (meter-scale) local
|
|
1780
|
+
// frame, regardless of the current tileset.modelMatrix value.
|
|
1781
|
+
this._rootTransform = Transforms.eastNorthUpToFixedFrame(
|
|
1782
|
+
tileset.boundingSphere.center,
|
|
1783
|
+
);
|
|
1784
|
+
|
|
1785
|
+
// Compute the SH inverse rotation from the first tile's coordinate frame.
|
|
1786
|
+
// SH coefficients are encoded in the GLB Y-up training space. To evaluate
|
|
1787
|
+
// them correctly the view direction must be transformed by
|
|
1788
|
+
// inverse(computedTransform × axisCorrectionMatrix × worldTransform).
|
|
1789
|
+
// All tiles in a typical GS tileset share the same root coordinate frame,
|
|
1790
|
+
// so using the first tile is sufficient.
|
|
1791
|
+
{
|
|
1792
|
+
const ft = tiles[0];
|
|
1793
|
+
const shFwd = Matrix4.multiplyTransformation(
|
|
1794
|
+
ft.computedTransform,
|
|
1795
|
+
this._axisCorrectionMatrix,
|
|
1796
|
+
scratchMatrix4C,
|
|
1797
|
+
);
|
|
1798
|
+
Matrix4.multiplyTransformation(
|
|
1799
|
+
shFwd,
|
|
1800
|
+
ft.content.worldTransform ?? Matrix4.IDENTITY,
|
|
1801
|
+
shFwd,
|
|
1802
|
+
);
|
|
1803
|
+
Matrix4.getRotation(
|
|
1804
|
+
Matrix4.inverse(shFwd, shFwd),
|
|
1805
|
+
this._shInverseRotation,
|
|
1806
|
+
);
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
for (const tile of tiles) {
|
|
1810
|
+
GaussianSplatPrimitive.transformTile(tile);
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1492
1813
|
const totalElements = tiles.reduce(
|
|
1493
1814
|
(total, tile) => total + tile.content.pointsLength,
|
|
1494
1815
|
0,
|
|
1495
1816
|
);
|
|
1496
1817
|
const aggregateAttributeValues = (
|
|
1818
|
+
key,
|
|
1497
1819
|
componentDatatype,
|
|
1498
1820
|
getAttributeCallback,
|
|
1499
1821
|
numberOfComponents,
|
|
1500
1822
|
) => {
|
|
1501
1823
|
let aggregate;
|
|
1502
1824
|
let offset = 0;
|
|
1825
|
+
let requiredLength = 0;
|
|
1503
1826
|
for (const tile of tiles) {
|
|
1504
|
-
const
|
|
1505
|
-
const attribute = getAttributeCallback(content);
|
|
1827
|
+
const attribute = getAttributeCallback(tile.content);
|
|
1506
1828
|
const componentsPerAttribute = defined(numberOfComponents)
|
|
1507
1829
|
? numberOfComponents
|
|
1508
1830
|
: AttributeType.getNumberOfComponents(attribute.type);
|
|
1509
1831
|
const buffer = defined(attribute.typedArray)
|
|
1510
1832
|
? attribute.typedArray
|
|
1511
1833
|
: attribute;
|
|
1834
|
+
requiredLength += buffer.length;
|
|
1512
1835
|
if (!defined(aggregate)) {
|
|
1513
|
-
aggregate =
|
|
1836
|
+
aggregate = acquireAggregateScratchBuffer(
|
|
1837
|
+
this,
|
|
1838
|
+
key,
|
|
1514
1839
|
componentDatatype,
|
|
1515
1840
|
totalElements * componentsPerAttribute,
|
|
1516
1841
|
);
|
|
1517
1842
|
}
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
if (!defined(aggregate)) {
|
|
1846
|
+
return ComponentDatatype.createTypedArray(componentDatatype, 0);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
for (const tile of tiles) {
|
|
1850
|
+
const content = tile.content;
|
|
1851
|
+
const attribute = getAttributeCallback(content);
|
|
1852
|
+
const buffer = defined(attribute.typedArray)
|
|
1853
|
+
? attribute.typedArray
|
|
1854
|
+
: attribute;
|
|
1518
1855
|
aggregate.set(buffer, offset);
|
|
1519
1856
|
offset += buffer.length;
|
|
1520
1857
|
}
|
|
1521
|
-
return aggregate;
|
|
1858
|
+
return trimAggregateScratchBuffer(aggregate, requiredLength);
|
|
1522
1859
|
};
|
|
1523
1860
|
|
|
1524
1861
|
const aggregateShData = () => {
|
|
@@ -1576,24 +1913,28 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
1576
1913
|
};
|
|
1577
1914
|
|
|
1578
1915
|
const positions = aggregateAttributeValues(
|
|
1916
|
+
"positions",
|
|
1579
1917
|
ComponentDatatype.FLOAT,
|
|
1580
1918
|
(content) => content.positions,
|
|
1581
1919
|
3,
|
|
1582
1920
|
);
|
|
1583
1921
|
|
|
1584
1922
|
const scales = aggregateAttributeValues(
|
|
1923
|
+
"scales",
|
|
1585
1924
|
ComponentDatatype.FLOAT,
|
|
1586
1925
|
(content) => content.scales,
|
|
1587
1926
|
3,
|
|
1588
1927
|
);
|
|
1589
1928
|
|
|
1590
1929
|
const rotations = aggregateAttributeValues(
|
|
1930
|
+
"rotations",
|
|
1591
1931
|
ComponentDatatype.FLOAT,
|
|
1592
1932
|
(content) => content.rotations,
|
|
1593
1933
|
4,
|
|
1594
1934
|
);
|
|
1595
1935
|
|
|
1596
1936
|
const colors = aggregateAttributeValues(
|
|
1937
|
+
"colors",
|
|
1597
1938
|
ComponentDatatype.UNSIGNED_BYTE,
|
|
1598
1939
|
(content) =>
|
|
1599
1940
|
ModelUtility.getAttributeBySemantic(
|
|
@@ -1625,6 +1966,8 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
|
|
|
1625
1966
|
sphericalHarmonicsTexture: undefined,
|
|
1626
1967
|
lastTextureWidth: 0,
|
|
1627
1968
|
lastTextureHeight: 0,
|
|
1969
|
+
splatRowMask: 0, // set by processGeneratedSplatTextureData
|
|
1970
|
+
splatRowShift: 0, // set by processGeneratedSplatTextureData
|
|
1628
1971
|
state: SnapshotState.BUILDING,
|
|
1629
1972
|
};
|
|
1630
1973
|
|