Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ export interface PLYHeader {
export class GaussianSplattingMesh extends Mesh {
private _vertexCount = 0;
private _worker: Nullable<Worker> = null;
private _modelViewMatrix = Matrix.Identity();
private _modelViewProjectionMatrix = Matrix.Identity();
private _depthMix: BigInt64Array;
private _canPostToWorker = true;
private _readyToDisplay = false;
Expand Down Expand Up @@ -330,6 +330,13 @@ export class GaussianSplattingMesh extends Mesh {
private static readonly _BatchSize = 16; // 16 splats per instance
private _cameraViewInfos = new Map<number, ICameraViewInfo>();

private static readonly _DefaultViewUpdateThreshold = 1e-4;

/**
* Cosine value of the angle threshold to update view dependent splat sorting. Default is 0.0001.
*/
public viewUpdateThreshold: number = GaussianSplattingMesh._DefaultViewUpdateThreshold;

protected _disableDepthSort = false;
/**
* If true, disables depth sorting of the splats (default: false)
Expand Down Expand Up @@ -559,12 +566,15 @@ export class GaussianSplattingMesh extends Mesh {
}

public _getCameraDirection(camera: Camera): Vector3 {
const cameraMatrix = camera.getViewMatrix();
this.getWorldMatrix().multiplyToRef(cameraMatrix, this._modelViewMatrix);
const cameraViewMatrix = camera.getViewMatrix();
const cameraProjectionMatrix = camera.getProjectionMatrix();
const cameraViewProjectionMatrix = TmpVectors.Matrix[0];
cameraViewMatrix.multiplyToRef(cameraProjectionMatrix, cameraViewProjectionMatrix);
this.getWorldMatrix().multiplyToRef(cameraViewProjectionMatrix, this._modelViewProjectionMatrix);

// return vector used to compute distance to camera
const localDirection = TmpVectors.Vector3[1];
localDirection.set(this._modelViewMatrix.m[2], this._modelViewMatrix.m[6], this._modelViewMatrix.m[10]);
localDirection.set(this._modelViewProjectionMatrix.m[8], this._modelViewProjectionMatrix.m[9], this._modelViewProjectionMatrix.m[10]);
localDirection.normalize();

return localDirection;
Expand Down Expand Up @@ -627,22 +637,21 @@ export class GaussianSplattingMesh extends Mesh {

const previousCameraDirection = cameraViewInfos.cameraDirection;
const dot = Vector3.Dot(cameraDirection, previousCameraDirection);
if ((forced || Math.abs(dot - 1) >= 0.01) && this._canPostToWorker) {
if ((forced || Math.abs(dot - 1) >= this.viewUpdateThreshold) && this._canPostToWorker) {
cameraViewInfos.cameraDirection.copyFrom(cameraDirection);
cameraViewInfos.frameIdLastUpdate = frameId;
this._canPostToWorker = false;
if (this._worker) {
this._worker!.postMessage(
{
view: this._modelViewMatrix.m,
modelViewProjection: this._modelViewProjectionMatrix.m,
depthMix: this._depthMix,
useRightHandedSystem: this._scene.useRightHandedSystem,
cameraId: camera.uniqueId,
},
[this._depthMix.buffer]
);
} else if (_native && _native.sortSplats) {
_native.sortSplats(this._modelViewMatrix, this._splatPositions!, this._splatIndex!, this._scene.useRightHandedSystem);
_native.sortSplats(this._modelViewProjectionMatrix, this._splatPositions!, this._splatIndex!, this._scene.useRightHandedSystem);
if (cameraViewInfos.splatIndexBufferSet) {
cameraViewInfos.mesh.thinInstanceBufferUpdated("splatIndex");
} else {
Expand Down Expand Up @@ -1446,7 +1455,7 @@ export class GaussianSplattingMesh extends Mesh {
newGS.makeGeometryUnique();
newGS._vertexCount = this._vertexCount;
newGS._copyTextures(this);
newGS._modelViewMatrix = Matrix.Identity();
newGS._modelViewProjectionMatrix = Matrix.Identity();
newGS._splatPositions = this._splatPositions;
newGS._readyToDisplay = false;
newGS._disableDepthSort = this._disableDepthSort;
Expand Down Expand Up @@ -1474,12 +1483,12 @@ export class GaussianSplattingMesh extends Mesh {
// udpate on view changed
else {
const cameraId = e.data.cameraId;
const viewProj = e.data.view;
const modelViewProjection = e.data.modelViewProjection;

const vertexCountPadded = (positions.length / 4 + 15) & ~0xf;
if (!positions || !viewProj) {
if (!positions || !modelViewProjection) {
// Sanity check, it shouldn't happen!
throw new Error("positions or view is not defined!");
throw new Error("positions or modelViewProjection matrix is not defined!");
}

depthMix = e.data.depthMix;
Expand All @@ -1491,13 +1500,9 @@ export class GaussianSplattingMesh extends Mesh {
indices[2 * j] = j;
}

let depthFactor = -1;
if (e.data.useRightHandedSystem) {
depthFactor = 1;
}

for (let j = 0; j < vertexCountPadded; j++) {
floatMix[2 * j + 1] = 10000 + (viewProj[2] * positions[4 * j + 0] + viewProj[6] * positions[4 * j + 1] + viewProj[10] * positions[4 * j + 2]) * depthFactor;
floatMix[2 * j + 1] =
10000 - (modelViewProjection[2] * positions[4 * j + 0] + modelViewProjection[6] * positions[4 * j + 1] + modelViewProjection[10] * positions[4 * j + 2]);
}

depthMix.sort();
Expand Down
Loading