Skip to content

Commit 0e46d6e

Browse files
authored
Merge branch 'main' into fix-hidden-label-background
2 parents a455bca + edccce4 commit 0e46d6e

File tree

7 files changed

+169
-57
lines changed

7 files changed

+169
-57
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- Improved performance and reduced memory usage of `Event` class. [#12896](https://github.com/CesiumGS/cesium/pull/12896)
1313
- Fixes vertical misalignment of glyphs in labels with small fonts [#8474](https://github.com/CesiumGS/cesium/issues/8474)
1414
- Prevent runtime errors for certain forms of invalid PNTS files [#12872](https://github.com/CesiumGS/cesium/issues/12872)
15+
- Fixes issue where multiple instances of a Gaussian splat tileset would transform tile positions incorrectly and render out of position. [#12795](https://github.com/CesiumGS/cesium/issues/12795)
1516
- Fix disappearing label background after updating label while `label.show` is `false`. [#12138](https://github.com/CesiumGS/cesium/issues/12138)
1617

1718
#### Additions :tada:

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,4 +431,5 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
431431
- [Easy Mahaffey](https://github.com/easymaahffey)
432432
- [Pamela Augustine](https://github.com/pamelaAugustine)
433433
- [宋时旺](https://github.com/BlockCnFuture)
434+
- [Marco Zhan](https://github.com/marcoYxz)
434435
- [Adam Beili](https://github.com/Beilinson)

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ function handleBuildWarnings(result) {
123123
export async function build() {
124124
// Configure build options from command line arguments.
125125
const minify = argv.minify ?? false;
126-
const removePragmas = argv.pragmas ?? false;
126+
const removePragmas = argv.removePragmas ?? false;
127127
const sourcemap = argv.sourcemap ?? true;
128128
const node = argv.node ?? true;
129129

packages/engine/Source/Scene/GaussianSplat3DTileContent.js

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,28 @@ function GaussianSplat3DTileContent(loader, tileset, tile, resource) {
3131
}
3232

3333
/**
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.
34+
* Local copy of the position attribute buffer that has been transformed into root tile space. Originals are kept in the gltf loader.
35+
* Used for rendering
3736
* @type {undefined|Float32Array}
3837
* @private
3938
*/
40-
this._originalPositions = undefined;
41-
this._originalRotations = undefined;
42-
this._originalScales = undefined;
39+
this._positions = undefined;
40+
41+
/**
42+
* Local copy of the rotation attribute buffer that has been transformed into root tile space. Originals are kept in the gltf loader.
43+
* Used for rendering
44+
* @type {undefined|Float32Array}
45+
* @private
46+
*/
47+
this._rotations = undefined;
48+
49+
/**
50+
* Local copy of the scale attribute buffer that has been transformed into root tile space. Originals are kept in the gltf loader.
51+
* Used for rendering
52+
* @type {undefined|Float32Array}
53+
* @private
54+
*/
55+
this._scales = undefined;
4356

4457
/**
4558
* glTF primitive data that contains the Gaussian splat data needed for rendering.
@@ -368,6 +381,38 @@ Object.defineProperties(GaussianSplat3DTileContent.prototype, {
368381
},
369382
},
370383

384+
/**
385+
* Get the transformed positions of this tile's Gaussian splats.
386+
* @type {undefined|Float32Array}
387+
* @private
388+
*/
389+
positions: {
390+
get: function () {
391+
return this._positions;
392+
},
393+
},
394+
/**
395+
* Get the transformed rotations of this tile's Gaussian splats.
396+
* @type {undefined|Float32Array}
397+
* @private
398+
*/
399+
rotations: {
400+
get: function () {
401+
return this._rotations;
402+
},
403+
},
404+
405+
/**
406+
* Get the transformed scales of this tile's Gaussian splats.
407+
* @type {undefined|Float32Array}
408+
* @private
409+
*/
410+
scales: {
411+
get: function () {
412+
return this._scales;
413+
},
414+
},
415+
371416
/**
372417
* The number of spherical harmonic coefficients used for the Gaussian splats.
373418
* @type {number}
@@ -629,21 +674,21 @@ GaussianSplat3DTileContent.prototype.update = function (primitive, frameState) {
629674
this.worldTransform = loader.components.scene.nodes[0].matrix;
630675
this._ready = true;
631676

632-
this._originalPositions = new Float32Array(
677+
this._positions = new Float32Array(
633678
ModelUtility.getAttributeBySemantic(
634679
this.gltfPrimitive,
635680
VertexAttributeSemantic.POSITION,
636681
).typedArray,
637682
);
638683

639-
this._originalRotations = new Float32Array(
684+
this._rotations = new Float32Array(
640685
ModelUtility.getAttributeBySemantic(
641686
this.gltfPrimitive,
642687
VertexAttributeSemantic.ROTATION,
643688
).typedArray,
644689
);
645690

646-
this._originalScales = new Float32Array(
691+
this._scales = new Float32Array(
647692
ModelUtility.getAttributeBySemantic(
648693
this.gltfPrimitive,
649694
VertexAttributeSemantic.SCALE,

packages/engine/Source/Scene/GaussianSplatPrimitive.js

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,9 @@ GaussianSplatPrimitive.transformTile = function (tile) {
450450
computedModelMatrix,
451451
scratchMatrix4A,
452452
);
453-
const positions = tile.content._originalPositions;
454-
const rotations = tile.content._originalRotations;
455-
const scales = tile.content._originalScales;
453+
const positions = tile.content.positions;
454+
const rotations = tile.content.rotations;
455+
const scales = tile.content.scales;
456456
const attributePositions = ModelUtility.getAttributeBySemantic(
457457
gltfPrimitive,
458458
VertexAttributeSemantic.POSITION,
@@ -471,19 +471,19 @@ GaussianSplatPrimitive.transformTile = function (tile) {
471471
const position = new Cartesian3();
472472
const rotation = new Quaternion();
473473
const scale = new Cartesian3();
474-
for (let i = 0; i < positions.length / 3; ++i) {
475-
position.x = positions[i * 3];
476-
position.y = positions[i * 3 + 1];
477-
position.z = positions[i * 3 + 2];
474+
for (let i = 0; i < attributePositions.length / 3; ++i) {
475+
position.x = attributePositions[i * 3];
476+
position.y = attributePositions[i * 3 + 1];
477+
position.z = attributePositions[i * 3 + 2];
478478

479-
rotation.x = rotations[i * 4];
480-
rotation.y = rotations[i * 4 + 1];
481-
rotation.z = rotations[i * 4 + 2];
482-
rotation.w = rotations[i * 4 + 3];
479+
rotation.x = attributeRotations[i * 4];
480+
rotation.y = attributeRotations[i * 4 + 1];
481+
rotation.z = attributeRotations[i * 4 + 2];
482+
rotation.w = attributeRotations[i * 4 + 3];
483483

484-
scale.x = scales[i * 3];
485-
scale.y = scales[i * 3 + 1];
486-
scale.z = scales[i * 3 + 2];
484+
scale.x = attributeScales[i * 3];
485+
scale.y = attributeScales[i * 3 + 1];
486+
scale.z = attributeScales[i * 3 + 2];
487487

488488
Matrix4.fromTranslationQuaternionRotationScale(
489489
position,
@@ -498,18 +498,18 @@ GaussianSplatPrimitive.transformTile = function (tile) {
498498
Matrix4.getRotation(scratchMatrix4C, rotation);
499499
Matrix4.getScale(scratchMatrix4C, scale);
500500

501-
attributePositions[i * 3] = position.x;
502-
attributePositions[i * 3 + 1] = position.y;
503-
attributePositions[i * 3 + 2] = position.z;
501+
positions[i * 3] = position.x;
502+
positions[i * 3 + 1] = position.y;
503+
positions[i * 3 + 2] = position.z;
504504

505-
attributeRotations[i * 4] = rotation.x;
506-
attributeRotations[i * 4 + 1] = rotation.y;
507-
attributeRotations[i * 4 + 2] = rotation.z;
508-
attributeRotations[i * 4 + 3] = rotation.w;
505+
rotations[i * 4] = rotation.x;
506+
rotations[i * 4 + 1] = rotation.y;
507+
rotations[i * 4 + 2] = rotation.z;
508+
rotations[i * 4 + 3] = rotation.w;
509509

510-
attributeScales[i * 3] = scale.x;
511-
attributeScales[i * 3 + 1] = scale.y;
512-
attributeScales[i * 3 + 2] = scale.z;
510+
scales[i * 3] = scale.x;
511+
scales[i * 3 + 1] = scale.y;
512+
scales[i * 3 + 2] = scale.z;
513513
}
514514
};
515515

@@ -860,21 +860,27 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
860860
const aggregateAttributeValues = (
861861
componentDatatype,
862862
getAttributeCallback,
863+
numberOfComponents,
863864
) => {
864865
let aggregate;
865866
let offset = 0;
866867
for (const tile of tiles) {
867-
const primitive = tile.content.gltfPrimitive;
868-
const attribute = getAttributeCallback(primitive);
868+
const content = tile.content;
869+
const attribute = getAttributeCallback(content);
870+
const componentsPerAttribute = defined(numberOfComponents)
871+
? numberOfComponents
872+
: AttributeType.getNumberOfComponents(attribute.type);
873+
const buffer = defined(attribute.typedArray)
874+
? attribute.typedArray
875+
: attribute;
869876
if (!defined(aggregate)) {
870877
aggregate = ComponentDatatype.createTypedArray(
871878
componentDatatype,
872-
totalElements *
873-
AttributeType.getNumberOfComponents(attribute.type),
879+
totalElements * componentsPerAttribute,
874880
);
875881
}
876-
aggregate.set(attribute.typedArray, offset);
877-
offset += attribute.typedArray.length;
882+
aggregate.set(buffer, offset);
883+
offset += buffer.length;
878884
}
879885
return aggregate;
880886
};
@@ -906,36 +912,27 @@ GaussianSplatPrimitive.prototype.update = function (frameState) {
906912

907913
this._positions = aggregateAttributeValues(
908914
ComponentDatatype.FLOAT,
909-
(gltfPrimitive) =>
910-
ModelUtility.getAttributeBySemantic(
911-
gltfPrimitive,
912-
VertexAttributeSemantic.POSITION,
913-
),
915+
(content) => content.positions,
916+
3,
914917
);
915918

916919
this._scales = aggregateAttributeValues(
917920
ComponentDatatype.FLOAT,
918-
(gltfPrimitive) =>
919-
ModelUtility.getAttributeBySemantic(
920-
gltfPrimitive,
921-
VertexAttributeSemantic.SCALE,
922-
),
921+
(content) => content.scales,
922+
3,
923923
);
924924

925925
this._rotations = aggregateAttributeValues(
926926
ComponentDatatype.FLOAT,
927-
(gltfPrimitive) =>
928-
ModelUtility.getAttributeBySemantic(
929-
gltfPrimitive,
930-
VertexAttributeSemantic.ROTATION,
931-
),
927+
(content) => content.rotations,
928+
4,
932929
);
933930

934931
this._colors = aggregateAttributeValues(
935932
ComponentDatatype.UNSIGNED_BYTE,
936-
(gltfPrimitive) =>
933+
(content) =>
937934
ModelUtility.getAttributeBySemantic(
938-
gltfPrimitive,
935+
content.gltfPrimitive,
939936
VertexAttributeSemantic.COLOR,
940937
),
941938
);

packages/engine/Specs/Scene/GaussianSplat3DTileContentSpec.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111

1212
import Cesium3DTilesTester from "../../../../Specs/Cesium3DTilesTester.js";
1313
import createScene from "../../../../Specs/createScene.js";
14+
import pollToPromise from "../../../../Specs/pollToPromise.js";
1415

1516
describe(
1617
"Scene/GaussianSplat3DTileContent",
@@ -96,6 +97,7 @@ describe(
9697
},
9798
);
9899
});
100+
99101
it("Create and destroy GaussianSplat3DTileContent", async function () {
100102
const tileset = await Cesium3DTilesTester.loadTileset(
101103
scene,
@@ -116,6 +118,69 @@ describe(
116118
expect(tile.isDestroyed()).toBe(true);
117119
expect(tile.content).toBeUndefined();
118120
});
121+
122+
it("Load multiple instances of Gaussian splat tileset and validate transformed attributes", async function () {
123+
const tileset = await Cesium3DTilesTester.loadTileset(
124+
scene,
125+
tilesetUrl,
126+
options,
127+
);
128+
scene.camera.lookAt(
129+
tileset.boundingSphere.center,
130+
new HeadingPitchRange(0.0, -1.57, tileset.boundingSphere.radius),
131+
);
132+
133+
const tileset2 = await Cesium3DTilesTester.loadTileset(
134+
scene,
135+
tilesetUrl,
136+
options,
137+
);
138+
139+
const tile = await Cesium3DTilesTester.waitForTileContentReady(
140+
scene,
141+
tileset.root,
142+
);
143+
144+
scene.camera.lookAt(
145+
tileset2.boundingSphere.center,
146+
new HeadingPitchRange(0.0, -1.57, tileset2.boundingSphere.radius),
147+
);
148+
149+
const tile2 = await Cesium3DTilesTester.waitForTileContentReady(
150+
scene,
151+
tileset2.root,
152+
);
153+
const content = tile.content;
154+
const content2 = tile2.content;
155+
156+
expect(content).toBeDefined();
157+
expect(content instanceof GaussianSplat3DTileContent).toBe(true);
158+
expect(content2).toBeDefined();
159+
expect(content2 instanceof GaussianSplat3DTileContent).toBe(true);
160+
161+
await pollToPromise(function () {
162+
scene.renderForSpecs();
163+
return (
164+
tile.content._transformed === true &&
165+
tile2.content._transformed === true
166+
);
167+
});
168+
169+
const positions1 = tile.content._positions;
170+
const positions2 = tile2.content._positions;
171+
172+
expect(positions1.every((p, i) => p === positions2[i])).toBe(true);
173+
174+
const rotations1 = tile.content._rotations;
175+
const rotations2 = tile2.content._rotations;
176+
177+
expect(rotations1.every((r, i) => r === rotations2[i])).toBe(true);
178+
179+
const scales1 = tile.content._scales;
180+
const scales2 = tile2.content._scales;
181+
182+
expect(scales1.every((s, i) => s === scales2[i])).toBe(true);
183+
});
119184
},
120185
"WebGL",
121186
);

scripts/build.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,9 @@ export async function bundleWorkers(options) {
387387
workerConfig.logOverride = {
388388
"empty-import-meta": "silent",
389389
};
390+
workerConfig.plugins = options.removePragmas
391+
? [stripPragmaPlugin]
392+
: undefined;
390393
} else {
391394
workerConfig.format = "esm";
392395
workerConfig.splitting = true;

0 commit comments

Comments
 (0)