Skip to content

Commit 0dc7bf8

Browse files
authored
Merge pull request #12706 from CesiumGS/gsplat-modelmatrix-update
Update with modelMatrix and correctly handle rotation
2 parents 1bafc49 + bca8988 commit 0dc7bf8

File tree

3 files changed

+70
-27
lines changed

3 files changed

+70
-27
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
- Updates use of deprecated options on createImageBitmap. [#12664](https://github.com/CesiumGS/cesium/pull/12664)
1010
- Fixed raymarching step size for cylindrical voxels. [#12681](https://github.com/CesiumGS/cesium/pull/12681)
1111

12+
- Fixes handling of tileset modelMatrix changes for translations and rotations in GaussianSplatPrimitive. [#12706](https://github.com/CesiumGS/cesium/pull/12706)
13+
1214
#### Additions :tada:
1315

1416
- Added `HeightReference` to `Cesium3DTileset.ConstructorOptions` to allow clamping point features in 3D Tile vector data to terrain or 3D Tiles [#11710](https://github.com/CesiumGS/cesium/pull/11710)

packages/engine/Source/Scene/GaussianSplat3DTileContent.js

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import RuntimeError from "../Core/RuntimeError.js";
55
import Axis from "./Axis.js";
66
import GaussianSplatPrimitive from "./GaussianSplatPrimitive.js";
77
import destroyObject from "../Core/destroyObject.js";
8+
import ModelUtility from "./Model/ModelUtility.js";
9+
import VertexAttributeSemantic from "./VertexAttributeSemantic.js";
810

911
/**
1012
* Represents the contents of a glTF or glb using the {@link https://github.com/CesiumGS/glTF/tree/draft-spz-splat-compression/extensions/2.0/Khronos/KHR_spz_gaussian_splats_compression|KHR_spz_gaussian_splats_compression} extension.
@@ -28,6 +30,17 @@ function GaussianSplat3DTileContent(loader, tileset, tile, resource) {
2830
});
2931
}
3032

33+
/**
34+
* Original position, scale and rotation values for splats. Used to maintain
35+
* consistency when multiple transforms may occur. Downstream consumers otherwise may not know
36+
* the underlying data was modified.
37+
* @type {undefined|Float32Array}
38+
* @private
39+
*/
40+
this._originalPositions = undefined;
41+
this._originalRotations = undefined;
42+
this._originalScales = undefined;
43+
3144
/**
3245
* glTF primitive data that contains the Gaussian splat data needed for rendering.
3346
* @type {undefined|Primitive}
@@ -350,19 +363,15 @@ GaussianSplat3DTileContent.fromGltf = async function (
350363

351364
/**
352365
* Updates the content of the tile and prepares it for rendering.
353-
* @param {Cesium3DTileset}
366+
* @param {Cesium3DTileset}Data attribution
354367
* @param {FrameState} frameState - The current frame state.
355368
* @private
356369
*/
357370
GaussianSplat3DTileContent.prototype.update = function (primitive, frameState) {
358371
const loader = this._loader;
359372

360373
if (this._ready) {
361-
if (
362-
!this._transformed &&
363-
this._tile !== primitive.root &&
364-
primitive.root.content.ready
365-
) {
374+
if (!this._transformed && primitive.root.content.ready) {
366375
GaussianSplatPrimitive.transformTile(this._tile);
367376
this._transformed = true;
368377
}
@@ -382,6 +391,27 @@ GaussianSplat3DTileContent.prototype.update = function (primitive, frameState) {
382391
this.worldTransform = loader.components.scene.nodes[0].matrix;
383392
this._ready = true;
384393

394+
this._originalPositions = new Float32Array(
395+
ModelUtility.getAttributeBySemantic(
396+
this.splatPrimitive,
397+
VertexAttributeSemantic.POSITION,
398+
).typedArray,
399+
);
400+
401+
this._originalRotations = new Float32Array(
402+
ModelUtility.getAttributeBySemantic(
403+
this.splatPrimitive,
404+
VertexAttributeSemantic.ROTATION,
405+
).typedArray,
406+
);
407+
408+
this._originalScales = new Float32Array(
409+
ModelUtility.getAttributeBySemantic(
410+
this.splatPrimitive,
411+
VertexAttributeSemantic.SCALE,
412+
).typedArray,
413+
);
414+
385415
return;
386416
}
387417

packages/engine/Source/Scene/GaussianSplatPrimitive.js

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import AttributeType from "./AttributeType.js";
2929
import ModelComponents from "./ModelComponents.js";
3030
import Axis from "./Axis.js";
3131
import Cartesian3 from "../Core/Cartesian3.js";
32-
import Transforms from "../Core/Transforms.js";
3332
import Quaternion from "../Core/Quaternion.js";
3433
import SplitDirection from "./SplitDirection.js";
3534
import destroyObject from "../Core/destroyObject.js";
@@ -438,27 +437,31 @@ GaussianSplatPrimitive.transformTile = function (tile) {
438437
computedModelMatrix,
439438
);
440439

441-
const center = tile.tileset.boundingSphere.center;
442-
const toGlobal = Transforms.eastNorthUpToFixedFrame(center);
443-
const toLocal = Matrix4.inverse(toGlobal, scratchMatrix4B);
444-
440+
const toGlobal = Matrix4.multiply(
441+
tile.tileset.modelMatrix,
442+
Matrix4.fromArray(tile.tileset.root.transform),
443+
scratchMatrix4B,
444+
);
445+
const toLocal = Matrix4.inverse(toGlobal, scratchMatrix4C);
445446
const transform = Matrix4.multiplyTransformation(
446447
toLocal,
447448
computedModelMatrix,
448449
scratchMatrix4A,
449450
);
450-
451-
const positions = ModelUtility.getAttributeBySemantic(
451+
const positions = tile.content._originalPositions;
452+
const rotations = tile.content._originalRotations;
453+
const scales = tile.content._originalScales;
454+
const attributePositions = ModelUtility.getAttributeBySemantic(
452455
splatPrimitive,
453456
VertexAttributeSemantic.POSITION,
454457
).typedArray;
455458

456-
const rotations = ModelUtility.getAttributeBySemantic(
459+
const attributeRotations = ModelUtility.getAttributeBySemantic(
457460
splatPrimitive,
458461
VertexAttributeSemantic.ROTATION,
459462
).typedArray;
460463

461-
const scales = ModelUtility.getAttributeBySemantic(
464+
const attributeScales = ModelUtility.getAttributeBySemantic(
462465
splatPrimitive,
463466
VertexAttributeSemantic.SCALE,
464467
).typedArray;
@@ -493,18 +496,18 @@ GaussianSplatPrimitive.transformTile = function (tile) {
493496
Matrix4.getRotation(scratchMatrix4C, rotation);
494497
Matrix4.getScale(scratchMatrix4C, scale);
495498

496-
positions[i * 3] = position.x;
497-
positions[i * 3 + 1] = position.y;
498-
positions[i * 3 + 2] = position.z;
499+
attributePositions[i * 3] = position.x;
500+
attributePositions[i * 3 + 1] = position.y;
501+
attributePositions[i * 3 + 2] = position.z;
499502

500-
rotations[i * 4] = rotation.x;
501-
rotations[i * 4 + 1] = rotation.y;
502-
rotations[i * 4 + 2] = rotation.z;
503-
rotations[i * 4 + 3] = rotation.w;
503+
attributeRotations[i * 4] = rotation.x;
504+
attributeRotations[i * 4 + 1] = rotation.y;
505+
attributeRotations[i * 4 + 2] = rotation.z;
506+
attributeRotations[i * 4 + 3] = rotation.w;
504507

505-
scales[i * 3] = scale.x;
506-
scales[i * 3 + 1] = scale.y;
507-
scales[i * 3 + 2] = scale.z;
508+
attributeScales[i * 3] = scale.x;
509+
attributeScales[i * 3 + 1] = scale.y;
510+
attributeScales[i * 3 + 2] = scale.z;
508511
}
509512
};
510513

@@ -706,8 +709,11 @@ GaussianSplatPrimitive.buildGSplatDrawCommand = function (
706709

707710
primitive._vertexArrayLen = primitive._indexes.length;
708711

709-
const center = tileset.boundingSphere.center;
710-
const modelMatrix = Transforms.eastNorthUpToFixedFrame(center);
712+
const modelMatrix = Matrix4.multiply(
713+
tileset.modelMatrix,
714+
Matrix4.fromArray(tileset.root.transform),
715+
scratchMatrix4B,
716+
);
711717

712718
const command = new DrawCommand({
713719
boundingVolume: tileset.boundingSphere,
@@ -751,6 +757,11 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
751757
frameState.commandList.push(this._drawCommand);
752758
}
753759

760+
if (tileset._modelMatrixChanged) {
761+
this._dirty = true;
762+
return;
763+
}
764+
754765
if (frameState.passes.pick === true) {
755766
return;
756767
}

0 commit comments

Comments
 (0)